Skip to content

Commit

Permalink
Add read methods to buffer classes
Browse files Browse the repository at this point in the history
  • Loading branch information
ThadHouse committed Jan 16, 2024
1 parent bc30e17 commit 8d615e3
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 22 deletions.
27 changes: 26 additions & 1 deletion src/wpiutil/Serialization/Protobuf/IProtobuf.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Google.Protobuf;
using System;
using Google.Protobuf;
using Google.Protobuf.Reflection;

namespace WPIUtil.Serialization.Protobuf;
Expand All @@ -17,4 +18,28 @@ public interface IProtobuf<T, MessageType> : IProtobufBase where MessageType : I
T Unpack(MessageType msg);

void Pack(MessageType msg, T value);

void UnpackInto(ref T value, MessageType msg)
{
throw new NotSupportedException("Object does not support UnpackInto");
}

void ForEachDescriptor(Func<string, bool> exists, Action<string, byte[]> fn)
{
ForEachDescriptorImpl(Descriptor.File, exists, fn);
}

private static void ForEachDescriptorImpl(FileDescriptor desc, Func<string, bool> exists, Action<string, byte[]> fn)
{
string name = $"proto:{desc.Name}";
if (exists(name))
{
return;
}
foreach (var d in desc.Dependencies)
{
ForEachDescriptorImpl(d, exists, fn);
}
fn(name, desc.ToProto().ToByteArray());
}
}
19 changes: 10 additions & 9 deletions src/wpiutil/Serialization/Protobuf/ProtobufBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,18 @@

namespace WPIUtil.Serialization.Protobuf;

public sealed class ProtobufBuffer<T, MessageType> where MessageType : IMessage
public struct ProtobufBuffer<T, MessageType> where MessageType : IMessage
where T : IProtobufSerializable<T, MessageType>
{
private ProtobufBuffer()
public ProtobufBuffer()
{
Proto = T.Proto;
m_msg = Proto.CreateMessage();
}

public static ProtobufBuffer<T, MessageType> Create()
{
return new ProtobufBuffer<T, MessageType>();
}

public IProtobuf<T, MessageType> Proto { get; }

public string TypeString => Proto.TypeString;
public readonly string TypeString => Proto.TypeString;

public ReadOnlySpan<byte> Write(T value)
{
Expand All @@ -33,12 +28,18 @@ public ReadOnlySpan<byte> Write(T value)
return m_buf.AsSpan()[..size];
}

public T Read(ReadOnlySpan<byte> buffer)
public readonly T Read(ReadOnlySpan<byte> buffer)
{
m_msg.MergeFrom(buffer);
return Proto.Unpack(m_msg);
}

public readonly void ReadInto(ref T output, ReadOnlySpan<byte> buffer)
{
m_msg.MergeFrom(buffer);
Proto.UnpackInto(ref output, m_msg);
}

private readonly MessageType m_msg;
private byte[] m_buf = new byte[1024];
}
9 changes: 8 additions & 1 deletion src/wpiutil/Serialization/Struct/Struct.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace WPIUtil.Serialization.Struct;
using System;

namespace WPIUtil.Serialization.Struct;

public interface IStructBase
{
Expand All @@ -17,4 +19,9 @@ public interface IStruct<T> : IStructBase
T Unpack(ref StructUnpacker buffer);

void Pack(ref StructPacker buffer, T value);

void UnpackInto(ref T value, ref StructUnpacker buffer)
{
throw new NotSupportedException("Object does not support UnpackInto");
}
}
47 changes: 36 additions & 11 deletions src/wpiutil/Serialization/Struct/StructBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,21 @@

namespace WPIUtil.Serialization.Struct;

public sealed class StructBuffer<T>
public struct StructBuffer<T> where T : IStructSerializable<T>
{
private readonly int m_structSize;
private byte[] m_buf;
public IStruct<T> Struct { get; }

public readonly string TypeString => Struct.TypeString;

private StructBuffer(IStruct<T> value)
public StructBuffer()
{
m_structSize = value.Size;
Struct = T.Struct;
m_structSize = Struct.Size;
m_buf = new byte[m_structSize];
Struct = value;
}

public static StructBuffer<T> Create(IStruct<T> value) => new(value);

public IStruct<T> Struct { get; }

public string TypeString => Struct.TypeString;

public void Reserve(int nelem)
{
if ((nelem * m_structSize) > m_buf.Length)
Expand All @@ -28,13 +25,25 @@ public void Reserve(int nelem)
}
}

public ReadOnlySpan<byte> Write(T value)
public readonly ReadOnlySpan<byte> Write(T value)
{
StructPacker packer = new(m_buf);
Struct.Pack(ref packer, value);
return packer.Filled;
}

public readonly T Read(ReadOnlySpan<byte> buffer)
{
StructUnpacker unpacker = new(buffer);
return Struct.Unpack(ref unpacker);
}

public readonly void ReadInto(ref T output, ReadOnlySpan<byte> buffer)
{
StructUnpacker unpacker = new(buffer);
Struct.UnpackInto(ref output, ref unpacker);
}

public ReadOnlySpan<byte> WriteArray(ReadOnlySpan<T> values)
{
if ((values.Length * m_structSize) > m_buf.Length)
Expand All @@ -48,4 +57,20 @@ public ReadOnlySpan<byte> WriteArray(ReadOnlySpan<T> values)
}
return packer.Filled;
}

public readonly T[] ReadArray(ReadOnlySpan<byte> buffer)
{
if ((buffer.Length % m_structSize) != 0)
{
throw new Exception("Buffer size not a multiple of struct size");
}
int nelem = buffer.Length / m_structSize;
T[] arr = new T[nelem];
StructUnpacker unpacker = new(buffer);
for (int i = 0; i < nelem; i++)
{
arr[i] = Struct.Unpack(ref unpacker);
}
return arr;
}
}

0 comments on commit 8d615e3

Please sign in to comment.