From e5623ab50b2a962d79d703baa6cd216933d479a2 Mon Sep 17 00:00:00 2001 From: Thad House Date: Sun, 4 Aug 2024 23:14:37 -0700 Subject: [PATCH] Finish up the runtime --- WPILib.sln | 7 + src/epilogue/CustomLoggingForAttribute.cs | 5 +- src/epilogue/EpilogueConfiguration.cs | 11 +- src/epilogue/LogImportance.cs | 5 +- src/epilogue/LogStrategy.cs | 5 +- src/epilogue/LoggedAttribute.cs | 2 +- src/epilogue/Logging/ClassSpecificLogger.cs | 50 ++-- src/epilogue/Logging/DataLogger.cs | 9 - src/epilogue/Logging/Errors/CrashOnError.cs | 12 + src/epilogue/Logging/Errors/ErrorPrinter.cs | 10 + src/epilogue/Logging/Errors/IErrorHandler.cs | 5 +- src/epilogue/Logging/Errors/LoggerDisabler.cs | 29 ++- src/epilogue/Logging/FileLogger.cs | 128 ++++++++++ src/epilogue/Logging/IDataLogger.cs | 61 +++++ src/epilogue/Logging/LazyLogger.cs | 231 ++++++++++++++++++ .../Logging/LogBackedSendableBuilder.cs | 173 +++++++++++++ src/epilogue/Logging/MultiLogger.cs | 169 +++++++++++++ src/epilogue/Logging/NTDataLogger.cs | 129 ++++++++++ src/epilogue/Logging/NullLogger.cs | 104 ++++++++ src/epilogue/Logging/SubLogger.cs | 125 ++++++++++ src/epilogue/NotLoggedAttribute.cs | 5 +- src/ntcore/Generated/BooleanArrayTopic.cs | 22 +- src/ntcore/Generated/DoubleArrayTopic.cs | 22 +- src/ntcore/Generated/DoubleTopic.cs | 22 +- src/ntcore/Generated/FloatArrayTopic.cs | 22 +- src/ntcore/Generated/FloatTopic.cs | 22 +- src/ntcore/Generated/IntegerArrayTopic.cs | 22 +- src/ntcore/Generated/RawTopic.cs | 20 +- src/ntcore/Natives/NtCore.cs | 12 +- src/ntcore/ProtobufTopic.cs | 8 +- src/ntcore/Strings/StringArrayTopic.cs | 22 +- src/ntcore/StructArrayTopic.cs | 8 +- src/ntcore/StructTopic.cs | 8 +- src/ntcore/Topic.cs | 12 +- src/wpiutil/Sendable/ISendableBuilder.cs | 2 +- test/epilogue.test/ClassSpecificLoggerTest.cs | 3 + test/epilogue.test/LazyLoggerTest.cs | 45 ++++ test/epilogue.test/TestLogger.cs | 120 +++++++++ test/epilogue.test/epilogue.test.csproj | 13 + 39 files changed, 1525 insertions(+), 155 deletions(-) delete mode 100644 src/epilogue/Logging/DataLogger.cs create mode 100644 src/epilogue/Logging/Errors/CrashOnError.cs create mode 100644 src/epilogue/Logging/Errors/ErrorPrinter.cs create mode 100644 src/epilogue/Logging/FileLogger.cs create mode 100644 src/epilogue/Logging/IDataLogger.cs create mode 100644 src/epilogue/Logging/LazyLogger.cs create mode 100644 src/epilogue/Logging/LogBackedSendableBuilder.cs create mode 100644 src/epilogue/Logging/MultiLogger.cs create mode 100644 src/epilogue/Logging/NTDataLogger.cs create mode 100644 src/epilogue/Logging/NullLogger.cs create mode 100644 src/epilogue/Logging/SubLogger.cs create mode 100644 test/epilogue.test/ClassSpecificLoggerTest.cs create mode 100644 test/epilogue.test/LazyLoggerTest.cs create mode 100644 test/epilogue.test/TestLogger.cs create mode 100644 test/epilogue.test/epilogue.test.csproj diff --git a/WPILib.sln b/WPILib.sln index 85fef836..a4ee540c 100644 --- a/WPILib.sln +++ b/WPILib.sln @@ -49,6 +49,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "newcommands", "src\newcomma EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "epilogue", "src\epilogue\epilogue.csproj", "{B8A9AFC6-01F1-44AC-95D4-0683EF31E117}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "epilogue.test", "test\epilogue.test\epilogue.test.csproj", "{A658C098-9968-4F4A-9230-C91B40FF7541}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -134,6 +136,10 @@ Global {B8A9AFC6-01F1-44AC-95D4-0683EF31E117}.Debug|Any CPU.Build.0 = Debug|Any CPU {B8A9AFC6-01F1-44AC-95D4-0683EF31E117}.Release|Any CPU.ActiveCfg = Release|Any CPU {B8A9AFC6-01F1-44AC-95D4-0683EF31E117}.Release|Any CPU.Build.0 = Release|Any CPU + {A658C098-9968-4F4A-9230-C91B40FF7541}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A658C098-9968-4F4A-9230-C91B40FF7541}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A658C098-9968-4F4A-9230-C91B40FF7541}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A658C098-9968-4F4A-9230-C91B40FF7541}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {8F38C25E-641E-47FC-AC0A-0717F2159E8F} = {DB664556-4BF0-4874-8CB6-DC24E60A67AF} @@ -154,5 +160,6 @@ Global {A364B855-95A2-435D-A627-A25F1215AB4E} = {1CA9AB3B-4828-4F07-8C0E-88EF7C5A9ACD} {B09918CC-E71F-4E49-AA20-81559D3583B2} = {DB664556-4BF0-4874-8CB6-DC24E60A67AF} {B8A9AFC6-01F1-44AC-95D4-0683EF31E117} = {DB664556-4BF0-4874-8CB6-DC24E60A67AF} + {A658C098-9968-4F4A-9230-C91B40FF7541} = {AD95ECD8-E708-4FB4-9B7E-A8A8EF3FCB3E} EndGlobalSection EndGlobal diff --git a/src/epilogue/CustomLoggingForAttribute.cs b/src/epilogue/CustomLoggingForAttribute.cs index 3db14033..442db973 100644 --- a/src/epilogue/CustomLoggingForAttribute.cs +++ b/src/epilogue/CustomLoggingForAttribute.cs @@ -1,6 +1,7 @@ namespace Epilogue; [AttributeUsage(AttributeTargets.Class)] -public sealed class CustomLoggerForAttribute : Attribute { +public sealed class CustomLoggerForAttribute : Attribute +{ Type[] Types { get; init; } = []; -} \ No newline at end of file +} diff --git a/src/epilogue/EpilogueConfiguration.cs b/src/epilogue/EpilogueConfiguration.cs index dad8fef9..301fcf37 100644 --- a/src/epilogue/EpilogueConfiguration.cs +++ b/src/epilogue/EpilogueConfiguration.cs @@ -1,10 +1,13 @@ +using Epilogue.Logging; +using Epilogue.Logging.Errors; using NetworkTables; namespace Epilogue; -public class EpilogueConfiguration { - public DataLogger DataLogger { get; set; } = new NTDataLogger(NetworkTableInstance.Default); +public class EpilogueConfiguration +{ + public IDataLogger DataLogger { get; set; } = new NTDataLogger(NetworkTableInstance.Default); public LogImportance MinimumImportance { get; set; } = LogImportance.Debug; - public ErrorHandler ErrorHandler { get; set; } = new(); + public IErrorHandler ErrorHandler { get; set; } = new ErrorPrinter(); public string Root { get; set; } = "Robot"; -} \ No newline at end of file +} diff --git a/src/epilogue/LogImportance.cs b/src/epilogue/LogImportance.cs index 316e3261..f3bd7fe6 100644 --- a/src/epilogue/LogImportance.cs +++ b/src/epilogue/LogImportance.cs @@ -1,7 +1,8 @@ namespace Epilogue; -public enum LogImportance { +public enum LogImportance +{ Debug, Info, Critical, -} \ No newline at end of file +} diff --git a/src/epilogue/LogStrategy.cs b/src/epilogue/LogStrategy.cs index 381b45ea..bcef29ed 100644 --- a/src/epilogue/LogStrategy.cs +++ b/src/epilogue/LogStrategy.cs @@ -1,6 +1,7 @@ namespace Epilogue; -public enum LogStrategy { +public enum LogStrategy +{ OptIn, OptOut, -} \ No newline at end of file +} diff --git a/src/epilogue/LoggedAttribute.cs b/src/epilogue/LoggedAttribute.cs index e0e7d3da..2c1a6b1b 100644 --- a/src/epilogue/LoggedAttribute.cs +++ b/src/epilogue/LoggedAttribute.cs @@ -6,4 +6,4 @@ public sealed class LoggedAttribute : Attribute public string Name { get; init; } = ""; public LogStrategy Strategy { get; init; } = LogStrategy.OptOut; public LogImportance Importance { get; init; } = LogImportance.Debug; -} \ No newline at end of file +} diff --git a/src/epilogue/Logging/ClassSpecificLogger.cs b/src/epilogue/Logging/ClassSpecificLogger.cs index ba0f8898..ba44f29e 100644 --- a/src/epilogue/Logging/ClassSpecificLogger.cs +++ b/src/epilogue/Logging/ClassSpecificLogger.cs @@ -1,51 +1,71 @@ +using System.Runtime.InteropServices; +using Epilogue.Logging.Errors; using WPIUtil.Sendable; namespace Epilogue.Logging; -public abstract class ClassSpecificLogger { +public abstract class ClassSpecificLogger +{ private readonly Dictionary m_sendables = []; - protected ClassSpecificLogger(Type loggedType) { + protected ClassSpecificLogger(Type loggedType) + { LoggedType = loggedType; } public bool Disabled { get; private set; } - public void Disable() { + public void Disable() + { Disabled = true; } - public void Reenable() { + public void Reenable() + { Disabled = false; } public Type LoggedType { get; } - protected virtual void LogSendable(DataLogger dataLogger, ISendable? sendable) { - if (sendable == null) { + protected virtual void LogSendable(IDataLogger dataLogger, ISendable? sendable) + { + if (sendable is null) + { return; } - var builder = m_sendables. - } + ref ISendableBuilder? builder = ref CollectionsMarshal.GetValueRefOrAddDefault(m_sendables, sendable, out var _); + if (builder is null) + { + builder = new LogBackedSenabledBuilder(dataLogger); + sendable.InitSendable(builder); + } + builder.Update(); + } } -public abstract class ClassSpecificLogger : ClassSpecificLogger { +public abstract class ClassSpecificLogger : ClassSpecificLogger +{ protected ClassSpecificLogger() : base(typeof(T)) { } - protected abstract void Update(DataLogger dataLogger, T obj); + protected abstract void Update(IDataLogger dataLogger, T obj); - public void TryUpdate(DataLogger dataLogger, T obj, ErrorHandler errorHandler) { - if (Disabled) { + public void TryUpdate(IDataLogger dataLogger, T obj, IErrorHandler errorHandler) + { + if (Disabled) + { return; } - try { + try + { Update(dataLogger, obj); - } catch (Exception e) { - errorHandler(e, this); + } + catch (Exception e) + { + errorHandler.Handle(e, this); } } } diff --git a/src/epilogue/Logging/DataLogger.cs b/src/epilogue/Logging/DataLogger.cs deleted file mode 100644 index c397bec1..00000000 --- a/src/epilogue/Logging/DataLogger.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Epilogue.Logging; - -public interface DataLogger { - public static DataLogger Multi(params DataLogger[] loggers) { - return new MultiLogger(loggers); - } - - public DataLogger Lazy => new LazyLogger(this); -} \ No newline at end of file diff --git a/src/epilogue/Logging/Errors/CrashOnError.cs b/src/epilogue/Logging/Errors/CrashOnError.cs new file mode 100644 index 00000000..5bfc0330 --- /dev/null +++ b/src/epilogue/Logging/Errors/CrashOnError.cs @@ -0,0 +1,12 @@ + +namespace Epilogue.Logging.Errors; + +public class CrashOnError : IErrorHandler +{ + public void Handle(Exception exception, ClassSpecificLogger logger) + { +#pragma warning disable CA2201 // Do not raise reserved exception types + throw new Exception($"[EPILOGUE] An error occured while logging an instance of {logger.LoggedType.Name}", exception); +#pragma warning restore CA2201 // Do not raise reserved exception types + } +} diff --git a/src/epilogue/Logging/Errors/ErrorPrinter.cs b/src/epilogue/Logging/Errors/ErrorPrinter.cs new file mode 100644 index 00000000..7996487b --- /dev/null +++ b/src/epilogue/Logging/Errors/ErrorPrinter.cs @@ -0,0 +1,10 @@ + +namespace Epilogue.Logging.Errors; + +public class ErrorPrinter : IErrorHandler +{ + public void Handle(Exception exception, ClassSpecificLogger logger) + { + Console.Error.WriteLine($"[EPILOGUE] An error occured while logging an instance of {logger.LoggedType.Name}: {exception.Message}"); + } +} diff --git a/src/epilogue/Logging/Errors/IErrorHandler.cs b/src/epilogue/Logging/Errors/IErrorHandler.cs index 82f69c66..dd9984cd 100644 --- a/src/epilogue/Logging/Errors/IErrorHandler.cs +++ b/src/epilogue/Logging/Errors/IErrorHandler.cs @@ -1,11 +1,12 @@ namespace Epilogue.Logging.Errors; -public interface IErrorHandler { +public interface IErrorHandler +{ void Handle(Exception exception, ClassSpecificLogger logger); public static IErrorHandler CrashOnError() => new CrashOnError(); - public static IErrorHandler PrintErrorMessages() => new ErrorPrint(); + public static IErrorHandler PrintErrorMessages() => new ErrorPrinter(); public static LoggerDisabler Disabling(int maximumPermissableErrors) => LoggerDisabler.ForLimit(maximumPermissableErrors); } diff --git a/src/epilogue/Logging/Errors/LoggerDisabler.cs b/src/epilogue/Logging/Errors/LoggerDisabler.cs index 9ab040cc..8585f96b 100644 --- a/src/epilogue/Logging/Errors/LoggerDisabler.cs +++ b/src/epilogue/Logging/Errors/LoggerDisabler.cs @@ -1,18 +1,39 @@ +using System.Runtime.InteropServices; + namespace Epilogue.Logging.Errors; -public class LoggerDisabler : IErrorHandler { +public class LoggerDisabler : IErrorHandler +{ private readonly int m_threshold; private readonly Dictionary m_errorCounts = []; - public LoggerDisabler(int threshold) { + public LoggerDisabler(int threshold) + { m_threshold = threshold; } - public static LoggerDisabler ForLimit(int threshold) => new LoggerDisabler(threshold); + public static LoggerDisabler ForLimit(int threshold) => new(threshold); public void Handle(Exception exception, ClassSpecificLogger logger) { - throw new NotImplementedException(); + int errorCount = ++CollectionsMarshal.GetValueRefOrAddDefault(m_errorCounts, logger, out var _); + + if (errorCount > m_threshold) + { + logger.Disable(); + Console.Error.WriteLine($"[EPILOGUE] Too many errors detected in {logger.GetType().Name} (maximum allowed: {m_threshold}). The most recent error follows:"); + Console.Error.WriteLine(exception.Message); + Console.Error.WriteLine(exception.StackTrace); + } + } + + public void Reset() + { + foreach (var logger in m_errorCounts) + { + logger.Key.Reenable(); + } + m_errorCounts.Clear(); } } diff --git a/src/epilogue/Logging/FileLogger.cs b/src/epilogue/Logging/FileLogger.cs new file mode 100644 index 00000000..690162f7 --- /dev/null +++ b/src/epilogue/Logging/FileLogger.cs @@ -0,0 +1,128 @@ +using System.Runtime.InteropServices; +using WPIUtil.Logging; +using WPIUtil.Serialization.Struct; +using static WPIUtil.WpiGuard; + +namespace Epilogue.Logging; + +public class FileLogger : IDataLogger +{ + private readonly DataLog m_dataLog; + private readonly Dictionary m_entries = []; + private readonly Dictionary m_subLoggers = []; + + public FileLogger(DataLog dataLog) + { + m_dataLog = RequireNotNull(dataLog); + } + + public IDataLogger Lazy => new LazyLogger(this); + public IDataLogger GetSubLogger(string path) => IDataLogger.GetDefaultSubLogger(this, path, m_subLoggers); + + private E GetEntry(string identifier, Func ctor) where E : DataLogEntry + { + ref var entry = ref CollectionsMarshal.GetValueRefOrAddDefault(m_entries, identifier, out var _); + entry ??= ctor(m_dataLog, identifier); + return (E)entry; + } + + public void Log(string identifier, bool value) + { + GetEntry(identifier, static (a, b) => new BooleanLogEntry(a, b)).Append(value); + } + + public void Log(string identifier, int value) + { + GetEntry(identifier, static (a, b) => new IntegerLogEntry(a, b)).Append(value); + } + + public void Log(string identifier, long value) + { + GetEntry(identifier, static (a, b) => new IntegerLogEntry(a, b)).Append(value); + } + + public void Log(string identifier, float value) + { + GetEntry(identifier, static (a, b) => new FloatLogEntry(a, b)).Append(value); + } + + public void Log(string identifier, double value) + { + GetEntry(identifier, static (a, b) => new DoubleLogEntry(a, b)).Append(value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + GetEntry(identifier, static (a, b) => new RawLogEntry(a, b)).Append(value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + GetEntry(identifier, static (a, b) => new BooleanArrayLogEntry(a, b)).Append(value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + long[] widended = new long[value.Length]; + for (int i = 0; i < value.Length; i++) + { + widended[i] = value[i]; + } + GetEntry(identifier, static (a, b) => new IntegerArrayLogEntry(a, b)).Append(widended); + } + + public void Log(string identifier, ReadOnlySpan value) + { + GetEntry(identifier, static (a, b) => new IntegerArrayLogEntry(a, b)).Append(value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + GetEntry(identifier, static (a, b) => new FloatArrayLogEntry(a, b)).Append(value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + GetEntry(identifier, static (a, b) => new DoubleArrayLogEntry(a, b)).Append(value); + } + + public void Log(string identifier, string value) + { + GetEntry(identifier, static (a, b) => new StringLogEntry(a, b)).Append(value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + GetEntry(identifier, static (a, b) => new StringLogEntry(a, b)).Append(value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + GetEntry(identifier, static (a, b) => new StringArrayLogEntry(a, b)).Append(value); + } + + public void Log(string identifier, in T value) where T : IStructSerializable + { + GetEntry(identifier, static (a, b) => new StructLogEntry(a, b)).Append(value); + } + + public void Log(string identifier, T[] value) where T : IStructSerializable + { + GetEntry(identifier, static (a, b) => new StructArrayLogEntry(a, b)).Append(value); + } + + public void Log(string identifier, Span value) where T : IStructSerializable + { + GetEntry(identifier, static (a, b) => new StructArrayLogEntry(a, b)).Append(value); + } + + public void Log(string identifier, ReadOnlySpan value) where T : IStructSerializable + { + GetEntry(identifier, static (a, b) => new StructArrayLogEntry(a, b)).Append(value); + } + + public void Log(string identifier, T value) where T : Enum + { + GetEntry(identifier, static (a, b) => new StringLogEntry(a, b)).Append(value.ToString()); + } +} diff --git a/src/epilogue/Logging/IDataLogger.cs b/src/epilogue/Logging/IDataLogger.cs new file mode 100644 index 00000000..a9e61dfa --- /dev/null +++ b/src/epilogue/Logging/IDataLogger.cs @@ -0,0 +1,61 @@ +using System.Runtime.InteropServices; +using WPIUtil.Serialization.Struct; + +namespace Epilogue.Logging; + +public interface IDataLogger +{ + public static IDataLogger Multi(params IDataLogger[] loggers) + { + return new MultiLogger(loggers); + } + + IDataLogger Lazy { get; } + + IDataLogger GetSubLogger(string path); + + internal static IDataLogger GetDefaultSubLogger(IDataLogger thisInstance, string path, Dictionary subLoggers) + { + ref var subLogger = ref CollectionsMarshal.GetValueRefOrAddDefault(subLoggers, path, out var _); + subLogger ??= new(path, thisInstance); + return subLogger; + } + + void Log(string identifier, bool value); + + void Log(string identifier, int value); + + void Log(string identifier, long value); + + void Log(string identifier, float value); + + void Log(string identifier, double value); + + void Log(string identifier, ReadOnlySpan value); + + void Log(string identifier, ReadOnlySpan value); + + void Log(string identifier, ReadOnlySpan value); + + void Log(string identifier, ReadOnlySpan value); + + void Log(string identifier, ReadOnlySpan value); + + void Log(string identifier, ReadOnlySpan value); + + void Log(string identifier, string value); + + void Log(string identifier, ReadOnlySpan value); + + void Log(string identifier, ReadOnlySpan value); + + void Log(string identifier, in T value) where T : IStructSerializable; + + void Log(string identifier, T[] value) where T : IStructSerializable; + + void Log(string identifier, Span value) where T : IStructSerializable; + + void Log(string identifier, ReadOnlySpan value) where T : IStructSerializable; + + void Log(string identifier, T value) where T : Enum; +} diff --git a/src/epilogue/Logging/LazyLogger.cs b/src/epilogue/Logging/LazyLogger.cs new file mode 100644 index 00000000..1b476e14 --- /dev/null +++ b/src/epilogue/Logging/LazyLogger.cs @@ -0,0 +1,231 @@ +namespace Epilogue.Logging; + +using System; +using System.Runtime.InteropServices; +using WPIUtil.Serialization.Struct; +using static WPIUtil.WpiGuard; + +public class LazyLogger : IDataLogger +{ + private readonly IDataLogger m_logger; + + private readonly Dictionary m_previousValues = []; + private readonly Dictionary m_subLoggers = []; + + public LazyLogger(IDataLogger logger) + { + m_logger = RequireNotNull(logger); + } + + public IDataLogger Lazy => this; + public IDataLogger GetSubLogger(string path) => IDataLogger.GetDefaultSubLogger(this, path, m_subLoggers); + + public void Log(string identifier, bool value) + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is bool oldValue && oldValue == value) + { + return; + } + preivous = value; + m_logger.Log(identifier, value); + } + + public void Log(string identifier, int value) + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is int oldValue && oldValue == value) + { + return; + } + preivous = value; + m_logger.Log(identifier, value); + } + + public void Log(string identifier, long value) + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is long oldValue && oldValue == value) + { + return; + } + preivous = value; + m_logger.Log(identifier, value); + } + + public void Log(string identifier, float value) + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is float oldValue && oldValue == value) + { + return; + } + preivous = value; + m_logger.Log(identifier, value); + } + + public void Log(string identifier, double value) + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is double oldValue && oldValue == value) + { + return; + } + preivous = value; + m_logger.Log(identifier, value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is byte[] oldValue && oldValue.AsSpan().SequenceEqual(value)) + { + return; + } + preivous = value.ToArray(); + m_logger.Log(identifier, value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is bool[] oldValue && oldValue.AsSpan().SequenceEqual(value)) + { + return; + } + preivous = value.ToArray(); + m_logger.Log(identifier, value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is int[] oldValue && oldValue.AsSpan().SequenceEqual(value)) + { + return; + } + preivous = value.ToArray(); + m_logger.Log(identifier, value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is long[] oldValue && oldValue.AsSpan().SequenceEqual(value)) + { + return; + } + preivous = value.ToArray(); + m_logger.Log(identifier, value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is float[] oldValue && oldValue.AsSpan().SequenceEqual(value)) + { + return; + } + preivous = value.ToArray(); + m_logger.Log(identifier, value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is double[] oldValue && oldValue.AsSpan().SequenceEqual(value)) + { + return; + } + preivous = value.ToArray(); + m_logger.Log(identifier, value); + } + + public void Log(string identifier, string value) + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is string oldValue && oldValue == value) + { + return; + } + preivous = value; + m_logger.Log(identifier, value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is char[] oldValue && oldValue.AsSpan().SequenceEqual(value)) + { + return; + } + preivous = value.ToArray(); + m_logger.Log(identifier, value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is string[] oldValue && oldValue.AsSpan().SequenceEqual(value)) + { + return; + } + preivous = value.ToArray(); + m_logger.Log(identifier, value); + } + + public void Log(string identifier, in T value) where T : IStructSerializable + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is T oldValue && EqualityComparer.Default.Equals(oldValue, value)) + { + return; + } + preivous = value; + m_logger.Log(identifier, value); + } + + public void Log(string identifier, T[] value) where T : IStructSerializable + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is T[] oldValue && oldValue.AsSpan().SequenceEqual(value)) + { + return; + } + preivous = value; + m_logger.Log(identifier, value); + } + + public void Log(string identifier, Span value) where T : IStructSerializable + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is T[] oldValue && oldValue.AsSpan().SequenceEqual(value)) + { + return; + } + preivous = value.ToArray(); + m_logger.Log(identifier, value); + } + + public void Log(string identifier, ReadOnlySpan value) where T : IStructSerializable + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is T[] oldValue && oldValue.AsSpan().SequenceEqual(value)) + { + return; + } + preivous = value.ToArray(); + m_logger.Log(identifier, value); + } + + public void Log(string identifier, T value) where T : Enum + { + ref var preivous = ref CollectionsMarshal.GetValueRefOrAddDefault(m_previousValues, identifier, out var _); + if (preivous is T oldValue && EqualityComparer.Default.Equals(oldValue, value)) + { + return; + } + preivous = value; + m_logger.Log(identifier, value); + } +} diff --git a/src/epilogue/Logging/LogBackedSendableBuilder.cs b/src/epilogue/Logging/LogBackedSendableBuilder.cs new file mode 100644 index 00000000..480235f9 --- /dev/null +++ b/src/epilogue/Logging/LogBackedSendableBuilder.cs @@ -0,0 +1,173 @@ +using WPIUtil.Sendable; +using static WPIUtil.WpiGuard; + +namespace Epilogue.Logging; + +public class LogBackedSenabledBuilder : ISendableBuilder +{ + private readonly IDataLogger m_logger; + private readonly List m_updates = []; + + public LogBackedSenabledBuilder(IDataLogger logger) + { + m_logger = RequireNotNull(logger); + } + + public ISendableBuilder.BackingKind BackendKind => throw new NotImplementedException(); + + public bool IsPublished => throw new NotImplementedException(); + + public void AddBooleanArrayProperty(string key, Func getter, Action setter) + { + m_updates.Add(() => m_logger.Log(key, getter())); + } + + public void AddBooleanProperty(string key, Func getter, Action setter) + { + m_updates.Add(() => m_logger.Log(key, getter())); + } + + public void AddDisposable(IDisposable disposable) + { + // ignore + } + + public void AddDoubleArrayProperty(string key, Func getter, Action setter) + { + m_updates.Add(() => m_logger.Log(key, getter())); + } + + public void AddDoubleProperty(string key, Func getter, Action setter) + { + m_updates.Add(() => m_logger.Log(key, getter())); + } + + public void AddFloatArrayProperty(string key, Func getter, Action setter) + { + m_updates.Add(() => m_logger.Log(key, getter())); + } + + public void AddFloatProperty(string key, Func getter, Action setter) + { + m_updates.Add(() => m_logger.Log(key, getter())); + } + + public void AddIntegerArrayProperty(string key, Func getter, Action setter) + { + m_updates.Add(() => m_logger.Log(key, getter())); + } + + public void AddIntegerProperty(string key, Func getter, Action setter) + { + m_updates.Add(() => m_logger.Log(key, getter())); + } + + public void AddRawProperty(string key, string typeString, Func getter, Action setter) + { + m_updates.Add(() => m_logger.Log(key, getter())); + } + + public void AddStringArrayProperty(string key, Func getter, Action setter) + { + m_updates.Add(() => m_logger.Log(key, getter())); + } + + public void AddStringProperty(string key, Func getter, Action? setter) + { + m_updates.Add(() => m_logger.Log(key, getter())); + } + + public void ClearProperties() + { + m_updates.Clear(); + } + + public void Dispose() + { + GC.SuppressFinalize(this); + ClearProperties(); + } + + public void PublishConstBoolean(string key, bool value) + { + m_logger.Log(key, value); + } + + public void PublishConstBooleanArray(string key, ReadOnlySpan value) + { + m_logger.Log(key, value); + } + + public void PublishConstDouble(string key, double value) + { + m_logger.Log(key, value); + } + + public void PublishConstDoubleArray(string key, ReadOnlySpan value) + { + m_logger.Log(key, value); + } + + public void PublishConstFloat(string key, float value) + { + m_logger.Log(key, value); + } + + public void PublishConstFloatArray(string key, ReadOnlySpan value) + { + m_logger.Log(key, value); + } + + public void PublishConstInteger(string key, long value) + { + m_logger.Log(key, value); + } + + public void PublishConstIntegerArray(string key, ReadOnlySpan value) + { + m_logger.Log(key, value); + } + + public void PublishConstRaw(string key, string typeString, ReadOnlySpan value) + { + m_logger.Log(key, value); + } + + public void PublishConstString(string key, string value) + { + m_logger.Log(key, value); + } + + public void PublishConstString(string key, ReadOnlySpan value) + { + m_logger.Log(key, value); + } + + public void PublishConstStringArray(string key, ReadOnlySpan value) + { + m_logger.Log(key, value); + } + + public void SetActuator(bool value) + { + // ignore + } + + public void SetSafeState(Action func) + { + // ignore + } + + public void SetSmartDashboardType(string type) + { + m_logger.Log(".type", type); + } + + public void Update() + { + foreach (var update in m_updates) + { + update(); + } + } +} diff --git a/src/epilogue/Logging/MultiLogger.cs b/src/epilogue/Logging/MultiLogger.cs new file mode 100644 index 00000000..f8623e37 --- /dev/null +++ b/src/epilogue/Logging/MultiLogger.cs @@ -0,0 +1,169 @@ +using WPIUtil.Serialization.Struct; + +namespace Epilogue.Logging; + +public class MultiLogger : IDataLogger +{ + private readonly List m_loggers; + private readonly Dictionary m_subLoggers = []; + + internal MultiLogger(params IDataLogger[] loggers) + { + m_loggers = new List(loggers); + } + + public IDataLogger Lazy => new LazyLogger(this); + public IDataLogger GetSubLogger(string path) => IDataLogger.GetDefaultSubLogger(this, path, m_subLoggers); + + public void Log(string identifier, bool value) + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } + + public void Log(string identifier, int value) + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } + + public void Log(string identifier, long value) + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } + + public void Log(string identifier, float value) + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } + + public void Log(string identifier, double value) + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } + + public void Log(string identifier, ReadOnlySpan value) + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } + + public void Log(string identifier, ReadOnlySpan value) + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } + + public void Log(string identifier, ReadOnlySpan value) + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } + + public void Log(string identifier, ReadOnlySpan value) + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } + + public void Log(string identifier, ReadOnlySpan value) + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } + + public void Log(string identifier, ReadOnlySpan value) + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } + + public void Log(string identifier, string value) + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } + + public void Log(string identifier, ReadOnlySpan value) + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } + + public void Log(string identifier, ReadOnlySpan value) + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } + + public void Log(string identifier, in T value) where T : IStructSerializable + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } + + public void Log(string identifier, T[] value) where T : IStructSerializable + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } + + public void Log(string identifier, Span value) where T : IStructSerializable + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } + + public void Log(string identifier, ReadOnlySpan value) where T : IStructSerializable + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } + + public void Log(string identifier, T value) where T : Enum + { + foreach (var logger in m_loggers) + { + logger.Log(identifier, value); + } + } +} diff --git a/src/epilogue/Logging/NTDataLogger.cs b/src/epilogue/Logging/NTDataLogger.cs new file mode 100644 index 00000000..1db601a6 --- /dev/null +++ b/src/epilogue/Logging/NTDataLogger.cs @@ -0,0 +1,129 @@ +using System.Runtime.InteropServices; +using NetworkTables; +using WPIUtil.Serialization.Struct; +using static WPIUtil.WpiGuard; + +namespace Epilogue.Logging; + +public class NTDataLogger : IDataLogger +{ + private readonly NetworkTableInstance m_nt; + + private readonly Dictionary m_publishers = []; + private readonly Dictionary m_subLoggers = []; + + public NTDataLogger(NetworkTableInstance nt) + { + m_nt = RequireNotNull(nt); + } + + public IDataLogger Lazy => new LazyLogger(this); + public IDataLogger GetSubLogger(string path) => IDataLogger.GetDefaultSubLogger(this, path, m_subLoggers); + + private E GetEntry(string identifier, Func ctor) where E : IPublisher + { + ref var entry = ref CollectionsMarshal.GetValueRefOrAddDefault(m_publishers, identifier, out var _); + entry ??= ctor(m_nt, identifier); + return (E)entry; + } + + public void Log(string identifier, bool value) + { + GetEntry(identifier, (a, b) => a.GetBooleanTopic(b).Publish()).Set(value); + } + + public void Log(string identifier, int value) + { + GetEntry(identifier, (a, b) => a.GetIntegerTopic(b).Publish()).Set(value); + } + + public void Log(string identifier, long value) + { + GetEntry(identifier, (a, b) => a.GetIntegerTopic(b).Publish()).Set(value); + } + + public void Log(string identifier, float value) + { + GetEntry(identifier, (a, b) => a.GetFloatTopic(b).Publish()).Set(value); + } + + public void Log(string identifier, double value) + { + GetEntry(identifier, (a, b) => a.GetDoubleTopic(b).Publish()).Set(value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + GetEntry(identifier, (a, b) => a.GetRawTopic(b).Publish("raw")).Set(value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + GetEntry(identifier, (a, b) => a.GetBooleanArrayTopic(b).Publish()).Set(value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + long[] widended = new long[value.Length]; + for (int i = 0; i < value.Length; i++) + { + widended[i] = value[i]; + } + GetEntry(identifier, (a, b) => a.GetIntegerArrayTopic(b).Publish()).Set(widended); + } + + public void Log(string identifier, ReadOnlySpan value) + { + GetEntry(identifier, (a, b) => a.GetIntegerArrayTopic(b).Publish()).Set(value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + GetEntry(identifier, (a, b) => a.GetFloatArrayTopic(b).Publish()).Set(value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + GetEntry(identifier, (a, b) => a.GetDoubleArrayTopic(b).Publish()).Set(value); + } + + public void Log(string identifier, string value) + { + GetEntry(identifier, (a, b) => a.GetStringTopic(b).Publish()).Set(value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + GetEntry(identifier, (a, b) => a.GetStringTopic(b).Publish()).Set(value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + GetEntry(identifier, (a, b) => a.GetStringArrayTopic(b).Publish()).Set(value); + } + + public void Log(string identifier, in T value) where T : IStructSerializable + { + GetEntry(identifier, (a, b) => a.GetStructTopic(b).Publish()).Set(value); + } + + public void Log(string identifier, T[] value) where T : IStructSerializable + { + GetEntry(identifier, (a, b) => a.GetStructArrayTopic(b).Publish()).Set(value); + } + + public void Log(string identifier, Span value) where T : IStructSerializable + { + GetEntry(identifier, (a, b) => a.GetStructArrayTopic(b).Publish()).Set(value); + } + + public void Log(string identifier, ReadOnlySpan value) where T : IStructSerializable + { + GetEntry(identifier, (a, b) => a.GetStructArrayTopic(b).Publish()).Set(value); + } + + public void Log(string identifier, T value) where T : Enum + { + GetEntry(identifier, (a, b) => a.GetStringTopic(b).Publish()).Set(value.ToString()); + } +} diff --git a/src/epilogue/Logging/NullLogger.cs b/src/epilogue/Logging/NullLogger.cs new file mode 100644 index 00000000..a7b88a58 --- /dev/null +++ b/src/epilogue/Logging/NullLogger.cs @@ -0,0 +1,104 @@ +using WPIUtil.Serialization.Struct; + +namespace Epilogue.Logging; + +public class NullLogger : IDataLogger +{ + public IDataLogger Lazy => this; + public IDataLogger GetSubLogger(string path) => this; + + public void Log(string identifier, bool value) + { + + } + + public void Log(string identifier, int value) + { + + } + + public void Log(string identifier, long value) + { + + } + + public void Log(string identifier, float value) + { + + } + + public void Log(string identifier, double value) + { + + } + + public void Log(string identifier, ReadOnlySpan value) + { + + } + + public void Log(string identifier, ReadOnlySpan value) + { + + } + + public void Log(string identifier, ReadOnlySpan value) + { + + } + + public void Log(string identifier, ReadOnlySpan value) + { + + } + + public void Log(string identifier, ReadOnlySpan value) + { + + } + + public void Log(string identifier, ReadOnlySpan value) + { + + } + + public void Log(string identifier, string value) + { + + } + + public void Log(string identifier, ReadOnlySpan value) + { + + } + + public void Log(string identifier, ReadOnlySpan value) + { + + } + + public void Log(string identifier, in T value) where T : IStructSerializable + { + + } + + public void Log(string identifier, T[] value) where T : IStructSerializable + { + + } + + public void Log(string identifier, Span value) where T : IStructSerializable + { + + } + + public void Log(string identifier, ReadOnlySpan value) where T : IStructSerializable + { + + } + + public void Log(string identifier, T value) where T : Enum + { + + } +} diff --git a/src/epilogue/Logging/SubLogger.cs b/src/epilogue/Logging/SubLogger.cs new file mode 100644 index 00000000..8bdcf54d --- /dev/null +++ b/src/epilogue/Logging/SubLogger.cs @@ -0,0 +1,125 @@ +using System.Runtime.InteropServices; +using CommunityToolkit.Diagnostics; +using WPIUtil.Serialization.Struct; +using static WPIUtil.WpiGuard; + +namespace Epilogue.Logging; + +public class SubLogger : IDataLogger +{ + private readonly string m_prefix; + private readonly IDataLogger m_impl; + private readonly Dictionary m_subLoggers = []; + + public SubLogger(string prefix, IDataLogger impl) + { + Guard.IsNotNull(prefix); + if (prefix.EndsWith("/", StringComparison.InvariantCultureIgnoreCase)) + { + m_prefix = prefix; + } + else + { + m_prefix = prefix + "/"; + } + m_impl = RequireNotNull(impl); + } + + public IDataLogger Lazy => new LazyLogger(this); + public IDataLogger GetSubLogger(string path) => IDataLogger.GetDefaultSubLogger(this, path, m_subLoggers); + + public void Log(string identifier, bool value) + { + m_impl.Log(m_prefix + identifier, value); + } + + public void Log(string identifier, int value) + { + m_impl.Log(m_prefix + identifier, value); + } + + public void Log(string identifier, long value) + { + m_impl.Log(m_prefix + identifier, value); + } + + public void Log(string identifier, float value) + { + m_impl.Log(m_prefix + identifier, value); + } + + public void Log(string identifier, double value) + { + m_impl.Log(m_prefix + identifier, value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + m_impl.Log(m_prefix + identifier, value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + m_impl.Log(m_prefix + identifier, value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + m_impl.Log(m_prefix + identifier, value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + m_impl.Log(m_prefix + identifier, value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + m_impl.Log(m_prefix + identifier, value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + m_impl.Log(m_prefix + identifier, value); + } + + public void Log(string identifier, string value) + { + m_impl.Log(m_prefix + identifier, value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + m_impl.Log(m_prefix + identifier, value); + } + + public void Log(string identifier, ReadOnlySpan value) + { + m_impl.Log(m_prefix + identifier, value); + } + + public void Log(string identifier, in T value) where T : IStructSerializable + { + m_impl.Log(m_prefix + identifier, value); + } + + public void Log(string identifier, T[] value) where T : IStructSerializable + { + m_impl.Log(m_prefix + identifier, value); + } + + public void Log(string identifier, Span value) where T : IStructSerializable + { + m_impl.Log(m_prefix + identifier, value); + } + + public void Log(string identifier, ReadOnlySpan value) where T : IStructSerializable + { + m_impl.Log(m_prefix + identifier, value); + } + + public void Log(string identifier, T value) where T : Enum + { + m_impl.Log(m_prefix + identifier, value); + } +} diff --git a/src/epilogue/NotLoggedAttribute.cs b/src/epilogue/NotLoggedAttribute.cs index bf34f3ee..8c4e9c77 100644 --- a/src/epilogue/NotLoggedAttribute.cs +++ b/src/epilogue/NotLoggedAttribute.cs @@ -1,5 +1,6 @@ namespace Epilogue; [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Method)] -public sealed class NotLoggedAttribute : Attribute { -} \ No newline at end of file +public sealed class NotLoggedAttribute : Attribute +{ +} diff --git a/src/ntcore/Generated/BooleanArrayTopic.cs b/src/ntcore/Generated/BooleanArrayTopic.cs index b0a12b4e..40a24725 100644 --- a/src/ntcore/Generated/BooleanArrayTopic.cs +++ b/src/ntcore/Generated/BooleanArrayTopic.cs @@ -54,7 +54,7 @@ public BooleanArrayTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, /// subscriber public IBooleanArraySubscriber Subscribe( bool[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new BooleanArrayEntryImpl( this, @@ -83,7 +83,7 @@ public IBooleanArraySubscriber Subscribe( public IBooleanArraySubscriber SubscribeEx( string typeString, bool[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new BooleanArrayEntryImpl( this, @@ -112,7 +112,7 @@ public IBooleanArraySubscriber SubscribeEx( public IBooleanArraySubscriber SubscribeEx( ReadOnlySpan typeString, bool[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new BooleanArrayEntryImpl( this, @@ -137,7 +137,7 @@ public IBooleanArraySubscriber SubscribeEx( /// publish options /// publisher public IBooleanArrayPublisher Publish( - PubSubOptions options) + PubSubOptions options = default) { return new BooleanArrayEntryImpl( this, @@ -165,7 +165,7 @@ public IBooleanArrayPublisher Publish( /// publisher public IBooleanArrayPublisher PublishEx( string typeString, string properties, - PubSubOptions options) + PubSubOptions options = default) { return new BooleanArrayEntryImpl( this, @@ -194,7 +194,7 @@ public IBooleanArrayPublisher PublishEx( public IBooleanArrayPublisher PublishEx( ReadOnlySpan typeString, string properties, - PubSubOptions options) + PubSubOptions options = default) { return new BooleanArrayEntryImpl( this, @@ -223,7 +223,7 @@ public IBooleanArrayPublisher PublishEx( public IBooleanArrayPublisher PublishEx( string typeString, ReadOnlySpan properties, - PubSubOptions options) + PubSubOptions options = default) { return new BooleanArrayEntryImpl( this, @@ -252,7 +252,7 @@ public IBooleanArrayPublisher PublishEx( public IBooleanArrayPublisher PublishEx( ReadOnlySpan typeString, ReadOnlySpan properties, - PubSubOptions options) + PubSubOptions options = default) { return new BooleanArrayEntryImpl( this, @@ -284,7 +284,7 @@ public IBooleanArrayPublisher PublishEx( /// entry public IBooleanArrayEntry GetEntry( bool[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new BooleanArrayEntryImpl( this, @@ -318,7 +318,7 @@ public IBooleanArrayEntry GetEntry( public IBooleanArrayEntry GetEntryEx( string typeString, bool[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new BooleanArrayEntryImpl( this, @@ -352,7 +352,7 @@ public IBooleanArrayEntry GetEntryEx( public IBooleanArrayEntry GetEntryEx( ReadOnlySpan typeString, bool[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new BooleanArrayEntryImpl( this, diff --git a/src/ntcore/Generated/DoubleArrayTopic.cs b/src/ntcore/Generated/DoubleArrayTopic.cs index 9d85e450..53e4db14 100644 --- a/src/ntcore/Generated/DoubleArrayTopic.cs +++ b/src/ntcore/Generated/DoubleArrayTopic.cs @@ -54,7 +54,7 @@ public DoubleArrayTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, /// subscriber public IDoubleArraySubscriber Subscribe( double[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleArrayEntryImpl( this, @@ -83,7 +83,7 @@ public IDoubleArraySubscriber Subscribe( public IDoubleArraySubscriber SubscribeEx( string typeString, double[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleArrayEntryImpl( this, @@ -112,7 +112,7 @@ public IDoubleArraySubscriber SubscribeEx( public IDoubleArraySubscriber SubscribeEx( ReadOnlySpan typeString, double[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleArrayEntryImpl( this, @@ -137,7 +137,7 @@ public IDoubleArraySubscriber SubscribeEx( /// publish options /// publisher public IDoubleArrayPublisher Publish( - PubSubOptions options) + PubSubOptions options = default) { return new DoubleArrayEntryImpl( this, @@ -165,7 +165,7 @@ public IDoubleArrayPublisher Publish( /// publisher public IDoubleArrayPublisher PublishEx( string typeString, string properties, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleArrayEntryImpl( this, @@ -194,7 +194,7 @@ public IDoubleArrayPublisher PublishEx( public IDoubleArrayPublisher PublishEx( ReadOnlySpan typeString, string properties, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleArrayEntryImpl( this, @@ -223,7 +223,7 @@ public IDoubleArrayPublisher PublishEx( public IDoubleArrayPublisher PublishEx( string typeString, ReadOnlySpan properties, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleArrayEntryImpl( this, @@ -252,7 +252,7 @@ public IDoubleArrayPublisher PublishEx( public IDoubleArrayPublisher PublishEx( ReadOnlySpan typeString, ReadOnlySpan properties, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleArrayEntryImpl( this, @@ -284,7 +284,7 @@ public IDoubleArrayPublisher PublishEx( /// entry public IDoubleArrayEntry GetEntry( double[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleArrayEntryImpl( this, @@ -318,7 +318,7 @@ public IDoubleArrayEntry GetEntry( public IDoubleArrayEntry GetEntryEx( string typeString, double[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleArrayEntryImpl( this, @@ -352,7 +352,7 @@ public IDoubleArrayEntry GetEntryEx( public IDoubleArrayEntry GetEntryEx( ReadOnlySpan typeString, double[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleArrayEntryImpl( this, diff --git a/src/ntcore/Generated/DoubleTopic.cs b/src/ntcore/Generated/DoubleTopic.cs index 4821e848..0184c30b 100644 --- a/src/ntcore/Generated/DoubleTopic.cs +++ b/src/ntcore/Generated/DoubleTopic.cs @@ -54,7 +54,7 @@ public DoubleTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, handl /// subscriber public IDoubleSubscriber Subscribe( double defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleEntryImpl( this, @@ -83,7 +83,7 @@ public IDoubleSubscriber Subscribe( public IDoubleSubscriber SubscribeEx( string typeString, double defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleEntryImpl( this, @@ -112,7 +112,7 @@ public IDoubleSubscriber SubscribeEx( public IDoubleSubscriber SubscribeEx( ReadOnlySpan typeString, double defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleEntryImpl( this, @@ -137,7 +137,7 @@ public IDoubleSubscriber SubscribeEx( /// publish options /// publisher public IDoublePublisher Publish( - PubSubOptions options) + PubSubOptions options = default) { return new DoubleEntryImpl( this, @@ -165,7 +165,7 @@ public IDoublePublisher Publish( /// publisher public IDoublePublisher PublishEx( string typeString, string properties, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleEntryImpl( this, @@ -194,7 +194,7 @@ public IDoublePublisher PublishEx( public IDoublePublisher PublishEx( ReadOnlySpan typeString, string properties, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleEntryImpl( this, @@ -223,7 +223,7 @@ public IDoublePublisher PublishEx( public IDoublePublisher PublishEx( string typeString, ReadOnlySpan properties, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleEntryImpl( this, @@ -252,7 +252,7 @@ public IDoublePublisher PublishEx( public IDoublePublisher PublishEx( ReadOnlySpan typeString, ReadOnlySpan properties, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleEntryImpl( this, @@ -284,7 +284,7 @@ public IDoublePublisher PublishEx( /// entry public IDoubleEntry GetEntry( double defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleEntryImpl( this, @@ -318,7 +318,7 @@ public IDoubleEntry GetEntry( public IDoubleEntry GetEntryEx( string typeString, double defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleEntryImpl( this, @@ -352,7 +352,7 @@ public IDoubleEntry GetEntryEx( public IDoubleEntry GetEntryEx( ReadOnlySpan typeString, double defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new DoubleEntryImpl( this, diff --git a/src/ntcore/Generated/FloatArrayTopic.cs b/src/ntcore/Generated/FloatArrayTopic.cs index 76560ea4..d18d026d 100644 --- a/src/ntcore/Generated/FloatArrayTopic.cs +++ b/src/ntcore/Generated/FloatArrayTopic.cs @@ -54,7 +54,7 @@ public FloatArrayTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, h /// subscriber public IFloatArraySubscriber Subscribe( float[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new FloatArrayEntryImpl( this, @@ -83,7 +83,7 @@ public IFloatArraySubscriber Subscribe( public IFloatArraySubscriber SubscribeEx( string typeString, float[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new FloatArrayEntryImpl( this, @@ -112,7 +112,7 @@ public IFloatArraySubscriber SubscribeEx( public IFloatArraySubscriber SubscribeEx( ReadOnlySpan typeString, float[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new FloatArrayEntryImpl( this, @@ -137,7 +137,7 @@ public IFloatArraySubscriber SubscribeEx( /// publish options /// publisher public IFloatArrayPublisher Publish( - PubSubOptions options) + PubSubOptions options = default) { return new FloatArrayEntryImpl( this, @@ -165,7 +165,7 @@ public IFloatArrayPublisher Publish( /// publisher public IFloatArrayPublisher PublishEx( string typeString, string properties, - PubSubOptions options) + PubSubOptions options = default) { return new FloatArrayEntryImpl( this, @@ -194,7 +194,7 @@ public IFloatArrayPublisher PublishEx( public IFloatArrayPublisher PublishEx( ReadOnlySpan typeString, string properties, - PubSubOptions options) + PubSubOptions options = default) { return new FloatArrayEntryImpl( this, @@ -223,7 +223,7 @@ public IFloatArrayPublisher PublishEx( public IFloatArrayPublisher PublishEx( string typeString, ReadOnlySpan properties, - PubSubOptions options) + PubSubOptions options = default) { return new FloatArrayEntryImpl( this, @@ -252,7 +252,7 @@ public IFloatArrayPublisher PublishEx( public IFloatArrayPublisher PublishEx( ReadOnlySpan typeString, ReadOnlySpan properties, - PubSubOptions options) + PubSubOptions options = default) { return new FloatArrayEntryImpl( this, @@ -284,7 +284,7 @@ public IFloatArrayPublisher PublishEx( /// entry public IFloatArrayEntry GetEntry( float[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new FloatArrayEntryImpl( this, @@ -318,7 +318,7 @@ public IFloatArrayEntry GetEntry( public IFloatArrayEntry GetEntryEx( string typeString, float[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new FloatArrayEntryImpl( this, @@ -352,7 +352,7 @@ public IFloatArrayEntry GetEntryEx( public IFloatArrayEntry GetEntryEx( ReadOnlySpan typeString, float[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new FloatArrayEntryImpl( this, diff --git a/src/ntcore/Generated/FloatTopic.cs b/src/ntcore/Generated/FloatTopic.cs index 9195a148..0f8edf7f 100644 --- a/src/ntcore/Generated/FloatTopic.cs +++ b/src/ntcore/Generated/FloatTopic.cs @@ -54,7 +54,7 @@ public FloatTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, handle /// subscriber public IFloatSubscriber Subscribe( float defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new FloatEntryImpl( this, @@ -83,7 +83,7 @@ public IFloatSubscriber Subscribe( public IFloatSubscriber SubscribeEx( string typeString, float defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new FloatEntryImpl( this, @@ -112,7 +112,7 @@ public IFloatSubscriber SubscribeEx( public IFloatSubscriber SubscribeEx( ReadOnlySpan typeString, float defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new FloatEntryImpl( this, @@ -137,7 +137,7 @@ public IFloatSubscriber SubscribeEx( /// publish options /// publisher public IFloatPublisher Publish( - PubSubOptions options) + PubSubOptions options = default) { return new FloatEntryImpl( this, @@ -165,7 +165,7 @@ public IFloatPublisher Publish( /// publisher public IFloatPublisher PublishEx( string typeString, string properties, - PubSubOptions options) + PubSubOptions options = default) { return new FloatEntryImpl( this, @@ -194,7 +194,7 @@ public IFloatPublisher PublishEx( public IFloatPublisher PublishEx( ReadOnlySpan typeString, string properties, - PubSubOptions options) + PubSubOptions options = default) { return new FloatEntryImpl( this, @@ -223,7 +223,7 @@ public IFloatPublisher PublishEx( public IFloatPublisher PublishEx( string typeString, ReadOnlySpan properties, - PubSubOptions options) + PubSubOptions options = default) { return new FloatEntryImpl( this, @@ -252,7 +252,7 @@ public IFloatPublisher PublishEx( public IFloatPublisher PublishEx( ReadOnlySpan typeString, ReadOnlySpan properties, - PubSubOptions options) + PubSubOptions options = default) { return new FloatEntryImpl( this, @@ -284,7 +284,7 @@ public IFloatPublisher PublishEx( /// entry public IFloatEntry GetEntry( float defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new FloatEntryImpl( this, @@ -318,7 +318,7 @@ public IFloatEntry GetEntry( public IFloatEntry GetEntryEx( string typeString, float defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new FloatEntryImpl( this, @@ -352,7 +352,7 @@ public IFloatEntry GetEntryEx( public IFloatEntry GetEntryEx( ReadOnlySpan typeString, float defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new FloatEntryImpl( this, diff --git a/src/ntcore/Generated/IntegerArrayTopic.cs b/src/ntcore/Generated/IntegerArrayTopic.cs index 1ce48442..69e63924 100644 --- a/src/ntcore/Generated/IntegerArrayTopic.cs +++ b/src/ntcore/Generated/IntegerArrayTopic.cs @@ -54,7 +54,7 @@ public IntegerArrayTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, /// subscriber public IIntegerArraySubscriber Subscribe( long[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new IntegerArrayEntryImpl( this, @@ -83,7 +83,7 @@ public IIntegerArraySubscriber Subscribe( public IIntegerArraySubscriber SubscribeEx( string typeString, long[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new IntegerArrayEntryImpl( this, @@ -112,7 +112,7 @@ public IIntegerArraySubscriber SubscribeEx( public IIntegerArraySubscriber SubscribeEx( ReadOnlySpan typeString, long[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new IntegerArrayEntryImpl( this, @@ -137,7 +137,7 @@ public IIntegerArraySubscriber SubscribeEx( /// publish options /// publisher public IIntegerArrayPublisher Publish( - PubSubOptions options) + PubSubOptions options = default) { return new IntegerArrayEntryImpl( this, @@ -165,7 +165,7 @@ public IIntegerArrayPublisher Publish( /// publisher public IIntegerArrayPublisher PublishEx( string typeString, string properties, - PubSubOptions options) + PubSubOptions options = default) { return new IntegerArrayEntryImpl( this, @@ -194,7 +194,7 @@ public IIntegerArrayPublisher PublishEx( public IIntegerArrayPublisher PublishEx( ReadOnlySpan typeString, string properties, - PubSubOptions options) + PubSubOptions options = default) { return new IntegerArrayEntryImpl( this, @@ -223,7 +223,7 @@ public IIntegerArrayPublisher PublishEx( public IIntegerArrayPublisher PublishEx( string typeString, ReadOnlySpan properties, - PubSubOptions options) + PubSubOptions options = default) { return new IntegerArrayEntryImpl( this, @@ -252,7 +252,7 @@ public IIntegerArrayPublisher PublishEx( public IIntegerArrayPublisher PublishEx( ReadOnlySpan typeString, ReadOnlySpan properties, - PubSubOptions options) + PubSubOptions options = default) { return new IntegerArrayEntryImpl( this, @@ -284,7 +284,7 @@ public IIntegerArrayPublisher PublishEx( /// entry public IIntegerArrayEntry GetEntry( long[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new IntegerArrayEntryImpl( this, @@ -318,7 +318,7 @@ public IIntegerArrayEntry GetEntry( public IIntegerArrayEntry GetEntryEx( string typeString, long[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new IntegerArrayEntryImpl( this, @@ -352,7 +352,7 @@ public IIntegerArrayEntry GetEntryEx( public IIntegerArrayEntry GetEntryEx( ReadOnlySpan typeString, long[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new IntegerArrayEntryImpl( this, diff --git a/src/ntcore/Generated/RawTopic.cs b/src/ntcore/Generated/RawTopic.cs index d579232e..3bbafccb 100644 --- a/src/ntcore/Generated/RawTopic.cs +++ b/src/ntcore/Generated/RawTopic.cs @@ -47,7 +47,7 @@ public RawTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, handle) public IRawSubscriber Subscribe( string typeString, byte[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new RawEntryImpl( this, @@ -76,7 +76,7 @@ public IRawSubscriber Subscribe( public IRawSubscriber Subscribe( ReadOnlySpan typeString, byte[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new RawEntryImpl( this, @@ -103,7 +103,7 @@ public IRawSubscriber Subscribe( /// publisher public IRawPublisher Publish( string typeString, - PubSubOptions options) + PubSubOptions options = default) { return new RawEntryImpl( this, @@ -130,7 +130,7 @@ public IRawPublisher Publish( /// publisher public IRawPublisher Publish( ReadOnlySpan typeString, - PubSubOptions options) + PubSubOptions options = default) { return new RawEntryImpl( this, @@ -158,7 +158,7 @@ public IRawPublisher Publish( /// publisher public IRawPublisher PublishEx( string typeString, string properties, - PubSubOptions options) + PubSubOptions options = default) { return new RawEntryImpl( this, @@ -187,7 +187,7 @@ public IRawPublisher PublishEx( public IRawPublisher PublishEx( ReadOnlySpan typeString, string properties, - PubSubOptions options) + PubSubOptions options = default) { return new RawEntryImpl( this, @@ -216,7 +216,7 @@ public IRawPublisher PublishEx( public IRawPublisher PublishEx( string typeString, ReadOnlySpan properties, - PubSubOptions options) + PubSubOptions options = default) { return new RawEntryImpl( this, @@ -245,7 +245,7 @@ public IRawPublisher PublishEx( public IRawPublisher PublishEx( ReadOnlySpan typeString, ReadOnlySpan properties, - PubSubOptions options) + PubSubOptions options = default) { return new RawEntryImpl( this, @@ -279,7 +279,7 @@ public IRawPublisher PublishEx( public IRawEntry GetEntry( string typeString, byte[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new RawEntryImpl( this, @@ -313,7 +313,7 @@ public IRawEntry GetEntry( public IRawEntry GetEntry( ReadOnlySpan typeString, byte[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new RawEntryImpl( this, diff --git a/src/ntcore/Natives/NtCore.cs b/src/ntcore/Natives/NtCore.cs index 70d5c755..96da0885 100644 --- a/src/ntcore/Natives/NtCore.cs +++ b/src/ntcore/Natives/NtCore.cs @@ -269,7 +269,7 @@ public static bool GetTopicExists(T handle) where T : struct, INtEntryHandle [LibraryImport("ntcore", EntryPoint = "NT_Subscribe")] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] - public static partial NtSubscriber Subscribe(NtTopic topic, NetworkTableType type, WpiString typeStr, in PubSubOptions options); + public static partial NtSubscriber Subscribe(NtTopic topic, NetworkTableType type, WpiString typeStr, in PubSubOptions options = default); [LibraryImport("ntcore", EntryPoint = "NT_Unsubscribe")] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] @@ -277,11 +277,11 @@ public static bool GetTopicExists(T handle) where T : struct, INtEntryHandle [LibraryImport("ntcore", EntryPoint = "NT_Publish")] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] - public static partial NtPublisher Publish(NtTopic topic, NetworkTableType type, WpiString typeStr, in PubSubOptions options); + public static partial NtPublisher Publish(NtTopic topic, NetworkTableType type, WpiString typeStr, in PubSubOptions options = default); [LibraryImport("ntcore", EntryPoint = "NT_PublishEx")] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] - public static partial NtPublisher PublishEx(NtTopic topic, NetworkTableType type, WpiString typeStr, WpiString properties, in PubSubOptions options); + public static partial NtPublisher PublishEx(NtTopic topic, NetworkTableType type, WpiString typeStr, WpiString properties, in PubSubOptions options = default); [LibraryImport("ntcore", EntryPoint = "NT_Unpublish")] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] @@ -294,7 +294,7 @@ public static void Unpublish(T pubsubentry) where T : struct, INtEntryHandle [LibraryImport("ntcore", EntryPoint = "NT_GetEntryEx")] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] - public static unsafe partial NtEntry GetEntry(NtTopic topic, NetworkTableType type, WpiString typeStr, in PubSubOptions options); + public static unsafe partial NtEntry GetEntry(NtTopic topic, NetworkTableType type, WpiString typeStr, in PubSubOptions options = default); [LibraryImport("ntcore", EntryPoint = "NT_ReleaseEntry")] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] @@ -328,9 +328,9 @@ public static NtTopic GetTopicFromHandle(T pubsubentry) where T : struct, INt [LibraryImport("ntcore", EntryPoint = "NT_SubscribeMultiple")] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] - internal static partial NtMultiSubscriber SubscribeMultiple(NtInst inst, [MarshalUsing(typeof(WpiStringMarshaller), ElementIndirectionDepth = 1)] ReadOnlySpan prefixes, nuint prefixesLen, in PubSubOptions options); + internal static partial NtMultiSubscriber SubscribeMultiple(NtInst inst, [MarshalUsing(typeof(WpiStringMarshaller), ElementIndirectionDepth = 1)] ReadOnlySpan prefixes, nuint prefixesLen, in PubSubOptions options = default); - public static NtMultiSubscriber SubscribeMultiple(NtInst inst, [MarshalUsing(typeof(WpiStringMarshaller), ElementIndirectionDepth = 1)] ReadOnlySpan prefixes, in PubSubOptions options) + public static NtMultiSubscriber SubscribeMultiple(NtInst inst, [MarshalUsing(typeof(WpiStringMarshaller), ElementIndirectionDepth = 1)] ReadOnlySpan prefixes, in PubSubOptions options = default) { return SubscribeMultiple(inst, prefixes, (nuint)prefixes.Length, options); } diff --git a/src/ntcore/ProtobufTopic.cs b/src/ntcore/ProtobufTopic.cs index d898cb7e..a13931b8 100644 --- a/src/ntcore/ProtobufTopic.cs +++ b/src/ntcore/ProtobufTopic.cs @@ -15,22 +15,22 @@ public ProtobufTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, han { } - public IProtobufSubscriber Subscribe(T defaultValue, PubSubOptions options) + public IProtobufSubscriber Subscribe(T defaultValue, PubSubOptions options = default) { return new ProtobufEntryImpl(this, NtCore.Subscribe(Handle, NetworkTableType.Raw, T.Proto.TypeString, options), defaultValue, false); } - public IProtobufPublisher Publish(PubSubOptions options) + public IProtobufPublisher Publish(PubSubOptions options = default) { return new ProtobufEntryImpl(this, NtCore.Publish(Handle, NetworkTableType.Raw, T.Proto.TypeString, options), default!, false); } - public IProtobufPublisher PublishEx(string properties, PubSubOptions options) + public IProtobufPublisher PublishEx(string properties, PubSubOptions options = default) { return new ProtobufEntryImpl(this, NtCore.PublishEx(Handle, NetworkTableType.Raw, T.Proto.TypeString, properties, options), default!, false); } - public IProtobufEntry GetEntry(T defaultValue, PubSubOptions options) + public IProtobufEntry GetEntry(T defaultValue, PubSubOptions options = default) { return new ProtobufEntryImpl(this, NtCore.GetEntry(Handle, NetworkTableType.Raw, T.Proto.TypeString, options), defaultValue, false); } diff --git a/src/ntcore/Strings/StringArrayTopic.cs b/src/ntcore/Strings/StringArrayTopic.cs index 3a18b06e..32fcc2e4 100644 --- a/src/ntcore/Strings/StringArrayTopic.cs +++ b/src/ntcore/Strings/StringArrayTopic.cs @@ -54,7 +54,7 @@ public StringArrayTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, /// subscriber public IStringArraySubscriber Subscribe( string[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new StringArrayEntryImpl( this, @@ -83,7 +83,7 @@ public IStringArraySubscriber Subscribe( public IStringArraySubscriber SubscribeEx( string typeString, string[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new StringArrayEntryImpl( this, @@ -112,7 +112,7 @@ public IStringArraySubscriber SubscribeEx( public IStringArraySubscriber SubscribeEx( ReadOnlySpan typeString, string[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new StringArrayEntryImpl( this, @@ -137,7 +137,7 @@ public IStringArraySubscriber SubscribeEx( /// publish options /// publisher public IStringArrayPublisher Publish( - PubSubOptions options) + PubSubOptions options = default) { return new StringArrayEntryImpl( this, @@ -165,7 +165,7 @@ public IStringArrayPublisher Publish( /// publisher public IStringArrayPublisher PublishEx( string typeString, string properties, - PubSubOptions options) + PubSubOptions options = default) { return new StringArrayEntryImpl( this, @@ -194,7 +194,7 @@ public IStringArrayPublisher PublishEx( public IStringArrayPublisher PublishEx( ReadOnlySpan typeString, string properties, - PubSubOptions options) + PubSubOptions options = default) { return new StringArrayEntryImpl( this, @@ -223,7 +223,7 @@ public IStringArrayPublisher PublishEx( public IStringArrayPublisher PublishEx( string typeString, ReadOnlySpan properties, - PubSubOptions options) + PubSubOptions options = default) { return new StringArrayEntryImpl( this, @@ -252,7 +252,7 @@ public IStringArrayPublisher PublishEx( public IStringArrayPublisher PublishEx( ReadOnlySpan typeString, ReadOnlySpan properties, - PubSubOptions options) + PubSubOptions options = default) { return new StringArrayEntryImpl( this, @@ -284,7 +284,7 @@ public IStringArrayPublisher PublishEx( /// entry public IStringArrayEntry GetEntry( string[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new StringArrayEntryImpl( this, @@ -318,7 +318,7 @@ public IStringArrayEntry GetEntry( public IStringArrayEntry GetEntryEx( string typeString, string[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new StringArrayEntryImpl( this, @@ -352,7 +352,7 @@ public IStringArrayEntry GetEntryEx( public IStringArrayEntry GetEntryEx( ReadOnlySpan typeString, string[] defaultValue, - PubSubOptions options) + PubSubOptions options = default) { return new StringArrayEntryImpl( this, diff --git a/src/ntcore/StructArrayTopic.cs b/src/ntcore/StructArrayTopic.cs index 6aa16339..4b6a2949 100644 --- a/src/ntcore/StructArrayTopic.cs +++ b/src/ntcore/StructArrayTopic.cs @@ -15,22 +15,22 @@ public StructArrayTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, { } - public IStructArraySubscriber Subscribe(T[] defaultValue, PubSubOptions options) + public IStructArraySubscriber Subscribe(T[] defaultValue, PubSubOptions options = default) { return new StructArrayEntryImpl(this, NtCore.Subscribe(Handle, NetworkTableType.Raw, T.Struct.TypeString, options), defaultValue, false); } - public IStructArrayPublisher Publish(PubSubOptions options) + public IStructArrayPublisher Publish(PubSubOptions options = default) { return new StructArrayEntryImpl(this, NtCore.Publish(Handle, NetworkTableType.Raw, T.Struct.TypeString, options), default!, false); } - public IStructArrayPublisher PublishEx(string properties, PubSubOptions options) + public IStructArrayPublisher PublishEx(string properties, PubSubOptions options = default) { return new StructArrayEntryImpl(this, NtCore.PublishEx(Handle, NetworkTableType.Raw, T.Struct.TypeString, properties, options), default!, false); } - public IStructArrayEntry GetEntry(T[] defaultValue, PubSubOptions options) + public IStructArrayEntry GetEntry(T[] defaultValue, PubSubOptions options = default) { return new StructArrayEntryImpl(this, NtCore.GetEntry(Handle, NetworkTableType.Raw, T.Struct.TypeString, options), defaultValue, false); } diff --git a/src/ntcore/StructTopic.cs b/src/ntcore/StructTopic.cs index f6f227f2..6ef5af5d 100644 --- a/src/ntcore/StructTopic.cs +++ b/src/ntcore/StructTopic.cs @@ -15,22 +15,22 @@ public StructTopic(NetworkTableInstance inst, NtTopic handle) : base(inst, handl { } - public IStructSubscriber Subscribe(T defaultValue, PubSubOptions options) + public IStructSubscriber Subscribe(T defaultValue, PubSubOptions options = default) { return new StructEntryImpl(this, NtCore.Subscribe(Handle, NetworkTableType.Raw, T.Struct.TypeString, options), defaultValue, false); } - public IStructPublisher Publish(PubSubOptions options) + public IStructPublisher Publish(PubSubOptions options = default) { return new StructEntryImpl(this, NtCore.Publish(Handle, NetworkTableType.Raw, T.Struct.TypeString, options), default!, false); } - public IStructPublisher PublishEx(string properties, PubSubOptions options) + public IStructPublisher PublishEx(string properties, PubSubOptions options = default) { return new StructEntryImpl(this, NtCore.PublishEx(Handle, NetworkTableType.Raw, T.Struct.TypeString, properties, options), default!, false); } - public IStructEntry GetEntry(T defaultValue, PubSubOptions options) + public IStructEntry GetEntry(T defaultValue, PubSubOptions options = default) { return new StructEntryImpl(this, NtCore.GetEntry(Handle, NetworkTableType.Raw, T.Struct.TypeString, options), defaultValue, false); } diff --git a/src/ntcore/Topic.cs b/src/ntcore/Topic.cs index ead4009f..c2dfb526 100644 --- a/src/ntcore/Topic.cs +++ b/src/ntcore/Topic.cs @@ -81,29 +81,29 @@ public string Properties set => NtCore.SetTopicProperties(Handle, value); } - public IGenericSubscriber GenericSubscribe(in PubSubOptions options) => GenericSubscribe("", options); + public IGenericSubscriber GenericSubscribe(in PubSubOptions options = default) => GenericSubscribe("", options); - public IGenericSubscriber GenericSubscribe(string typeString, in PubSubOptions options) + public IGenericSubscriber GenericSubscribe(string typeString, in PubSubOptions options = default) { return new GenericEntryImpl(this, NtCore.Subscribe(Handle, NetworkTableTypeHelpers.GetFromString(typeString), typeString, options)); } - public IGenericPublisher GenericPublish(string typeString, in PubSubOptions options) + public IGenericPublisher GenericPublish(string typeString, in PubSubOptions options = default) { return new GenericEntryImpl(this, NtCore.Publish(Handle, NetworkTableTypeHelpers.GetFromString(typeString), typeString, options)); } - public IGenericPublisher GenericPublishEx(string typeString, string properties, in PubSubOptions options) + public IGenericPublisher GenericPublishEx(string typeString, string properties, in PubSubOptions options = default) { return new GenericEntryImpl(this, NtCore.PublishEx(Handle, NetworkTableTypeHelpers.GetFromString(typeString), typeString, properties, options)); } - public IGenericEntry GetGenericEntry(in PubSubOptions options) + public IGenericEntry GetGenericEntry(in PubSubOptions options = default) { return GetGenericEntry("", options); } - public IGenericEntry GetGenericEntry(string typeString, in PubSubOptions options) + public IGenericEntry GetGenericEntry(string typeString, in PubSubOptions options = default) { return new GenericEntryImpl(this, NtCore.GetEntry(Handle, NetworkTableTypeHelpers.GetFromString(typeString), typeString, options)); } diff --git a/src/wpiutil/Sendable/ISendableBuilder.cs b/src/wpiutil/Sendable/ISendableBuilder.cs index 399c9459..6cde8834 100644 --- a/src/wpiutil/Sendable/ISendableBuilder.cs +++ b/src/wpiutil/Sendable/ISendableBuilder.cs @@ -34,7 +34,7 @@ enum BackingKind void PublishConstDouble(string key, double value); - void AddStringProperty(string key, Func? getter, Action? setter); + void AddStringProperty(string key, Func getter, Action? setter); void PublishConstString(string key, string value); diff --git a/test/epilogue.test/ClassSpecificLoggerTest.cs b/test/epilogue.test/ClassSpecificLoggerTest.cs new file mode 100644 index 00000000..e794e6b6 --- /dev/null +++ b/test/epilogue.test/ClassSpecificLoggerTest.cs @@ -0,0 +1,3 @@ +using Xunit; + +namespace Epilogue; diff --git a/test/epilogue.test/LazyLoggerTest.cs b/test/epilogue.test/LazyLoggerTest.cs new file mode 100644 index 00000000..a157d683 --- /dev/null +++ b/test/epilogue.test/LazyLoggerTest.cs @@ -0,0 +1,45 @@ +using Epilogue.Logging; +using Xunit; + +namespace Epilogue; + +public class LazyLoggerTest +{ + [Fact] + public void LazyOfLazyReturnsSelf() + { + var lazy = new LazyLogger(new NullLogger()); + Assert.Same(lazy, lazy.Lazy); + } + + [Fact] + public void LazyInt() + { + var logger = new TestLogger(); + var lazy = logger.Lazy; + + { + // First time logging to "int" should go through. + lazy.Log("int", 0); + Assert.Equal(new TestLogger.LogEntry[] { new("int", 0) }, logger.Entries); + } + + { + // Logging the current value shouldn't go through + lazy.Log("int", 0); + Assert.Equal(new TestLogger.LogEntry[] { new("int", 0) }, logger.Entries); + } + + { + // Logging a new value should go through. + lazy.Log("int", 1); + Assert.Equal(new TestLogger.LogEntry[] { new("int", 0), new("int", 1) }, logger.Entries); + } + + { + // Logging a previous value should go through. + lazy.Log("int", 0); + Assert.Equal(new TestLogger.LogEntry[] { new("int", 0), new("int", 1), new("int", 0) }, logger.Entries); + } + } +} diff --git a/test/epilogue.test/TestLogger.cs b/test/epilogue.test/TestLogger.cs new file mode 100644 index 00000000..fc617d84 --- /dev/null +++ b/test/epilogue.test/TestLogger.cs @@ -0,0 +1,120 @@ +using System.Runtime.InteropServices; +using Epilogue.Logging; +using WPIUtil.Serialization.Struct; + +namespace Epilogue; + +public class TestLogger : IDataLogger +{ + public record LogEntry(string identifier, object value); + + private readonly Dictionary m_subLoggers = []; + + private readonly List m_entries = []; + + public List Entries => m_entries; + + public IDataLogger Lazy => new LazyLogger(this); + + public IDataLogger GetSubLogger(string path) + { + ref var subLogger = ref CollectionsMarshal.GetValueRefOrAddDefault(m_subLoggers, path, out var _); + subLogger ??= new(path, this); + return subLogger; + } + + public void Log(string identifier, bool value) + { + m_entries.Add(new LogEntry(identifier, value)); + } + + public void Log(string identifier, int value) + { + m_entries.Add(new LogEntry(identifier, value)); + } + + public void Log(string identifier, long value) + { + m_entries.Add(new LogEntry(identifier, value)); + } + + public void Log(string identifier, float value) + { + m_entries.Add(new LogEntry(identifier, value)); + } + + public void Log(string identifier, double value) + { + m_entries.Add(new LogEntry(identifier, value)); + } + + public void Log(string identifier, ReadOnlySpan value) + { + m_entries.Add(new LogEntry(identifier, value.ToArray())); + } + + public void Log(string identifier, ReadOnlySpan value) + { + m_entries.Add(new LogEntry(identifier, value.ToArray())); + } + + public void Log(string identifier, ReadOnlySpan value) + { + m_entries.Add(new LogEntry(identifier, value.ToArray())); + } + + public void Log(string identifier, ReadOnlySpan value) + { + m_entries.Add(new LogEntry(identifier, value.ToArray())); + } + + public void Log(string identifier, ReadOnlySpan value) + { + m_entries.Add(new LogEntry(identifier, value.ToArray())); + } + + public void Log(string identifier, ReadOnlySpan value) + { + m_entries.Add(new LogEntry(identifier, value.ToArray())); + } + + public void Log(string identifier, string value) + { + m_entries.Add(new LogEntry(identifier, value)); + } + + public void Log(string identifier, ReadOnlySpan value) + { + m_entries.Add(new LogEntry(identifier, value.ToArray())); + } + + public void Log(string identifier, ReadOnlySpan value) + { + m_entries.Add(new LogEntry(identifier, value.ToArray())); + } + + public void Log(string identifier, in T value) where T : IStructSerializable + { + m_entries.Add(new LogEntry(identifier, value)); + } + + public void Log(string identifier, T[] value) where T : IStructSerializable + { + m_entries.Add(new LogEntry(identifier, value)); + } + + public void Log(string identifier, Span value) where T : IStructSerializable + { + m_entries.Add(new LogEntry(identifier, value.ToArray())); + } + + public void Log(string identifier, ReadOnlySpan value) where T : IStructSerializable + { + m_entries.Add(new LogEntry(identifier, value.ToArray())); + } + + public void Log(string identifier, T value) where T : Enum + { + m_entries.Add(new LogEntry(identifier, value)); + } +} diff --git a/test/epilogue.test/epilogue.test.csproj b/test/epilogue.test/epilogue.test.csproj new file mode 100644 index 00000000..0290f8f8 --- /dev/null +++ b/test/epilogue.test/epilogue.test.csproj @@ -0,0 +1,13 @@ + + + + + + + + + + true + + +