From ab9cc2b1bac3c65e3feea2ce2ddd3c949b762f72 Mon Sep 17 00:00:00 2001 From: Thad House Date: Mon, 26 Feb 2024 21:53:33 -0800 Subject: [PATCH] Fix up equals in NetworkTables. --- .../LogGenerator/LogGeneratorModelTest.cs | 7 ++- .../LogGenerator/LogGeneratorTestVb.cs | 4 +- codehelp/CodeHelpers.Test/TestHelpers.cs | 8 ++- .../CodeHelpers/LogGenerator/LoggableType.cs | 7 ++- codehelp/CodeHelpers/TypeDeclarationModel.cs | 24 +++++--- src/ntcore/NetworkTableInstance.cs | 7 ++- src/ntcore/NetworkTableValue.cs | 56 ++++++++++++++++++- src/ntcore/ProtobufTopic.cs | 29 +++------- src/ntcore/StructArrayTopic.cs | 29 +++------- src/ntcore/StructTopic.cs | 29 +++------- src/ntcore/Topic.cs | 2 +- 11 files changed, 115 insertions(+), 87 deletions(-) diff --git a/codehelp/CodeHelpers.Test/LogGenerator/LogGeneratorModelTest.cs b/codehelp/CodeHelpers.Test/LogGenerator/LogGeneratorModelTest.cs index 99e1d176..57f62f72 100644 --- a/codehelp/CodeHelpers.Test/LogGenerator/LogGeneratorModelTest.cs +++ b/codehelp/CodeHelpers.Test/LogGenerator/LogGeneratorModelTest.cs @@ -7,7 +7,8 @@ namespace CodeHelpers.Test.LogGenerator; public class LogGeneratorModelTest { [Fact] - public void TestEqualModel() { + public void TestEqualModel() + { var a = new LoggableType( TypeDeclaration: new( Kind: TypeKind.Struct, @@ -15,7 +16,7 @@ public void TestEqualModel() { Namespace: new("ABC", new("NS", null)), Parent: null, TypeName: "ABC", - TypeParameters: [] + TypeParameters: [] ), LoggableMembers: [] ); @@ -26,7 +27,7 @@ public void TestEqualModel() { Namespace: new("ABC", new("NS", null)), Parent: null, TypeName: "ABC", - TypeParameters: [] + TypeParameters: [] ), LoggableMembers: [] ); diff --git a/codehelp/CodeHelpers.Test/LogGenerator/LogGeneratorTestVb.cs b/codehelp/CodeHelpers.Test/LogGenerator/LogGeneratorTestVb.cs index c56a84f1..c8a13244 100644 --- a/codehelp/CodeHelpers.Test/LogGenerator/LogGeneratorTestVb.cs +++ b/codehelp/CodeHelpers.Test/LogGenerator/LogGeneratorTestVb.cs @@ -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 { diff --git a/codehelp/CodeHelpers.Test/TestHelpers.cs b/codehelp/CodeHelpers.Test/TestHelpers.cs index 9cec37a7..30c57ccd 100644 --- a/codehelp/CodeHelpers.Test/TestHelpers.cs +++ b/codehelp/CodeHelpers.Test/TestHelpers.cs @@ -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; } -} \ No newline at end of file +} diff --git a/codehelp/CodeHelpers/LogGenerator/LoggableType.cs b/codehelp/CodeHelpers/LogGenerator/LoggableType.cs index d9b9a53b..3736c61a 100644 --- a/codehelp/CodeHelpers/LogGenerator/LoggableType.cs +++ b/codehelp/CodeHelpers/LogGenerator/LoggableType.cs @@ -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; } } diff --git a/codehelp/CodeHelpers/TypeDeclarationModel.cs b/codehelp/CodeHelpers/TypeDeclarationModel.cs index f1238b52..9cff712c 100644 --- a/codehelp/CodeHelpers/TypeDeclarationModel.cs +++ b/codehelp/CodeHelpers/TypeDeclarationModel.cs @@ -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); diff --git a/src/ntcore/NetworkTableInstance.cs b/src/ntcore/NetworkTableInstance.cs index d0725455..55bde863 100644 --- a/src/ntcore/NetworkTableInstance.cs +++ b/src/ntcore/NetworkTableInstance.cs @@ -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; @@ -596,12 +597,12 @@ public NtListener AddLogger(int minLevel, int maxLevel, Action +public readonly partial struct NetworkTableValue : INativeArrayFree, + IEquatable { public static unsafe void FreeArray(NetworkTableValueMarshaller.NativeNetworkTableValue* array, int len) { @@ -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. diff --git a/src/ntcore/ProtobufTopic.cs b/src/ntcore/ProtobufTopic.cs index 148b4ce5..d898cb7e 100644 --- a/src/ntcore/ProtobufTopic.cs +++ b/src/ntcore/ProtobufTopic.cs @@ -7,44 +7,32 @@ namespace NetworkTables; public sealed class ProtobufTopic : Topic, IEquatable?>, IEqualityOperators?, ProtobufTopic?, bool> where T : IProtobufSerializable { - public IGenericProtobuf 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 Wrap(Topic topic) + public ProtobufTopic(Topic topic) : base(topic.Instance, topic.Handle) { - return new ProtobufTopic(topic); } - public static ProtobufTopic Wrap(NetworkTableInstance instance, NtTopic handle) + public ProtobufTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, handle) { - return new ProtobufTopic(instance, handle); } public IProtobufSubscriber Subscribe(T defaultValue, PubSubOptions options) { - return new ProtobufEntryImpl(this, NtCore.Subscribe(Handle, NetworkTableType.Raw, Proto.TypeString, options), defaultValue, false); + return new ProtobufEntryImpl(this, NtCore.Subscribe(Handle, NetworkTableType.Raw, T.Proto.TypeString, options), defaultValue, false); } public IProtobufPublisher Publish(PubSubOptions options) { - return new ProtobufEntryImpl(this, NtCore.Publish(Handle, NetworkTableType.Raw, Proto.TypeString, options), default!, false); + return new ProtobufEntryImpl(this, NtCore.Publish(Handle, NetworkTableType.Raw, T.Proto.TypeString, options), default!, false); } public IProtobufPublisher PublishEx(string properties, PubSubOptions options) { - return new ProtobufEntryImpl(this, NtCore.PublishEx(Handle, NetworkTableType.Raw, Proto.TypeString, properties, options), default!, false); + return new ProtobufEntryImpl(this, NtCore.PublishEx(Handle, NetworkTableType.Raw, T.Proto.TypeString, properties, options), default!, false); } public IProtobufEntry GetEntry(T defaultValue, PubSubOptions options) { - return new ProtobufEntryImpl(this, NtCore.GetEntry(Handle, NetworkTableType.Raw, Proto.TypeString, options), defaultValue, false); + return new ProtobufEntryImpl(this, NtCore.GetEntry(Handle, NetworkTableType.Raw, T.Proto.TypeString, options), defaultValue, false); } public override bool Equals(object? obj) @@ -54,13 +42,12 @@ public override bool Equals(object? obj) public bool Equals(ProtobufTopic? other) { - return other is not null && - EqualityComparer>.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? left, ProtobufTopic? right) diff --git a/src/ntcore/StructArrayTopic.cs b/src/ntcore/StructArrayTopic.cs index e3f0ed51..6aa16339 100644 --- a/src/ntcore/StructArrayTopic.cs +++ b/src/ntcore/StructArrayTopic.cs @@ -7,44 +7,32 @@ namespace NetworkTables; public sealed class StructArrayTopic : Topic, IEquatable?>, IEqualityOperators?, StructArrayTopic?, bool> where T : IStructSerializable { - public IStruct 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 Wrap(Topic topic) + public StructArrayTopic(Topic topic) : base(topic.Instance, topic.Handle) { - return new StructArrayTopic(topic); } - public static StructArrayTopic Wrap(NetworkTableInstance instance, NtTopic handle) + public StructArrayTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, handle) { - return new StructArrayTopic(instance, handle); } public IStructArraySubscriber Subscribe(T[] defaultValue, PubSubOptions options) { - return new StructArrayEntryImpl(this, NtCore.Subscribe(Handle, NetworkTableType.Raw, Proto.TypeString, options), defaultValue, false); + return new StructArrayEntryImpl(this, NtCore.Subscribe(Handle, NetworkTableType.Raw, T.Struct.TypeString, options), defaultValue, false); } public IStructArrayPublisher Publish(PubSubOptions options) { - return new StructArrayEntryImpl(this, NtCore.Publish(Handle, NetworkTableType.Raw, Proto.TypeString, options), default!, false); + return new StructArrayEntryImpl(this, NtCore.Publish(Handle, NetworkTableType.Raw, T.Struct.TypeString, options), default!, false); } public IStructArrayPublisher PublishEx(string properties, PubSubOptions options) { - return new StructArrayEntryImpl(this, NtCore.PublishEx(Handle, NetworkTableType.Raw, Proto.TypeString, properties, options), default!, false); + return new StructArrayEntryImpl(this, NtCore.PublishEx(Handle, NetworkTableType.Raw, T.Struct.TypeString, properties, options), default!, false); } public IStructArrayEntry GetEntry(T[] defaultValue, PubSubOptions options) { - return new StructArrayEntryImpl(this, NtCore.GetEntry(Handle, NetworkTableType.Raw, Proto.TypeString, options), defaultValue, false); + return new StructArrayEntryImpl(this, NtCore.GetEntry(Handle, NetworkTableType.Raw, T.Struct.TypeString, options), defaultValue, false); } public override bool Equals(object? obj) @@ -54,13 +42,12 @@ public override bool Equals(object? obj) public bool Equals(StructArrayTopic? other) { - return other is not null && - EqualityComparer>.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? left, StructArrayTopic? right) diff --git a/src/ntcore/StructTopic.cs b/src/ntcore/StructTopic.cs index be075bce..f6f227f2 100644 --- a/src/ntcore/StructTopic.cs +++ b/src/ntcore/StructTopic.cs @@ -7,44 +7,32 @@ namespace NetworkTables; public sealed class StructTopic : Topic, IEquatable?>, IEqualityOperators?, StructTopic?, bool> where T : IStructSerializable { - public IStruct Proto { get; } = T.Struct; - - private StructTopic(Topic topic) : base(topic.Instance, topic.Handle) - { - } - - internal StructTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, handle) - { - } - - public static StructTopic Wrap(Topic topic) + public StructTopic(Topic topic) : base(topic.Instance, topic.Handle) { - return new StructTopic(topic); } - public static StructTopic Wrap(NetworkTableInstance instance, NtTopic handle) + public StructTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, handle) { - return new StructTopic(instance, handle); } public IStructSubscriber Subscribe(T defaultValue, PubSubOptions options) { - return new StructEntryImpl(this, NtCore.Subscribe(Handle, NetworkTableType.Raw, Proto.TypeString, options), defaultValue, false); + return new StructEntryImpl(this, NtCore.Subscribe(Handle, NetworkTableType.Raw, T.Struct.TypeString, options), defaultValue, false); } public IStructPublisher Publish(PubSubOptions options) { - return new StructEntryImpl(this, NtCore.Publish(Handle, NetworkTableType.Raw, Proto.TypeString, options), default!, false); + return new StructEntryImpl(this, NtCore.Publish(Handle, NetworkTableType.Raw, T.Struct.TypeString, options), default!, false); } public IStructPublisher PublishEx(string properties, PubSubOptions options) { - return new StructEntryImpl(this, NtCore.PublishEx(Handle, NetworkTableType.Raw, Proto.TypeString, properties, options), default!, false); + return new StructEntryImpl(this, NtCore.PublishEx(Handle, NetworkTableType.Raw, T.Struct.TypeString, properties, options), default!, false); } public IStructEntry GetEntry(T defaultValue, PubSubOptions options) { - return new StructEntryImpl(this, NtCore.GetEntry(Handle, NetworkTableType.Raw, Proto.TypeString, options), defaultValue, false); + return new StructEntryImpl(this, NtCore.GetEntry(Handle, NetworkTableType.Raw, T.Struct.TypeString, options), defaultValue, false); } public override bool Equals(object? obj) @@ -54,13 +42,12 @@ public override bool Equals(object? obj) public bool Equals(StructTopic? other) { - return other is not null && - EqualityComparer>.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 ==(StructTopic? left, StructTopic? right) diff --git a/src/ntcore/Topic.cs b/src/ntcore/Topic.cs index ac425963..ead4009f 100644 --- a/src/ntcore/Topic.cs +++ b/src/ntcore/Topic.cs @@ -121,7 +121,7 @@ public bool Equals(Topic? other) public override int GetHashCode() { - return HashCode.Combine(Handle); + return Handle.Handle; } public static bool operator ==(Topic? left, Topic? right)