Skip to content

Commit

Permalink
Fix protobuf erasure
Browse files Browse the repository at this point in the history
  • Loading branch information
ThadHouse committed Jan 16, 2024
1 parent 3eb38cd commit 74b8d24
Show file tree
Hide file tree
Showing 11 changed files with 284 additions and 27 deletions.
15 changes: 15 additions & 0 deletions src/ntcore/NetworkTableInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using Google.Protobuf;
using NetworkTables.Handles;
using NetworkTables.Natives;
using WPIMath.Geometry;
using WPIUtil;
using WPIUtil.Concurrent;
using WPIUtil.Natives;
using WPIUtil.Serialization.Protobuf;

namespace NetworkTables;

Expand Down Expand Up @@ -485,4 +488,16 @@ public override int GetHashCode()
{
return !(left == right);
}

public void AddSchema(IProtobufBase proto)
{
throw new NotImplementedException();
}

public ProtobufTopic<T> GetProtobufTopic<T>(string name) where T : IProtobufSerializable<T>
{

GetProtobufTopic<Rotation2d>("Hello");
throw new NotImplementedException();
}
}
9 changes: 9 additions & 0 deletions src/ntcore/ProtobufEntry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Google.Protobuf;
using WPIUtil.Serialization.Protobuf;

namespace NetworkTables;

public interface IProtobufEntry<T> : IProtobufSubscriber<T>, IProtobufPublisher<T> where T : IProtobufSerializable<T>
{
void Unpublish();
}
139 changes: 139 additions & 0 deletions src/ntcore/ProtobufEntryImpl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
using System;
using System.Buffers;
using System.Reflection.Metadata;
using Google.Protobuf;
using NetworkTables.Handles;
using NetworkTables.Natives;
using WPIUtil.Serialization.Protobuf;

namespace NetworkTables;

internal sealed class ProtobufEntryImpl<T, THandle> : EntryBase<THandle>, IProtobufEntry<T> where THandle : struct, INtEntryHandle where T : IProtobufSerializable<T>
{
internal ProtobufEntryImpl(ProtobufTopic<T> topic, THandle handle, T defaultValue, bool schemaPublished) : base(handle)
{
Topic = topic;
m_defaultValue = defaultValue;
m_buf = new ProtobufBuffer<T>();
m_schemaPublished = schemaPublished;
}

private readonly T m_defaultValue;
private readonly ProtobufBuffer<T> m_buf;
private bool m_schemaPublished;
private readonly object m_lockObject = new();

public override ProtobufTopic<T> Topic { get; }

public T Get()
{
throw new System.NotImplementedException();
}

public T Get(T defaultValue)
{
throw new System.NotImplementedException();
}

public TimestampedObject<T> GetAtomic()
{
throw new System.NotImplementedException();
}

public TimestampedObject<T> GetAtomic(T defaultValue)
{
throw new System.NotImplementedException();
}

public bool GetInto(ref T output)
{
throw new System.NotImplementedException();
}

public TimestampedObject<T>[] ReadQueue()
{
throw new System.NotImplementedException();
}

public T[] ReadQueueValues()
{
throw new System.NotImplementedException();
}

public void Set(T value)
{
throw new System.NotImplementedException();
}

public void Set(long time, T value)
{
throw new System.NotImplementedException();
}

public void SetDefault(T value)
{
try
{
lock (m_lockObject)
{
if (!m_schemaPublished)
{
m_schemaPublished = true;
Topic.Instance.AddSchema(m_buf.Proto);
}
ReadOnlySpan<byte> buf = m_buf.Write(value);
NtCore.SetDefaultEntryValue(Handle, RefNetworkTableValue.MakeRaw(buf));
}
}
catch
{

}
}

public void Unpublish()
{
NtCore.Unpublish(Handle);
}

private T FromRaw(ReadOnlySpan<byte> raw, T defaultValue)
{
if (raw.Length == 0)
{
return defaultValue;
}

try
{
lock (m_lockObject)
{
return m_buf.Read(raw);
}
}
catch
{
return defaultValue;
}
}

private TimestampedObject<T> FromRaw(TimestampedRaw raw, T defaultValue)
{
if (raw.Value.Length == 0)
{
return new TimestampedObject<T>(0, 0, defaultValue);
}
try
{
lock (m_lockObject)
{
return new TimestampedObject<T>(raw.Timestamp, raw.ServerTime, m_buf.Read(raw.Value));
}
}
catch
{
return new TimestampedObject<T>(0, 0, defaultValue);
}
}

private static readonly ReadOnlyMemory<byte> m_emptyRaw = Array.Empty<byte>();
}
15 changes: 15 additions & 0 deletions src/ntcore/ProtobufPublisher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Google.Protobuf;
using WPIUtil.Serialization.Protobuf;

namespace NetworkTables;

public interface IProtobufPublisher<T> : Publisher where T : IProtobufSerializable<T>
{
new ProtobufTopic<T> Topic { get; }

void Set(T value);

void Set(long time, T value);

void SetDefault(T value);
}
23 changes: 23 additions & 0 deletions src/ntcore/ProtobufSubscriber.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Google.Protobuf;
using WPIUtil.Serialization.Protobuf;

