Skip to content

Commit c3bb76d

Browse files
committed
[Proto] Metadata and Deserialization design
1 parent 4f16c77 commit c3bb76d

16 files changed

Lines changed: 374 additions & 24 deletions
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using Lagrange.Proto.Primitives;
2+
using Lagrange.Proto.Serialization.Metadata;
3+
4+
namespace Lagrange.Proto.Serialization.Converter.Generic;
5+
6+
internal class ProtoNullableConverter<T> : ProtoConverter<T?> where T : struct
7+
{
8+
private readonly ProtoConverter<T> _converter = ProtoTypeResolver.GetConverter<T>();
9+
10+
public override WireType WireType => _converter.WireType;
11+
12+
public override void Write(int field, ProtoWriter writer, T? value)
13+
{
14+
if (value.HasValue) _converter.Write(0, writer, value.Value);
15+
}
16+
17+
public override T? Read(int field, ref ProtoReader reader)
18+
{
19+
return _converter.Read(field, ref reader);
20+
}
21+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System.Runtime.CompilerServices;
2+
using Lagrange.Proto.Primitives;
3+
4+
namespace Lagrange.Proto.Serialization.Converter;
5+
6+
internal class ProtoBooleanConverter : ProtoConverter<bool>
7+
{
8+
public override WireType WireType => WireType.VarInt;
9+
10+
public override void Write(int field, ProtoWriter writer, bool value)
11+
{
12+
writer.WriteRawByte(Unsafe.As<bool, byte>(ref value));
13+
}
14+
15+
public override bool Read(int field, ref ProtoReader reader)
16+
{
17+
byte b = reader.DecodeVarInt<byte>();
18+
return Unsafe.As<byte, bool>(ref b);
19+
}
20+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Lagrange.Proto.Primitives;
2+
3+
namespace Lagrange.Proto.Serialization.Converter;
4+
5+
public class ProtoBytesConverter : ProtoConverter<byte[]>
6+
{
7+
public override WireType WireType => WireType.LengthDelimited;
8+
9+
public override void Write(int field, ProtoWriter writer, byte[] value)
10+
{
11+
writer.EncodeVarInt(value.Length);
12+
writer.WriteRawBytes(value);
13+
}
14+
15+
public override byte[] Read(int field, ref ProtoReader reader)
16+
{
17+
int length = reader.DecodeVarInt<int>();
18+
if (length == 0) return [];
19+
20+
var buffer = GC.AllocateUninitializedArray<byte>(length);
21+
var span = reader.CreateSpan(length);
22+
span.CopyTo(buffer);
23+
24+
return buffer;
25+
}
26+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System.Numerics;
2+
using Lagrange.Proto.Primitives;
3+
4+
namespace Lagrange.Proto.Serialization.Converter;
5+
6+
internal class ProtoFixed32Converter<T> : ProtoConverter<T> where T : unmanaged, INumber<T>
7+
{
8+
public override WireType WireType => WireType.Fixed32;
9+
10+
public override void Write(int field, ProtoWriter writer, T value)
11+
{
12+
writer.EncodeFixed32<T>(value);
13+
}
14+
15+
public override T Read(int field, ref ProtoReader reader)
16+
{
17+
return reader.DecodeFixed32<T>();
18+
}
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System.Numerics;
2+
using Lagrange.Proto.Primitives;
3+
4+
namespace Lagrange.Proto.Serialization.Converter;
5+
6+
internal class ProtoFixed64Converter<T> : ProtoConverter<T> where T : unmanaged, INumber<T>
7+
{
8+
public override WireType WireType => WireType.Fixed64;
9+
10+
public override void Write(int field, ProtoWriter writer, T value)
11+
{
12+
writer.EncodeFixed64<T>(value);
13+
}
14+
15+
public override T Read(int field, ref ProtoReader reader)
16+
{
17+
return reader.DecodeFixed64<T>();
18+
}
19+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using Lagrange.Proto.Primitives;
2+
3+
namespace Lagrange.Proto.Serialization.Converter;
4+
5+
public class ProtoReadOnlyMemoryByteConverter : ProtoConverter<ReadOnlyMemory<byte>>
6+
{
7+
public override WireType WireType => WireType.LengthDelimited;
8+
9+
public override void Write(int field, ProtoWriter writer, ReadOnlyMemory<byte> value)
10+
{
11+
writer.EncodeVarInt(value.Length);
12+
writer.WriteRawBytes(value.Span);
13+
}
14+
15+
public override ReadOnlyMemory<byte> Read(int field, ref ProtoReader reader)
16+
{
17+
int length = reader.DecodeVarInt<int>();
18+
if (length == 0) return ReadOnlyMemory<byte>.Empty;
19+
20+
var buffer = GC.AllocateUninitializedArray<byte>(length);
21+
var span = reader.CreateSpan(length);
22+
span.CopyTo(buffer);
23+
return new ReadOnlyMemory<byte>(buffer, 0, length);
24+
}
25+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System.Text;
2+
using Lagrange.Proto.Primitives;
3+
4+
namespace Lagrange.Proto.Serialization.Converter;
5+
6+
internal class ProtoStringConverter : ProtoConverter<string>
7+
{
8+
public override WireType WireType => WireType.LengthDelimited;
9+
10+
public override void Write(int field, ProtoWriter writer, string value)
11+
{
12+
writer.EncodeString(value);
13+
}
14+
15+
public override string Read(int field, ref ProtoReader reader)
16+
{
17+
int length = reader.DecodeVarInt<int>();
18+
var span = reader.CreateSpan(length);
19+
if (span.IsEmpty) return string.Empty;
20+
21+
return Encoding.UTF8.GetString(span);
22+
}
23+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System.Numerics;
2+
using Lagrange.Proto.Primitives;
3+
4+
namespace Lagrange.Proto.Serialization.Converter;
5+
6+
internal class ProtoVarIntConverter<T> : ProtoConverter<T> where T : unmanaged, INumber<T>
7+
{
8+
public override WireType WireType => WireType.VarInt;
9+
10+
public override void Write(int field, ProtoWriter writer, T value)
11+
{
12+
writer.EncodeVarInt<T>(value);
13+
}
14+
15+
public override T Read(int field, ref ProtoReader reader)
16+
{
17+
return reader.DecodeVarInt<T>();
18+
}
19+
}

Lagrange.Proto/Serialization/Metadata/ProtoFieldInfo.cs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using System.Diagnostics;
2+
using Lagrange.Proto.Primitives;
23

34
namespace Lagrange.Proto.Serialization.Metadata;
45

6+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
57
public abstract class ProtoFieldInfo(int field, WireType wireType, Type declared, Type property)
68
{
79
public int Field { get; } = field;
@@ -30,10 +32,23 @@ internal ProtoConverter EffectiveConverter
3032
private protected ProtoConverter? _effectiveConverter;
3133
private protected abstract void SetGetter(Delegate? getter);
3234
private protected abstract void SetSetter(Delegate? setter);
35+
36+
public abstract void Read(ref ProtoReader reader, object target);
37+
38+
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
39+
private string DebuggerDisplay => $"Field = {Field}, WireType = {WireType}, PropertyType = {PropertyType}, DeclaredType = {DeclaredType}";
40+
3341
}
3442

35-
public class ProtoFieldInfo<T>(int field, WireType wireType, Type declared) : ProtoFieldInfo(field, wireType, declared, typeof(T))
43+
public class ProtoFieldInfo<T> : ProtoFieldInfo
3644
{
45+
public ProtoFieldInfo(int field, WireType wireType, Type declared) : base(field, wireType, declared, typeof(T))
46+
{
47+
var converter = ProtoTypeResolver.GetConverter<T>();
48+
_effectiveConverter = converter;
49+
_typedEffectiveConverter = converter;
50+
}
51+
3752
private Func<object, T>? _typedGet;
3853
private Action<object, T>? _typedSet;
3954

@@ -59,7 +74,7 @@ public class ProtoFieldInfo<T>(int field, WireType wireType, Type declared) : Pr
5974
}
6075

6176
private ProtoConverter<T>? _typedEffectiveConverter;
62-
77+
6378
private protected override void SetGetter(Delegate? getter)
6479
{
6580
Debug.Assert(getter is null or Func<object, object?> or Func<object, T>);
@@ -103,4 +118,12 @@ private protected override void SetSetter(Delegate? setter)
103118
break;
104119
}
105120
}
121+
122+
public override void Read(ref ProtoReader reader, object target)
123+
{
124+
Debug.Assert(_typedEffectiveConverter != null);
125+
126+
T value = _typedEffectiveConverter.Read(Field, ref reader);
127+
_typedSet?.Invoke(target, value);
128+
}
106129
}

Lagrange.Proto/Serialization/Metadata/ProtoTypeInfo.cs

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)