.Net Core 3预览SequenceReader长度分隔解析

问题描述 投票:0回答:2

我正在尝试在 .Net Core Preview 8 中使用

SequenceReader<T>
来解析 Guacamole Protocol 网络流量。

流量可能如下所示:

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

这是一条错误指令。有 3 个字段:

  • 操作码 =
    error
  • 原因=
    some text here
  • 状态 =
    0
    (请参阅状态代码

字段以逗号分隔(以分号终止),但每个字段也有长度前缀。我想这样你就可以解析类似的东西:

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;
}

根据我对初始提案的理解,这应该可行,尽管我认为也可以简化,因为提案中的一些方法使生活比 .Net Core Preview 8 中提供的方法更容易。

但是,这段代码的问题是

SequenceReader
似乎并不像我所期望的那样
Advance
。它的
Position
Consumed
属性在前进时保持不变,所以最后的
element
我切片是 always 一个空序列。

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

.net-core guacamole
2个回答
4
投票

我猜

.Reader
这里是一个财产;这很重要,因为
SequenceReader<T>
是一个 可变结构,但每次访问
.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
)中,您还不会更改状态,因为您只是改变了本地独立克隆。


也可以考虑

ref
-返回属性
.Reader


0
投票

我有一个问题,我们如何才能将鳄梨酱连接到 .net core Web api?

© www.soinside.com 2019 - 2024. All rights reserved.