namespace NetworkTables;

public interface IProtobufSubscriber<T> : Subscriber where T : IProtobufSerializable<T>
{
new ProtobufTopic<T> Topic { get; }

T Get();

T Get(T defaultValue);

bool GetInto(ref T output);

TimestampedObject<T> GetAtomic();

TimestampedObject<T> GetAtomic(T defaultValue);

TimestampedObject<T>[] ReadQueue();

T[] ReadQueueValues();
}
24 changes: 24 additions & 0 deletions src/ntcore/ProtobufTopic.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Google.Protobuf;
using NetworkTables.Handles;
using NetworkTables.Natives;
using WPIUtil.Serialization.Protobuf;

namespace NetworkTables;

public sealed class ProtobufTopic<T> : Topic where T : IProtobufSerializable<T>
{
private IProtobufBase m_proto = T.Proto;

private ProtobufTopic(Topic topic) : base(topic.Instance, topic.Handle)
{
}

private ProtobufTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, handle)
{
}

public IProtobufSubscriber<T> Subscribe(T defaultValue, PubSubOptions options)
{
return new ProtobufEntryImpl<T, NtSubscriber>(this, NtCore.Subscribe(Handle, NetworkTableType.Raw, m_proto.TypeString, options), defaultValue, false);
}
}
9 changes: 4 additions & 5 deletions src/wpiutil/Logging/ProtobufLogEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,19 @@

namespace WPIUtil.Logging;

public sealed class ProtobufLogEntry<T, MessageType> : DataLogEntry where MessageType : IMessage
where T : IProtobufSerializable<T, MessageType>
public sealed class ProtobufLogEntry<T> : DataLogEntry where T : IProtobufSerializable<T>
{
private readonly ProtobufBuffer<T, MessageType> m_storage = new();
private readonly ProtobufBuffer<T> m_storage = new();
private readonly object m_lockObject = new();

private ProtobufLogEntry(DataLog log, string name, IProtobufBase proto, string metadata = "", long timestamp = 0) : base(log, name, proto.TypeString, metadata, timestamp)
{
log.AddSchema(proto, timestamp);
}

public ProtobufLogEntry<T, MessageType> Create(DataLog log, string name, string metadata = "", long timestamp = 0)
public ProtobufLogEntry<T> Create(DataLog log, string name, string metadata = "", long timestamp = 0)
{
return new ProtobufLogEntry<T, MessageType>(log, name, T.Proto, metadata, timestamp);
return new ProtobufLogEntry<T>(log, name, T.Proto, metadata, timestamp);
}

public void Append(T value, long timestamp = 0)
Expand Down
61 changes: 47 additions & 14 deletions src/wpiutil/Serialization/Protobuf/IProtobuf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,6 @@ public interface IProtobufBase
string TypeString => $"proto:{Descriptor.FullName}";
MessageDescriptor Descriptor { get; }
IProtobufBase[] Nested => [];
}

public interface IProtobuf<T, MessageType> : IProtobufBase where MessageType : IMessage
{
MessageType CreateMessage();

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)
{
Expand All @@ -43,3 +29,50 @@ private static void ForEachDescriptorImpl(FileDescriptor desc, Func<string, bool
fn(name, desc.ToProto().ToByteArray());
}
}

public interface IProtobuf<T> : IProtobufBase
{
abstract IMessage CreateMessage();

T Unpack(IMessage msg);

void Pack(IMessage msg, T value);

void UnpackInto(ref T value, IMessage msg);
}

public interface IProtobuf<T, MessageType> : IProtobuf<T> where MessageType : IMessage<MessageType>
{

IMessage IProtobuf<T>.CreateMessage()
{
throw new NotImplementedException();
}

void IProtobuf<T>.Pack(IMessage msg, T value)
{
Pack((MessageType)msg, value);
}

T IProtobuf<T>.Unpack(IMessage msg)
{
return Unpack((MessageType)msg);
}

void IProtobuf<T>.UnpackInto(ref T value, IMessage msg)
{
UnpackInto(ref value, (MessageType)msg);
}

new MessageType CreateMessage();

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");
}
}
4 changes: 2 additions & 2 deletions src/wpiutil/Serialization/Protobuf/IProtobufSerializable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace WPIUtil.Serialization.Protobuf;

public interface IProtobufSerializable<T, MessageType> : IWPISerializable<T> where MessageType : IMessage
public interface IProtobufSerializable<T> : IWPISerializable<T>
{
public static abstract IProtobuf<T, MessageType> Proto { get; }
public static abstract IProtobuf<T> Proto { get; }
}
7 changes: 3 additions & 4 deletions src/wpiutil/Serialization/Protobuf/ProtobufBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@

namespace WPIUtil.Serialization.Protobuf;

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

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

public readonly string TypeString => Proto.TypeString;

Expand Down Expand Up @@ -40,6 +39,6 @@ public readonly void ReadInto(ref T output, ReadOnlySpan<byte> buffer)
Proto.UnpackInto(ref output, m_msg);
}

private readonly MessageType m_msg;
private readonly IMessage m_msg;
private byte[] m_buf = new byte[1024];
}
Loading

0 comments on commit 74b8d24

Please sign in to comment.