【问题标题】:.Net Core 3 Preview SequenceReader Length Delimited Parsing.Net Core 3 Preview SequenceReader 长度定界解析
【发布时间】:2020-01-02 14:59:57
【问题描述】:

我正在尝试在 .Net Core Preview 8 中使用 SequenceReader<T> 来解析 Guacamole Protocol 网络流量。

流量可能如下所示:

5.error,14.some text here,1.0;

这是一个单一的error instruction。有3个字段:

  • 操作码 = error
  • 原因 = some text here
  • 状态 = 0(见Status Codes

字段以逗号分隔(分号终止),但每个字段也有长度前缀。我想这样你就可以解析如下内容:

5.error,24.some, text, with, commas,1.0;

产生Reason = some, text, with, commas

简单的逗号分隔解析很简单(有或没有SequenceReader)。但是,为了利用长度,我尝试了以下方法:

public static bool TryGetNextElement(this ref SerializationContext context, out ReadOnlySequence<byte> element)
{
    element = default;
    var start = context.Reader.Position;
    if (!context.Reader.TryReadTo(out ReadOnlySequence<byte> lengthSlice, Utf8Bytes.Period, advancePastDelimiter: true))
        return false;
    if (!lengthSlice.TryGetInt(out var length))
        return false;
    context.Reader.Advance(length);
    element = context.Reader.Sequence.Slice(start, context.Reader.Position);
    return true;
}

根据我对initial proposal 的理解,这应该可行,但我认为也可以简化,因为提案中的某些方法比 .Net Core Preview 8 中提供的方法更容易一些。

但是,此代码的问题在于 SequenceReader 似乎不像我所期望的那样 Advance。它的PositionConsumed 属性在前进时保持不变,所以最后的element I 切片始终是一个空序列。

我需要做什么才能正确解析此协议?

【问题讨论】:

  • 我可以在这里看到SerializationContext 吗?特别是,SequenceReader&lt;T&gt; 是一个可变结构,所以知道.Reader 是一个属性还是一个字段真的很重要

标签: .net-core guacamole


【解决方案1】:

我猜.Reader 这里是一个属性;这很重要,因为SequenceReader&lt;T&gt; 是一个可变结构,但每次访问.SomeProperty 时,您都在使用阅读器的独立副本。可以将其隐藏在属性后面,但您需要确保使用本地,然后完成后推回,即

var reader = context.Reader;
var start = reader.Position;
if (!reader.TryReadTo(out ReadOnlySequence<byte> lengthSlice,
        Utf8Bytes.Period, advancePastDelimiter: true))
    return false;
if (!lengthSlice.TryGetInt(out var length))
    return false;
reader.Advance(length);
element = reader.Sequence.Slice(start, reader.Position);

context.Reader = reader; // update position
return true;

请注意,这样做的一个很好的特性是,在失败的情况下 (return false),你还没有改变状态,因为你已经只是在变异你的本地独立克隆。


可以还考虑为.Reader 使用ref-return 属性。

【讨论】:

  • 很棒的答案,谢谢。仍在尝试完全掌握所有ref/in/out。获取副本非常有意义,并解释了一切。我天真地在 OP 中获得了 4 个新的阅读器副本,所以当然位置总是被重置?我知道我是个柠檬,只是不知道在哪里! :D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-28
  • 2019-11-02
  • 2020-01-05
  • 2019-09-28
  • 2017-12-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多