Skip to content

Commit

Permalink
Fix up equals in NetworkTables.
Browse files Browse the repository at this point in the history
  • Loading branch information
ThadHouse committed Feb 27, 2024
1 parent 4796d57 commit ab9cc2b
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ namespace CodeHelpers.Test.LogGenerator;
public class LogGeneratorModelTest
{
[Fact]
public void TestEqualModel() {
public void TestEqualModel()
{
var a = new LoggableType(
TypeDeclaration: new(
Kind: TypeKind.Struct,
Modifiers: TypeModifiers.IsReadOnly,
Namespace: new("ABC", new("NS", null)),
Parent: null,
TypeName: "ABC",
TypeParameters: []
TypeParameters: []
),
LoggableMembers: []
);
Expand All @@ -26,7 +27,7 @@ public void TestEqualModel() {
Namespace: new("ABC", new("NS", null)),
Parent: null,
TypeName: "ABC",
TypeParameters: []
TypeParameters: []
),
LoggableMembers: []
);
Expand Down
4 changes: 2 additions & 2 deletions codehelp/CodeHelpers.Test/LogGenerator/LogGeneratorTestVb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ namespace CodeHelpers.Test.LogGenerator;

using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.VisualBasic.Testing;
using Microsoft.CodeAnalysis.Testing;
using Microsoft.CodeAnalysis.Testing.Verifiers;
using Microsoft.CodeAnalysis.Text;
using WPILib.CodeHelpers.LogGenerator.SourceGenerator;
using Microsoft.CodeAnalysis.VisualBasic.Testing;
using Stereologue;
using WPILib.CodeHelpers.LogGenerator.SourceGenerator;

public class LogGeneratorTestVb
{
Expand Down
8 changes: 5 additions & 3 deletions codehelp/CodeHelpers.Test/TestHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
namespace CodeHelpers.Test;

public static class TestHelpers {
public static class TestHelpers
{
public static string NormalizeLineEndings(this string input)
{
//Normalize to fully \n
input = input.Replace("\r\n", "\n");
if (OperatingSystem.IsWindows()) {
if (OperatingSystem.IsWindows())
{
// If windows, go to /r/n
input = input.Replace("\n", "\r\n");
}
return input;
}
}
}
7 changes: 5 additions & 2 deletions codehelp/CodeHelpers/LogGenerator/LoggableType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ private int AddClassDeclaration(IndentedStringBuilder builder)

if ((TypeDeclaration.Modifiers & TypeModifiers.IsRefLikeType) == 0)
{
if (builder.Language == LanguageKind.CSharp) {
if (builder.Language == LanguageKind.CSharp)
{
iLogged = Strings.LoggerInterfaceFullyQualified;
} else if (builder.Language == LanguageKind.VisualBasic) {
}
else if (builder.Language == LanguageKind.VisualBasic)
{
iLogged = Strings.LoggerInterfaceFullyQualifiedVb;
}
}
Expand Down
24 changes: 16 additions & 8 deletions codehelp/CodeHelpers/TypeDeclarationModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,30 +138,38 @@ public int WriteClassDeclaration(IndentedStringBuilder builder, bool addUnsafe,
var inheritanceSpan = inheritanceToAdd.AsSpan();
if (!inheritanceSpan.IsEmpty)
{
if (builder.Language == LanguageKind.CSharp) {
if (builder.Language == LanguageKind.CSharp)
{
builder.StartLine();
builder.Append(" : ");
bool first = false;
foreach (var item in inheritanceSpan) {
if (!first) {
foreach (var item in inheritanceSpan)
{
if (!first)
{
first = true;
}
else {
else
{
builder.Append(", ");
}
builder.Append(item);
}
builder.EndLine();
}
else if (builder.Language == LanguageKind.VisualBasic) {
else if (builder.Language == LanguageKind.VisualBasic)
{
builder.StartLine();
builder.Append(" Implements ");
bool first = false;
foreach (var item in inheritanceSpan) {
if (!first) {
foreach (var item in inheritanceSpan)
{
if (!first)
{
first = true;
}
else {
else
{
builder.Append(", ");
}
builder.Append(item);
Expand Down
7 changes: 4 additions & 3 deletions src/ntcore/NetworkTableInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// THIS FILE WAS AUTO-GENERATED BY ./ntcore/generate_topics.py. DO NOT MODIFY

using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using System.Runtime.InteropServices;
using System.Text;
Expand Down Expand Up @@ -596,20 +597,20 @@ public NtListener AddLogger(int minLevel, int maxLevel, Action<NetworkTableEvent
return m_listeners.AddLogger(minLevel, maxLevel, callback);
}

public override bool Equals(object? obj)
public override bool Equals([NotNullWhen(true)] object? obj)
{
return Equals(obj as NetworkTableInstance);
}

public bool Equals(NetworkTableInstance? other)
public bool Equals([NotNullWhen(true)] NetworkTableInstance? other)
{
return other is not null &&
Handle == other.Handle;
}

public override int GetHashCode()
{
return Handle.GetHashCode();
return Handle.Handle;
}

public static bool operator ==(NetworkTableInstance? left, NetworkTableInstance? right)
Expand Down
56 changes: 54 additions & 2 deletions src/ntcore/NetworkTableValue.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
using NetworkTables.Natives;
Expand All @@ -7,7 +8,8 @@ namespace NetworkTables;

[NativeMarshalling(typeof(NetworkTableValueMarshaller))]
[StructLayout(LayoutKind.Auto)]
public readonly partial struct NetworkTableValue : INativeArrayFree<NetworkTableValueMarshaller.NativeNetworkTableValue>
public readonly partial struct NetworkTableValue : INativeArrayFree<NetworkTableValueMarshaller.NativeNetworkTableValue>,
IEquatable<NetworkTableValue>
{
public static unsafe void FreeArray(NetworkTableValueMarshaller.NativeNetworkTableValue* array, int len)
{
Expand Down Expand Up @@ -217,7 +219,57 @@ public static NetworkTableValue MakeStringArray(string[] value, long time)
return new NetworkTableValue(NetworkTableType.StringArray, value, time);
}

// TODO Equals and HashCode
public override int GetHashCode()
{
int objectHash = Type switch
{
NetworkTableType.Double => m_structValue.doubleValue.GetHashCode(),
NetworkTableType.Integer => m_structValue.longValue.GetHashCode(),
NetworkTableType.Float => m_structValue.floatValue.GetHashCode(),
NetworkTableType.Boolean => m_structValue.boolValue.GetHashCode(),
_ => m_objectValue?.GetHashCode() ?? 0
};
return HashCode.Combine(Type, objectHash);
}

public override bool Equals([NotNullWhen(true)] object? obj)
{
if (obj is NetworkTableValue value)
{
return Equals(value);
}
return false;
}

public bool Equals(NetworkTableValue other)
{
return Type == other.Type && Type switch
{
NetworkTableType.Unassigned => true,
NetworkTableType.Boolean => m_structValue.boolValue == other.m_structValue.boolValue,
NetworkTableType.Double => m_structValue.doubleValue == other.m_structValue.doubleValue,
NetworkTableType.String => m_objectValue == other.m_objectValue,
NetworkTableType.Raw => m_objectValue is not null && other.m_objectValue is not null && ((byte[])m_objectValue).AsSpan().SequenceEqual(((byte[])other.m_objectValue).AsSpan()),
NetworkTableType.BooleanArray => m_objectValue is not null && other.m_objectValue is not null && ((bool[])m_objectValue).AsSpan().SequenceEqual(((bool[])other.m_objectValue).AsSpan()),
NetworkTableType.DoubleArray => m_objectValue is not null && other.m_objectValue is not null && ((double[])m_objectValue).AsSpan().SequenceEqual(((double[])other.m_objectValue).AsSpan()),
NetworkTableType.StringArray => m_objectValue is not null && other.m_objectValue is not null && ((string[])m_objectValue).AsSpan().SequenceEqual(((string[])other.m_objectValue).AsSpan()),
NetworkTableType.Integer => m_structValue.longValue == other.m_structValue.longValue,
NetworkTableType.Float => m_structValue.floatValue == other.m_structValue.floatValue,
NetworkTableType.IntegerArray => m_objectValue is not null && other.m_objectValue is not null && ((long[])m_objectValue).AsSpan().SequenceEqual(((long[])other.m_objectValue).AsSpan()),
NetworkTableType.FloatArray => m_objectValue is not null && other.m_objectValue is not null && ((float[])m_objectValue).AsSpan().SequenceEqual(((float[])other.m_objectValue).AsSpan()),
_ => false,
};
}

public static bool operator ==(NetworkTableValue? left, NetworkTableValue? right)
{
return left.Equals(right);
}

public static bool operator !=(NetworkTableValue? left, NetworkTableValue? right)
{
return !(left == right);
}

/**
* Get the data type.
Expand Down
29 changes: 8 additions & 21 deletions src/ntcore/ProtobufTopic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,32 @@ namespace NetworkTables;

public sealed class ProtobufTopic<T> : Topic, IEquatable<ProtobufTopic<T>?>, IEqualityOperators<ProtobufTopic<T>?, ProtobufTopic<T>?, bool> where T : IProtobufSerializable<T>
{
public IGenericProtobuf<T> Proto { get; } = T.Proto;

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

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

public static ProtobufTopic<T> Wrap(Topic topic)
public ProtobufTopic(Topic topic) : base(topic.Instance, topic.Handle)
{
return new ProtobufTopic<T>(topic);
}

public static ProtobufTopic<T> Wrap(NetworkTableInstance instance, NtTopic handle)
public ProtobufTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, handle)
{
return new ProtobufTopic<T>(instance, handle);
}

public IProtobufSubscriber<T> Subscribe(T defaultValue, PubSubOptions options)
{
return new ProtobufEntryImpl<T, NtSubscriber>(this, NtCore.Subscribe(Handle, NetworkTableType.Raw, Proto.TypeString, options), defaultValue, false);
return new ProtobufEntryImpl<T, NtSubscriber>(this, NtCore.Subscribe(Handle, NetworkTableType.Raw, T.Proto.TypeString, options), defaultValue, false);
}

public IProtobufPublisher<T> Publish(PubSubOptions options)
{
return new ProtobufEntryImpl<T, NtPublisher>(this, NtCore.Publish(Handle, NetworkTableType.Raw, Proto.TypeString, options), default!, false);
return new ProtobufEntryImpl<T, NtPublisher>(this, NtCore.Publish(Handle, NetworkTableType.Raw, T.Proto.TypeString, options), default!, false);
}

public IProtobufPublisher<T> PublishEx(string properties, PubSubOptions options)
{
return new ProtobufEntryImpl<T, NtPublisher>(this, NtCore.PublishEx(Handle, NetworkTableType.Raw, Proto.TypeString, properties, options), default!, false);
return new ProtobufEntryImpl<T, NtPublisher>(this, NtCore.PublishEx(Handle, NetworkTableType.Raw, T.Proto.TypeString, properties, options), default!, false);
}

public IProtobufEntry<T> GetEntry(T defaultValue, PubSubOptions options)
{
return new ProtobufEntryImpl<T, NtEntry>(this, NtCore.GetEntry(Handle, NetworkTableType.Raw, Proto.TypeString, options), defaultValue, false);
return new ProtobufEntryImpl<T, NtEntry>(this, NtCore.GetEntry(Handle, NetworkTableType.Raw, T.Proto.TypeString, options), defaultValue, false);
}

public override bool Equals(object? obj)
Expand All @@ -54,13 +42,12 @@ public override bool Equals(object? obj)

public bool Equals(ProtobufTopic<T>? other)
{
return other is not null &&
EqualityComparer<IGenericProtobuf<T>>.Default.Equals(Proto, other.Proto);
return other?.Equals((Topic)this) ?? false;
}

public override int GetHashCode()
{
return HashCode.Combine(base.GetHashCode(), Proto);
return base.GetHashCode();
}

public static bool operator ==(ProtobufTopic<T>? left, ProtobufTopic<T>? right)
Expand Down
29 changes: 8 additions & 21 deletions src/ntcore/StructArrayTopic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,32 @@ namespace NetworkTables;

public sealed class StructArrayTopic<T> : Topic, IEquatable<StructArrayTopic<T>?>, IEqualityOperators<StructArrayTopic<T>?, StructArrayTopic<T>?, bool> where T : IStructSerializable<T>
{
public IStruct<T> Proto { get; } = T.Struct;

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

internal StructArrayTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, handle)
{
}

public static StructArrayTopic<T> Wrap(Topic topic)
public StructArrayTopic(Topic topic) : base(topic.Instance, topic.Handle)
{
return new StructArrayTopic<T>(topic);
}

public static StructArrayTopic<T> Wrap(NetworkTableInstance instance, NtTopic handle)
public StructArrayTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, handle)
{
return new StructArrayTopic<T>(instance, handle);
}

public IStructArraySubscriber<T> Subscribe(T[] defaultValue, PubSubOptions options)
{
return new StructArrayEntryImpl<T, NtSubscriber>(this, NtCore.Subscribe(Handle, NetworkTableType.Raw, Proto.TypeString, options), defaultValue, false);
return new StructArrayEntryImpl<T, NtSubscriber>(this, NtCore.Subscribe(Handle, NetworkTableType.Raw, T.Struct.TypeString, options), defaultValue, false);
}

public IStructArrayPublisher<T> Publish(PubSubOptions options)
{
return new StructArrayEntryImpl<T, NtPublisher>(this, NtCore.Publish(Handle, NetworkTableType.Raw, Proto.TypeString, options), default!, false);
return new StructArrayEntryImpl<T, NtPublisher>(this, NtCore.Publish(Handle, NetworkTableType.Raw, T.Struct.TypeString, options), default!, false);
}

public IStructArrayPublisher<T> PublishEx(string properties, PubSubOptions options)
{
return new StructArrayEntryImpl<T, NtPublisher>(this, NtCore.PublishEx(Handle, NetworkTableType.Raw, Proto.TypeString, properties, options), default!, false);
return new StructArrayEntryImpl<T, NtPublisher>(this, NtCore.PublishEx(Handle, NetworkTableType.Raw, T.Struct.TypeString, properties, options), default!, false);
}

public IStructArrayEntry<T> GetEntry(T[] defaultValue, PubSubOptions options)
{
return new StructArrayEntryImpl<T, NtEntry>(this, NtCore.GetEntry(Handle, NetworkTableType.Raw, Proto.TypeString, options), defaultValue, false);
return new StructArrayEntryImpl<T, NtEntry>(this, NtCore.GetEntry(Handle, NetworkTableType.Raw, T.Struct.TypeString, options), defaultValue, false);
}

public override bool Equals(object? obj)
Expand All @@ -54,13 +42,12 @@ public override bool Equals(object? obj)

public bool Equals(StructArrayTopic<T>? other)
{
return other is not null &&
EqualityComparer<IStruct<T>>.Default.Equals(Proto, other.Proto);
return other?.Equals((Topic)this) ?? false;
}

public override int GetHashCode()
{
return HashCode.Combine(base.GetHashCode(), Proto);
return base.GetHashCode();
}

public static bool operator ==(StructArrayTopic<T>? left, StructArrayTopic<T>? right)
Expand Down
Loading

0 comments on commit ab9cc2b

Please sign in to comment.