diff --git a/src/NATS.Client/v1/AckType.cs b/src/NATS.Client/v1/AckType.cs index aadd3bbd..80927d09 100644 --- a/src/NATS.Client/v1/AckType.cs +++ b/src/NATS.Client/v1/AckType.cs @@ -1,4 +1,4 @@ -// Copyright 2021 The NATS Authors +// Copyright 2021 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -32,8 +32,9 @@ public AckType(string text, bool terminal) Bytes = Encoding.ASCII.GetBytes(text); IsTerminal = terminal; } - - public byte[] BodyBytes(long delayNanoseconds) { + + public byte[] BodyBytes(long delayNanoseconds) + { return delayNanoseconds < 1 ? Bytes : Encoding.ASCII.GetBytes($"{Text} {{\"delay\": {delayNanoseconds}}}"); } } diff --git a/src/NATS.Client/v1/AsyncSubscription.cs b/src/NATS.Client/v1/AsyncSubscription.cs index 072310aa..48af7044 100644 --- a/src/NATS.Client/v1/AsyncSubscription.cs +++ b/src/NATS.Client/v1/AsyncSubscription.cs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 The NATS Authors +// Copyright 2015-2018 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/src/NATS.Client/v1/Channel.cs b/src/NATS.Client/v1/Channel.cs index ffcbb4b0..6f3176fd 100644 --- a/src/NATS.Client/v1/Channel.cs +++ b/src/NATS.Client/v1/Channel.cs @@ -50,7 +50,8 @@ public static SingleUseChannel GetOrCreate() public static void Return(SingleUseChannel ch) { ch.reset(); - if (Channels.Count < 1024) Channels.Add(ch); + if (Channels.Count < 1024) + Channels.Add(ch); } internal T get(int timeout) @@ -93,15 +94,36 @@ internal void reset() internal sealed class Channel { readonly Queue q; + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + readonly Object qLock = new Object(); +After: + readonly object qLock = new object(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + readonly Object qLock = new Object(); +After: + readonly object qLock = new object(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: readonly Object qLock = new Object(); +After: + readonly object qLock = new object(); +*/ + readonly object qLock = new object(); bool finished = false; public string Name { get; set; } - internal Channel() : this(1024) {} + internal Channel() : this(1024) { } - internal Channel(string name) : this(1024, name) {} + internal Channel(string name) : this(1024, name) { } internal Channel(int initialCapacity, string name = null) { @@ -168,9 +190,31 @@ internal T get(int timeout) // Returns the number of items delivered into the buffer. internal int get(int timeout, T[] buffer) { - if (buffer.Length < 1) throw new ArgumentException(); + if (buffer.Length < 1) + throw new ArgumentException(); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int delivered = 0; +After: + var delivered = 0; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int delivered = 0; +After: + var delivered = 0; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int delivered = 0; +After: + var delivered = 0; +*/ + + + var delivered = 0; var lockWasTaken = false; try @@ -184,7 +228,7 @@ internal int get(int timeout, T[] buffer) if (q.Count > 0) { - for (int ii = 0; ii < buffer.Length && q.Count > 0; ++ii) + for (var ii = 0; ii < buffer.Length && q.Count > 0; ++ii) { buffer[ii] = q.Dequeue(); delivered++; @@ -219,7 +263,7 @@ internal int get(int timeout, T[] buffer) // we can have an empty queue if there was a spurious wakeup. if (q.Count > 0) { - for (int ii = 0; ii < buffer.Length && q.Count > 0; ++ii) + for (var ii = 0; ii < buffer.Length && q.Count > 0; ++ii) { buffer[ii] = q.Dequeue(); delivered++; diff --git a/src/NATS.Client/v1/Connection.cs b/src/NATS.Client/v1/Connection.cs index 0d5a250f..b22f99aa 100644 --- a/src/NATS.Client/v1/Connection.cs +++ b/src/NATS.Client/v1/Connection.cs @@ -43,7 +43,7 @@ public enum ConnState /// The is disconnected. /// DISCONNECTED = 0, - + /// /// The is connected to a NATS Server. /// @@ -81,7 +81,7 @@ public enum ConnState internal enum ClientProtcolVersion { // clientProtoZero is the original client protocol from 2009. - // http://nats.io/documentation/internals/nats-protocol/ + // http://nats.io/documentation/internals/nats-protocol/ ClientProtoZero = 0, // ClientProtoInfo signals a client can receive more then the original INFO block. @@ -105,7 +105,7 @@ public class Connection : IConnection // NOTE: We aren't using Mutex here to support enterprises using // .NET 4.0. - private readonly object mu = new Object(); + private readonly object mu = new object(); private readonly Nuid _nuid = new Nuid(); @@ -118,36 +118,57 @@ public class Connection : IConnection private readonly List wg = new List(2); - private Uri url = null; + private Uri url = null; private IServerProvider srvProvider; // we have a buffered reader for writing, and reading. // This is for both performance, and having to work around // interlinked read/writes (supported by the underlying network // stream, but not the BufferedStream). - private Stream bw = null; - private Stream br = null; - private MemoryStream pending = null; + private Stream bw = null; + private Stream br = null; + private MemoryStream pending = null; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Object flusherLock = new Object(); +After: + object flusherLock = new Object(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Object flusherLock = new Object(); +After: + object flusherLock = new Object(); +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: Object flusherLock = new Object(); - bool flusherKicked = false; - bool flusherDone = false; +After: + object flusherLock = new Object(); +*/ - private ServerInfo serverInfo = null; - private Dictionary subs = - new Dictionary(); - + object flusherLock = new object(); + bool flusherKicked = false; + bool flusherDone = false; + + private ServerInfo serverInfo = null; + + private Dictionary subs = + new Dictionary(); + private readonly ConcurrentQueue> pongs = new ConcurrentQueue>(); - internal MsgArg msgArgs = new MsgArg(); + internal MsgArg msgArgs = new MsgArg(); internal ConnState status = ConnState.CLOSED; internal Exception lastEx; - Timer ptmr = null; - int pout = 0; + Timer ptmr = null; + int pout = 0; internal static Random random = new Random(); @@ -162,19 +183,19 @@ private readonly Dictionary waitingRequests // Prepare protocol messages for efficiency private byte[] PING_P_BYTES = null; - private int PING_P_BYTES_LEN; + private int PING_P_BYTES_LEN; private byte[] PONG_P_BYTES = null; - private int PONG_P_BYTES_LEN; + private int PONG_P_BYTES_LEN; private byte[] PUB_P_BYTES = null; - private int PUB_P_BYTES_LEN = 0; + private int PUB_P_BYTES_LEN = 0; private byte[] HPUB_P_BYTES = null; - private int HPUB_P_BYTES_LEN = 0; + private int HPUB_P_BYTES_LEN = 0; private byte[] CRLF_BYTES = null; - private int CRLF_BYTES_LEN = 0; + private int CRLF_BYTES_LEN = 0; byte[] pubProtoBuf = null; @@ -194,7 +215,7 @@ private class CallbackScheduler : IDisposable private readonly object runningLock = new object(); private readonly Channel tasks = new Channel() { Name = "Tasks" }; - private Task executorTask = null; + private Task executorTask = null; private bool schedulerRunning = false; private bool Running @@ -209,7 +230,7 @@ private bool Running set { - lock (runningLock) + lock (runningLock) { schedulerRunning = value; } @@ -219,8 +240,29 @@ private bool Running private void process() { while (Running) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Action action = tasks.get(-1); +After: + var action = tasks.get(-1); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Action action = tasks.get(-1); +After: + var action = tasks.get(-1); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: Action action = tasks.get(-1); +After: + var action = tasks.get(-1); +*/ + + { + var action = tasks.get(-1); try { action(); @@ -238,7 +280,7 @@ internal void Start() // Use the default task scheduler and do not let child tasks launched // when running actions to attach to this task (Issue #273) executorTask = Task.Factory.StartNew( - process, + process, CancellationToken.None, TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); @@ -311,8 +353,29 @@ internal class Control private Control() { } internal Control(string s) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: string[] parts = s.Split(separator, 2); +After: + var parts = s.Split(separator, 2); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string[] parts = s.Split(separator, 2); +After: + var parts = s.Split(separator, 2); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string[] parts = s.Split(separator, 2); +After: + var parts = s.Split(separator, 2); +*/ + + { + var parts = s.Split(separator, 2); if (parts.Length == 1) { @@ -444,7 +507,7 @@ public virtual void close(TcpClient c) public void makeTLS() { - + RemoteCertificateValidationCallback cb = null; @@ -457,10 +520,31 @@ public void makeTLS() sslStream = new SslStream(stream, false, cb, null, EncryptionPolicy.RequireEncryption); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + SslProtocols protocol = (SslProtocols)Enum.Parse(typeof(SslProtocols), "Tls12"); +After: + var protocol = (SslProtocols)Enum.Parse(typeof(SslProtocols), "Tls12"); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + SslProtocols protocol = (SslProtocols)Enum.Parse(typeof(SslProtocols), "Tls12"); +After: + var protocol = (SslProtocols)Enum.Parse(typeof(SslProtocols), "Tls12"); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + SslProtocols protocol = (SslProtocols)Enum.Parse(typeof(SslProtocols), "Tls12"); +After: + var protocol = (SslProtocols)Enum.Parse(typeof(SslProtocols), "Tls12"); +*/ + try { - SslProtocols protocol = (SslProtocols)Enum.Parse(typeof(SslProtocols), "Tls12"); + var protocol = (SslProtocols)Enum.Parse(typeof(SslProtocols), "Tls12"); sslStream.AuthenticateAsClientAsync(hostName, options.certificates, protocol, options.CheckCertificateRevocation).Wait(); } catch (Exception ex) @@ -628,13 +712,13 @@ internal SubChannelProcessor(Connection c) Channel = new Channel() { - Name = "SubChannelProcessor " + this.GetHashCode(), + Name = "SubChannelProcessor " + GetHashCode(), }; // Use the default task scheduler and do not let child tasks launched // when delivering messages to attach to this task (Issue #273) channelTask = Task.Factory.StartNew( - DeliverMessages, + DeliverMessages, CancellationToken.None, TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); @@ -745,13 +829,13 @@ internal Connection(Options options) opts.ReconnectDelayHandler = DefaultReconnectDelayHandler; } - if(opts.TCPConnection != null) + if (opts.TCPConnection != null) { conn = opts.TCPConnection; } srvProvider = opts.ServerProvider ?? new ServerPool(); - + PING_P_BYTES = Encoding.UTF8.GetBytes(IC.pingProto); PING_P_BYTES_LEN = PING_P_BYTES.Length; @@ -774,7 +858,7 @@ internal Connection(Options options) globalRequestInbox = NewInbox(); } - + private void buildPublishProtocolBuffers(int size) { pubProtoBuf = new byte[size]; @@ -785,6 +869,27 @@ private void buildPublishProtocolBuffers(int size) // subject and reply. // Caller must lock. private void ensurePublishProtocolBuffer(string subject, string reply) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int pubProtoBufSize = HPUB_P_BYTES_LEN +After: + var pubProtoBufSize = HPUB_P_BYTES_LEN +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int pubProtoBufSize = HPUB_P_BYTES_LEN +After: + var pubProtoBufSize = HPUB_P_BYTES_LEN +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int pubProtoBufSize = HPUB_P_BYTES_LEN +After: + var pubProtoBufSize = HPUB_P_BYTES_LEN +*/ + { // Publish protocol buffer sizing: // @@ -793,7 +898,7 @@ private void ensurePublishProtocolBuffer(string subject, string reply) // + SIZE field maximum + 1 (= log(2147483647) + 1 = 11) // + (optional) REPLY field length + 1 - int pubProtoBufSize = HPUB_P_BYTES_LEN + var pubProtoBufSize = HPUB_P_BYTES_LEN + (1 + subject.Length) + (34) // Include payload/header sizes and stamp + (reply != null ? reply.Length + 1 : 0); @@ -818,10 +923,35 @@ private void ensurePublishProtocolBuffer(string subject, string reply) private void pickServer() { url = null; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Srv s = srvProvider.First(); + if (s == null) + throw new NATSNoServersException("Unable to choose server; no servers available."); +After: + var s = srvProvider.First() ?? throw new NATSNoServersException("Unable to choose server; no servers available."); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Srv s = srvProvider.First(); + if (s == null) + throw new NATSNoServersException("Unable to choose server; no servers available."); +After: + var s = srvProvider.First() ?? throw new NATSNoServersException("Unable to choose server; no servers available."); +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: Srv s = srvProvider.First(); if (s == null) throw new NATSNoServersException("Unable to choose server; no servers available."); +After: + var s = srvProvider.First() ?? throw new NATSNoServersException("Unable to choose server; no servers available."); +*/ + + + var s = srvProvider.First() ?? throw new NATSNoServersException("Unable to choose server; no servers available."); url = s.Url; } @@ -960,8 +1090,29 @@ private void startPingTimer() } private string generateThreadName(string prefix) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string name = "unknown"; +After: + var name = "unknown"; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string name = "unknown"; +After: + var name = "unknown"; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string name = "unknown"; +After: + var name = "unknown"; +*/ + + { + var name = "unknown"; if (opts.Name != null) { name = opts.Name; @@ -975,11 +1126,33 @@ private void spinUpSocketWatchers() Thread t = null; waitForExits(); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + ManualResetEvent readLoopStartEvent = new ManualResetEvent(false); +After: + var readLoopStartEvent = new ManualResetEvent(false); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + ManualResetEvent readLoopStartEvent = new ManualResetEvent(false); +After: + var readLoopStartEvent = new ManualResetEvent(false); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + ManualResetEvent readLoopStartEvent = new ManualResetEvent(false); +After: + var readLoopStartEvent = new ManualResetEvent(false); +*/ + // Ensure threads are started before we continue with // ManualResetEvents. - ManualResetEvent readLoopStartEvent = new ManualResetEvent(false); - t = new Thread(() => { + var readLoopStartEvent = new ManualResetEvent(false); + t = new Thread(() => + { readLoopStartEvent.Set(); readLoop(); }); @@ -987,9 +1160,31 @@ private void spinUpSocketWatchers() t.Start(); t.Name = generateThreadName("Reader"); wg.Add(t); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + ManualResetEvent flusherStartEvent = new ManualResetEvent(false); +After: + var flusherStartEvent = new ManualResetEvent(false); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + ManualResetEvent flusherStartEvent = new ManualResetEvent(false); +After: + var flusherStartEvent = new ManualResetEvent(false); +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: ManualResetEvent flusherStartEvent = new ManualResetEvent(false); - t = new Thread(() => { +After: + var flusherStartEvent = new ManualResetEvent(false); +*/ + + + var flusherStartEvent = new ManualResetEvent(false); + t = new Thread(() => + { flusherStartEvent.Set(); flusher(); }); @@ -1037,7 +1232,7 @@ public IPAddress ClientIP { clientIp = serverInfo.ClientIp; } - + return !string.IsNullOrEmpty(clientIp) ? IPAddress.Parse(clientIp) : null; } } @@ -1072,8 +1267,29 @@ public string ConnectedId { if (status != ConnState.CONNECTED) return IC._EMPTY_; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + return this.serverInfo.ServerId; +After: + return serverInfo.ServerId; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + return this.serverInfo.ServerId; +After: + return serverInfo.ServerId; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: return this.serverInfo.ServerId; +After: + return serverInfo.ServerId; +*/ + + + return serverInfo.ServerId; } } } @@ -1133,8 +1349,29 @@ public string[] DiscoveredServers // Process a connected connection and initialize properly. // Caller must lock. private void processConnectInit(Srv s) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this.status = ConnState.CONNECTING; +After: + status = ConnState.CONNECTING; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this.status = ConnState.CONNECTING; +After: + status = ConnState.CONNECTING; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: this.status = ConnState.CONNECTING; +After: + status = ConnState.CONNECTING; +*/ + + { + status = ConnState.CONNECTING; var orgTimeout = conn.ReceiveTimeout; @@ -1158,7 +1395,7 @@ private void processConnectInit(Srv s) } finally { - if(conn.isSetup()) + if (conn.isSetup()) conn.ReceiveTimeout = orgTimeout; } @@ -1178,16 +1415,58 @@ private void processConnectInit(Srv s) } internal bool connect(Srv s, out Exception exToThrow) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + bool authAuthError = false; +After: + var authAuthError = false; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + bool authAuthError = false; +After: + var authAuthError = false; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: bool authAuthError = false; +After: + var authAuthError = false; +*/ + + { + var authAuthError = false; url = s.Url; try { exToThrow = null; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + String lastAuthExMessage = null; +After: + string lastAuthExMessage = null; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + String lastAuthExMessage = null; +After: + string lastAuthExMessage = null; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: String lastAuthExMessage = null; +After: + string lastAuthExMessage = null; +*/ - for(var i = 0; i < 6; i++) //Precaution to not end up in server returning ExTypeA, ExTypeB, ExTypeA etc. + + string lastAuthExMessage = null; + + for (var i = 0; i < 6; i++) //Precaution to not end up in server returning ExTypeA, ExTypeB, ExTypeA etc. { try { @@ -1203,8 +1482,29 @@ internal bool connect(Srv s, out Exception exToThrow) } } catch (NATSConnectionException ex) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string message = ex.Message.ToLower(); +After: + var message = ex.Message.ToLower(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string message = ex.Message.ToLower(); +After: + var message = ex.Message.ToLower(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string message = ex.Message.ToLower(); +After: + var message = ex.Message.ToLower(); +*/ + + { + var message = ex.Message.ToLower(); if (!NATSException.IsAuthenticationOrAuthorizationError(message, true)) { authAuthError = true; @@ -1239,7 +1539,7 @@ internal bool connect(Srv s, out Exception exToThrow) internal void ScheduleErrorEvent(object sender, NATSException ex, Subscription subscription = null) { - callbackScheduler.Add(() => + callbackScheduler.Add(() => opts.AsyncErrorEventHandlerOrDefault(sender, new ErrEventArgs(this, subscription, ex.Message))); } @@ -1280,8 +1580,29 @@ internal void connect(bool reconnectOnConnect) // secure. This can be dictated from either end and should // only be called after the INIT protocol has been received. private void checkForSecure(Srv s) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + bool makeTlsConn = false; +After: + var makeTlsConn = false; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: bool makeTlsConn = false; +After: + var makeTlsConn = false; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + bool makeTlsConn = false; +After: + var makeTlsConn = false; +*/ + + { + var makeTlsConn = false; if (Opts.TlsFirst) { makeTlsConn = true; @@ -1350,7 +1671,7 @@ internal void SendSub(string subject, string queue, long sid) { writeString(IC.subProto, subject, queue, sid.ToNumericString()); } - + private void writeString(string format, string a, string b) { writeString(string.Format(format, a, b)); @@ -1362,8 +1683,29 @@ private void writeString(string format, string a, string b, string c) } private void writeString(string value) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + byte[] sendBytes = System.Text.Encoding.UTF8.GetBytes(value); +After: + var sendBytes = System.Text.Encoding.UTF8.GetBytes(value); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: byte[] sendBytes = System.Text.Encoding.UTF8.GetBytes(value); +After: + var sendBytes = System.Text.Encoding.UTF8.GetBytes(value); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + byte[] sendBytes = System.Text.Encoding.UTF8.GetBytes(value); +After: + var sendBytes = System.Text.Encoding.UTF8.GetBytes(value); +*/ + + { + var sendBytes = System.Text.Encoding.UTF8.GetBytes(value); bw.Write(sendBytes, 0, sendBytes.Length); } @@ -1378,8 +1720,29 @@ private void sendProto(byte[] value, int length) // Generate a connect protocol message, issuing user/password if // applicable. The lock is assumed to be held upon entering. private string connectProto() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string u = url.UserInfo; +After: + var u = url.UserInfo; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string u = url.UserInfo; +After: + var u = url.UserInfo; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string u = url.UserInfo; +After: + var u = url.UserInfo; +*/ + + { + var u = url.UserInfo; string user = null; string pass = null; string token = null; @@ -1387,8 +1750,29 @@ private string connectProto() string sig = null; if (!string.IsNullOrEmpty(u)) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: int at = u.IndexOf(':'); +After: + var at = u.IndexOf(':'); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int at = u.IndexOf(':'); +After: + var at = u.IndexOf(':'); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int at = u.IndexOf(':'); +After: + var at = u.IndexOf(':'); +*/ + + { + var at = u.IndexOf(':'); if (at == -1) { token = Uri.UnescapeDataString(u); @@ -1433,13 +1817,14 @@ private string connectProto() { if (opts.UserSignatureEventHandler == null) { - if (userJWT == null) { + if (userJWT == null) + { throw new NATSConnectionException("Nkey defined without a user signature event handler"); } throw new NATSConnectionException("User signature event handle has not been been defined."); } - var args = new UserSignatureEventArgs(Encoding.ASCII.GetBytes(this.serverInfo.Nonce)); + var args = new UserSignatureEventArgs(Encoding.ASCII.GetBytes(serverInfo.Nonce)); try { opts.UserSignatureEventHandler(this, args); @@ -1452,10 +1837,31 @@ private string connectProto() if (args.SignedNonce == null) throw new NATSConnectionException("Signature Event Handler did not set the SignedNonce."); - sig = NaCl.CryptoBytes.ToBase64String(args.SignedNonce); - } + sig = NaCl.CryptoBytes.ToBase64String(args.SignedNonce); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + ConnectInfo info = new ConnectInfo(opts.Verbose, opts.Pedantic, userJWT, nkey, sig, user, +After: + var info = new ConnectInfo(opts.Verbose, opts.Pedantic, userJWT, nkey, sig, user, +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + ConnectInfo info = new ConnectInfo(opts.Verbose, opts.Pedantic, userJWT, nkey, sig, user, +After: + var info = new ConnectInfo(opts.Verbose, opts.Pedantic, userJWT, nkey, sig, user, +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: ConnectInfo info = new ConnectInfo(opts.Verbose, opts.Pedantic, userJWT, nkey, sig, user, +After: + var info = new ConnectInfo(opts.Verbose, opts.Pedantic, userJWT, nkey, sig, user, +*/ + + } + + var info = new ConnectInfo(opts.Verbose, opts.Pedantic, userJWT, nkey, sig, user, pass, token, opts.Secure, opts.Name, !opts.NoEcho); if (opts.NoEcho && info.protocol < 1) @@ -1469,8 +1875,29 @@ private string connectProto() // caller must lock. private void sendConnect() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string protocolMsg = connectProto(); +After: + var protocolMsg = connectProto(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string protocolMsg = connectProto(); +After: + var protocolMsg = connectProto(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string protocolMsg = connectProto(); +After: + var protocolMsg = connectProto(); +*/ + + { + var protocolMsg = connectProto(); try { writeString(protocolMsg); @@ -1578,8 +2005,29 @@ private void processReconnect() pending = new MemoryStream(); bw = new BufferedStream(pending); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Thread t = new Thread(() => +After: + var t = new Thread(() => +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Thread t = new Thread(() => +After: + var t = new Thread(() => +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: Thread t = new Thread(() => +After: + var t = new Thread(() => +*/ + + + var t = new Thread(() => { doReconnect(); }); @@ -1629,9 +2077,30 @@ private static void sleep(int millis) // if non-null. // Caller must lock. private void scheduleConnEvent(EventHandler connEvent, Exception error = null) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + EventHandler eh = connEvent; +After: + var eh = connEvent; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + EventHandler eh = connEvent; +After: + var eh = connEvent; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + EventHandler eh = connEvent; +After: + var eh = connEvent; +*/ + { // Schedule a reference to the event handler. - EventHandler eh = connEvent; + var eh = connEvent; if (eh != null) { callbackScheduler.Add( @@ -1641,8 +2110,29 @@ private void scheduleConnEvent(EventHandler connEvent, Exception } private void DefaultReconnectDelayHandler(object o, ReconnectDelayEventArgs args) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int jitter = srvProvider.HasSecureServer() ? random.Next(opts.ReconnectJitterTLS) : random.Next(opts.ReconnectJitter); +After: + var jitter = srvProvider.HasSecureServer() ? random.Next(opts.ReconnectJitterTLS) : random.Next(opts.ReconnectJitter); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: int jitter = srvProvider.HasSecureServer() ? random.Next(opts.ReconnectJitterTLS) : random.Next(opts.ReconnectJitter); +After: + var jitter = srvProvider.HasSecureServer() ? random.Next(opts.ReconnectJitterTLS) : random.Next(opts.ReconnectJitter); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int jitter = srvProvider.HasSecureServer() ? random.Next(opts.ReconnectJitterTLS) : random.Next(opts.ReconnectJitter); +After: + var jitter = srvProvider.HasSecureServer() ? random.Next(opts.ReconnectJitterTLS) : random.Next(opts.ReconnectJitter); +*/ + + { + var jitter = srvProvider.HasSecureServer() ? random.Next(opts.ReconnectJitterTLS) : random.Next(opts.ReconnectJitter); Thread.Sleep(opts.ReconnectWait + jitter); } @@ -1677,8 +2167,35 @@ private void doReconnect() scheduleConnEvent(Opts.DisconnectedEventHandlerOrDefault, errorForHandler); Srv cur; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: int timesAllServersSeen = 0; bool doSleep = false; +After: + var timesAllServersSeen = 0; + var doSleep = false; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int timesAllServersSeen = 0; + bool doSleep = false; +After: + var timesAllServersSeen = 0; + var doSleep = false; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int timesAllServersSeen = 0; + bool doSleep = false; +After: + var timesAllServersSeen = 0; + var doSleep = false; +*/ + + var timesAllServersSeen = 0; + var doSleep = false; Srv first = null; while ((cur = srvProvider.SelectNextServer(Opts.MaxReconnect)) != null) { @@ -1725,7 +2242,7 @@ private void doReconnect() try { // try to create a new connection - if(!createConn(cur, out lastEx)) + if (!createConn(cur, out lastEx)) continue; } catch (Exception) @@ -1803,7 +2320,7 @@ private void doReconnect() } finally { - if(lockWasTaken) + if (lockWasTaken) Monitor.Exit(mu); } } @@ -1814,8 +2331,29 @@ private bool isConnecting() } private void processOpError(Exception e) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: bool disconnected = false; +After: + var disconnected = false; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + bool disconnected = false; +After: + var disconnected = false; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + bool disconnected = false; +After: + var disconnected = false; +*/ + + { + var disconnected = false; lock (mu) { @@ -1843,9 +2381,30 @@ private void processOpError(Exception e) } private void readLoop() +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + byte[] buffer = new byte[defaultReadLength]; +After: + var buffer = new byte[defaultReadLength]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + byte[] buffer = new byte[defaultReadLength]; +After: + var buffer = new byte[defaultReadLength]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + byte[] buffer = new byte[defaultReadLength]; +After: + var buffer = new byte[defaultReadLength]; +*/ + { // Stack based buffer. - byte[] buffer = new byte[defaultReadLength]; + var buffer = new byte[defaultReadLength]; var parser = new Parser(this); int len; @@ -1893,17 +2452,59 @@ internal void deliverMsgs(Channel ch) lock (mu) { batchSize = opts.subscriptionBatchSize; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Msg[] mm = new Msg[batchSize]; +After: + var mm = new Msg[batchSize]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Msg[] mm = new Msg[batchSize]; +After: + var mm = new Msg[batchSize]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Msg[] mm = new Msg[batchSize]; +After: + var mm = new Msg[batchSize]; +*/ + } // dispatch buffer - Msg[] mm = new Msg[batchSize]; + var mm = new Msg[batchSize]; while (true) { if (isClosed()) return; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int delivered = ch.get(-1, mm); +After: + var delivered = ch.get(-1, mm); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int delivered = ch.get(-1, mm); +After: + var delivered = ch.get(-1, mm); +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int delivered = ch.get(-1, mm); +After: + var delivered = ch.get(-1, mm); +*/ + + + var delivered = ch.get(-1, mm); if (delivered == 0) { // the channel has been closed, exit silently. @@ -1912,9 +2513,30 @@ internal void deliverMsgs(Channel ch) // Note, this seems odd message having the sub process itself, // but this is good for performance. - for (int ii = 0; ii < delivered; ++ii) - { + for (var ii = 0; ii < delivered; ++ii) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Msg m = mm[ii]; +After: + var m = mm[ii]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: Msg m = mm[ii]; +After: + var m = mm[ii]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Msg m = mm[ii]; +After: + var m = mm[ii]; +*/ + + { + var m = mm[ii]; mm[ii] = null; // do not hold onto the Msg any longer than we need to if (!m.sub.processMsg(m)) { @@ -1935,13 +2557,52 @@ internal void deliverMsgs(Channel ch) // just copy the chars into bytes. This increased // publish peformance by 30% as compared to Encoding. private int writeStringToBuffer(byte[] buffer, int offset, string value) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int length = value.Length; + int end = offset + length; + + for (int i = 0; i < length; i++) +After: + var length = value.Length; + var end = offset + length; + + for (var i = 0; i < length; i++) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int length = value.Length; + int end = offset + length; + + for (int i = 0; i < length; i++) +After: + var length = value.Length; + var end = offset + length; + + for (var i = 0; i < length; i++) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int length = value.Length; int end = offset + length; for (int i = 0; i < length; i++) +After: + var length = value.Length; + var end = offset + length; + + for (var i = 0; i < length; i++) +*/ + + { + var length = value.Length; + var end = offset + length; + + for (var i = 0; i < length; i++) { - buffer[i+offset] = (byte)value[i]; + buffer[i + offset] = (byte)value[i]; } return end; @@ -2041,28 +2702,130 @@ private int writeInt32ToBuffer(byte[] buffer, int offset, int value) const int radix_cube = radix * radix * radix; if (value >= 10) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int v = value; +After: + var v = value; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int v = value; +After: + var v = value; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int v = value; +After: + var v = value; +*/ + { // calculate Log10 to get the digit count (via Log2 and bit tricks) - int v = value; + var v = value; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: int lg2 = MultiplyDeBruijnBitPosition[(uint)(v * 0x07C4ACDD) >> 27]; int t = (lg2 + 1) * 1233 >> 12; int lg10 = t - (value < PowersOf10[t] ? 1 : 0) + 1; +After: + var lg2 = MultiplyDeBruijnBitPosition[(uint)(v * 0x07C4ACDD) >> 27]; + var t = (lg2 + 1) * 1233 >> 12; + var lg10 = t - (value < PowersOf10[t] ? 1 : 0) + 1; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int lg2 = MultiplyDeBruijnBitPosition[(uint)(v * 0x07C4ACDD) >> 27]; + int t = (lg2 + 1) * 1233 >> 12; + int lg10 = t - (value < PowersOf10[t] ? 1 : 0) + 1; +After: + var lg2 = MultiplyDeBruijnBitPosition[(uint)(v * 0x07C4ACDD) >> 27]; + var t = (lg2 + 1) * 1233 >> 12; + var lg10 = t - (value < PowersOf10[t] ? 1 : 0) + 1; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int lg2 = MultiplyDeBruijnBitPosition[(uint)(v * 0x07C4ACDD) >> 27]; + int t = (lg2 + 1) * 1233 >> 12; + int lg10 = t - (value < PowersOf10[t] ? 1 : 0) + 1; +After: + var lg2 = MultiplyDeBruijnBitPosition[(uint)(v * 0x07C4ACDD) >> 27]; + var t = (lg2 + 1) * 1233 >> 12; + var lg10 = t - (value < PowersOf10[t] ? 1 : 0) + 1; +*/ + + var lg2 = MultiplyDeBruijnBitPosition[(uint)(v * 0x07C4ACDD) >> 27]; + var t = (lg2 + 1) * 1233 >> 12; + var lg10 = t - (value < PowersOf10[t] ? 1 : 0) + 1; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int itr = offset + lg10; +After: + var itr = offset + lg10; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int itr = offset + lg10; +After: + var itr = offset + lg10; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int itr = offset + lg10; +After: + var itr = offset + lg10; +*/ + // once we have the count of digits, start from the end of the output // number in the buffer - int itr = offset + lg10; + var itr = offset + lg10; while (value >= radix_sqr) { itr -= 3; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int temp_v = value / radix_cube; + int temp_off = 3 * (value - (temp_v * radix_cube)); +After: + var temp_v = value / radix_cube; + var temp_off = 3 * (value - (temp_v * radix_cube)); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: int temp_v = value / radix_cube; int temp_off = 3 * (value - (temp_v * radix_cube)); - buffer[itr] = rev_3digit_lut[temp_off]; +After: + var temp_v = value / radix_cube; + var temp_off = 3 * (value - (temp_v * radix_cube)); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int temp_v = value / radix_cube; + int temp_off = 3 * (value - (temp_v * radix_cube)); +After: + var temp_v = value / radix_cube; + var temp_off = 3 * (value - (temp_v * radix_cube)); +*/ + + var temp_v = value / radix_cube; + var temp_off = 3 * (value - (temp_v * radix_cube)); + buffer[itr] = rev_3digit_lut[temp_off]; buffer[itr + 1] = rev_3digit_lut[temp_off + 1]; buffer[itr + 2] = rev_3digit_lut[temp_off + 2]; value = temp_v; @@ -2071,15 +2834,42 @@ private int writeInt32ToBuffer(byte[] buffer, int offset, int value) while (value >= radix) { itr -= 2; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: int temp_v = value / radix_sqr; int temp_off = 2 * (value - (temp_v * radix_sqr)); - buffer[itr] = rev_2digit_lut[temp_off]; - buffer[itr + 1] = rev_2digit_lut[temp_off + 1]; - value = temp_v; - } +After: + var temp_v = value / radix_sqr; + var temp_off = 2 * (value - (temp_v * radix_sqr)); +*/ - if (value != 0) - { +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int temp_v = value / radix_sqr; + int temp_off = 2 * (value - (temp_v * radix_sqr)); +After: + var temp_v = value / radix_sqr; + var temp_off = 2 * (value - (temp_v * radix_sqr)); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int temp_v = value / radix_sqr; + int temp_off = 2 * (value - (temp_v * radix_sqr)); +After: + var temp_v = value / radix_sqr; + var temp_off = 2 * (value - (temp_v * radix_sqr)); +*/ + + var temp_v = value / radix_sqr; + var temp_off = 2 * (value - (temp_v * radix_sqr)); + buffer[itr] = rev_2digit_lut[temp_off]; + buffer[itr + 1] = rev_2digit_lut[temp_off + 1]; + value = temp_v; + } + + if (value != 0) + { buffer[--itr] = (byte)('0' + value); } @@ -2102,13 +2892,40 @@ private int setMsgArgsAryOffsets(byte[] buffer, long length) if (convertToStrBuf.Length < length) { convertToStrBuf = new char[length]; - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int count = 0; + int i = 0; +After: + var count = 0; + var i = 0; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int count = 0; + int i = 0; +After: + var count = 0; + var i = 0; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int count = 0; int i = 0; +After: + var count = 0; + var i = 0; +*/ + + } + + var count = 0; + var i = 0; // We support up to 5 elements in this protocol version - for ( ; i < length && count < 5; i++) + for (; i < length && count < 5; i++) { convertToStrBuf[i] = (char)buffer[i]; if (buffer[i] == ' ') @@ -2130,27 +2947,48 @@ private int setMsgArgsAryOffsets(byte[] buffer, long length) // // These strings, once created, are never copied. internal void processHeaderMsgArgs(byte[] buffer, long length) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int argCount = setMsgArgsAryOffsets(buffer, length); +After: + var argCount = setMsgArgsAryOffsets(buffer, length); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int argCount = setMsgArgsAryOffsets(buffer, length); +After: + var argCount = setMsgArgsAryOffsets(buffer, length); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int argCount = setMsgArgsAryOffsets(buffer, length); +After: + var argCount = setMsgArgsAryOffsets(buffer, length); +*/ + + { + var argCount = setMsgArgsAryOffsets(buffer, length); switch (argCount) { - case 4: - msgArgs.subject = new string(convertToStrBuf, 0, argEnds[0]); - msgArgs.sid = ToInt64(buffer, argEnds[0] + 1, argEnds[1]); - msgArgs.reply = null; - msgArgs.hdr = (int)ToInt64(buffer, argEnds[1] + 1, argEnds[2]); - msgArgs.size = (int)ToInt64(buffer, argEnds[2] + 1, argEnds[3]); - break; - case 5: - msgArgs.subject = new string(convertToStrBuf, 0, argEnds[0]); - msgArgs.sid = ToInt64(buffer, argEnds[0] + 1, argEnds[1]); - msgArgs.reply = new string(convertToStrBuf, argEnds[1] + 1, argEnds[2] - argEnds[1] - 1); - msgArgs.hdr = (int)ToInt64(buffer, argEnds[2] + 1, argEnds[3]); - msgArgs.size = (int)ToInt64(buffer, argEnds[3] + 1, argEnds[4]); - break; - default: - throw new NATSException("Unable to parse message arguments: " + Encoding.UTF8.GetString(buffer, 0, (int)length)); + case 4: + msgArgs.subject = new string(convertToStrBuf, 0, argEnds[0]); + msgArgs.sid = ToInt64(buffer, argEnds[0] + 1, argEnds[1]); + msgArgs.reply = null; + msgArgs.hdr = (int)ToInt64(buffer, argEnds[1] + 1, argEnds[2]); + msgArgs.size = (int)ToInt64(buffer, argEnds[2] + 1, argEnds[3]); + break; + case 5: + msgArgs.subject = new string(convertToStrBuf, 0, argEnds[0]); + msgArgs.sid = ToInt64(buffer, argEnds[0] + 1, argEnds[1]); + msgArgs.reply = new string(convertToStrBuf, argEnds[1] + 1, argEnds[2] - argEnds[1] - 1); + msgArgs.hdr = (int)ToInt64(buffer, argEnds[2] + 1, argEnds[3]); + msgArgs.size = (int)ToInt64(buffer, argEnds[3] + 1, argEnds[4]); + break; + default: + throw new NATSException("Unable to parse message arguments: " + Encoding.UTF8.GetString(buffer, 0, (int)length)); } if (msgArgs.size < 0) @@ -2169,26 +3007,47 @@ internal void processHeaderMsgArgs(byte[] buffer, long length) // Same as above, except when we know there is no header. internal void processMsgArgs(byte[] buffer, long length) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int argCount = setMsgArgsAryOffsets(buffer, length); +After: + var argCount = setMsgArgsAryOffsets(buffer, length); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: int argCount = setMsgArgsAryOffsets(buffer, length); +After: + var argCount = setMsgArgsAryOffsets(buffer, length); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int argCount = setMsgArgsAryOffsets(buffer, length); +After: + var argCount = setMsgArgsAryOffsets(buffer, length); +*/ + + { + var argCount = setMsgArgsAryOffsets(buffer, length); msgArgs.hdr = 0; switch (argCount) { - case 3: - msgArgs.subject = new string(convertToStrBuf, 0, argEnds[0]); - msgArgs.sid = ToInt64(buffer, argEnds[0] + 1, argEnds[1]); - msgArgs.reply = null; - msgArgs.size = (int)ToInt64(buffer, argEnds[1] + 1, argEnds[2]); - break; - case 4: - msgArgs.subject = new string(convertToStrBuf, 0, argEnds[0]); - msgArgs.sid = ToInt64(buffer, argEnds[0] + 1, argEnds[1]); - msgArgs.reply = new string(convertToStrBuf, argEnds[1] + 1, argEnds[2] - argEnds[1] - 1); - msgArgs.size = (int)ToInt64(buffer, argEnds[2] + 1, argEnds[3]); - break; - default: - throw new NATSException("Unable to parse message arguments: " + Encoding.UTF8.GetString(buffer, 0, (int)length)); + case 3: + msgArgs.subject = new string(convertToStrBuf, 0, argEnds[0]); + msgArgs.sid = ToInt64(buffer, argEnds[0] + 1, argEnds[1]); + msgArgs.reply = null; + msgArgs.size = (int)ToInt64(buffer, argEnds[1] + 1, argEnds[2]); + break; + case 4: + msgArgs.subject = new string(convertToStrBuf, 0, argEnds[0]); + msgArgs.sid = ToInt64(buffer, argEnds[0] + 1, argEnds[1]); + msgArgs.reply = new string(convertToStrBuf, argEnds[1] + 1, argEnds[2] - argEnds[1] - 1); + msgArgs.size = (int)ToInt64(buffer, argEnds[2] + 1, argEnds[3]); + break; + default: + throw new NATSException("Unable to parse message arguments: " + Encoding.UTF8.GetString(buffer, 0, (int)length)); } if (msgArgs.size < 0) @@ -2204,48 +3063,111 @@ internal void processMsgArgs(byte[] buffer, long length) // A simple ToInt64. // Assumes: positive integers. static long ToInt64(byte[] buffer, int start, int end) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int length = end - start; +After: + var length = end - start; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int length = end - start; +After: + var length = end - start; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int length = end - start; +After: + var length = end - start; +*/ + + { + var length = end - start; switch (length) { - case 0: - return 0; - case 1: - return buffer[start] - '0'; - case 2: - return 10 * (buffer[start] - '0') - + (buffer[start + 1] - '0'); - case 3: - return 100 * (buffer[start] - '0') - + 10 * (buffer[start + 1] - '0') - + (buffer[start + 2] - '0'); - case 4: - return 1000 * (buffer[start] - '0') - + 100 * (buffer[start + 1] - '0') - + 10 * (buffer[start + 2] - '0') - + (buffer[start + 3] - '0'); - case 5: - return 10000 * (buffer[start] - '0') - + 1000 * (buffer[start + 1] - '0') - + 100 * (buffer[start + 2] - '0') - + 10 * (buffer[start + 3] - '0') - + (buffer[start + 4] - '0'); - case 6: - return 100000 * (buffer[start] - '0') - + 10000 * (buffer[start + 1] - '0') - + 1000 * (buffer[start + 2] - '0') - + 100 * (buffer[start + 3] - '0') - + 10 * (buffer[start + 4] - '0') - + (buffer[start + 5] - '0'); - default: - if (length < 0) - throw new ArgumentOutOfRangeException("end"); - break; - } + case 0: + return 0; + case 1: + return buffer[start] - '0'; + case 2: + return 10 * (buffer[start] - '0') + + (buffer[start + 1] - '0'); + case 3: + return 100 * (buffer[start] - '0') + + 10 * (buffer[start + 1] - '0') + + (buffer[start + 2] - '0'); + case 4: + return 1000 * (buffer[start] - '0') + + 100 * (buffer[start + 1] - '0') + + 10 * (buffer[start + 2] - '0') + + (buffer[start + 3] - '0'); + case 5: + return 10000 * (buffer[start] - '0') + + 1000 * (buffer[start + 1] - '0') + + 100 * (buffer[start + 2] - '0') + + 10 * (buffer[start + 3] - '0') + + (buffer[start + 4] - '0'); + case 6: + return 100000 * (buffer[start] - '0') + + 10000 * (buffer[start + 1] - '0') + + 1000 * (buffer[start + 2] - '0') + + 100 * (buffer[start + 3] - '0') + + 10 * (buffer[start + 4] - '0') + + (buffer[start + 5] - '0'); + default: + if (length < 0) + throw new ArgumentOutOfRangeException("end"); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + long value = 0L; +After: + var value = 0L; +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: long value = 0L; +After: + var value = 0L; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + long value = 0L; +After: + var value = 0L; +*/ + + break; + } + + var value = 0L; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int i = start; +After: + var i = start; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int i = start; +After: + var i = start; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int i = start; +After: + var i = start; +*/ + + + var i = start; while (i < end) { value *= 10L; @@ -2261,8 +3183,29 @@ static long ToInt64(byte[] buffer, int start, int end) // their own channel. If the channel is full, the connection is // considered a slow subscriber. internal void processMsg(byte[] msgBytes, long length) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + bool maxReached = false; +After: + var maxReached = false; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + bool maxReached = false; +After: + var maxReached = false; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: bool maxReached = false; +After: + var maxReached = false; +*/ + + { + var maxReached = false; Subscription s; lock (mu) @@ -2277,8 +3220,29 @@ internal void processMsg(byte[] msgBytes, long length) { maxReached = s.tallyMessage(length); if (maxReached == false) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Msg msg = msgArgs.reply != null && msgArgs.reply.StartsWith(JetStreamConstants.JsAckSubjectPrefix) +After: + var msg = msgArgs.reply != null && msgArgs.reply.StartsWith(JetStreamConstants.JsAckSubjectPrefix) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: Msg msg = msgArgs.reply != null && msgArgs.reply.StartsWith(JetStreamConstants.JsAckSubjectPrefix) +After: + var msg = msgArgs.reply != null && msgArgs.reply.StartsWith(JetStreamConstants.JsAckSubjectPrefix) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Msg msg = msgArgs.reply != null && msgArgs.reply.StartsWith(JetStreamConstants.JsAckSubjectPrefix) +After: + var msg = msgArgs.reply != null && msgArgs.reply.StartsWith(JetStreamConstants.JsAckSubjectPrefix) +*/ + + { + var msg = msgArgs.reply != null && msgArgs.reply.StartsWith(JetStreamConstants.JsAckSubjectPrefix) ? new JetStreamMsg(this, msgArgs, s, msgBytes, length) : new Msg(msgArgs, s, msgBytes, length); @@ -2371,8 +3335,29 @@ private void flusher() } while (!isFlusherDone()) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + bool val = waitForFlusherKick(); +After: + var val = waitForFlusherKick(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + bool val = waitForFlusherKick(); +After: + var val = waitForFlusherKick(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: bool val = waitForFlusherKick(); +After: + var val = waitForFlusherKick(); +*/ + + { + var val = waitForFlusherKick(); if (val == false) return; @@ -2407,7 +3392,7 @@ internal void processPing() // processPong is used to process responses to the client's ping // messages. We use pings for the flush mechanism as well. internal void processPong() - { + { if (pongs.TryDequeue(out var ch)) ch?.add(true); @@ -2461,15 +3446,36 @@ public Exception LastError { get { - return this.lastEx; + return lastEx; } } // processErr processes any error messages from the server and // sets the connection's lastError. internal void processErr(MemoryStream errorStream) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string normalizedErrorText = getNormalizedError(errorStream); +After: + var normalizedErrorText = getNormalizedError(errorStream); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string normalizedErrorText = getNormalizedError(errorStream); +After: + var normalizedErrorText = getNormalizedError(errorStream); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string normalizedErrorText = getNormalizedError(errorStream); +After: + var normalizedErrorText = getNormalizedError(errorStream); +*/ + + { + var normalizedErrorText = getNormalizedError(errorStream); if (IC.STALE_CONNECTION.Equals(normalizedErrorText)) { @@ -2481,12 +3487,39 @@ internal void processErr(MemoryStream errorStream) // is handled before the connection close from the server. // This can happen in reconnect scenarios. processOpError(new NATSConnectionException(IC.AUTH_TIMEOUT)); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + NATSException ex = new NATSException("Error from processErr(): " + normalizedErrorText); + bool invokeDelegates = false; +After: + var ex = new NATSException("Error from processErr(): " + normalizedErrorText); + var invokeDelegates = false; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + NATSException ex = new NATSException("Error from processErr(): " + normalizedErrorText); + bool invokeDelegates = false; +After: + var ex = new NATSException("Error from processErr(): " + normalizedErrorText); + var invokeDelegates = false; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + NATSException ex = new NATSException("Error from processErr(): " + normalizedErrorText); + bool invokeDelegates = false; +After: + var ex = new NATSException("Error from processErr(): " + normalizedErrorText); + var invokeDelegates = false; +*/ + } else { - NATSException ex = new NATSException("Error from processErr(): " + normalizedErrorText); - bool invokeDelegates = false; - + var ex = new NATSException("Error from processErr(): " + normalizedErrorText); + var invokeDelegates = false; + lock (mu) { lastEx = ex; @@ -2494,10 +3527,31 @@ internal void processErr(MemoryStream errorStream) if (status != ConnState.CONNECTING) { invokeDelegates = true; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + bool authAuthError = NATSException.IsAuthenticationOrAuthorizationError(normalizedErrorText); +After: + var authAuthError = NATSException.IsAuthenticationOrAuthorizationError(normalizedErrorText); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + bool authAuthError = NATSException.IsAuthenticationOrAuthorizationError(normalizedErrorText); +After: + var authAuthError = NATSException.IsAuthenticationOrAuthorizationError(normalizedErrorText); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + bool authAuthError = NATSException.IsAuthenticationOrAuthorizationError(normalizedErrorText); +After: + var authAuthError = NATSException.IsAuthenticationOrAuthorizationError(normalizedErrorText); +*/ + } } - bool authAuthError = NATSException.IsAuthenticationOrAuthorizationError(normalizedErrorText); + var authAuthError = NATSException.IsAuthenticationOrAuthorizationError(normalizedErrorText); close(ConnState.CLOSED, invokeDelegates, ex, authAuthError); if (authAuthError) @@ -2510,8 +3564,29 @@ internal void processErr(MemoryStream errorStream) // getNormalizedError extracts a string from a MemoryStream, then normalizes it // by removing leading and trailing spaces and quotes, and converting to lowercase private string getNormalizedError(MemoryStream errorStream) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string s = Encoding.UTF8.GetString(errorStream.ToArray(), 0, (int)errorStream.Position); +After: + var s = Encoding.UTF8.GetString(errorStream.ToArray(), 0, (int)errorStream.Position); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string s = Encoding.UTF8.GetString(errorStream.ToArray(), 0, (int)errorStream.Position); +After: + var s = Encoding.UTF8.GetString(errorStream.ToArray(), 0, (int)errorStream.Position); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string s = Encoding.UTF8.GetString(errorStream.ToArray(), 0, (int)errorStream.Position); +After: + var s = Encoding.UTF8.GetString(errorStream.ToArray(), 0, (int)errorStream.Position); +*/ + + { + var s = Encoding.UTF8.GetString(errorStream.ToArray(), 0, (int)errorStream.Position); return s.Trim('\'', '"', ' ', '\t', '\r', '\n').ToLower(); } @@ -2525,9 +3600,30 @@ private string getNormalizedError(MemoryStream errorStream) // HPUB SUBJECT REPLY 23 23␍␊NATS/1.0␍␊Header: X␍␊␍␊␍␊ private void WriteHPUBProto(byte[] dst, string subject, string reply, int headerSize, int msgSize, out int length, out int offset) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int index = HPUB_P_BYTES_LEN; +After: + var index = HPUB_P_BYTES_LEN; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int index = HPUB_P_BYTES_LEN; +After: + var index = HPUB_P_BYTES_LEN; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int index = HPUB_P_BYTES_LEN; +After: + var index = HPUB_P_BYTES_LEN; +*/ + { // skip past the predefined "HPUB " - int index = HPUB_P_BYTES_LEN; + var index = HPUB_P_BYTES_LEN; // Subject index = writeStringToBuffer(dst, index, subject); @@ -2549,14 +3645,14 @@ private void WriteHPUBProto(byte[] dst, string subject, string reply, int header // " TOTALSIZE" dst[index] = (byte)' '; index++; - index = writeInt32ToBuffer(dst, index, msgSize+headerSize); + index = writeInt32ToBuffer(dst, index, msgSize + headerSize); // "\r\n" dst[index] = CRLF_BYTES[0]; dst[index + 1] = CRLF_BYTES[1]; if (CRLF_BYTES_LEN > 2) { - for (int i = 2; i < CRLF_BYTES_LEN; ++i) + for (var i = 2; i < CRLF_BYTES_LEN; ++i) dst[index + i] = CRLF_BYTES[i]; } index += CRLF_BYTES_LEN; @@ -2573,9 +3669,30 @@ private void WriteHPUBProto(byte[] dst, string subject, string reply, int header // and length so the future write will ignore the H. private void WritePUBProto(byte[] dst, string subject, string reply, int msgSize, out int length, out int offset) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int index = HPUB_P_BYTES_LEN; +After: + var index = HPUB_P_BYTES_LEN; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int index = HPUB_P_BYTES_LEN; +After: + var index = HPUB_P_BYTES_LEN; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int index = HPUB_P_BYTES_LEN; +After: + var index = HPUB_P_BYTES_LEN; +*/ + { // skip past the predefined "HPUB " - int index = HPUB_P_BYTES_LEN; + var index = HPUB_P_BYTES_LEN; // Subject index = writeStringToBuffer(dst, index, subject); @@ -2601,12 +3718,12 @@ private void WritePUBProto(byte[] dst, string subject, string reply, int msgSize dst[index + 1] = CRLF_BYTES[1]; if (CRLF_BYTES_LEN > 2) { - for (int i = 2; i < CRLF_BYTES_LEN; ++i) + for (var i = 2; i < CRLF_BYTES_LEN; ++i) dst[index + i] = CRLF_BYTES[i]; } index += CRLF_BYTES_LEN; - length = index-1; + length = index - 1; offset = 1; } @@ -2618,8 +3735,50 @@ internal void PublishImpl(string subject, string reply, MsgHeader inHeaders, byt if (string.IsNullOrWhiteSpace(subject)) { throw new NATSBadSubscriptionException(); - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int count = 0; + if (data != null) + { + if (offset < 0) + { + throw new ArgumentOutOfRangeException("offset"); + } + int len = data.Length; +After: + var count = 0; + if (data != null) + { + if (offset < 0) + { + throw new ArgumentOutOfRangeException("offset"); + } + var len = data.Length; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int count = 0; + if (data != null) + { + if (offset < 0) + { + throw new ArgumentOutOfRangeException("offset"); + } + int len = data.Length; +After: + var count = 0; + if (data != null) + { + if (offset < 0) + { + throw new ArgumentOutOfRangeException("offset"); + } + var len = data.Length; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int count = 0; if (data != null) { @@ -2628,7 +3787,28 @@ internal void PublishImpl(string subject, string reply, MsgHeader inHeaders, byt throw new ArgumentOutOfRangeException("offset"); } int len = data.Length; - count = inCount ?? len; +After: + var count = 0; + if (data != null) + { + if (offset < 0) + { + throw new ArgumentOutOfRangeException("offset"); + } + var len = data.Length; +*/ + + } + + var count = 0; + if (data != null) + { + if (offset < 0) + { + throw new ArgumentOutOfRangeException("offset"); + } + var len = data.Length; + count = inCount ?? len; if (count < 0) { throw new ArgumentOutOfRangeException("count"); @@ -2662,7 +3842,7 @@ internal void PublishImpl(string subject, string reply, MsgHeader inHeaders, byt { throw new NATSMaxPayloadException(); } - + if (lastEx != null) throw lastEx; @@ -2686,8 +3866,29 @@ internal void PublishImpl(string subject, string reply, MsgHeader inHeaders, byt // we have exceeded our reconnect outbound buffer limits. // Don't use IsReconnecting to avoid locking. if (status == ConnState.RECONNECTING) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: int rbsize = opts.ReconnectBufferSize; +After: + var rbsize = opts.ReconnectBufferSize; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int rbsize = opts.ReconnectBufferSize; +After: + var rbsize = opts.ReconnectBufferSize; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int rbsize = opts.ReconnectBufferSize; +After: + var rbsize = opts.ReconnectBufferSize; +*/ + + { + var rbsize = opts.ReconnectBufferSize; if (rbsize != 0) { if (rbsize == -1) @@ -2732,7 +3933,7 @@ internal void PublishImpl(string subject, string reply, MsgHeader inHeaders, byt } } // publish - + /// /// Publishes to the given . /// @@ -2957,8 +4158,29 @@ private void RequestResponseHandler(object sender, MsgHandlerEventArgs args) // We have a jetstream subject (remapped), so if there's only one // request assume we're OK and handle it. if (waitingRequests.Count == 1) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: InFlightRequest[] values = new InFlightRequest[1]; +After: + var values = new InFlightRequest[1]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + InFlightRequest[] values = new InFlightRequest[1]; +After: + var values = new InFlightRequest[1]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + InFlightRequest[] values = new InFlightRequest[1]; +After: + var values = new InFlightRequest[1]; +*/ + + { + var values = new InFlightRequest[1]; waitingRequests.Values.CopyTo(values, 0); request = values[0]; @@ -3022,7 +4244,7 @@ internal Msg RequestSyncImpl(string subject, MsgHeader headers, byte[] data, int { if (string.IsNullOrWhiteSpace(subject)) throw new NATSBadSubscriptionException(); - + // a timeout of 0 will never succeed - do not allow it. if (timeout == 0) throw new ArgumentException("Timeout must not be 0.", nameof(timeout)); @@ -3447,17 +4669,60 @@ private Task OldRequestAsyncImpl(string subject, MsgHeader headers, byte[] ct.ThrowIfCancellationRequested(); Msg m = null; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string inbox = NewInbox(); +After: + var inbox = NewInbox(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string inbox = NewInbox(); +After: + var inbox = NewInbox(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string inbox = NewInbox(); +After: + var inbox = NewInbox(); +*/ + + var inbox = NewInbox(); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + SyncSubscription s = subscribeSync(inbox, null); +After: + var s = subscribeSync(inbox, null); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + SyncSubscription s = subscribeSync(inbox, null); +After: + var s = subscribeSync(inbox, null); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + SyncSubscription s = subscribeSync(inbox, null); +After: + var s = subscribeSync(inbox, null); +*/ + // Use synchronous subscriber to minimize overhead. // An async subscriber would be easier, but creates // yet another task internally. The cost is it could // take up to CANCEL_IVL ms to cancel. - SyncSubscription s = subscribeSync(inbox, null); + var s = subscribeSync(inbox, null); s.AutoUnsubscribe(1); PublishImpl(subject, inbox, headers, data, offset, count, true); - +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: int timeRemaining = timeout; while (m == null && ct.IsCancellationRequested == false) @@ -3475,31 +4740,147 @@ private Task OldRequestAsyncImpl(string subject, MsgHeader headers, byte[] else { int waitTime = timeRemaining < REQ_CANCEL_IVL ? - timeRemaining : REQ_CANCEL_IVL; +After: + var timeRemaining = timeout; + while (m == null && ct.IsCancellationRequested == false) + { + if (timeout == Timeout.Infinite) + { + // continue in a loop until cancellation + // is requested. try { - m = s.NextMessage(waitTime); + m = s.NextMessage(REQ_CANCEL_IVL); } - catch (NATSTimeoutException) + catch (NATSTimeoutException) { /* ignore */ }; + } + else + { + var waitTime = timeRemaining < REQ_CANCEL_IVL ? +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int timeRemaining = timeout; + + while (m == null && ct.IsCancellationRequested == false) + { + if (timeout == Timeout.Infinite) + { + // continue in a loop until cancellation + // is requested. + try { - timeRemaining -= waitTime; - if (timeRemaining <= 0) - { - s.unsubscribe(false); - throw; - } + m = s.NextMessage(REQ_CANCEL_IVL); } + catch (NATSTimeoutException) { /* ignore */ }; + } + else + { + int waitTime = timeRemaining < REQ_CANCEL_IVL ? +After: + var timeRemaining = timeout; - if (IsNoRespondersMsg(m)) + while (m == null && ct.IsCancellationRequested == false) + { + if (timeout == Timeout.Infinite) + { + // continue in a loop until cancellation + // is requested. + try { - throw new NATSNoRespondersException(); + m = s.NextMessage(REQ_CANCEL_IVL); } + catch (NATSTimeoutException) { /* ignore */ }; } - } + else + { + var waitTime = timeRemaining < REQ_CANCEL_IVL ? +*/ - // we either have a message or have been cancelled. - s.unsubscribe(false); +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int timeRemaining = timeout; + + while (m == null && ct.IsCancellationRequested == false) + { + if (timeout == Timeout.Infinite) + { + // continue in a loop until cancellation + // is requested. + try + { + m = s.NextMessage(REQ_CANCEL_IVL); + } + catch (NATSTimeoutException) { /* ignore */ }; + } + else + { + int waitTime = timeRemaining < REQ_CANCEL_IVL ? +After: + var timeRemaining = timeout; + + while (m == null && ct.IsCancellationRequested == false) + { + if (timeout == Timeout.Infinite) + { + // continue in a loop until cancellation + // is requested. + try + { + m = s.NextMessage(REQ_CANCEL_IVL); + } + catch (NATSTimeoutException) { /* ignore */ }; + } + else + { + var waitTime = timeRemaining < REQ_CANCEL_IVL ? +*/ + + + var timeRemaining = timeout; + + while (m == null && ct.IsCancellationRequested == false) + { + if (timeout == Timeout.Infinite) + { + // continue in a loop until cancellation + // is requested. + try + { + m = s.NextMessage(REQ_CANCEL_IVL); + } + catch (NATSTimeoutException) { /* ignore */ }; + } + else + { + var waitTime = timeRemaining < REQ_CANCEL_IVL ? + timeRemaining : REQ_CANCEL_IVL; + + try + { + m = s.NextMessage(waitTime); + } + catch (NATSTimeoutException) + { + timeRemaining -= waitTime; + if (timeRemaining <= 0) + { + s.unsubscribe(false); + throw; + } + } + + if (IsNoRespondersMsg(m)) + { + throw new NATSNoRespondersException(); + } + } + } + + // we either have a message or have been cancelled. + s.unsubscribe(false); // Throw if cancelled. Note, the cancellation occured // after we've received a message, go ahead and honor @@ -4233,8 +5614,29 @@ internal AsyncSubscription subscribeAsync(string subject, string queue, if (createAsyncSubscriptionDelegate == null) { createAsyncSubscriptionDelegate = (lConn, lSubject, lQueue) => - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + AsyncSubscription asub = new AsyncSubscription(lConn, lSubject, lQueue); +After: + var asub = new AsyncSubscription(lConn, lSubject, lQueue); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + AsyncSubscription asub = new AsyncSubscription(lConn, lSubject, lQueue); +After: + var asub = new AsyncSubscription(lConn, lSubject, lQueue); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: AsyncSubscription asub = new AsyncSubscription(lConn, lSubject, lQueue); +After: + var asub = new AsyncSubscription(lConn, lSubject, lQueue); +*/ + + { + var asub = new AsyncSubscription(lConn, lSubject, lQueue); asub.SetPendingLimits(opts.PendingMessageLimit, opts.PendingBytesLimit); return asub; }; @@ -4255,7 +5657,7 @@ internal AsyncSubscription subscribeAsync(string subject, string queue, // subscribe is the internal subscribe // function that indicates interest in a subject. - internal SyncSubscription subscribeSync(string subject, string queue, + internal SyncSubscription subscribeSync(string subject, string queue, CreateSyncSubscriptionDelegate syncSubDelegate = null) { if (!Subscription.IsValidSubject(subject)) @@ -4279,8 +5681,29 @@ internal SyncSubscription subscribeSync(string subject, string queue, if (syncSubDelegate == null) { syncSubDelegate = (lConn, lSubject, lQueue) => - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + SyncSubscription ssub = new SyncSubscription(this, subject, queue); +After: + var ssub = new SyncSubscription(this, subject, queue); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: SyncSubscription ssub = new SyncSubscription(this, subject, queue); +After: + var ssub = new SyncSubscription(this, subject, queue); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + SyncSubscription ssub = new SyncSubscription(this, subject, queue); +After: + var ssub = new SyncSubscription(this, subject, queue); +*/ + + { + var ssub = new SyncSubscription(this, subject, queue); ssub.SetPendingLimits(opts.PendingMessageLimit, opts.PendingBytesLimit); return ssub; }; @@ -4425,7 +5848,7 @@ public IAsyncSubscription SubscribeAsync(string subject, string queue, EventHand internal Task unsubscribe(Subscription sub, int max, bool drain, int timeout) { var task = CompletedTask.Get(); - + lock (mu) { if (isClosed()) @@ -4549,8 +5972,8 @@ public void Flush(int timeout) throw new ArgumentOutOfRangeException( "timeout", "Timeout must be greater than 0"); - } - +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: SingleUseChannel ch = SingleUseChannel.GetOrCreate(); try @@ -4616,15 +6039,26 @@ public TimeSpan RTT() } bool rv = ch.get(opts.Timeout); - sw.Stop(); +After: + var ch = SingleUseChannel.GetOrCreate(); + + try + { + lock (mu) + { + if (isClosed()) + throw new NATSConnectionClosedException(); + + sendPing(ch); + } + + var rv = ch.get(timeout); if (!rv) { throw new NATSConnectionClosedException(); } SingleUseChannel.Return(ch); - - return sw.Elapsed; } catch (Exception e) { @@ -4638,111 +6072,505 @@ public TimeSpan RTT() saveFlushException(e); throw; } - + // wrap other system exceptions - var ex = new NATSException("RTT error.", e); + var ex = new NATSException("Flush error.", e); saveFlushException(ex); throw ex; } } /// - /// Performs a round trip to the server and returns when it receives the internal reply. + /// A timespan representing the elapsed time. /// - /// The is closed. - /// A timeout occurred while sending the request or receiving the response. - /// There was an unexpected exception performing an internal NATS call while executing the - /// request. See for more details. - /// There was a failure while writing to the network. - public void Flush() + /// + /// If the connection is closed. + /// Miscellaneous other exceptions + public TimeSpan RTT() { - Flush(DEFAULT_FLUSH_TIMEOUT); - } + var sw = new Stopwatch(); + var ch = SingleUseChannel.GetOrCreate(); - /// - /// Immediately flushes the underlying connection buffer if the connection is valid. - /// - /// The is closed. - /// There was an unexpected exception performing an internal NATS call while executing the - /// request. See for more details. - public void FlushBuffer() - { - lock (mu) + try { - if (isClosed()) - throw new NATSConnectionClosedException(); + lock (mu) + { + if (isClosed()) + { + throw new NATSConnectionClosedException(); + } - if (status == ConnState.CONNECTED) - bw.Flush(); - } - } + sw.Start(); + sendPing(ch); + } - // resendSubscriptions will send our subscription state back to the - // server. Used in reconnects - private void resendSubscriptions() - { - foreach (Subscription s in subs.Values) + var rv = ch.get(opts.Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + SingleUseChannel ch = SingleUseChannel.GetOrCreate(); + + try { - if (s is IAsyncSubscription) + lock (mu) { - ((AsyncSubscription)s).enableAsyncProcessing(); + if (isClosed()) + throw new NATSConnectionClosedException(); + + sendPing(ch); } - SendSub(s.Subject, s.Queue, s.sid); + + bool rv = ch.get(timeout); + if (!rv) + { + throw new NATSConnectionClosedException(); + } + + SingleUseChannel.Return(ch); } + catch (Exception e) + { + removeFlushEntry(ch); - bw.Flush(); + // Note, don't call saveFlushException in a finally clause + // because we don't know if the caller will handle the rethrown + // exception. + if (e is NATSTimeoutException || e is NATSConnectionClosedException) + { + saveFlushException(e); + throw; + } + + // wrap other system exceptions + var ex = new NATSException("Flush error.", e); + saveFlushException(ex); + throw ex; + } } - // This will clear any pending flush calls and release pending calls. - // Lock must be held by the caller. - private void clearPendingFlushCalls() + /// + /// A timespan representing the elapsed time. + /// + /// + /// If the connection is closed. + /// Miscellaneous other exceptions + public TimeSpan RTT() { - while(pongs.TryDequeue(out var ch)) - ch?.add(true); - } - + Stopwatch sw = new Stopwatch(); + SingleUseChannel ch = SingleUseChannel.GetOrCreate(); - // Clears any in-flight requests by cancelling them all - // Caller must lock - private void clearPendingRequestCalls() - { - lock (mu) + try { - foreach (var request in waitingRequests) + lock (mu) { - request.Value.Waiter.TrySetCanceled(); + if (isClosed()) + { + throw new NATSConnectionClosedException(); + } + + sw.Start(); + sendPing(ch); } - waitingRequests.Clear(); - } - } + bool rv = ch.get(opts.Timeout); +After: + var ch = SingleUseChannel.GetOrCreate(); - // Low level close call that will do correct cleanup and set - // desired status. Also controls whether user defined callbacks - // will be triggered. The lock should not be held entering this - // function. This function will handle the locking manually. - private void close(ConnState closeState, bool invokeDelegates, Exception error, bool authAuthError) - { - lock (mu) + try { - if (isClosed()) + lock (mu) { - status = closeState; - return; + if (isClosed()) + throw new NATSConnectionClosedException(); + + sendPing(ch); } - status = ConnState.CLOSED; + var rv = ch.get(timeout); + if (!rv) + { + throw new NATSConnectionClosedException(); + } - // Kick the routines so they fall out. - // fch will be closed on finalizer - kickFlusher(); + SingleUseChannel.Return(ch); } - - lock (mu) + catch (Exception e) { - // Clear any queued pongs, e.g. pending flush calls. - clearPendingFlushCalls(); - if (pending != null) + removeFlushEntry(ch); + + // Note, don't call saveFlushException in a finally clause + // because we don't know if the caller will handle the rethrown + // exception. + if (e is NATSTimeoutException || e is NATSConnectionClosedException) + { + saveFlushException(e); + throw; + } + + // wrap other system exceptions + var ex = new NATSException("Flush error.", e); + saveFlushException(ex); + throw ex; + } + } + + /// + /// A timespan representing the elapsed time. + /// + /// + /// If the connection is closed. + /// Miscellaneous other exceptions + public TimeSpan RTT() + { + var sw = new Stopwatch(); + var ch = SingleUseChannel.GetOrCreate(); + + try + { + lock (mu) + { + if (isClosed()) + { + throw new NATSConnectionClosedException(); + } + + sw.Start(); + sendPing(ch); + } + + var rv = ch.get(opts.Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + SingleUseChannel ch = SingleUseChannel.GetOrCreate(); + + try + { + lock (mu) + { + if (isClosed()) + throw new NATSConnectionClosedException(); + + sendPing(ch); + } + + bool rv = ch.get(timeout); + if (!rv) + { + throw new NATSConnectionClosedException(); + } + + SingleUseChannel.Return(ch); + } + catch (Exception e) + { + removeFlushEntry(ch); + + // Note, don't call saveFlushException in a finally clause + // because we don't know if the caller will handle the rethrown + // exception. + if (e is NATSTimeoutException || e is NATSConnectionClosedException) + { + saveFlushException(e); + throw; + } + + // wrap other system exceptions + var ex = new NATSException("Flush error.", e); + saveFlushException(ex); + throw ex; + } + } + + /// + /// A timespan representing the elapsed time. + /// + /// + /// If the connection is closed. + /// Miscellaneous other exceptions + public TimeSpan RTT() + { + Stopwatch sw = new Stopwatch(); + SingleUseChannel ch = SingleUseChannel.GetOrCreate(); + + try + { + lock (mu) + { + if (isClosed()) + { + throw new NATSConnectionClosedException(); + } + + sw.Start(); + sendPing(ch); + } + + bool rv = ch.get(opts.Timeout); +After: + var ch = SingleUseChannel.GetOrCreate(); + + try + { + lock (mu) + { + if (isClosed()) + throw new NATSConnectionClosedException(); + + sendPing(ch); + } + + var rv = ch.get(timeout); + if (!rv) + { + throw new NATSConnectionClosedException(); + } + + SingleUseChannel.Return(ch); + } + catch (Exception e) + { + removeFlushEntry(ch); + + // Note, don't call saveFlushException in a finally clause + // because we don't know if the caller will handle the rethrown + // exception. + if (e is NATSTimeoutException || e is NATSConnectionClosedException) + { + saveFlushException(e); + throw; + } + + // wrap other system exceptions + var ex = new NATSException("Flush error.", e); + saveFlushException(ex); + throw ex; + } + } + + /// + /// A timespan representing the elapsed time. + /// + /// + /// If the connection is closed. + /// Miscellaneous other exceptions + public TimeSpan RTT() + { + var sw = new Stopwatch(); + var ch = SingleUseChannel.GetOrCreate(); + + try + { + lock (mu) + { + if (isClosed()) + { + throw new NATSConnectionClosedException(); + } + + sw.Start(); + sendPing(ch); + } + + var rv = ch.get(opts.Timeout); +*/ + + } + + var ch = SingleUseChannel.GetOrCreate(); + + try + { + lock (mu) + { + if (isClosed()) + throw new NATSConnectionClosedException(); + + sendPing(ch); + } + + var rv = ch.get(timeout); + if (!rv) + { + throw new NATSConnectionClosedException(); + } + + SingleUseChannel.Return(ch); + } + catch (Exception e) + { + removeFlushEntry(ch); + + // Note, don't call saveFlushException in a finally clause + // because we don't know if the caller will handle the rethrown + // exception. + if (e is NATSTimeoutException || e is NATSConnectionClosedException) + { + saveFlushException(e); + throw; + } + + // wrap other system exceptions + var ex = new NATSException("Flush error.", e); + saveFlushException(ex); + throw ex; + } + } + + /// + /// A timespan representing the elapsed time. + /// + /// + /// If the connection is closed. + /// Miscellaneous other exceptions + public TimeSpan RTT() + { + var sw = new Stopwatch(); + var ch = SingleUseChannel.GetOrCreate(); + + try + { + lock (mu) + { + if (isClosed()) + { + throw new NATSConnectionClosedException(); + } + + sw.Start(); + sendPing(ch); + } + + var rv = ch.get(opts.Timeout); + sw.Stop(); + if (!rv) + { + throw new NATSConnectionClosedException(); + } + + SingleUseChannel.Return(ch); + + return sw.Elapsed; + } + catch (Exception e) + { + removeFlushEntry(ch); + + // Note, don't call saveFlushException in a finally clause + // because we don't know if the caller will handle the rethrown + // exception. + if (e is NATSTimeoutException || e is NATSConnectionClosedException) + { + saveFlushException(e); + throw; + } + + // wrap other system exceptions + var ex = new NATSException("RTT error.", e); + saveFlushException(ex); + throw ex; + } + } + + /// + /// Performs a round trip to the server and returns when it receives the internal reply. + /// + /// The is closed. + /// A timeout occurred while sending the request or receiving the response. + /// There was an unexpected exception performing an internal NATS call while executing the + /// request. See for more details. + /// There was a failure while writing to the network. + public void Flush() + { + Flush(DEFAULT_FLUSH_TIMEOUT); + } + + /// + /// Immediately flushes the underlying connection buffer if the connection is valid. + /// + /// The is closed. + /// There was an unexpected exception performing an internal NATS call while executing the + /// request. See for more details. + public void FlushBuffer() + { + lock (mu) + { + if (isClosed()) + throw new NATSConnectionClosedException(); + + if (status == ConnState.CONNECTED) + bw.Flush(); + } + } + + // resendSubscriptions will send our subscription state back to the + // server. Used in reconnects + private void resendSubscriptions() + { + foreach (var s in subs.Values) + { + if (s is IAsyncSubscription) + { + ((AsyncSubscription)s).enableAsyncProcessing(); + } + SendSub(s.Subject, s.Queue, s.sid); + } + + bw.Flush(); + } + + // This will clear any pending flush calls and release pending calls. + // Lock must be held by the caller. + private void clearPendingFlushCalls() + { + while (pongs.TryDequeue(out var ch)) + ch?.add(true); + } + + + // Clears any in-flight requests by cancelling them all + // Caller must lock + private void clearPendingRequestCalls() + { + lock (mu) + { + foreach (var request in waitingRequests) + { + request.Value.Waiter.TrySetCanceled(); + } + waitingRequests.Clear(); + } + } + + + // Low level close call that will do correct cleanup and set + // desired status. Also controls whether user defined callbacks + // will be triggered. The lock should not be held entering this + // function. This function will handle the locking manually. + private void close(ConnState closeState, bool invokeDelegates, Exception error, bool authAuthError) + { + lock (mu) + { + if (isClosed()) + { + status = closeState; + return; + } + + status = ConnState.CLOSED; + + // Kick the routines so they fall out. + // fch will be closed on finalizer + kickFlusher(); + } + + lock (mu) + { + // Clear any queued pongs, e.g. pending flush calls. + clearPendingFlushCalls(); + if (pending != null) pending.Dispose(); // Clear any pending request calls @@ -4754,7 +6582,7 @@ private void close(ConnState closeState, bool invokeDelegates, Exception error, { // Close sync subscriber channels and release any // pending NextMsg() calls. - foreach (Subscription s in subs.Values) + foreach (var s in subs.Values) { s.close(); } @@ -4920,6 +6748,86 @@ internal void pushDrainException(Subscription s, Exception ex) private void drain(int timeout) { ICollection lsubs = null; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + bool timedOut = false; + + lock (mu) + { + if (isClosed()) + throw new NATSConnectionClosedException(); + + // if we're already draining, exit. + if (isDrainingSubs() || isDrainingPubs()) + return; + + lsubs = subs.Values; + status = ConnState.DRAINING_SUBS; + } + + Task[] tasks = new Task[lsubs.Count]; + int i = 0; +After: + var timedOut = false; + + lock (mu) + { + if (isClosed()) + throw new NATSConnectionClosedException(); + + // if we're already draining, exit. + if (isDrainingSubs() || isDrainingPubs()) + return; + + lsubs = subs.Values; + status = ConnState.DRAINING_SUBS; + } + + var tasks = new Task[lsubs.Count]; + var i = 0; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + bool timedOut = false; + + lock (mu) + { + if (isClosed()) + throw new NATSConnectionClosedException(); + + // if we're already draining, exit. + if (isDrainingSubs() || isDrainingPubs()) + return; + + lsubs = subs.Values; + status = ConnState.DRAINING_SUBS; + } + + Task[] tasks = new Task[lsubs.Count]; + int i = 0; +After: + var timedOut = false; + + lock (mu) + { + if (isClosed()) + throw new NATSConnectionClosedException(); + + // if we're already draining, exit. + if (isDrainingSubs() || isDrainingPubs()) + return; + + lsubs = subs.Values; + status = ConnState.DRAINING_SUBS; + } + + var tasks = new Task[lsubs.Count]; + var i = 0; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: bool timedOut = false; lock (mu) @@ -4937,6 +6845,43 @@ private void drain(int timeout) Task[] tasks = new Task[lsubs.Count]; int i = 0; +After: + var timedOut = false; + + lock (mu) + { + if (isClosed()) + throw new NATSConnectionClosedException(); + + // if we're already draining, exit. + if (isDrainingSubs() || isDrainingPubs()) + return; + + lsubs = subs.Values; + status = ConnState.DRAINING_SUBS; + } + + var tasks = new Task[lsubs.Count]; + var i = 0; +*/ + + var timedOut = false; + + lock (mu) + { + if (isClosed()) + throw new NATSConnectionClosedException(); + + // if we're already draining, exit. + if (isDrainingSubs() || isDrainingPubs()) + return; + + lsubs = subs.Values; + status = ConnState.DRAINING_SUBS; + } + + var tasks = new Task[lsubs.Count]; + var i = 0; foreach (var s in lsubs) { try @@ -5145,7 +7090,7 @@ public IStatistics Stats { lock (mu) { - return new Statistics(this.stats); + return new Statistics(stats); } } } @@ -5192,25 +7137,88 @@ public long MaxPayload /// /// A string that represents the current instance. public override string ToString() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + StringBuilder sb = new StringBuilder(); +After: + var sb = new StringBuilder(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: StringBuilder sb = new StringBuilder(); +After: + var sb = new StringBuilder(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + StringBuilder sb = new StringBuilder(); +After: + var sb = new StringBuilder(); +*/ + + { + var sb = new StringBuilder(); sb.Append("{"); sb.AppendFormat("url={0};", url); sb.AppendFormat("info={0};", serverInfo); sb.AppendFormat("status={0};", status); sb.Append("Subscriptions={"); - foreach (Subscription s in subs.Values) + foreach (var s in subs.Values) { sb.Append("Subscription {" + s.ToString() + "};"); } sb.Append("};"); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string[] servers = Servers; +After: + var servers = Servers; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string[] servers = Servers; +After: + var servers = Servers; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string[] servers = Servers; +After: + var servers = Servers; +*/ + + + var servers = Servers; if (servers != null) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + bool printedFirst = false; +After: + var printedFirst = false; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: bool printedFirst = false; +After: + var printedFirst = false; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + bool printedFirst = false; +After: + var printedFirst = false; +*/ + + { + var printedFirst = false; sb.Append("Servers {"); - foreach (string s in servers) + foreach (var s in servers) { if (printedFirst) sb.Append(","); @@ -5226,7 +7234,7 @@ public override string ToString() #region IDisposable Support // To detect redundant calls - private bool disposedValue = false; + private bool disposedValue = false; /// /// Closes the connection and optionally releases the managed resources. @@ -5336,7 +7344,7 @@ public IObjectStoreManagement CreateObjectStoreManagementContext(ObjectStoreOpti #endregion } // class Conn - + internal static class StreamExtensions { /// @@ -5354,8 +7362,33 @@ internal static string ReadUntilCrlf(this Stream stream) const int maxAllowedSize = MaxControlLineSize * 16; var buffer = new byte[MaxControlLineSize]; int byteValue; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: bool foundCR = false; var read = 0; +After: + var read = 0; + var read = 0; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + bool foundCR = false; +After: + var foundCR = false; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + bool foundCR = false; + var read = 0; +After: + var read = 0; + var read = 0; +*/ + + var foundCR = false; + var foundCR = false; while ((byteValue = stream.ReadByte()) != -1) { @@ -5369,7 +7402,7 @@ internal static string ReadUntilCrlf(this Stream stream) } Array.Resize(ref buffer, Math.Min(buffer.Length * 2, maxAllowedSize)); } - + if (byteValue == '\r') { foundCR = true; @@ -5393,7 +7426,7 @@ internal static string ReadUntilCrlf(this Stream stream) { throw new NATSProtocolException("Control line does not end with CRLF."); } - + return Encoding.UTF8.GetString(buffer, 0, read); } } diff --git a/src/NATS.Client/v1/ConnectionFactory.cs b/src/NATS.Client/v1/ConnectionFactory.cs index d2771312..68c7c503 100644 --- a/src/NATS.Client/v1/ConnectionFactory.cs +++ b/src/NATS.Client/v1/ConnectionFactory.cs @@ -47,7 +47,7 @@ public IConnection CreateConnection(string url, bool reconnectOnConnect = false) { return CreateConnection(GetDefaultOptions(url), reconnectOnConnect); } - + /// /// Attempt to connect to the NATS server referenced by with NATS 2.0 credentials. /// @@ -69,8 +69,29 @@ public IConnection CreateConnection(string url, string credentialsPath, bool rec { if (string.IsNullOrWhiteSpace(credentialsPath)) throw new ArgumentException("Invalid credentials path", nameof(credentialsPath)); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Options opts = GetDefaultOptions(url); +After: + var opts = GetDefaultOptions(url); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Options opts = GetDefaultOptions(url); +After: + var opts = GetDefaultOptions(url); +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: Options opts = GetDefaultOptions(url); +After: + var opts = GetDefaultOptions(url); +*/ + + + var opts = GetDefaultOptions(url); opts.SetUserCredentials(credentialsPath); return CreateConnection(opts, reconnectOnConnect); } @@ -99,12 +120,33 @@ public IConnection CreateConnection(string url, string jwt, string privateNkey, throw new ArgumentException("Invalid jwt path", nameof(jwt)); if (string.IsNullOrWhiteSpace(privateNkey)) throw new ArgumentException("Invalid nkey path", nameof(privateNkey)); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Options opts = GetDefaultOptions(url); +After: + var opts = GetDefaultOptions(url); +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: Options opts = GetDefaultOptions(url); +After: + var opts = GetDefaultOptions(url); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Options opts = GetDefaultOptions(url); +After: + var opts = GetDefaultOptions(url); +*/ + + + var opts = GetDefaultOptions(url); opts.SetUserCredentials(jwt, privateNkey); return CreateConnection(opts, reconnectOnConnect); } - + /// /// Attempt to connect to the NATS server referenced by /// with NATS 2.0 the user jwt and nkey seed credentials provided directly in the string. @@ -115,8 +157,29 @@ public IConnection CreateConnection(string url, string jwt, string privateNkey, /// /// public IConnection CreateConnectionWithCredentials(string url, string credentialsText, bool reconnectOnConnect = false) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: Options opts = GetDefaultOptions(url); +After: + var opts = GetDefaultOptions(url); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Options opts = GetDefaultOptions(url); +After: + var opts = GetDefaultOptions(url); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Options opts = GetDefaultOptions(url); +After: + var opts = GetDefaultOptions(url); +*/ + + { + var opts = GetDefaultOptions(url); opts.SetUserCredentialsFromString(credentialsText); return CreateConnection(opts, reconnectOnConnect); } @@ -137,8 +200,29 @@ public IConnection CreateConnectionWithCredentials(string url, string credential /// /// public IConnection CreateConnectionWithCredentials(string url, string userJwtText, string nkeySeedText, bool reconnectOnConnect = false) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: Options opts = GetDefaultOptions(url); +After: + var opts = GetDefaultOptions(url); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Options opts = GetDefaultOptions(url); +After: + var opts = GetDefaultOptions(url); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Options opts = GetDefaultOptions(url); +After: + var opts = GetDefaultOptions(url); +*/ + + { + var opts = GetDefaultOptions(url); opts.SetUserCredentialsFromStrings(userJwtText, nkeySeedText); return CreateConnection(opts, reconnectOnConnect); } @@ -150,8 +234,29 @@ public IConnection CreateConnectionWithCredentials(string url, string userJwtTex /// or properties /// The default object for the NATS client. public static Options GetDefaultOptions(string server = null) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: Options opts = new Options(); +After: + var opts = new Options(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Options opts = new Options(); +After: + var opts = new Options(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Options opts = new Options(); +After: + var opts = new Options(); +*/ + + { + var opts = new Options(); if (server != null) { opts.Url = server; @@ -176,8 +281,29 @@ public static Options GetDefaultOptions(string server = null) /// An exception was encountered while connecting to a NATS Server. See for more /// details. public IConnection CreateSecureConnection(string url, bool reconnectOnConnect = false) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: Options opts = GetDefaultOptions(url); +After: + var opts = GetDefaultOptions(url); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Options opts = GetDefaultOptions(url); +After: + var opts = GetDefaultOptions(url); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Options opts = GetDefaultOptions(url); +After: + var opts = GetDefaultOptions(url); +*/ + + { + var opts = GetDefaultOptions(url); opts.Secure = true; return CreateConnection(opts, reconnectOnConnect); } @@ -210,8 +336,29 @@ public IConnection CreateConnection(bool reconnectOnConnect = false) /// An exception was encountered while connecting to a NATS Server. See for more /// details. public IConnection CreateConnection(Options opts, bool reconnectOnConnect = false) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: Connection nc = new Connection(opts); +After: + var nc = new Connection(opts); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Connection nc = new Connection(opts); +After: + var nc = new Connection(opts); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Connection nc = new Connection(opts); +After: + var nc = new Connection(opts); +*/ + + { + var nc = new Connection(opts); try { nc.connect(reconnectOnConnect); @@ -276,8 +423,29 @@ public IEncodedConnection CreateEncodedConnection(string url, bool reconnectOnCo /// An exception was encountered while connecting to a NATS Server. See for more /// details. public IEncodedConnection CreateEncodedConnection(Options opts, bool reconnectOnConnect = false) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: EncodedConnection nc = new EncodedConnection(opts); +After: + var nc = new EncodedConnection(opts); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + EncodedConnection nc = new EncodedConnection(opts); +After: + var nc = new EncodedConnection(opts); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + EncodedConnection nc = new EncodedConnection(opts); +After: + var nc = new EncodedConnection(opts); +*/ + + { + var nc = new EncodedConnection(opts); try { nc.connect(reconnectOnConnect); diff --git a/src/NATS.Client/v1/DefaultUserJWTHandler.cs b/src/NATS.Client/v1/DefaultUserJWTHandler.cs index f82465ab..a452e045 100644 --- a/src/NATS.Client/v1/DefaultUserJWTHandler.cs +++ b/src/NATS.Client/v1/DefaultUserJWTHandler.cs @@ -56,7 +56,29 @@ public DefaultUserJWTHandler(string jwtFilePath, string credsFilePath) /// Full path to the JWT or cred file. /// The encoded JWT public static string LoadUserFromFile(string path) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string text = File.ReadAllText(path).Trim(); + if (string.IsNullOrEmpty(text)) + { + throw new NATSException("Credentials file is empty"); + } + string user = JWTHandlerUtils.LoadUser(text); + if (user == null) + { + throw new NATSException("Credentials file does not contain a JWT"); + } +After: + var text = File.ReadAllText(path).Trim(); + if (string.IsNullOrEmpty(text)) + { + throw new NATSException("Credentials file is empty"); + } + var user = JWTHandlerUtils.LoadUser(text) ?? throw new NATSException("Credentials file does not contain a JWT"); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: string text = File.ReadAllText(path).Trim(); if (string.IsNullOrEmpty(text)) { @@ -67,9 +89,46 @@ public static string LoadUserFromFile(string path) { throw new NATSException("Credentials file does not contain a JWT"); } +After: + var text = File.ReadAllText(path).Trim(); + if (string.IsNullOrEmpty(text)) + { + throw new NATSException("Credentials file is empty"); + } + var user = JWTHandlerUtils.LoadUser(text) ?? throw new NATSException("Credentials file does not contain a JWT"); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string text = File.ReadAllText(path).Trim(); + if (string.IsNullOrEmpty(text)) + { + throw new NATSException("Credentials file is empty"); + } + string user = JWTHandlerUtils.LoadUser(text); + if (user == null) + { + throw new NATSException("Credentials file does not contain a JWT"); + } +After: + var text = File.ReadAllText(path).Trim(); + if (string.IsNullOrEmpty(text)) + { + throw new NATSException("Credentials file is empty"); + } + var user = JWTHandlerUtils.LoadUser(text) ?? throw new NATSException("Credentials file does not contain a JWT"); +*/ + + { + var text = File.ReadAllText(path).Trim(); + if (string.IsNullOrEmpty(text)) + { + throw new NATSException("Credentials file is empty"); + } + var user = JWTHandlerUtils.LoadUser(text) ?? throw new NATSException("Credentials file does not contain a JWT"); return user; } - + /// /// Generates a NATS Ed25519 keypair, used to sign server nonces, from a /// private credentials file. @@ -79,8 +138,50 @@ public static string LoadUserFromFile(string path) public static NkeyPair LoadNkeyPairFromSeedFile(string path) { StringReader reader = null; - try - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string text = File.ReadAllText(path).Trim(); + if (string.IsNullOrEmpty(text)) + { + throw new NATSException("Credentials file is empty"); + } + NkeyPair kp = JWTHandlerUtils.LoadNkeyPair(text); + if (kp == null) + { + throw new NATSException("Seed not found in credentials file."); + } +After: + var text = File.ReadAllText(path).Trim(); + if (string.IsNullOrEmpty(text)) + { + throw new NATSException("Credentials file is empty"); + } + var kp = JWTHandlerUtils.LoadNkeyPair(text) ?? throw new NATSException("Seed not found in credentials file."); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string text = File.ReadAllText(path).Trim(); + if (string.IsNullOrEmpty(text)) + { + throw new NATSException("Credentials file is empty"); + } + NkeyPair kp = JWTHandlerUtils.LoadNkeyPair(text); + if (kp == null) + { + throw new NATSException("Seed not found in credentials file."); + } +After: + var text = File.ReadAllText(path).Trim(); + if (string.IsNullOrEmpty(text)) + { + throw new NATSException("Credentials file is empty"); + } + var kp = JWTHandlerUtils.LoadNkeyPair(text) ?? throw new NATSException("Seed not found in credentials file."); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string text = File.ReadAllText(path).Trim(); if (string.IsNullOrEmpty(text)) { @@ -91,6 +192,23 @@ public static NkeyPair LoadNkeyPairFromSeedFile(string path) { throw new NATSException("Seed not found in credentials file."); } +After: + var text = File.ReadAllText(path).Trim(); + if (string.IsNullOrEmpty(text)) + { + throw new NATSException("Credentials file is empty"); + } + var kp = JWTHandlerUtils.LoadNkeyPair(text) ?? throw new NATSException("Seed not found in credentials file."); +*/ + + try + { + var text = File.ReadAllText(path).Trim(); + if (string.IsNullOrEmpty(text)) + { + throw new NATSException("Credentials file is empty"); + } + var kp = JWTHandlerUtils.LoadNkeyPair(text) ?? throw new NATSException("Seed not found in credentials file."); return kp; } finally diff --git a/src/NATS.Client/v1/EncodedConn.cs b/src/NATS.Client/v1/EncodedConn.cs index e5e934ae..d373ff99 100644 --- a/src/NATS.Client/v1/EncodedConn.cs +++ b/src/NATS.Client/v1/EncodedConn.cs @@ -26,7 +26,7 @@ namespace NATS.Client /// to a byte array. /// /// The to serialize. - public delegate byte[] Serializer(Object obj); + public delegate byte[] Serializer(object obj); /// /// Represents a method that will handle deserialization of a byte array @@ -35,7 +35,7 @@ namespace NATS.Client /// The byte array in a payload /// that contains the to deserialize. /// The being deserialized. - public delegate Object Deserializer(byte[] data); + public delegate object Deserializer(byte[] data); /// /// ENCODED CONNECTIONS, WHILE STILL FUNCTIONAL, WILL NO LONGER BE SUPPORTED @@ -43,12 +43,12 @@ namespace NATS.Client /// public class EncodedMessageEventArgs : EventArgs { - internal string subject = null; - internal string reply = null; - internal object obj = null; - internal Msg msg = null; + internal string subject = null; + internal string reply = null; + internal object obj = null; + internal Msg msg = null; - internal EncodedMessageEventArgs() {} + internal EncodedMessageEventArgs() { } /// /// Gets the subject for the received . @@ -84,7 +84,28 @@ public Msg Message { get { + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + return this.msg; +After: + return msg; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: return this.msg; +After: + return msg; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + return this.msg; +After: + return msg; +*/ + return msg; } } } @@ -96,14 +117,14 @@ public Msg Message /// public class EncodedConnection : Connection, IEncodedConnection { - private MemoryStream sStream = new MemoryStream(); - private object sStreamLock = new object(); + private MemoryStream sStream = new MemoryStream(); + private object sStreamLock = new object(); - private MemoryStream dStream = new MemoryStream(); - private object dStreamLock = new object(); + private MemoryStream dStream = new MemoryStream(); + private object dStreamLock = new object(); - private Serializer onSerialize = null; - private Deserializer onDeserialize = null; + private Serializer onSerialize = null; + private Deserializer onDeserialize = null; internal EncodedConnection(Options opts) : base(opts) @@ -190,6 +211,165 @@ private void PublishObjectImpl(string subject, string reply, MsgHeader headers, /// There was an unexpected exception performing an internal NATS call /// while publishing. See for more details. /// There was a failure while writing to the network. + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + public void Publish(string subject, Object obj) + { + PublishObjectImpl(subject, null, null, obj); + } + + /// + /// Publishes the serialized value of to the given . + /// + /// The subject to publish to over + /// the current connection. + /// Optional headers to publish with the message. + /// The to serialize and publish to the connected NATS server. + /// is + /// null or entirely whitespace. + /// exceeds the maximum payload size + /// supported by the NATS server. + /// The is closed. + /// is null. + /// -or- + /// There was an unexpected exception performing an internal NATS call + /// while publishing. See for more details. + /// There was a failure while writing to the network. + public void Publish(string subject, MsgHeader headers, Object obj) + { + PublishObjectImpl(subject, null, headers, obj); + } + + /// + /// Publishes the serialized value of to the given . + /// + /// The subject to publish to over + /// the current connection. + /// An optional reply subject. + /// The to serialize and publish to the connected NATS server. + /// is null or + /// entirely whitespace. + /// exceeds the maximum payload size + /// supported by the NATS server. + /// The is closed. + /// is null. + /// -or- + /// There was an unexpected exception performing an internal NATS call + /// while publishing. See for more details. + /// There was a failure while writing to the network. + public void Publish(string subject, string reply, object obj) + { + PublishObjectImpl(subject, reply, null, obj); + } + + /// + /// Publishes the serialized value of to the given . + /// + /// The subject to publish to over + /// the current connection. + /// An optional reply subject. + /// Optional headers to publish with the message. + /// The to serialize and publish to the connected NATS server. + /// is null or + /// entirely whitespace. +After: + public void Publish(string subject, object obj) + { + PublishObjectImpl(subject, null, null, obj); + } + + /// + /// Publishes the serialized value of to the given . + /// + /// The subject to publish to over + /// the current connection. + /// Optional headers to publish with the message. + /// The to serialize and publish to the connected NATS server. + /// is + /// null or entirely whitespace. +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + public void Publish(string subject, Object obj) + { + PublishObjectImpl(subject, null, null, obj); + } + + /// + /// Publishes the serialized value of to the given . + /// + /// The subject to publish to over + /// the current connection. + /// Optional headers to publish with the message. + /// The to serialize and publish to the connected NATS server. + /// is + /// null or entirely whitespace. + /// exceeds the maximum payload size + /// supported by the NATS server. + /// The is closed. + /// is null. + /// -or- + /// There was an unexpected exception performing an internal NATS call + /// while publishing. See for more details. + /// There was a failure while writing to the network. + public void Publish(string subject, MsgHeader headers, Object obj) + { + PublishObjectImpl(subject, null, headers, obj); + } + + /// + /// Publishes the serialized value of to the given . + /// + /// The subject to publish to over + /// the current connection. + /// An optional reply subject. + /// The to serialize and publish to the connected NATS server. + /// is null or + /// entirely whitespace. + /// exceeds the maximum payload size + /// supported by the NATS server. + /// The is closed. + /// is null. + /// -or- + /// There was an unexpected exception performing an internal NATS call + /// while publishing. See for more details. + /// There was a failure while writing to the network. + public void Publish(string subject, string reply, object obj) + { + PublishObjectImpl(subject, reply, null, obj); + } + + /// + /// Publishes the serialized value of to the given . + /// + /// The subject to publish to over + /// the current connection. + /// An optional reply subject. + /// Optional headers to publish with the message. + /// The to serialize and publish to the connected NATS server. + /// is null or + /// entirely whitespace. +After: + public void Publish(string subject, object obj) + { + PublishObjectImpl(subject, null, null, obj); + } + + /// + /// Publishes the serialized value of to the given . + /// + /// The subject to publish to over + /// the current connection. + /// Optional headers to publish with the message. + /// The to serialize and publish to the connected NATS server. + /// is + /// null or entirely whitespace. +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: public void Publish(string subject, Object obj) { PublishObjectImpl(subject, null, null, obj); @@ -239,6 +419,237 @@ public void Publish(string subject, string reply, object obj) PublishObjectImpl(subject, reply, null, obj); } + /// + /// Publishes the serialized value of to the given . + /// + /// The subject to publish to over + /// the current connection. + /// An optional reply subject. + /// Optional headers to publish with the message. + /// The to serialize and publish to the connected NATS server. + /// is null or + /// entirely whitespace. +After: + public void Publish(string subject, object obj) + { + PublishObjectImpl(subject, null, null, obj); + } + + /// + /// Publishes the serialized value of to the given . + /// + /// The subject to publish to over + /// the current connection. + /// Optional headers to publish with the message. + /// The to serialize and publish to the connected NATS server. + /// is + /// null or entirely whitespace. +*/ + public void Publish(string subject, object obj) + { + PublishObjectImpl(subject, null, null, obj); + } + + /// + /// Publishes the serialized value of to the given . + /// + /// The subject to publish to over + /// the current connection. + /// Optional headers to publish with the message. + /// The to serialize and publish to the connected NATS server. + /// is + /// null or entirely whitespace. + /// exceeds the maximum payload size + /// supported by the NATS server. + /// The is closed. + /// is null. + /// -or- + /// There was an unexpected exception performing an internal NATS call + /// while publishing. See for more details. + /// There was a failure while writing to the network. + public void Publish(string subject, MsgHeader headers, object obj) + { + PublishObjectImpl(subject, null, headers, obj); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + // Wrapper the handler for keeping a local copy of the event arguments around. +After: + /// + /// Publishes the serialized value of to the given . + /// + /// The subject to publish to over + /// the current connection. + /// An optional reply subject. + /// The to serialize and publish to the connected NATS server. + /// is null or + /// entirely whitespace. + /// exceeds the maximum payload size + /// supported by the NATS server. + /// The is closed. + /// is null. + /// -or- + /// There was an unexpected exception performing an internal NATS call + /// while publishing. See for more details. + /// There was a failure while writing to the network. + public void Publish(string subject, string reply, object obj) + { + PublishObjectImpl(subject, reply, null, obj); + } + + /// + /// Publishes the serialized value of to the given . + /// + /// The subject to publish to over + /// the current connection. + /// An optional reply subject. + /// Optional headers to publish with the message. + /// The to serialize and publish to the connected NATS server. + /// is null or + /// entirely whitespace. + /// exceeds the maximum payload size + /// supported by the NATS server. + /// The is closed. + /// is null. + /// -or- + /// There was an unexpected exception performing an internal NATS call + /// while publishing. See for more details. + /// There was a failure while writing to the network. + public void Publish(string subject, string reply, MsgHeader headers, object obj) + { + PublishObjectImpl(subject, reply, headers, obj); + } + + // Wrapper the handler for keeping a local copy of the event arguments around. +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + // Wrapper the handler for keeping a local copy of the event arguments around. +After: + /// + /// Publishes the serialized value of to the given . + /// + /// The subject to publish to over + /// the current connection. + /// An optional reply subject. + /// The to serialize and publish to the connected NATS server. + /// is null or + /// entirely whitespace. + /// exceeds the maximum payload size + /// supported by the NATS server. + /// The is closed. + /// is null. + /// -or- + /// There was an unexpected exception performing an internal NATS call + /// while publishing. See for more details. + /// There was a failure while writing to the network. + public void Publish(string subject, string reply, object obj) + { + PublishObjectImpl(subject, reply, null, obj); + } + + /// + /// Publishes the serialized value of to the given . + /// + /// The subject to publish to over + /// the current connection. + /// An optional reply subject. + /// Optional headers to publish with the message. + /// The to serialize and publish to the connected NATS server. + /// is null or + /// entirely whitespace. + /// exceeds the maximum payload size + /// supported by the NATS server. + /// The is closed. + /// is null. + /// -or- + /// There was an unexpected exception performing an internal NATS call + /// while publishing. See for more details. + /// There was a failure while writing to the network. + public void Publish(string subject, string reply, MsgHeader headers, object obj) + { + PublishObjectImpl(subject, reply, headers, obj); + } + + // Wrapper the handler for keeping a local copy of the event arguments around. +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + // Wrapper the handler for keeping a local copy of the event arguments around. +After: + /// + /// Publishes the serialized value of to the given . + /// + /// The subject to publish to over + /// the current connection. + /// An optional reply subject. + /// The to serialize and publish to the connected NATS server. + /// is null or + /// entirely whitespace. + /// exceeds the maximum payload size + /// supported by the NATS server. + /// The is closed. + /// is null. + /// -or- + /// There was an unexpected exception performing an internal NATS call + /// while publishing. See for more details. + /// There was a failure while writing to the network. + public void Publish(string subject, string reply, object obj) + { + PublishObjectImpl(subject, reply, null, obj); + } + + /// + /// Publishes the serialized value of to the given . + /// + /// The subject to publish to over + /// the current connection. + /// An optional reply subject. + /// Optional headers to publish with the message. + /// The to serialize and publish to the connected NATS server. + /// is null or + /// entirely whitespace. + /// exceeds the maximum payload size + /// supported by the NATS server. + /// The is closed. + /// is null. + /// -or- + /// There was an unexpected exception performing an internal NATS call + /// while publishing. See for more details. + /// There was a failure while writing to the network. + public void Publish(string subject, string reply, MsgHeader headers, object obj) + { + PublishObjectImpl(subject, reply, headers, obj); + } + + // Wrapper the handler for keeping a local copy of the event arguments around. +*/ + + } + + /// + /// Publishes the serialized value of to the given . + /// + /// The subject to publish to over + /// the current connection. + /// An optional reply subject. + /// The to serialize and publish to the connected NATS server. + /// is null or + /// entirely whitespace. + /// exceeds the maximum payload size + /// supported by the NATS server. + /// The is closed. + /// is null. + /// -or- + /// There was an unexpected exception performing an internal NATS call + /// while publishing. See for more details. + /// There was a failure while writing to the network. + public void Publish(string subject, string reply, object obj) + { + PublishObjectImpl(subject, reply, null, obj); + } + /// /// Publishes the serialized value of to the given . /// @@ -274,12 +685,54 @@ internal EncodedHandlerWrapper(EncodedConnection encc, EventHandler /// The exception that is thrown when a subscriber operation is performed on /// an invalid subscriber. @@ -306,7 +327,7 @@ internal NATSJetStreamClientException Instance(string extraMessage) [Obsolete("constant name had typo, replaced with JsSubFcHbNotValidQueue")] public static readonly ClientExDetail JsSubFcHbHbNotValidQueue = new ClientExDetail(Sub, 90006, "Flow Control and/or heartbeat is not valid in queue mode."); - + [Obsolete("constant name had typo, replaced with JsSoDeliverSubjectMismatch")] public static readonly ClientExDetail JsSoDeliverSubjectGroupMismatch = new ClientExDetail(So, 90103, "Builder deliver subject must match the consumer configuration deliver subject if both are provided."); diff --git a/src/NATS.Client/v1/IAsyncSubscription.cs b/src/NATS.Client/v1/IAsyncSubscription.cs index 079b7c33..cd65a87d 100644 --- a/src/NATS.Client/v1/IAsyncSubscription.cs +++ b/src/NATS.Client/v1/IAsyncSubscription.cs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 The NATS Authors +// Copyright 2015-2018 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/src/NATS.Client/v1/IConnection.cs b/src/NATS.Client/v1/IConnection.cs index 7faa5c3f..bf04a8ba 100644 --- a/src/NATS.Client/v1/IConnection.cs +++ b/src/NATS.Client/v1/IConnection.cs @@ -1,4 +1,4 @@ -// Copyright 2015-2023 The NATS Authors +// Copyright 2015-2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -97,7 +97,7 @@ public interface IConnection : IDisposable /// ReconnectOptions, optional /// void Reconnect(ReconnectOptions reconnectOptions = null); - + /// /// Publishes to the given . /// @@ -180,7 +180,7 @@ public interface IConnection : IDisposable /// to the connected NATS server. /// void Publish(string subject, string reply, byte[] data); - + /// /// Publishes to the given . /// @@ -442,7 +442,7 @@ public interface IConnection : IDisposable /// A with the response from the NATS server. /// Msg Request(Msg message, int timeout); - + /// /// Asynchronously sends a request payload and returns the response , or throws /// if the expires. @@ -946,7 +946,7 @@ public interface IConnection : IDisposable /// /// A timespan representing the elapsed time. TimeSpan RTT(); - + /// /// Performs a round trip to the server and returns when it receives the internal reply. /// @@ -1102,7 +1102,7 @@ public interface IConnection : IDisposable /// a StreamContext instance. /// an IStreamContext instance IStreamContext GetStreamContext(string streamName); - + /// /// Gets a stream context. /// diff --git a/src/NATS.Client/v1/IConnectionFactory.cs b/src/NATS.Client/v1/IConnectionFactory.cs index da1f7018..08d3d59d 100644 --- a/src/NATS.Client/v1/IConnectionFactory.cs +++ b/src/NATS.Client/v1/IConnectionFactory.cs @@ -1,4 +1,4 @@ -// Copyright 2015-2022 The NATS Authors +// Copyright 2015-2022 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/src/NATS.Client/v1/IEncodedConnection.cs b/src/NATS.Client/v1/IEncodedConnection.cs index d11949b1..29a70e01 100644 --- a/src/NATS.Client/v1/IEncodedConnection.cs +++ b/src/NATS.Client/v1/IEncodedConnection.cs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 The NATS Authors +// Copyright 2015-2018 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -332,4 +332,4 @@ public interface IEncodedConnection : IDisposable /// int SubscriptionCount { get; } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/IStatistics.cs b/src/NATS.Client/v1/IStatistics.cs index 48146b7b..04d16b5f 100644 --- a/src/NATS.Client/v1/IStatistics.cs +++ b/src/NATS.Client/v1/IStatistics.cs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 The NATS Authors +// Copyright 2015-2018 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/src/NATS.Client/v1/ISubscription.cs b/src/NATS.Client/v1/ISubscription.cs index 73bf9264..7a5f2a45 100644 --- a/src/NATS.Client/v1/ISubscription.cs +++ b/src/NATS.Client/v1/ISubscription.cs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 The NATS Authors +// Copyright 2015-2018 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -33,7 +33,7 @@ public interface ISubscription : IDisposable /// the id associated with the subscription, used by the connection when processing an incoming /// long Sid { get; } - + /// /// Gets the subject for this subscription. /// diff --git a/src/NATS.Client/v1/ISyncSubscription.cs b/src/NATS.Client/v1/ISyncSubscription.cs index 30038d06..891c7654 100644 --- a/src/NATS.Client/v1/ISyncSubscription.cs +++ b/src/NATS.Client/v1/ISyncSubscription.cs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 The NATS Authors +// Copyright 2015-2018 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/src/NATS.Client/v1/ITCPConnection.cs b/src/NATS.Client/v1/ITCPConnection.cs index 76a8512b..757253ee 100644 --- a/src/NATS.Client/v1/ITCPConnection.cs +++ b/src/NATS.Client/v1/ITCPConnection.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Net.Security; @@ -8,7 +8,7 @@ namespace NATS.Client { - public interface ITCPConnection : IDisposable + public interface ITCPConnection : IDisposable { bool Connected { get; } bool DataAvailable { get; } diff --git a/src/NATS.Client/v1/Info.cs b/src/NATS.Client/v1/Info.cs index 5400ee28..15207f67 100644 --- a/src/NATS.Client/v1/Info.cs +++ b/src/NATS.Client/v1/Info.cs @@ -36,7 +36,7 @@ internal class ConnectInfo public string version { get; private set; } = Defaults.Version; - public int protocol { get; private set; } = (int) ClientProtcolVersion.ClientProtoInfo; + public int protocol { get; private set; } = (int)ClientProtcolVersion.ClientProtoInfo; public string jwt { get; private set; } @@ -50,22 +50,112 @@ internal class ConnectInfo public bool no_responders { get; private set; } - internal ConnectInfo(bool verbose, bool pedantic, string ujwt, string nkey, string sig, + internal ConnectInfo(bool verbose, bool pedantic, string ujwt, string nkey, string sig, string user, string pass, string token, bool secure, string name, bool echo) { this.verbose = verbose; this.pedantic = pedantic; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: this.jwt = ujwt; +After: + jwt = ujwt; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this.jwt = ujwt; +After: + jwt = ujwt; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this.jwt = ujwt; +After: + jwt = ujwt; +*/ + + jwt = ujwt; this.nkey = nkey; this.sig = sig; this.user = user; this.pass = pass; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: this.ssl_required = secure; +After: + ssl_required = secure; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this.ssl_required = secure; +After: + ssl_required = secure; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this.ssl_required = secure; +After: + ssl_required = secure; +*/ + + ssl_required = secure; this.name = name; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this.auth_token = token; +After: + auth_token = token; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this.auth_token = token; +After: + auth_token = token; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: this.auth_token = token; +After: + auth_token = token; +*/ + + auth_token = token; this.echo = echo; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: this.headers = true; this.no_responders = true; +After: + headers = true; + no_responders = true; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this.headers = true; + this.no_responders = true; +After: + headers = true; + no_responders = true; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this.headers = true; + this.no_responders = true; +After: + headers = true; + no_responders = true; +*/ + + headers = true; + no_responders = true; } internal StringBuilder AppendAsJsonTo(StringBuilder sb) diff --git a/src/NATS.Client/v1/Internals/CompletedTask.cs b/src/NATS.Client/v1/Internals/CompletedTask.cs index a00074f7..82b6d7fd 100644 --- a/src/NATS.Client/v1/Internals/CompletedTask.cs +++ b/src/NATS.Client/v1/Internals/CompletedTask.cs @@ -1,4 +1,4 @@ -// Copyright 2015-2018 The NATS Authors +// Copyright 2015-2018 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -27,4 +27,4 @@ internal static Task Get() => Task.CompletedTask; #endif } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Internals/Digester.cs b/src/NATS.Client/v1/Internals/Digester.cs index 00c719d4..e4445cb8 100644 --- a/src/NATS.Client/v1/Internals/Digester.cs +++ b/src/NATS.Client/v1/Internals/Digester.cs @@ -27,7 +27,7 @@ public Digester() { hasher = IncrementalHash.CreateHash(HashAlgorithmName.SHA256); } - + public void AppendData(string s) { if (digest != null) @@ -36,7 +36,7 @@ public void AppendData(string s) } hasher.AppendData(Encoding.UTF8.GetBytes(s)); } - + public void AppendData(byte[] data) { if (digest != null) @@ -45,12 +45,33 @@ public void AppendData(byte[] data) } hasher.AppendData(data); } - + private void _prepareDigest() { if (digest == null) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + byte[] hash = hasher.GetHashAndReset(); +After: + var hash = hasher.GetHashAndReset(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: byte[] hash = hasher.GetHashAndReset(); +After: + var hash = hasher.GetHashAndReset(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + byte[] hash = hasher.GetHashAndReset(); +After: + var hash = hasher.GetHashAndReset(); +*/ + + { + var hash = hasher.GetHashAndReset(); digest = Convert.ToBase64String(hash).Replace('+', '-').Replace('/', '_'); entry = "SHA-256=" + digest; } @@ -69,12 +90,39 @@ public string GetDigestEntry() } public bool DigestEntriesMatch(string thatEntry) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string thisEntry = GetDigestEntry(); + int at = thisEntry.IndexOf("=", StringComparison.Ordinal); +After: + var thisEntry = GetDigestEntry(); + var at = thisEntry.IndexOf("=", StringComparison.Ordinal); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string thisEntry = GetDigestEntry(); + int at = thisEntry.IndexOf("=", StringComparison.Ordinal); +After: + var thisEntry = GetDigestEntry(); + var at = thisEntry.IndexOf("=", StringComparison.Ordinal); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string thisEntry = GetDigestEntry(); + int at = thisEntry.IndexOf("=", StringComparison.Ordinal); +After: + var thisEntry = GetDigestEntry(); + var at = thisEntry.IndexOf("=", StringComparison.Ordinal); +*/ + { try { - string thisEntry = GetDigestEntry(); - int at = thisEntry.IndexOf("=", StringComparison.Ordinal); - return thisEntry.Substring(0, at).ToUpper().Equals(thatEntry.Substring(0, at).ToUpper()) + var thisEntry = GetDigestEntry(); + var at = thisEntry.IndexOf("=", StringComparison.Ordinal); + return thisEntry.Substring(0, at).ToUpper().Equals(thatEntry.Substring(0, at).ToUpper()) && thisEntry.Substring(at).Equals(thatEntry.Substring(at)); } catch (Exception) @@ -83,4 +131,4 @@ public bool DigestEntriesMatch(string thatEntry) } } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Internals/Duration.cs b/src/NATS.Client/v1/Internals/Duration.cs index 13822a52..06c836ae 100644 --- a/src/NATS.Client/v1/Internals/Duration.cs +++ b/src/NATS.Client/v1/Internals/Duration.cs @@ -34,7 +34,7 @@ private Duration(long nanos) public static Duration OfNanos(long nanos) { return new Duration(nanos); - } + } /// /// Create a Duration from milliseconds @@ -42,7 +42,7 @@ public static Duration OfNanos(long nanos) public static Duration OfMillis(long millis) { return new Duration(millis * NanosPerMilli); - } + } /// /// Create a Duration from seconds @@ -102,7 +102,7 @@ public bool IsPositive() { return Nanos > 0; } - + public override bool Equals(object obj) { return Equals(obj as Duration); @@ -123,29 +123,115 @@ public override string ToString() return Nanos.ToString(); } - public string ToDescription() { - if (Nanos == 0) { + public string ToDescription() + { + if (Nanos == 0) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + long millis = Nanos / NanosPerMilli; +After: + var millis = Nanos / NanosPerMilli; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + long millis = Nanos / NanosPerMilli; +After: + var millis = Nanos / NanosPerMilli; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + long millis = Nanos / NanosPerMilli; +After: + var millis = Nanos / NanosPerMilli; +*/ + + { return "DUR0"; } - long millis = Nanos / NanosPerMilli; + var millis = Nanos / NanosPerMilli; if (millis < 1000) { return "DUR" + millis + "ms"; - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + long seconds = millis / 1000; +After: + var seconds = millis / 1000; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + long seconds = millis / 1000; +After: + var seconds = millis / 1000; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: long seconds = millis / 1000; +After: + var seconds = millis / 1000; +*/ + + } + + var seconds = millis / 1000; millis = millis - (seconds * 1000); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + long minutes = seconds / 60; +After: + var minutes = seconds / 60; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + long minutes = seconds / 60; +After: + var minutes = seconds / 60; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: long minutes = seconds / 60; +After: + var minutes = seconds / 60; +*/ + + var minutes = seconds / 60; seconds = seconds - (minutes * 60); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + long hours = minutes / 60; +After: + var hours = minutes / 60; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: long hours = minutes / 60; +After: + var hours = minutes / 60; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + long hours = minutes / 60; +After: + var hours = minutes / 60; +*/ + + var hours = minutes / 60; minutes = minutes - (hours * 60); if (hours > 0) { return $"DUR{hours}h{minutes}m{seconds}s{millis}ms"; } - + if (minutes > 0) { return $"DUR{minutes}m{seconds}s{millis}ms"; diff --git a/src/NATS.Client/v1/Internals/Encoding.cs b/src/NATS.Client/v1/Internals/Encoding.cs index b0cec8a3..4f96739d 100644 --- a/src/NATS.Client/v1/Internals/Encoding.cs +++ b/src/NATS.Client/v1/Internals/Encoding.cs @@ -19,9 +19,36 @@ namespace NATS.Client public static class EncodingUtils { public static string ToBase64UrlEncoded(byte[] bytes) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string s = Convert.ToBase64String(bytes); + int at = s.IndexOf('='); +After: + var s = Convert.ToBase64String(bytes); + var at = s.IndexOf('='); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: string s = Convert.ToBase64String(bytes); int at = s.IndexOf('='); +After: + var s = Convert.ToBase64String(bytes); + var at = s.IndexOf('='); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string s = Convert.ToBase64String(bytes); + int at = s.IndexOf('='); +After: + var s = Convert.ToBase64String(bytes); + var at = s.IndexOf('='); +*/ + + { + var s = Convert.ToBase64String(bytes); + var at = s.IndexOf('='); if (at != -1) { s = s.Substring(0, at); @@ -50,7 +77,7 @@ public static string FromBase64UrlEncoded(string s) } } } - + public class Base32 { public static byte[] Decode(string input) @@ -61,15 +88,63 @@ public static byte[] Decode(string input) } input = input.TrimEnd('='); //remove padding characters +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int byteCount = input.Length * 5 / 8; //this must be TRUNCATED + byte[] returnArray = new byte[byteCount]; +After: + var byteCount = input.Length * 5 / 8; //this must be TRUNCATED + var returnArray = new byte[byteCount]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int byteCount = input.Length * 5 / 8; //this must be TRUNCATED + byte[] returnArray = new byte[byteCount]; +After: + var byteCount = input.Length * 5 / 8; //this must be TRUNCATED + var returnArray = new byte[byteCount]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int byteCount = input.Length * 5 / 8; //this must be TRUNCATED byte[] returnArray = new byte[byteCount]; +After: + var byteCount = input.Length * 5 / 8; //this must be TRUNCATED + var returnArray = new byte[byteCount]; +*/ + + var byteCount = input.Length * 5 / 8; //this must be TRUNCATED + var returnArray = new byte[byteCount]; byte curByte = 0, bitsRemaining = 8; int mask = 0, arrayIndex = 0; - foreach (char c in input) - { + foreach (var c in input) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int cValue = CharToValue(c); +After: + var cValue = CharToValue(c); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: int cValue = CharToValue(c); +After: + var cValue = CharToValue(c); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int cValue = CharToValue(c); +After: + var cValue = CharToValue(c); +*/ + + { + var cValue = CharToValue(c); if (bitsRemaining > 5) { @@ -101,15 +176,60 @@ public static string Encode(byte[] input) if (input == null || input.Length == 0) { throw new ArgumentNullException("input"); - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int charCount = (int)Math.Ceiling(input.Length / 5d) * 8; + char[] returnArray = new char[charCount]; + byte nextChar = 0, bitsRemaining = 5; + int arrayIndex = 0; +After: + var charCount = (int)Math.Ceiling(input.Length / 5d) * 8; + var returnArray = new char[charCount]; + + byte nextChar = 0, bitsRemaining = 5; + var arrayIndex = 0; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: int charCount = (int)Math.Ceiling(input.Length / 5d) * 8; char[] returnArray = new char[charCount]; byte nextChar = 0, bitsRemaining = 5; int arrayIndex = 0; +After: + var charCount = (int)Math.Ceiling(input.Length / 5d) * 8; + var returnArray = new char[charCount]; + + byte nextChar = 0, bitsRemaining = 5; + var arrayIndex = 0; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int charCount = (int)Math.Ceiling(input.Length / 5d) * 8; + char[] returnArray = new char[charCount]; + + byte nextChar = 0, bitsRemaining = 5; + int arrayIndex = 0; +After: + var charCount = (int)Math.Ceiling(input.Length / 5d) * 8; + var returnArray = new char[charCount]; + + byte nextChar = 0, bitsRemaining = 5; + var arrayIndex = 0; +*/ + + } + + var charCount = (int)Math.Ceiling(input.Length / 5d) * 8; + var returnArray = new char[charCount]; + + byte nextChar = 0, bitsRemaining = 5; + var arrayIndex = 0; - foreach (byte b in input) + foreach (var b in input) { nextChar = (byte)(nextChar | (b >> (8 - bitsRemaining))); returnArray[arrayIndex++] = ValueToChar(nextChar); @@ -136,25 +256,51 @@ public static string Encode(byte[] input) } private static int CharToValue(char c) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int value = (int)c; +After: + var value = (int)c; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: int value = (int)c; +After: + var value = (int)c; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int value = (int)c; +After: + var value = (int)c; +*/ + + { + var value = (int)c; //65-90 == uppercase letters - if (value < 91 && value > 64) return value - 65; + if (value < 91 && value > 64) + return value - 65; //50-55 == numbers 2-7 - if (value < 56 && value > 49) return value - 24; + if (value < 56 && value > 49) + return value - 24; //97-122 == lowercase letters - if (value < 123 && value > 96) return value - 97; + if (value < 123 && value > 96) + return value - 97; throw new ArgumentException("Character is not a Base32 character.", "c"); } private static char ValueToChar(byte b) { - if (b < 26) return (char)(b + 65); - if (b < 32) return (char)(b + 24); + if (b < 26) + return (char)(b + 65); + if (b < 32) + return (char)(b + 24); throw new ArgumentException("Byte is not a value Base32 value.", "b"); } @@ -197,29 +343,134 @@ public static string ToBase32String(byte[] bytes) else if (bytes.Length == 0) { return string.Empty; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + StringBuilder builder = new StringBuilder(bytes.Length * InByteSize / OutByteSize); +After: + var builder = new StringBuilder(bytes.Length * InByteSize / OutByteSize); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + StringBuilder builder = new StringBuilder(bytes.Length * InByteSize / OutByteSize); +After: + var builder = new StringBuilder(bytes.Length * InByteSize / OutByteSize); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + StringBuilder builder = new StringBuilder(bytes.Length * InByteSize / OutByteSize); +After: + var builder = new StringBuilder(bytes.Length * InByteSize / OutByteSize); +*/ + } // Prepare container for the final value - StringBuilder builder = new StringBuilder(bytes.Length * InByteSize / OutByteSize); + var builder = new StringBuilder(bytes.Length * InByteSize / OutByteSize); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int bytesPosition = 0; +After: + var bytesPosition = 0; +*/ - // Position in the input buffer +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int bytesPosition = 0; +After: + var bytesPosition = 0; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int bytesPosition = 0; +After: + var bytesPosition = 0; +*/ + + + // Position in the input buffer + var bytesPosition = 0; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int bytesSubPosition = 0; +After: + var bytesSubPosition = 0; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int bytesSubPosition = 0; +After: + var bytesSubPosition = 0; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int bytesSubPosition = 0; +After: + var bytesSubPosition = 0; +*/ + // Offset inside a single byte that points to (from left to right) // 0 - highest bit, 7 - lowest bit - int bytesSubPosition = 0; + var bytesSubPosition = 0; // Byte to look up in the dictionary byte outputBase32Byte = 0; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int outputBase32BytePosition = 0; +After: + var outputBase32BytePosition = 0; +*/ - // The number of bits filled in the current output byte +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: int outputBase32BytePosition = 0; +After: + var outputBase32BytePosition = 0; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int outputBase32BytePosition = 0; +After: + var outputBase32BytePosition = 0; +*/ + + + // The number of bits filled in the current output byte + var outputBase32BytePosition = 0; // Iterate through input buffer until we reach past the end of it while (bytesPosition < bytes.Length) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int bitsAvailableInByte = Math.Min(InByteSize - bytesSubPosition, OutByteSize - outputBase32BytePosition); +After: + var bitsAvailableInByte = Math.Min(InByteSize - bytesSubPosition, OutByteSize - outputBase32BytePosition); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int bitsAvailableInByte = Math.Min(InByteSize - bytesSubPosition, OutByteSize - outputBase32BytePosition); +After: + var bitsAvailableInByte = Math.Min(InByteSize - bytesSubPosition, OutByteSize - outputBase32BytePosition); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int bitsAvailableInByte = Math.Min(InByteSize - bytesSubPosition, OutByteSize - outputBase32BytePosition); +After: + var bitsAvailableInByte = Math.Min(InByteSize - bytesSubPosition, OutByteSize - outputBase32BytePosition); +*/ + { // Calculate the number of bits we can extract out of current input byte to fill missing bits in the output byte - int bitsAvailableInByte = Math.Min(InByteSize - bytesSubPosition, OutByteSize - outputBase32BytePosition); + var bitsAvailableInByte = Math.Min(InByteSize - bytesSubPosition, OutByteSize - outputBase32BytePosition); // Make space in the output byte outputBase32Byte <<= bitsAvailableInByte; @@ -287,21 +538,119 @@ public static byte[] FromBase32String(string base32String) else if (base32String == string.Empty) { return new byte[0]; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string base32StringUpperCase = base32String.ToUpperInvariant(); +After: + var base32StringUpperCase = base32String.ToUpperInvariant(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string base32StringUpperCase = base32String.ToUpperInvariant(); +After: + var base32StringUpperCase = base32String.ToUpperInvariant(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string base32StringUpperCase = base32String.ToUpperInvariant(); +After: + var base32StringUpperCase = base32String.ToUpperInvariant(); +*/ + } // Convert to upper-case - string base32StringUpperCase = base32String.ToUpperInvariant(); + var base32StringUpperCase = base32String.ToUpperInvariant(); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + byte[] outputBytes = new byte[base32StringUpperCase.Length * OutByteSize / InByteSize]; +After: + var outputBytes = new byte[base32StringUpperCase.Length * OutByteSize / InByteSize]; +*/ - // Prepare output byte array +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + byte[] outputBytes = new byte[base32StringUpperCase.Length * OutByteSize / InByteSize]; +After: + var outputBytes = new byte[base32StringUpperCase.Length * OutByteSize / InByteSize]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: byte[] outputBytes = new byte[base32StringUpperCase.Length * OutByteSize / InByteSize]; +After: + var outputBytes = new byte[base32StringUpperCase.Length * OutByteSize / InByteSize]; +*/ + + + // Prepare output byte array + var outputBytes = new byte[base32StringUpperCase.Length * OutByteSize / InByteSize]; // Check the size if (outputBytes.Length == 0) { throw new ArgumentException("Specified string is not valid Base32 format because it doesn''t have enough data to construct a complete byte array"); - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int base32Position = 0; - // Position in the string + // Offset inside the character in the string + int base32SubPosition = 0; + + // Position within outputBytes array + int outputBytePosition = 0; + + // The number of bits filled in the current output byte + int outputByteSubPosition = 0; + + // Normally we would iterate on the input array but in this case we actually iterate on the output array + // We do it because output array doesn''t have overflow bits, while input does and it will cause output array overflow if we don''t stop in time + while (outputBytePosition < outputBytes.Length) + { + // Look up current character in the dictionary to convert it to byte + int currentBase32Byte = Base32Alphabet.IndexOf(base32StringUpperCase[base32Position]); + + // Check if found + if (currentBase32Byte < 0) + { + throw new ArgumentException(string.Format("Specified string is not valid Base32 format because character \"{0}\" does not exist in Base32 alphabet", base32String[base32Position])); + } + + // Calculate the number of bits we can extract out of current input character to fill missing bits in the output byte + int bitsAvailableInByte = Math.Min(OutByteSize - base32SubPosition, InByteSize - outputByteSubPosition); +After: + var base32Position = 0; + + // Offset inside the character in the string + var base32SubPosition = 0; + + // Position within outputBytes array + var outputBytePosition = 0; + + // The number of bits filled in the current output byte + var outputByteSubPosition = 0; + + // Normally we would iterate on the input array but in this case we actually iterate on the output array + // We do it because output array doesn''t have overflow bits, while input does and it will cause output array overflow if we don''t stop in time + while (outputBytePosition < outputBytes.Length) + { + // Look up current character in the dictionary to convert it to byte + var currentBase32Byte = Base32Alphabet.IndexOf(base32StringUpperCase[base32Position]); + + // Check if found + if (currentBase32Byte < 0) + { + throw new ArgumentException(string.Format("Specified string is not valid Base32 format because character \"{0}\" does not exist in Base32 alphabet", base32String[base32Position])); + } + + // Calculate the number of bits we can extract out of current input character to fill missing bits in the output byte + var bitsAvailableInByte = Math.Min(OutByteSize - base32SubPosition, InByteSize - outputByteSubPosition); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: int base32Position = 0; // Offset inside the character in the string @@ -328,6 +677,121 @@ public static byte[] FromBase32String(string base32String) // Calculate the number of bits we can extract out of current input character to fill missing bits in the output byte int bitsAvailableInByte = Math.Min(OutByteSize - base32SubPosition, InByteSize - outputByteSubPosition); +After: + var base32Position = 0; + + // Offset inside the character in the string + var base32SubPosition = 0; + + // Position within outputBytes array + var outputBytePosition = 0; + + // The number of bits filled in the current output byte + var outputByteSubPosition = 0; + + // Normally we would iterate on the input array but in this case we actually iterate on the output array + // We do it because output array doesn''t have overflow bits, while input does and it will cause output array overflow if we don''t stop in time + while (outputBytePosition < outputBytes.Length) + { + // Look up current character in the dictionary to convert it to byte + var currentBase32Byte = Base32Alphabet.IndexOf(base32StringUpperCase[base32Position]); + + // Check if found + if (currentBase32Byte < 0) + { + throw new ArgumentException(string.Format("Specified string is not valid Base32 format because character \"{0}\" does not exist in Base32 alphabet", base32String[base32Position])); + } + + // Calculate the number of bits we can extract out of current input character to fill missing bits in the output byte + var bitsAvailableInByte = Math.Min(OutByteSize - base32SubPosition, InByteSize - outputByteSubPosition); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int base32Position = 0; + + // Offset inside the character in the string + int base32SubPosition = 0; + + // Position within outputBytes array + int outputBytePosition = 0; + + // The number of bits filled in the current output byte + int outputByteSubPosition = 0; + + // Normally we would iterate on the input array but in this case we actually iterate on the output array + // We do it because output array doesn''t have overflow bits, while input does and it will cause output array overflow if we don''t stop in time + while (outputBytePosition < outputBytes.Length) + { + // Look up current character in the dictionary to convert it to byte + int currentBase32Byte = Base32Alphabet.IndexOf(base32StringUpperCase[base32Position]); + + // Check if found + if (currentBase32Byte < 0) + { + throw new ArgumentException(string.Format("Specified string is not valid Base32 format because character \"{0}\" does not exist in Base32 alphabet", base32String[base32Position])); + } + + // Calculate the number of bits we can extract out of current input character to fill missing bits in the output byte + int bitsAvailableInByte = Math.Min(OutByteSize - base32SubPosition, InByteSize - outputByteSubPosition); +After: + var base32Position = 0; + + // Offset inside the character in the string + var base32SubPosition = 0; + + // Position within outputBytes array + var outputBytePosition = 0; + + // The number of bits filled in the current output byte + var outputByteSubPosition = 0; + + // Normally we would iterate on the input array but in this case we actually iterate on the output array + // We do it because output array doesn''t have overflow bits, while input does and it will cause output array overflow if we don''t stop in time + while (outputBytePosition < outputBytes.Length) + { + // Look up current character in the dictionary to convert it to byte + var currentBase32Byte = Base32Alphabet.IndexOf(base32StringUpperCase[base32Position]); + + // Check if found + if (currentBase32Byte < 0) + { + throw new ArgumentException(string.Format("Specified string is not valid Base32 format because character \"{0}\" does not exist in Base32 alphabet", base32String[base32Position])); + } + + // Calculate the number of bits we can extract out of current input character to fill missing bits in the output byte + var bitsAvailableInByte = Math.Min(OutByteSize - base32SubPosition, InByteSize - outputByteSubPosition); +*/ + + } + + // Position in the string + var base32Position = 0; + + // Offset inside the character in the string + var base32SubPosition = 0; + + // Position within outputBytes array + var outputBytePosition = 0; + + // The number of bits filled in the current output byte + var outputByteSubPosition = 0; + + // Normally we would iterate on the input array but in this case we actually iterate on the output array + // We do it because output array doesn''t have overflow bits, while input does and it will cause output array overflow if we don''t stop in time + while (outputBytePosition < outputBytes.Length) + { + // Look up current character in the dictionary to convert it to byte + var currentBase32Byte = Base32Alphabet.IndexOf(base32StringUpperCase[base32Position]); + + // Check if found + if (currentBase32Byte < 0) + { + throw new ArgumentException(string.Format("Specified string is not valid Base32 format because character \"{0}\" does not exist in Base32 alphabet", base32String[base32Position])); + } + + // Calculate the number of bits we can extract out of current input character to fill missing bits in the output byte + var bitsAvailableInByte = Math.Min(OutByteSize - base32SubPosition, InByteSize - outputByteSubPosition); // Make space in the output byte outputBytes[outputBytePosition] <<= bitsAvailableInByte; @@ -359,6 +823,6 @@ public static byte[] FromBase32String(string base32String) } return outputBytes; - } + } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Internals/Formatting.cs b/src/NATS.Client/v1/Internals/Formatting.cs index 78b018cc..a3b66e1c 100644 --- a/src/NATS.Client/v1/Internals/Formatting.cs +++ b/src/NATS.Client/v1/Internals/Formatting.cs @@ -1,4 +1,4 @@ -using System.Globalization; +using System.Globalization; namespace NATS.Client.Internals { @@ -7,4 +7,4 @@ internal static class Formatting internal static string ToNumericString(this int v) => v.ToString(CultureInfo.InvariantCulture); internal static string ToNumericString(this long v) => v.ToString(CultureInfo.InvariantCulture); } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Internals/HeaderStatusReader.cs b/src/NATS.Client/v1/Internals/HeaderStatusReader.cs index 4a50144b..0eac4595 100644 --- a/src/NATS.Client/v1/Internals/HeaderStatusReader.cs +++ b/src/NATS.Client/v1/Internals/HeaderStatusReader.cs @@ -13,10 +13,12 @@ public class HeaderStatusReader /// /// A byte array of a serialized MsgStatus/MsgHeader class. /// Count of bytes in the serialized array. - public HeaderStatusReader(byte[] bytes, int byteCount) { + public HeaderStatusReader(byte[] bytes, int byteCount) + { // basic validation first to help fail fast - if (bytes == null || bytes.Length == 0) { + if (bytes == null || bytes.Length == 0) + { throw new NATSInvalidHeaderException(SerializedHeaderCannotBeNullOrEmpty); } if (bytes.Length < byteCount) @@ -29,32 +31,86 @@ public HeaderStatusReader(byte[] bytes, int byteCount) { } // is tis the correct version - for (int x = 0; x < HeaderVersionBytesLen; x++) { - if (bytes[x] != HeaderVersionBytes[x]) { + for (var x = 0; x < HeaderVersionBytesLen; x++) + { + if (bytes[x] != HeaderVersionBytes[x]) + { throw new NATSInvalidHeaderException(InvalidHeaderVersion); } } // does the header end properly _serializedLength = byteCount; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Token terminus = new Token(bytes, _serializedLength, _serializedLength - 2, TokenType.Crlf); + Token token = new Token(bytes, _serializedLength, HeaderVersionBytesLen, null); +After: + var terminus = new Token(bytes, _serializedLength, _serializedLength - 2, TokenType.Crlf); + var token = new Token(bytes, _serializedLength, HeaderVersionBytesLen, null); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: Token terminus = new Token(bytes, _serializedLength, _serializedLength - 2, TokenType.Crlf); Token token = new Token(bytes, _serializedLength, HeaderVersionBytesLen, null); +After: + var terminus = new Token(bytes, _serializedLength, _serializedLength - 2, TokenType.Crlf); + var token = new Token(bytes, _serializedLength, HeaderVersionBytesLen, null); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Token terminus = new Token(bytes, _serializedLength, _serializedLength - 2, TokenType.Crlf); + Token token = new Token(bytes, _serializedLength, HeaderVersionBytesLen, null); +After: + var terminus = new Token(bytes, _serializedLength, _serializedLength - 2, TokenType.Crlf); + var token = new Token(bytes, _serializedLength, HeaderVersionBytesLen, null); +*/ + + var terminus = new Token(bytes, _serializedLength, _serializedLength - 2, TokenType.Crlf); + var token = new Token(bytes, _serializedLength, HeaderVersionBytesLen, null); _header = new MsgHeader(); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + bool hadStatus = false; +After: + var hadStatus = false; +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: bool hadStatus = false; - if (token.IsType(TokenType.Space)) { +After: + var hadStatus = false; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + bool hadStatus = false; +After: + var hadStatus = false; +*/ + + + var hadStatus = false; + if (token.IsType(TokenType.Space)) + { token = InitStatus(bytes, _serializedLength, token); - if (token.SamePoint(terminus)) { + if (token.SamePoint(terminus)) + { return; // status only } hadStatus = true; } - if (token.IsType(TokenType.Crlf)) { + if (token.IsType(TokenType.Crlf)) + { InitHeader(bytes, _serializedLength, token, hadStatus); } - else { + else + { throw new NATSInvalidHeaderException(InvalidHeaderComposition); } } @@ -65,19 +121,72 @@ public HeaderStatusReader(byte[] bytes, int byteCount) { public MsgStatus Status => _status; - private void InitHeader(byte[] serialized, int len, Token tCrlf, bool hadStatus) { - // REGULAR HEADER + private void InitHeader(byte[] serialized, int len, Token tCrlf, bool hadStatus) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Token peek = new Token(serialized, len, tCrlf, null); +After: + var peek = new Token(serialized, len, tCrlf, null); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Token peek = new Token(serialized, len, tCrlf, null); +After: + var peek = new Token(serialized, len, tCrlf, null); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: Token peek = new Token(serialized, len, tCrlf, null); - while (peek.IsType(TokenType.Text)) { +After: + var peek = new Token(serialized, len, tCrlf, null); +*/ + + { + // REGULAR HEADER + var peek = new Token(serialized, len, tCrlf, null); + while (peek.IsType(TokenType.Text)) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Token tKey = new Token(serialized, len, tCrlf, TokenType.Key); + Token tVal = new Token(serialized, len, tKey, null); +After: + var tKey = new Token(serialized, len, tCrlf, TokenType.Key); + var tVal = new Token(serialized, len, tKey, null); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: Token tKey = new Token(serialized, len, tCrlf, TokenType.Key); Token tVal = new Token(serialized, len, tKey, null); - if (tVal.IsType(TokenType.Space)) { +After: + var tKey = new Token(serialized, len, tCrlf, TokenType.Key); + var tVal = new Token(serialized, len, tKey, null); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Token tKey = new Token(serialized, len, tCrlf, TokenType.Key); + Token tVal = new Token(serialized, len, tKey, null); +After: + var tKey = new Token(serialized, len, tCrlf, TokenType.Key); + var tVal = new Token(serialized, len, tKey, null); +*/ + + { + var tKey = new Token(serialized, len, tCrlf, TokenType.Key); + var tVal = new Token(serialized, len, tKey, null); + if (tVal.IsType(TokenType.Space)) + { tVal = new Token(serialized, len, tVal, null); } - if (tVal.IsType(TokenType.Text)) { + if (tVal.IsType(TokenType.Text)) + { tCrlf = new Token(serialized, len, tVal, TokenType.Crlf); } - else { + else + { tVal.MustBe(TokenType.Crlf); tCrlf = tVal; } @@ -87,21 +196,51 @@ private void InitHeader(byte[] serialized, int len, Token tCrlf, bool hadStatus) peek.MustBe(TokenType.Crlf); } - private Token InitStatus(byte[] serialized, int len, Token tSpace) { + private Token InitStatus(byte[] serialized, int len, Token tSpace) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: Token tCode = new Token(serialized, len, tSpace, TokenType.Word); Token tVal = new Token(serialized, len, tCode, null); +After: + var tCode = new Token(serialized, len, tSpace, TokenType.Word); + var tVal = new Token(serialized, len, tCode, null); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Token tCode = new Token(serialized, len, tSpace, TokenType.Word); + Token tVal = new Token(serialized, len, tCode, null); +After: + var tCode = new Token(serialized, len, tSpace, TokenType.Word); + var tVal = new Token(serialized, len, tCode, null); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Token tCode = new Token(serialized, len, tSpace, TokenType.Word); + Token tVal = new Token(serialized, len, tCode, null); +After: + var tCode = new Token(serialized, len, tSpace, TokenType.Word); + var tVal = new Token(serialized, len, tCode, null); +*/ + + { + var tCode = new Token(serialized, len, tSpace, TokenType.Word); + var tVal = new Token(serialized, len, tCode, null); Token crlf; - if (tVal.IsType(TokenType.Space)) { + if (tVal.IsType(TokenType.Space)) + { tVal = new Token(serialized, len, tVal, TokenType.Text); crlf = new Token(serialized, len, tVal, TokenType.Crlf); } - else { + else + { tVal.MustBe(TokenType.Crlf); crlf = tVal; } _status = new MsgStatus(tCode, tVal); return crlf; } - + } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Internals/InFlightRequest.cs b/src/NATS.Client/v1/Internals/InFlightRequest.cs index a33bc354..eee3c8b2 100644 --- a/src/NATS.Client/v1/Internals/InFlightRequest.cs +++ b/src/NATS.Client/v1/Internals/InFlightRequest.cs @@ -1,4 +1,4 @@ -// Copyright 2017-2020 The NATS Authors +// Copyright 2017-2020 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/src/NATS.Client/v1/Internals/InterlockedUtils.cs b/src/NATS.Client/v1/Internals/InterlockedUtils.cs index 81fb63cf..28838473 100644 --- a/src/NATS.Client/v1/Internals/InterlockedUtils.cs +++ b/src/NATS.Client/v1/Internals/InterlockedUtils.cs @@ -1,4 +1,4 @@ -// Copyright 2021 The NATS Authors +// Copyright 2021 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: diff --git a/src/NATS.Client/v1/Internals/JetStreamConstants.cs b/src/NATS.Client/v1/Internals/JetStreamConstants.cs index 48315862..ebd69dd9 100644 --- a/src/NATS.Client/v1/Internals/JetStreamConstants.cs +++ b/src/NATS.Client/v1/Internals/JetStreamConstants.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace NATS.Client.Internals { @@ -34,7 +34,7 @@ public static class JetStreamConstants /// The standard JetStream Prefix /// public const string DefaultApiPrefix = "$JS.API."; - + /// /// The standard JetStream API Prefix /// @@ -146,12 +146,12 @@ public static class JetStreamConstants /// JetStream expected message ID header name. /// public const string MsgIdHeader = "Nats-Msg-Id"; - + /// /// JetStream expected stream header name. /// public const string ExpStreamHeader = "Nats-Expected-Stream"; - + /// /// JetStream expected last sequence header name. /// @@ -161,12 +161,12 @@ public static class JetStreamConstants /// JetStream expected last message ID header Name. /// public const string ExpLastIdHeader = "Nats-Expected-Last-Msg-Id"; - + /// /// JetStream expected last sequence header name. /// public const string ExpLastSubjectSeqHeader = "Nats-Expected-Last-Subject-Sequence"; - + public const string LastConsumerHeader = "Nats-Last-Consumer"; public const string LastStreamHeader = "Nats-Last-Stream"; public const string ConsumerStalledHeader = "Nats-Consumer-Stalled"; @@ -176,46 +176,46 @@ public static class JetStreamConstants public const string RollupHeaderSubject = "sub"; public const string RollupHeaderAll = "all"; - public const string NatsStream = "Nats-Stream"; - public const string NatsSequence = "Nats-Sequence"; - public const string NatsTimestamp = "Nats-Time-Stamp"; - public const string NatsSubject = "Nats-Subject"; + public const string NatsStream = "Nats-Stream"; + public const string NatsSequence = "Nats-Sequence"; + public const string NatsTimestamp = "Nats-Time-Stamp"; + public const string NatsSubject = "Nats-Subject"; public const string NatsLastSequence = "Nats-Last-Sequence"; - + public const string NatsPendingMessages = "Nats-Pending-Messages"; - public const string NatsPendingBytes = "Nats-Pending-Bytes"; + public const string NatsPendingBytes = "Nats-Pending-Bytes"; public const int JsConsumerNotFoundErr = 10014; public const int JsNoMessageFoundErr = 10037; public const int JsWrongLastSequence = 10071; - public const string BadRequest = "Bad Request"; // 400 - public const string NoMessages = "No Messages"; // 404 - public const string ConsumerDeleted = "Consumer Deleted"; // 409 - public const string ConsumerIsPushBased = "Consumer is push based"; // 409 + public const string BadRequest = "Bad Request"; // 400 + public const string NoMessages = "No Messages"; // 404 + public const string ConsumerDeleted = "Consumer Deleted"; // 409 + public const string ConsumerIsPushBased = "Consumer is push based"; // 409 public const string MessageSizeExceedsMaxBytes = "Message Size Exceeds MaxBytes"; // 409 - public const string ExceededMaxWaiting = "Exceeded MaxWaiting"; // 409 - public const string ExceededMaxRequestBatch = "Exceeded MaxRequestBatch"; // 409 - public const string ExceededMaxRequestExpires = "Exceeded MaxRequestExpires"; // 409 + public const string ExceededMaxWaiting = "Exceeded MaxWaiting"; // 409 + public const string ExceededMaxRequestBatch = "Exceeded MaxRequestBatch"; // 409 + public const string ExceededMaxRequestExpires = "Exceeded MaxRequestExpires"; // 409 public const string ExceededMaxRequestMaxBytes = "Exceeded MaxRequestMaxBytes"; // 409 - public const string BatchCompleted = "Batch Completed"; // 409 informational - public const string ServerShutdown = "Server Shutdown"; // 409 informational with headers - + public const string BatchCompleted = "Batch Completed"; // 409 informational + public const string ServerShutdown = "Server Shutdown"; // 409 informational with headers + [Obsolete("This property is obsolete. Use LastConsumerHeader instead.", false)] public const string LastConsumerHdr = "Nats-Last-Consumer"; [Obsolete("This property is obsolete. Use LastStreamHeader instead.", false)] public const string LastStreamHdr = "Nats-Last-Stream"; - + [Obsolete("This property is obsolete. Use ConsumerStalledHeader instead.", false)] public const string ConsumerStalledHdr = "Nats-Consumer-Stalled"; - + [Obsolete("This property is obsolete. Use RollupHeader instead.", false)] public const string RollupHdr = "Nats-Rollup"; - + [Obsolete("This property is obsolete. Use MsgSizeHeader instead.", false)] public const string MsgSizeHdr = "Nats-Msg-Size"; } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Internals/JsonUtils.cs b/src/NATS.Client/v1/Internals/JsonUtils.cs index 9ef15791..de3fc706 100644 --- a/src/NATS.Client/v1/Internals/JsonUtils.cs +++ b/src/NATS.Client/v1/Internals/JsonUtils.cs @@ -24,81 +24,291 @@ public static class JsonUtils public static readonly JSONNode MinusOne = new JSONNumber(-1); public static int AsIntOrMinus1(JSONNode node, string field) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONNode possible = node[field]; +After: + var possible = node[field]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONNode possible = node[field]; +After: + var possible = node[field]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: JSONNode possible = node[field]; +After: + var possible = node[field]; +*/ + + { + var possible = node[field]; return possible.IsNumber ? possible.AsInt : -1; } public static long AsLongOrZero(JSONNode node, string field) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONNode possible = node[field]; +After: + var possible = node[field]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: JSONNode possible = node[field]; +After: + var possible = node[field]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONNode possible = node[field]; +After: + var possible = node[field]; +*/ + + { + var possible = node[field]; return possible.IsNumber ? possible.AsLong : 0; } public static long AsLongOrMinus1(JSONNode node, string field) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONNode possible = node[field]; +After: + var possible = node[field]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONNode possible = node[field]; +After: + var possible = node[field]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: JSONNode possible = node[field]; +After: + var possible = node[field]; +*/ + + { + var possible = node[field]; return possible.IsNumber ? possible.AsLong : -1; } public static ulong AsUlongOrZero(JSONNode node, string field) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONNode possible = node[field]; +After: + var possible = node[field]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: JSONNode possible = node[field]; +After: + var possible = node[field]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONNode possible = node[field]; +After: + var possible = node[field]; +*/ + + { + var possible = node[field]; return possible.IsNumber ? possible.AsUlong : 0; } public static ulong AsUlongOr(JSONNode node, string field, ulong dflt) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONNode possible = node[field]; +After: + var possible = node[field]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONNode possible = node[field]; +After: + var possible = node[field]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: JSONNode possible = node[field]; +After: + var possible = node[field]; +*/ + + { + var possible = node[field]; return possible.IsNumber ? possible.AsUlong : dflt; } public static Duration AsDuration(JSONNode node, string field, Duration dflt) { if (dflt == null) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: long l = node.GetValueOrDefault(field, long.MinValue).AsLong; +After: + var l = node.GetValueOrDefault(field, long.MinValue).AsLong; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + long l = node.GetValueOrDefault(field, long.MinValue).AsLong; +After: + var l = node.GetValueOrDefault(field, long.MinValue).AsLong; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + long l = node.GetValueOrDefault(field, long.MinValue).AsLong; +After: + var l = node.GetValueOrDefault(field, long.MinValue).AsLong; +*/ + + { + var l = node.GetValueOrDefault(field, long.MinValue).AsLong; return l == long.MinValue ? null : Duration.OfNanos(l); } return Duration.OfNanos(node.GetValueOrDefault(field, dflt.Nanos).AsLong); } public static List StringList(JSONNode node, string field) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + List list = new List(); +After: + var list = new List(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + List list = new List(); +After: + var list = new List(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: List list = new List(); +After: + var list = new List(); +*/ + + { + var list = new List(); foreach (var child in node[field].Children) { list.Add(child.Value); } - + return list; } public static List DurationList(JSONNode node, string field, bool nullIfEmpty = false) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + List list = new List(); +After: + var list = new List(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + List list = new List(); +After: + var list = new List(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: List list = new List(); +After: + var list = new List(); +*/ + + { + var list = new List(); foreach (var child in node[field].Children) { list.Add(Duration.OfNanos(child.AsLong)); } - + return list.Count == 0 && nullIfEmpty ? null : list; } public static List ListOf(JSONNode node, string field, Func provider, bool nullIfEmpty = false) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: List list = new List(); +After: + var list = new List(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + List list = new List(); +After: + var list = new List(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + List list = new List(); +After: + var list = new List(); +*/ + + { + var list = new List(); foreach (var child in node[field].Children) { list.Add(provider.Invoke(child)); } - + return list.Count == 0 && nullIfEmpty ? null : list; } public static List OptionalStringList(JSONNode node, string field) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + List list = StringList(node, field); +After: + var list = StringList(node, field); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: List list = StringList(node, field); +After: + var list = StringList(node, field); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + List list = StringList(node, field); +After: + var list = StringList(node, field); +*/ + + { + var list = StringList(node, field); return list.Count == 0 ? null : list; } @@ -111,8 +321,29 @@ public static IDictionary StringStringDictionay(JSONNode node, s public static IDictionary StringStringDictionary(JSONNode node, string field, bool nullIfEmpty = false) { IDictionary temp = new Dictionary(); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: JSONNode meta = node[field]; - foreach (string key in meta.Keys) +After: + var meta = node[field]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONNode meta = node[field]; +After: + var meta = node[field]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONNode meta = node[field]; +After: + var meta = node[field]; +*/ + + var meta = node[field]; + foreach (var key in meta.Keys) { temp[key] = meta[key]; } @@ -120,12 +351,39 @@ public static IDictionary StringStringDictionary(JSONNode node, } public static MsgHeader AsHeaders(JSONNode node, string field) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: MsgHeader h = new MsgHeader(); JSONNode hNode = node[field]; +After: + var h = new MsgHeader(); + var hNode = node[field]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + MsgHeader h = new MsgHeader(); + JSONNode hNode = node[field]; +After: + var h = new MsgHeader(); + var hNode = node[field]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + MsgHeader h = new MsgHeader(); + JSONNode hNode = node[field]; +After: + var h = new MsgHeader(); + var hNode = node[field]; +*/ + + { + var h = new MsgHeader(); + var hNode = node[field]; if (hNode != null) { - foreach (string key in hNode.Keys) + foreach (var key in hNode.Keys) { foreach (var val in hNode[key].Values) { @@ -135,11 +393,12 @@ public static MsgHeader AsHeaders(JSONNode node, string field) } return h; } - - public static byte[] AsByteArrayFromBase64(JSONNode node) { + + public static byte[] AsByteArrayFromBase64(JSONNode node) + { return string.IsNullOrWhiteSpace(node.Value) ? null : Convert.FromBase64String(node.Value); } - + public static DateTime AsDate(JSONNode node) { try @@ -151,7 +410,7 @@ public static DateTime AsDate(JSONNode node) return DateTime.MinValue; } } - + public static DateTime? AsOptionalDate(JSONNode node) { try @@ -179,15 +438,36 @@ public static string ToString(DateTime? dt) // Assume MinValue is Unset return !dt.HasValue || dt.Equals(DateTime.MinValue) ? null : UnsafeToString(dt.Value); } - + public static string UnsafeToString(DateTime dt) { return dt.ToUniversalTime().ToString("O"); } public static JSONArray ToArray(List list) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONArray arr = new JSONArray(); +After: + var arr = new JSONArray(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONArray arr = new JSONArray(); +After: + var arr = new JSONArray(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: JSONArray arr = new JSONArray(); +After: + var arr = new JSONArray(); +*/ + + { + var arr = new JSONArray(); if (list == null) { return arr; @@ -203,7 +483,7 @@ public static string ToKey(Type type) { return "\"" + type.Name + "\":"; } - + public static byte[] SimpleMessageBody(string name, long value) { return Encoding.ASCII.GetBytes("{\"" + name + "\":" + value + "}"); @@ -218,21 +498,22 @@ public static byte[] SimpleMessageBody(string name, string value) { return Encoding.ASCII.GetBytes("{\"" + name + "\":\"" + value + "\"}"); } - + public static byte[] Serialize(JSONNode node) { return Encoding.ASCII.GetBytes(node.ToString()); } - public static string ObjectString(string name, object o) { + public static string ObjectString(string name, object o) + { switch (o) { - case null: - return name + "=null"; - case JsonSerializable serializable: - return name + serializable.ToJsonNode(); - default: - return o.ToString(); + case null: + return name + "=null"; + case JsonSerializable serializable: + return name + serializable.ToJsonNode(); + default: + return o.ToString(); } } @@ -272,10 +553,33 @@ public static void AddField(JSONObject o, string field, JSONNode value) } } - public static void AddField(JSONObject o, string fname, IDictionary dictionary) { - if (dictionary != null && dictionary.Count > 0) { + public static void AddField(JSONObject o, string fname, IDictionary dictionary) + { + if (dictionary != null && dictionary.Count > 0) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: JSONObject d = new JSONObject(); - foreach (string key in dictionary.Keys) +After: + var d = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONObject d = new JSONObject(); +After: + var d = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject d = new JSONObject(); +After: + var d = new JSONObject(); +*/ + + { + var d = new JSONObject(); + foreach (var key in dictionary.Keys) { d[key] = dictionary[key]; } @@ -391,7 +695,7 @@ public static void AddField(JSONObject o, string field, ulong? value) o[field] = value; } } - + public static void AddField(JSONObject o, string field, bool value) { if (value) @@ -399,7 +703,7 @@ public static void AddField(JSONObject o, string field, bool value) o[field] = true; } } - + public static void AddField(JSONObject o, string field, bool? value) { if (value != null && value == true) @@ -411,9 +715,30 @@ public static void AddField(JSONObject o, string field, bool? value) public static void AddField(JSONObject o, string field, IList values) { if (values != null && values.Count > 0) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: JSONArray ja = new JSONArray(); - foreach (Duration d in values) +After: + var ja = new JSONArray(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONArray ja = new JSONArray(); +After: + var ja = new JSONArray(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONArray ja = new JSONArray(); +After: + var ja = new JSONArray(); +*/ + + { + var ja = new JSONArray(); + foreach (var d in values) { ja.Add(d.Nanos); } @@ -424,9 +749,30 @@ public static void AddField(JSONObject o, string field, IList values) public static void AddField(JSONObject o, string field, string[] values) { if (values != null && values.Length > 0) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: JSONArray ja = new JSONArray(); - foreach (string v in values) +After: + var ja = new JSONArray(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONArray ja = new JSONArray(); +After: + var ja = new JSONArray(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONArray ja = new JSONArray(); +After: + var ja = new JSONArray(); +*/ + + { + var ja = new JSONArray(); + foreach (var v in values) { ja.Add(v); } @@ -437,9 +783,30 @@ public static void AddField(JSONObject o, string field, string[] values) public static void AddField(JSONObject o, string field, IList values) { if (values != null && values.Count > 0) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONArray ja = new JSONArray(); +After: + var ja = new JSONArray(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: JSONArray ja = new JSONArray(); - foreach (string v in values) +After: + var ja = new JSONArray(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONArray ja = new JSONArray(); +After: + var ja = new JSONArray(); +*/ + + { + var ja = new JSONArray(); + foreach (var v in values) { ja.Add(v); } @@ -450,8 +817,29 @@ public static void AddField(JSONObject o, string field, IList values) public static void AddField(JSONObject o, string field, IList values) where T : JsonSerializable { if (values != null && values.Count > 0) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONArray ja = new JSONArray(); +After: + var ja = new JSONArray(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONArray ja = new JSONArray(); +After: + var ja = new JSONArray(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: JSONArray ja = new JSONArray(); +After: + var ja = new JSONArray(); +*/ + + { + var ja = new JSONArray(); foreach (JsonSerializable v in values) { ja.Add(v.ToJsonNode()); @@ -463,8 +851,29 @@ public static void AddField(JSONObject o, string field, IList values) wher public static void AddField(JSONObject o, string field, MsgHeader headers) { if (headers != null && headers.Count > 0) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject h = new JSONObject(); +After: + var h = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: JSONObject h = new JSONObject(); +After: + var h = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject h = new JSONObject(); +After: + var h = new JSONObject(); +*/ + + { + var h = new JSONObject(); foreach (string key in headers.Keys) { AddField(h, key, headers.GetValues(key)); diff --git a/src/NATS.Client/v1/Internals/JwtUtils.cs b/src/NATS.Client/v1/Internals/JwtUtils.cs index 723a20b4..e0ec53f8 100644 --- a/src/NATS.Client/v1/Internals/JwtUtils.cs +++ b/src/NATS.Client/v1/Internals/JwtUtils.cs @@ -152,26 +152,110 @@ public static string IssueUserJWT(NkeyPair signingKey, string publicUserKey, str { throw new ArgumentException( "IssueUserJWT requires an account key for the signingKey parameter, but got " + signingKey.Type); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + NkeyPair accountKey = Nkeys.FromPublicKey(nats.IssuerAccount.ToCharArray()); +After: + var accountKey = Nkeys.FromPublicKey(nats.IssuerAccount.ToCharArray()); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + NkeyPair accountKey = Nkeys.FromPublicKey(nats.IssuerAccount.ToCharArray()); +After: + var accountKey = Nkeys.FromPublicKey(nats.IssuerAccount.ToCharArray()); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + NkeyPair accountKey = Nkeys.FromPublicKey(nats.IssuerAccount.ToCharArray()); +After: + var accountKey = Nkeys.FromPublicKey(nats.IssuerAccount.ToCharArray()); +*/ + } // Validate the accountId: - NkeyPair accountKey = Nkeys.FromPublicKey(nats.IssuerAccount.ToCharArray()); + var accountKey = Nkeys.FromPublicKey(nats.IssuerAccount.ToCharArray()); if (accountKey.Type != Nkeys.PrefixType.Account) { throw new ArgumentException( "IssueUserJWT requires an account key for the accountId parameter, but got " + accountKey.Type); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + NkeyPair userKey = Nkeys.FromPublicKey(publicUserKey.ToCharArray()); +After: + var userKey = Nkeys.FromPublicKey(publicUserKey.ToCharArray()); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + NkeyPair userKey = Nkeys.FromPublicKey(publicUserKey.ToCharArray()); +After: + var userKey = Nkeys.FromPublicKey(publicUserKey.ToCharArray()); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + NkeyPair userKey = Nkeys.FromPublicKey(publicUserKey.ToCharArray()); +After: + var userKey = Nkeys.FromPublicKey(publicUserKey.ToCharArray()); +*/ + } // Validate the publicUserKey: - NkeyPair userKey = Nkeys.FromPublicKey(publicUserKey.ToCharArray()); + var userKey = Nkeys.FromPublicKey(publicUserKey.ToCharArray()); if (userKey.Type != Nkeys.PrefixType.User) { throw new ArgumentException("IssueUserJWT requires a user key for the publicUserKey parameter, but got " + userKey.Type); - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string accSigningKeyPub = signingKey.EncodedPublicKey; +After: + var accSigningKeyPub = signingKey.EncodedPublicKey; +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: string accSigningKeyPub = signingKey.EncodedPublicKey; +After: + var accSigningKeyPub = signingKey.EncodedPublicKey; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string accSigningKeyPub = signingKey.EncodedPublicKey; +After: + var accSigningKeyPub = signingKey.EncodedPublicKey; +*/ + + } + + var accSigningKeyPub = signingKey.EncodedPublicKey; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string claimName = string.IsNullOrWhiteSpace(name) ? publicUserKey : name; +After: + var claimName = string.IsNullOrWhiteSpace(name) ? publicUserKey : name; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string claimName = string.IsNullOrWhiteSpace(name) ? publicUserKey : name; +After: + var claimName = string.IsNullOrWhiteSpace(name) ? publicUserKey : name; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string claimName = string.IsNullOrWhiteSpace(name) ? publicUserKey : name; +After: + var claimName = string.IsNullOrWhiteSpace(name) ? publicUserKey : name; +*/ + + + var claimName = string.IsNullOrWhiteSpace(name) ? publicUserKey : name; return issueJWT(signingKey, publicUserKey, claimName, expiration, issuedAt, accSigningKeyPub, audience, nats); } @@ -190,8 +274,29 @@ public static string IssueUserJWT(NkeyPair signingKey, string publicUserKey, str /// a JWT public static string issueJWT(NkeyPair signingKey, string publicUserKey, string name, Duration expiration, long issuedAt, string accSigningKeyPub, string audience, JsonSerializable nats) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Claim claim = new Claim(); +After: + var claim = new Claim(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Claim claim = new Claim(); +After: + var claim = new Claim(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: Claim claim = new Claim(); +After: + var claim = new Claim(); +*/ + + { + var claim = new Claim(); claim.Aud = audience; claim.Iat = issuedAt; claim.Iss = accSigningKeyPub; @@ -199,22 +304,112 @@ public static string issueJWT(NkeyPair signingKey, string publicUserKey, string claim.Sub = publicUserKey; claim.Exp = expiration; claim.Nats = nats; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string claimJson = claim.ToJsonString(); +After: + var claimJson = claim.ToJsonString(); +*/ - // Issue At time is stored in unix seconds +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: string claimJson = claim.ToJsonString(); +After: + var claimJson = claim.ToJsonString(); +*/ - // Compute jti, a base32 encoded sha256 hash +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string claimJson = claim.ToJsonString(); +After: + var claimJson = claim.ToJsonString(); +*/ + + + // Issue At time is stored in unix seconds + var claimJson = claim.ToJsonString(); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: IncrementalHash hasher = IncrementalHash.CreateHash(HashAlgorithmName.SHA256); +After: + var hasher = IncrementalHash.CreateHash(HashAlgorithmName.SHA256); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + IncrementalHash hasher = IncrementalHash.CreateHash(HashAlgorithmName.SHA256); +After: + var hasher = IncrementalHash.CreateHash(HashAlgorithmName.SHA256); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + IncrementalHash hasher = IncrementalHash.CreateHash(HashAlgorithmName.SHA256); +After: + var hasher = IncrementalHash.CreateHash(HashAlgorithmName.SHA256); +*/ + + + // Compute jti, a base32 encoded sha256 hash + var hasher = IncrementalHash.CreateHash(HashAlgorithmName.SHA256); hasher.AppendData(Encoding.ASCII.GetBytes(claimJson)); claim.Jti = Base32.Encode(hasher.GetHashAndReset()); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string encBody = ToBase64UrlEncoded(claim.Serialize()); +After: + var encBody = ToBase64UrlEncoded(claim.Serialize()); +*/ - // all three components (header/body/signature) are base64url encoded +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: string encBody = ToBase64UrlEncoded(claim.Serialize()); +After: + var encBody = ToBase64UrlEncoded(claim.Serialize()); +*/ - // compute the signature off of header + body (. included on purpose) +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string encBody = ToBase64UrlEncoded(claim.Serialize()); +After: + var encBody = ToBase64UrlEncoded(claim.Serialize()); +*/ + + + // all three components (header/body/signature) are base64url encoded + var encBody = ToBase64UrlEncoded(claim.Serialize()); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + byte[] sig = Encoding.ASCII.GetBytes(EncodedClaimHeader + "." + encBody); + string encSig = ToBase64UrlEncoded(signingKey.Sign(sig)); +After: + var sig = Encoding.ASCII.GetBytes(EncodedClaimHeader + "." + encBody); + var encSig = ToBase64UrlEncoded(signingKey.Sign(sig)); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + byte[] sig = Encoding.ASCII.GetBytes(EncodedClaimHeader + "." + encBody); + string encSig = ToBase64UrlEncoded(signingKey.Sign(sig)); +After: + var sig = Encoding.ASCII.GetBytes(EncodedClaimHeader + "." + encBody); + var encSig = ToBase64UrlEncoded(signingKey.Sign(sig)); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: byte[] sig = Encoding.ASCII.GetBytes(EncodedClaimHeader + "." + encBody); string encSig = ToBase64UrlEncoded(signingKey.Sign(sig)); +After: + var sig = Encoding.ASCII.GetBytes(EncodedClaimHeader + "." + encBody); + var encSig = ToBase64UrlEncoded(signingKey.Sign(sig)); +*/ + + + // compute the signature off of header + body (. included on purpose) + var sig = Encoding.ASCII.GetBytes(EncodedClaimHeader + "." + encBody); + var encSig = ToBase64UrlEncoded(signingKey.Sign(sig)); // append signature to header and body and return it return EncodedClaimHeader + "." + encBody + "." + encSig; @@ -231,7 +426,8 @@ public static string GetClaimBody(string jwt) } } - public class UserClaim : JsonSerializable { + public class UserClaim : JsonSerializable + { public string IssuerAccount; // User public string[] Tags; // User/GenericFields public string Type = "user"; // User/GenericFields @@ -244,21 +440,66 @@ public class UserClaim : JsonSerializable { public string Locale; // User/UserPermissionLimits/Limits/UserLimits public long Subs = JwtUtils.NoLimit; // User/UserPermissionLimits/Limits/NatsLimits public long Data = JwtUtils.NoLimit; // User/UserPermissionLimits/Limits/NatsLimits - public long Payload = JwtUtils.NoLimit; // User/UserPermissionLimits/Limits/NatsLimits + public +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this.IssuerAccount = issuerAccount; +After: + IssuerAccount = issuerAccount; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this.IssuerAccount = issuerAccount; +After: + IssuerAccount = issuerAccount; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this.IssuerAccount = issuerAccount; +After: + IssuerAccount = issuerAccount; +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ +long Payload = JwtUtils.NoLimit; // User/UserPermissionLimits/Limits/NatsLimits public bool BearerToken; // User/UserPermissionLimits public string[] AllowedConnectionTypes; // User/UserPermissionLimits - - public UserClaim(string issuerAccount) { - this.IssuerAccount = issuerAccount; + + public UserClaim(string issuerAccount) + { + IssuerAccount = issuerAccount; } - - public UserClaim(string issuerAccount, string[] tags) { + + public UserClaim(string issuerAccount, string[] tags) + { IssuerAccount = issuerAccount; Tags = tags; } - - public override JSONNode ToJsonNode() { - JSONObject o = new JSONObject(); + + public override JSONNode ToJsonNode() + { + var o = new JSONObject(); AddField(o, "issuer_account", IssuerAccount); AddField(o, "tags", Tags); AddField(o, "type", Type); @@ -277,49 +518,120 @@ public override JSONNode ToJsonNode() { return o; } } - - public class TimeRange : JsonSerializable { + + public class TimeRange : JsonSerializable + { public string Start; public string End; - - public TimeRange(string start, string end) { + + public TimeRange(string start, string end) + { Start = start; End = end; } - - public override JSONNode ToJsonNode() { + + public override JSONNode ToJsonNode() +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + + { + var o = new JSONObject(); AddField(o, "start", Start); AddField(o, "end", End); return o; } } - - public class ResponsePermission : JsonSerializable { + + public class ResponsePermission : JsonSerializable + { public int MaxMsgs; public Duration Expires; - - public override JSONNode ToJsonNode() { + + public override JSONNode ToJsonNode() +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + + { + var o = new JSONObject(); AddField(o, "max", MaxMsgs); AsDuration(o, "ttl", Expires); return o; } } - - public class Permission : JsonSerializable { + + public class Permission : JsonSerializable + { public string[] Allow; public string[] Deny; - - public override JSONNode ToJsonNode() { + + public override JSONNode ToJsonNode() +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + + { + var o = new JSONObject(); AddField(o, "allow", Allow); AddField(o, "deny", Deny); return o; } } - - public class Claim : JsonSerializable { + + public class Claim : JsonSerializable + { public string Aud; public string Jti; public long Iat; @@ -328,9 +640,31 @@ public class Claim : JsonSerializable { public string Sub; public Duration Exp; public JsonSerializable Nats; - - public override JSONNode ToJsonNode() { + + public override JSONNode ToJsonNode() +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + + { + var o = new JSONObject(); AddField(o, "aud", Aud); AddFieldEvenEmpty(o, "jti", Jti); @@ -338,12 +672,13 @@ public override JSONNode ToJsonNode() { AddField(o, "iss", Iss); AddField(o, "name", Name); AddField(o, "sub", Sub); - - if (Exp != null && !Exp.IsZero() && !Exp.IsNegative()) { + + if (Exp != null && !Exp.IsZero() && !Exp.IsNegative()) + { long seconds = Exp.Millis / 1000; AddField(o, "exp", Iat + seconds); // relative to the iat } - + AddField(o, "nats", Nats); return o; } diff --git a/src/NATS.Client/v1/Internals/NatsConstants.cs b/src/NATS.Client/v1/Internals/NatsConstants.cs index 78ef66bd..93386256 100644 --- a/src/NATS.Client/v1/Internals/NatsConstants.cs +++ b/src/NATS.Client/v1/Internals/NatsConstants.cs @@ -1,4 +1,4 @@ -using System.Text; +using System.Text; namespace NATS.Client.Internals { @@ -9,22 +9,22 @@ internal static class NatsConstants internal static readonly byte[] HeaderVersionBytes = Encoding.ASCII.GetBytes(HeaderVersion); internal static readonly int HeaderVersionBytesLen = HeaderVersionBytes.Length; internal static readonly int MinimalValidHeaderLen = HeaderVersionBytesLen + 2; // 2 is crlf - + internal const int FlowOrHeartbeatStatusCode = 100; internal const int NoRespondersCode = 503; internal const int BadRequestCode = 400; internal const int NotFoundCode = 404; internal const int RequestTimeoutCode = 408; internal const int ConflictCode = 409; - + internal const string InvalidHeaderVersion = "Invalid header version"; - + internal const string InvalidHeaderComposition = "Invalid header composition"; - + internal const string InvalidHeaderStatusCode = "Invalid header status code"; - + internal const string SerializedHeaderCannotBeNullOrEmpty = "Serialized header cannot be null or empty."; - + internal const string Empty = ""; internal const char Dot = '.'; @@ -35,4 +35,4 @@ internal static class NatsConstants internal const string GreaterThan = ">"; } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Internals/Nuid.cs b/src/NATS.Client/v1/Internals/Nuid.cs index 9265d1d8..af0101a7 100644 --- a/src/NATS.Client/v1/Internals/Nuid.cs +++ b/src/NATS.Client/v1/Internals/Nuid.cs @@ -27,16 +27,16 @@ public sealed class Nuid private const int BASE = 64; private static readonly byte[] _digits = new byte[BASE]{ - (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', (byte)'H', + (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', (byte)'v', - (byte)'w', (byte)'x', (byte)'y', (byte)'z', (byte)'0', (byte)'1', (byte)'2', (byte)'3', + (byte)'w', (byte)'x', (byte)'y', (byte)'z', (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'-', (byte)'_', }; - + private readonly object _nuidLock = new object(); private readonly Random _rng; @@ -64,7 +64,7 @@ internal Nuid(RandomNumberGenerator rng = null, ulong? sequential = null, uint? _cryptoRng = RandomNumberGenerator.Create(); else _cryptoRng = rng; - + // Instantiating System.Random multiple times in quick succession without a // proper seed may result in instances that yield identical sequences on .NET FX. // See https://docs.microsoft.com/en-us/dotnet/api/system.random?view=netframework-4.8#instantiating-the-random-number-generator @@ -89,7 +89,7 @@ internal Nuid(RandomNumberGenerator rng = null, ulong? sequential = null, uint? /// /// Initializes a new instance of . /// - public Nuid() : this(null) {} + public Nuid() : this(null) { } /// /// Returns a random Nuid string. @@ -120,7 +120,7 @@ public string GetNext() } } - for (int i = NUID_LENGTH - 1; i >= PREFIX_LENGTH; i--) + for (var i = NUID_LENGTH - 1; i >= PREFIX_LENGTH; i--) { // We operate on unsigned integers and BASE is a power of two // therefore we can optimize sequential % BASE to sequential & (BASE - 1) @@ -156,7 +156,7 @@ public string GetNextSequence() } var nuidBuffer = new char[SEQUENTIAL_LENGTH]; - for (int i = SEQUENTIAL_LENGTH - 1; i >= 0 ; i--) + for (var i = SEQUENTIAL_LENGTH - 1; i >= 0; i--) { // We operate on unsigned integers and BASE is a power of two // therefore we can optimize sequential % BASE to sequential & (BASE - 1) @@ -173,7 +173,7 @@ public string GetNextSequence() /// Returns the next NUID from the global instance. /// public static string NextGlobal() => _global.GetNext(); - + /// /// Returns the sequence portion from the next NUID from the global instance. /// @@ -210,7 +210,7 @@ private void SetPrefix() _cryptoRng.GetBytes(randomBytes); - for(var i = 0; i < randomBytes.Length; i++) + for (var i = 0; i < randomBytes.Length; i++) { // We operate on unsigned integers and BASE is a power of two // therefore we can optimize randomBytes[i] % BASE to randomBytes[i] & (BASE - 1) diff --git a/src/NATS.Client/v1/Internals/ServerVersion.cs b/src/NATS.Client/v1/Internals/ServerVersion.cs index b850e7e1..bffe7057 100644 --- a/src/NATS.Client/v1/Internals/ServerVersion.cs +++ b/src/NATS.Client/v1/Internals/ServerVersion.cs @@ -15,7 +15,8 @@ namespace NATS.Client.Internals { - internal class ServerVersion : IComparable { + internal class ServerVersion : IComparable + { private const string NoExtra = "~"; readonly int major; @@ -23,12 +24,36 @@ internal class ServerVersion : IComparable { readonly int patch; readonly string extra; - internal ServerVersion(string v) { + internal ServerVersion(string v) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: string[] split = v.Replace("v", "").Replace("-", ".").Split('.'); - if (v.StartsWith("v")) { +After: + var split = v.Replace("v", "").Replace("-", ".").Split('.'); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string[] split = v.Replace("v", "").Replace("-", ".").Split('.'); +After: + var split = v.Replace("v", "").Replace("-", ".").Split('.'); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string[] split = v.Replace("v", "").Replace("-", ".").Split('.'); +After: + var split = v.Replace("v", "").Replace("-", ".").Split('.'); +*/ + + { + var split = v.Replace("v", "").Replace("-", ".").Split('.'); + if (v.StartsWith("v")) + { split = v.Substring(1).Replace("-", ".").Split('.'); } - else { + else + { split = v.Replace("-", ".").Split('.'); } int mjr; @@ -37,6 +62,35 @@ internal ServerVersion(string v) { if (int.TryParse(split[0], out mjr) && int.TryParse(split[1], out mnr) && int.TryParse(split[2], out ptch)) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + { + major = mjr; + minor = mnr; + patch = ptch; + string xtra = null; + for (int i = 3; i < split.Length; i++) + { + if (i == 3) + { + xtra = "-" + split[i]; + } + else + { + //noinspection StringConcatenationInLoop + xtra = xtra + "." + split[i]; + } + } + extra = xtra; + } + else + { +After: + { +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: { major = mjr; minor = mnr; @@ -58,33 +112,167 @@ internal ServerVersion(string v) { } else { +After: + { +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + { + major = mjr; + minor = mnr; + patch = ptch; + string xtra = null; + for (int i = 3; i < split.Length; i++) + { + if (i == 3) + { + xtra = "-" + split[i]; + } + else + { + //noinspection StringConcatenationInLoop + xtra = xtra + "." + split[i]; + } + } + extra = xtra; + } + else + { +After: + { +*/ + + { + major = mjr; + minor = mnr; + patch = ptch; + string xtra = null; + for (var i = 3; i < split.Length; i++) + { + if (i == 3) + { + xtra = "-" + split[i]; + } + else + { + //noinspection StringConcatenationInLoop + xtra = xtra + "." + split[i]; + } + } + extra = xtra; + } + else + { + major = mjr; + minor = mnr; + patch = ptch; + string xtra = null; + for (var i = 3; i < split.Length; i++) + { + if (i == 3) + { + xtra = "-" + split[i]; + } + else + { + //noinspection StringConcatenationInLoop + xtra = xtra + "." + split[i]; + } + } + extra = xtra; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + } +After: + else + { major = 0; minor = 0; patch = 0; extra = null; } } +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + } +After: + else + { + major = 0; + minor = 0; + patch = 0; + extra = null; + } + } +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + } +After: + else + { + major = 0; + minor = 0; + patch = 0; + extra = null; + } + } +*/ + + } + } public override string ToString() { - return $"{major}.{minor}.{patch}" + (extra == null ? "" : extra); + return $"{major}.{minor}.{patch}" + (extra ?? ""); } public int CompareTo(ServerVersion o) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int c = major.CompareTo(o.major); +After: + var c = major.CompareTo(o.major); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: int c = major.CompareTo(o.major); - if (c == 0) { +After: + var c = major.CompareTo(o.major); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int c = major.CompareTo(o.major); +After: + var c = major.CompareTo(o.major); +*/ + + { + var c = major.CompareTo(o.major); + if (c == 0) + { c = minor.CompareTo(o.minor); - if (c == 0) { + if (c == 0) + { c = patch.CompareTo(o.patch); - if (c == 0) { - if (extra == null) { + if (c == 0) + { + if (extra == null) + { c = o.extra == null ? 0 : 1; } - else if (o.extra == null) { + else if (o.extra == null) + { c = -1; } - else { + else + { c = extra.CompareTo(o.extra); } } @@ -93,23 +281,28 @@ public int CompareTo(ServerVersion o) return c; } - public static bool IsNewer(string v, string than) { + public static bool IsNewer(string v, string than) + { return new ServerVersion(v).CompareTo(new ServerVersion(than)) > 0; } - public static bool IsSame(string v, string than) { + public static bool IsSame(string v, string than) + { return new ServerVersion(v).CompareTo(new ServerVersion(than)) == 0; } - public static bool IsOlder(string v, string than) { + public static bool IsOlder(string v, string than) + { return new ServerVersion(v).CompareTo(new ServerVersion(than)) < 0; } - public static bool IsSameOrOlder(string v, string than) { + public static bool IsSameOrOlder(string v, string than) + { return new ServerVersion(v).CompareTo(new ServerVersion(than)) <= 0; } - public static bool IsSameOrNewer(string v, string than) { + public static bool IsSameOrNewer(string v, string than) + { return new ServerVersion(v).CompareTo(new ServerVersion(than)) >= 0; } } diff --git a/src/NATS.Client/v1/Internals/SimpleJSON/SimpleJson.cs b/src/NATS.Client/v1/Internals/SimpleJSON/SimpleJson.cs index 6e858387..1c156d3e 100644 --- a/src/NATS.Client/v1/Internals/SimpleJSON/SimpleJson.cs +++ b/src/NATS.Client/v1/Internals/SimpleJSON/SimpleJson.cs @@ -179,7 +179,8 @@ public Enumerator(Dictionary.Enumerator aDictEnum) } public KeyValuePair Current { - get { + get + { if (type == Type.Array) return new KeyValuePair(string.Empty, m_Array.Current); else if (type == Type.Object) @@ -337,19 +338,61 @@ public virtual JSONNode GetValueOrDefault(string aKey, JSONNode aDefault) } public override string ToString() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + StringBuilder sb = new StringBuilder(); +After: + var sb = new StringBuilder(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: StringBuilder sb = new StringBuilder(); +After: + var sb = new StringBuilder(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + StringBuilder sb = new StringBuilder(); +After: + var sb = new StringBuilder(); +*/ + + { + var sb = new StringBuilder(); WriteToStringBuilder(sb, 0, 0, JSONTextMode.Compact); return sb.ToString(); } public virtual string ToString(int aIndent) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + StringBuilder sb = new StringBuilder(); +After: + var sb = new StringBuilder(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + StringBuilder sb = new StringBuilder(); +After: + var sb = new StringBuilder(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: StringBuilder sb = new StringBuilder(); +After: + var sb = new StringBuilder(); +*/ + + { + var sb = new StringBuilder(); WriteToStringBuilder(sb, 0, aIndent, JSONTextMode.Indent); return sb.ToString(); } - + internal abstract void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode); public abstract Enumerator GetEnumerator(); @@ -363,7 +406,7 @@ public virtual string ToString(int aIndent) public virtual double AsDouble { - get => double.TryParse(Value,NumberStyles.Float, CultureInfo.InvariantCulture, out var v) ? v : 0.0; + get => double.TryParse(Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var v) ? v : 0.0; set => Value = value.ToString(CultureInfo.InvariantCulture); } @@ -375,7 +418,7 @@ public virtual int AsInt public virtual float AsFloat { - get => float.TryParse(Value,NumberStyles.Float, CultureInfo.InvariantCulture, out var v) ? v : 0.0f; + get => float.TryParse(Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var v) ? v : 0.0f; set => Value = value.ToString(CultureInfo.InvariantCulture); } @@ -487,8 +530,35 @@ public static implicit operator JSONNode(KeyValuePair aKeyValu { if (ReferenceEquals(a, b)) return true; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: bool aIsNull = a is JSONNull || ReferenceEquals(a, null) || a is JSONLazyCreator; bool bIsNull = b is JSONNull || ReferenceEquals(b, null) || b is JSONLazyCreator; +After: + var aIsNull = a is JSONNull || ReferenceEquals(a, null) || a is JSONLazyCreator; + var bIsNull = b is JSONNull || ReferenceEquals(b, null) || b is JSONLazyCreator; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + bool aIsNull = a is JSONNull || ReferenceEquals(a, null) || a is JSONLazyCreator; + bool bIsNull = b is JSONNull || ReferenceEquals(b, null) || b is JSONLazyCreator; +After: + var aIsNull = a is JSONNull || ReferenceEquals(a, null) || a is JSONLazyCreator; + var bIsNull = b is JSONNull || ReferenceEquals(b, null) || b is JSONLazyCreator; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + bool aIsNull = a is JSONNull || ReferenceEquals(a, null) || a is JSONLazyCreator; + bool bIsNull = b is JSONNull || ReferenceEquals(b, null) || b is JSONLazyCreator; +After: + var aIsNull = a is JSONNull || ReferenceEquals(a, null) || a is JSONLazyCreator; + var bIsNull = b is JSONNull || ReferenceEquals(b, null) || b is JSONLazyCreator; +*/ + + var aIsNull = a is JSONNull || ReferenceEquals(a, null) || a is JSONLazyCreator; + var bIsNull = b is JSONNull || ReferenceEquals(b, null) || b is JSONLazyCreator; if (aIsNull && bIsNull) return true; return !aIsNull && a.Equals(b); @@ -515,7 +585,8 @@ public override int GetHashCode() private static StringBuilder m_EscapeBuilder; internal static StringBuilder EscapeBuilder { - get { + get + { if (m_EscapeBuilder == null) m_EscapeBuilder = new StringBuilder(); return m_EscapeBuilder; @@ -527,78 +598,731 @@ internal static string Escape(string aText) sb.Length = 0; if (sb.Capacity < aText.Length + aText.Length / 10) sb.Capacity = aText.Length + aText.Length / 10; - foreach (char c in aText) + foreach (var c in aText) { switch (c) { - case '\\': - sb.Append("\\\\"); + case '\\': + sb.Append("\\\\"); + break; + case '\"': + sb.Append("\\\""); + break; + case '\n': + sb.Append("\\n"); + break; + case '\r': + sb.Append("\\r"); + break; + case '\t': + sb.Append("\\t"); + break; + case '\b': + sb.Append("\\b"); + break; + case '\f': + sb.Append("\\f"); + break; + default: + if (c < ' ' || (forceASCII && c > 127)) + { + ushort val = c; + sb.Append("\\u").Append(val.ToString("X4")); + } + else + sb.Append(c); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string result = sb.ToString(); +After: + var result = sb.ToString(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string result = sb.ToString(); +After: + var result = sb.ToString(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string result = sb.ToString(); +After: + var result = sb.ToString(); +*/ + + break; + } + } + var result = sb.ToString(); + sb.Length = 0; + return result; + } + + private static JSONNode ParseElement(string token, bool quoted) + { + if (quoted) + { + return token; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string tmp = token.ToLower(); + if (tmp == "false" || tmp == "true") + { + return tmp == "true"; + } + + if (tmp == "null") + { + return JSONNull.CreateOrGet(); + } + + JSONNumber jsonNumber = new JSONNumber(token); +After: + var tmp = token.ToLower(); + if (tmp == "false" || tmp == "true") + { + return tmp == "true"; + } + + if (tmp == "null") + { + return JSONNull.CreateOrGet(); + } + + var jsonNumber = new JSONNumber(token); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string tmp = token.ToLower(); + if (tmp == "false" || tmp == "true") + { + return tmp == "true"; + } + + if (tmp == "null") + { + return JSONNull.CreateOrGet(); + } + + JSONNumber jsonNumber = new JSONNumber(token); +After: + var tmp = token.ToLower(); + if (tmp == "false" || tmp == "true") + { + return tmp == "true"; + } + + if (tmp == "null") + { + return JSONNull.CreateOrGet(); + } + + var jsonNumber = new JSONNumber(token); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string tmp = token.ToLower(); + if (tmp == "false" || tmp == "true") + { + return tmp == "true"; + } + + if (tmp == "null") + { + return JSONNull.CreateOrGet(); + } + + JSONNumber jsonNumber = new JSONNumber(token); +After: + var tmp = token.ToLower(); + if (tmp == "false" || tmp == "true") + { + return tmp == "true"; + } + + if (tmp == "null") + { + return JSONNull.CreateOrGet(); + } + + var jsonNumber = new JSONNumber(token); +*/ + + } + + var tmp = token.ToLower(); + if (tmp == "false" || tmp == "true") + { + return tmp == "true"; + } + + if (tmp == "null") + { + return JSONNull.CreateOrGet(); + } + + var jsonNumber = new JSONNumber(token); + if (jsonNumber.IsNumber) + { + return jsonNumber; + } + + return token; + } + + public static JSONNode Parse(string aJSON) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Stack stack = new Stack(); +After: + var stack = new Stack(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Stack stack = new Stack(); +After: + var stack = new Stack(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Stack stack = new Stack(); +After: + var stack = new Stack(); +*/ + + { + var stack = new Stack(); + JSONNode ctx = null; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int i = 0; + StringBuilder Token = new StringBuilder(); + string TokenName = ""; + bool QuoteMode = false; + bool TokenIsQuoted = false; + while (i < aJSON.Length) + { + switch (aJSON[i]) + { + case '{': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + stack.Push(new JSONObject()); + if (ctx != null) + { + ctx.Add(TokenName, stack.Peek()); + } + TokenName = ""; + Token.Length = 0; + ctx = stack.Peek(); break; - case '\"': - sb.Append("\\\""); + + case '[': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + + stack.Push(new JSONArray()); + if (ctx != null) + { + ctx.Add(TokenName, stack.Peek()); + } + TokenName = ""; + Token.Length = 0; + ctx = stack.Peek(); break; - case '\n': - sb.Append("\\n"); + + case '}': + case ']': + if (QuoteMode) + { + + Token.Append(aJSON[i]); + break; + } + if (stack.Count == 0) + throw new Exception("JSON Parse: Too many closing brackets"); + + stack.Pop(); + if (Token.Length > 0 || TokenIsQuoted) + ctx.Add(TokenName, ParseElement(Token.ToString(), TokenIsQuoted)); + TokenIsQuoted = false; + TokenName = ""; + Token.Length = 0; + if (stack.Count > 0) + ctx = stack.Peek(); break; - case '\r': - sb.Append("\\r"); + + case ':': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + TokenName = Token.ToString(); + Token.Length = 0; + TokenIsQuoted = false; break; - case '\t': - sb.Append("\\t"); + + case '"': + QuoteMode ^= true; + TokenIsQuoted |= QuoteMode; + break; + + case ',': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + if (Token.Length > 0 || TokenIsQuoted) + ctx.Add(TokenName, ParseElement(Token.ToString(), TokenIsQuoted)); + TokenIsQuoted = false; + TokenName = ""; + Token.Length = 0; + TokenIsQuoted = false; break; - case '\b': - sb.Append("\\b"); + + case '\r': + case '\n': break; - case '\f': - sb.Append("\\f"); + + case ' ': + case '\t': + if (QuoteMode) + Token.Append(aJSON[i]); break; - default: - if (c < ' ' || (forceASCII && c > 127)) + + case '\\': + ++i; + if (QuoteMode) { - ushort val = c; - sb.Append("\\u").Append(val.ToString("X4")); - } - else - sb.Append(c); + char C = aJSON[i]; + switch (C) + { + case 't': + Token.Append('\t'); + break; + case 'r': + Token.Append('\r'); + break; + case 'n': + Token.Append('\n'); + break; + case 'b': + Token.Append('\b'); + break; + case 'f': + Token.Append('\f'); + break; + case 'u': + { + string s = aJSON.Substring(i + 1, 4); +After: + var i = 0; + var Token = new StringBuilder(); + var TokenName = ""; + var QuoteMode = false; + var TokenIsQuoted = false; + while (i < aJSON.Length) + { + switch (aJSON[i]) + { + case '{': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + stack.Push(new JSONObject()); + if (ctx != null) + { + ctx.Add(TokenName, stack.Peek()); + } + TokenName = ""; + Token.Length = 0; + ctx = stack.Peek(); + break; + + case '[': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + + stack.Push(new JSONArray()); + if (ctx != null) + { + ctx.Add(TokenName, stack.Peek()); + } + TokenName = ""; + Token.Length = 0; + ctx = stack.Peek(); + break; + + case '}': + case ']': + if (QuoteMode) + { + + Token.Append(aJSON[i]); + break; + } + if (stack.Count == 0) + throw new Exception("JSON Parse: Too many closing brackets"); + + stack.Pop(); + if (Token.Length > 0 || TokenIsQuoted) + ctx.Add(TokenName, ParseElement(Token.ToString(), TokenIsQuoted)); + TokenIsQuoted = false; + TokenName = ""; + Token.Length = 0; + if (stack.Count > 0) + ctx = stack.Peek(); + break; + + case ':': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + TokenName = Token.ToString(); + Token.Length = 0; + TokenIsQuoted = false; + break; + + case '"': + QuoteMode ^= true; + TokenIsQuoted |= QuoteMode; + break; + + case ',': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + if (Token.Length > 0 || TokenIsQuoted) + ctx.Add(TokenName, ParseElement(Token.ToString(), TokenIsQuoted)); + TokenIsQuoted = false; + TokenName = ""; + Token.Length = 0; + TokenIsQuoted = false; + break; + + case '\r': + case '\n': + break; + + case ' ': + case '\t': + if (QuoteMode) + Token.Append(aJSON[i]); + break; + + case '\\': + ++i; + if (QuoteMode) + { + var C = aJSON[i]; + switch (C) + { + case 't': + Token.Append('\t'); + break; + case 'r': + Token.Append('\r'); + break; + case 'n': + Token.Append('\n'); + break; + case 'b': + Token.Append('\b'); + break; + case 'f': + Token.Append('\f'); + break; + case 'u': + { + var s = aJSON.Substring(i + 1, 4); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int i = 0; + StringBuilder Token = new StringBuilder(); + string TokenName = ""; + bool QuoteMode = false; + bool TokenIsQuoted = false; + while (i < aJSON.Length) + { + switch (aJSON[i]) + { + case '{': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + stack.Push(new JSONObject()); + if (ctx != null) + { + ctx.Add(TokenName, stack.Peek()); + } + TokenName = ""; + Token.Length = 0; + ctx = stack.Peek(); + break; + + case '[': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + + stack.Push(new JSONArray()); + if (ctx != null) + { + ctx.Add(TokenName, stack.Peek()); + } + TokenName = ""; + Token.Length = 0; + ctx = stack.Peek(); + break; + + case '}': + case ']': + if (QuoteMode) + { + + Token.Append(aJSON[i]); + break; + } + if (stack.Count == 0) + throw new Exception("JSON Parse: Too many closing brackets"); + + stack.Pop(); + if (Token.Length > 0 || TokenIsQuoted) + ctx.Add(TokenName, ParseElement(Token.ToString(), TokenIsQuoted)); + TokenIsQuoted = false; + TokenName = ""; + Token.Length = 0; + if (stack.Count > 0) + ctx = stack.Peek(); + break; + + case ':': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + TokenName = Token.ToString(); + Token.Length = 0; + TokenIsQuoted = false; + break; + + case '"': + QuoteMode ^= true; + TokenIsQuoted |= QuoteMode; + break; + + case ',': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + if (Token.Length > 0 || TokenIsQuoted) + ctx.Add(TokenName, ParseElement(Token.ToString(), TokenIsQuoted)); + TokenIsQuoted = false; + TokenName = ""; + Token.Length = 0; + TokenIsQuoted = false; + break; + + case '\r': + case '\n': + break; + + case ' ': + case '\t': + if (QuoteMode) + Token.Append(aJSON[i]); + break; + + case '\\': + ++i; + if (QuoteMode) + { + char C = aJSON[i]; + switch (C) + { + case 't': + Token.Append('\t'); + break; + case 'r': + Token.Append('\r'); + break; + case 'n': + Token.Append('\n'); + break; + case 'b': + Token.Append('\b'); + break; + case 'f': + Token.Append('\f'); + break; + case 'u': + { + string s = aJSON.Substring(i + 1, 4); +After: + var i = 0; + var Token = new StringBuilder(); + var TokenName = ""; + var QuoteMode = false; + var TokenIsQuoted = false; + while (i < aJSON.Length) + { + switch (aJSON[i]) + { + case '{': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + stack.Push(new JSONObject()); + if (ctx != null) + { + ctx.Add(TokenName, stack.Peek()); + } + TokenName = ""; + Token.Length = 0; + ctx = stack.Peek(); + break; + + case '[': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + + stack.Push(new JSONArray()); + if (ctx != null) + { + ctx.Add(TokenName, stack.Peek()); + } + TokenName = ""; + Token.Length = 0; + ctx = stack.Peek(); + break; + + case '}': + case ']': + if (QuoteMode) + { + + Token.Append(aJSON[i]); + break; + } + if (stack.Count == 0) + throw new Exception("JSON Parse: Too many closing brackets"); + + stack.Pop(); + if (Token.Length > 0 || TokenIsQuoted) + ctx.Add(TokenName, ParseElement(Token.ToString(), TokenIsQuoted)); + TokenIsQuoted = false; + TokenName = ""; + Token.Length = 0; + if (stack.Count > 0) + ctx = stack.Peek(); + break; + + case ':': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + TokenName = Token.ToString(); + Token.Length = 0; + TokenIsQuoted = false; + break; + + case '"': + QuoteMode ^= true; + TokenIsQuoted |= QuoteMode; + break; + + case ',': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + if (Token.Length > 0 || TokenIsQuoted) + ctx.Add(TokenName, ParseElement(Token.ToString(), TokenIsQuoted)); + TokenIsQuoted = false; + TokenName = ""; + Token.Length = 0; + TokenIsQuoted = false; break; - } - } - string result = sb.ToString(); - sb.Length = 0; - return result; - } - private static JSONNode ParseElement(string token, bool quoted) - { - if (quoted) - { - return token; - } - - string tmp = token.ToLower(); - if (tmp == "false" || tmp == "true") - { - return tmp == "true"; - } + case '\r': + case '\n': + break; - if (tmp == "null") - { - return JSONNull.CreateOrGet(); - } + case ' ': + case '\t': + if (QuoteMode) + Token.Append(aJSON[i]); + break; - JSONNumber jsonNumber = new JSONNumber(token); - if (jsonNumber.IsNumber) - { - return jsonNumber; - } - - return token; - } + case '\\': + ++i; + if (QuoteMode) + { + var C = aJSON[i]; + switch (C) + { + case 't': + Token.Append('\t'); + break; + case 'r': + Token.Append('\r'); + break; + case 'n': + Token.Append('\n'); + break; + case 'b': + Token.Append('\b'); + break; + case 'f': + Token.Append('\f'); + break; + case 'u': + { + var s = aJSON.Substring(i + 1, 4); +*/ - public static JSONNode Parse(string aJSON) - { - Stack stack = new Stack(); - JSONNode ctx = null; +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int i = 0; StringBuilder Token = new StringBuilder(); string TokenName = ""; @@ -727,30 +1451,290 @@ public static JSONNode Parse(string aJSON) case 'u': { string s = aJSON.Substring(i + 1, 4); - Token.Append((char)int.Parse(s, NumberStyles.AllowHexSpecifier)); - i += 4; - break; - } - default: - Token.Append(C); - break; - } +After: + var i = 0; + var Token = new StringBuilder(); + var TokenName = ""; + var QuoteMode = false; + var TokenIsQuoted = false; + while (i < aJSON.Length) + { + switch (aJSON[i]) + { + case '{': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + stack.Push(new JSONObject()); + if (ctx != null) + { + ctx.Add(TokenName, stack.Peek()); + } + TokenName = ""; + Token.Length = 0; + ctx = stack.Peek(); + break; + + case '[': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + + stack.Push(new JSONArray()); + if (ctx != null) + { + ctx.Add(TokenName, stack.Peek()); + } + TokenName = ""; + Token.Length = 0; + ctx = stack.Peek(); + break; + + case '}': + case ']': + if (QuoteMode) + { + + Token.Append(aJSON[i]); + break; + } + if (stack.Count == 0) + throw new Exception("JSON Parse: Too many closing brackets"); + + stack.Pop(); + if (Token.Length > 0 || TokenIsQuoted) + ctx.Add(TokenName, ParseElement(Token.ToString(), TokenIsQuoted)); + TokenIsQuoted = false; + TokenName = ""; + Token.Length = 0; + if (stack.Count > 0) + ctx = stack.Peek(); + break; + + case ':': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; } + TokenName = Token.ToString(); + Token.Length = 0; + TokenIsQuoted = false; + break; + + case '"': + QuoteMode ^= true; + TokenIsQuoted |= QuoteMode; break; - case '/': - if (allowLineComments && !QuoteMode && i + 1 < aJSON.Length && aJSON[i+1] == '/') + + case ',': + if (QuoteMode) { - while (++i < aJSON.Length && aJSON[i] != '\n' && aJSON[i] != '\r') ; + Token.Append(aJSON[i]); break; } + if (Token.Length > 0 || TokenIsQuoted) + ctx.Add(TokenName, ParseElement(Token.ToString(), TokenIsQuoted)); + TokenIsQuoted = false; + TokenName = ""; + Token.Length = 0; + TokenIsQuoted = false; + break; + + case '\r': + case '\n': + break; + + case ' ': + case '\t': + if (QuoteMode) + Token.Append(aJSON[i]); + break; + + case '\\': + ++i; + if (QuoteMode) + { + var C = aJSON[i]; + switch (C) + { + case 't': + Token.Append('\t'); + break; + case 'r': + Token.Append('\r'); + break; + case 'n': + Token.Append('\n'); + break; + case 'b': + Token.Append('\b'); + break; + case 'f': + Token.Append('\f'); + break; + case 'u': + { + var s = aJSON.Substring(i + 1, 4); +*/ + + var i = 0; + var Token = new StringBuilder(); + var TokenName = ""; + var QuoteMode = false; + var TokenIsQuoted = false; + while (i < aJSON.Length) + { + switch (aJSON[i]) + { + case '{': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + stack.Push(new JSONObject()); + if (ctx != null) + { + ctx.Add(TokenName, stack.Peek()); + } + TokenName = ""; + Token.Length = 0; + ctx = stack.Peek(); + break; + + case '[': + if (QuoteMode) + { Token.Append(aJSON[i]); break; - case '\uFEFF': // remove / ignore BOM (Byte Order Mark) + } + + stack.Push(new JSONArray()); + if (ctx != null) + { + ctx.Add(TokenName, stack.Peek()); + } + TokenName = ""; + Token.Length = 0; + ctx = stack.Peek(); + break; + + case '}': + case ']': + if (QuoteMode) + { + + Token.Append(aJSON[i]); break; + } + if (stack.Count == 0) + throw new Exception("JSON Parse: Too many closing brackets"); + + stack.Pop(); + if (Token.Length > 0 || TokenIsQuoted) + ctx.Add(TokenName, ParseElement(Token.ToString(), TokenIsQuoted)); + TokenIsQuoted = false; + TokenName = ""; + Token.Length = 0; + if (stack.Count > 0) + ctx = stack.Peek(); + break; - default: + case ':': + if (QuoteMode) + { + Token.Append(aJSON[i]); + break; + } + TokenName = Token.ToString(); + Token.Length = 0; + TokenIsQuoted = false; + break; + + case '"': + QuoteMode ^= true; + TokenIsQuoted |= QuoteMode; + break; + + case ',': + if (QuoteMode) + { Token.Append(aJSON[i]); break; + } + if (Token.Length > 0 || TokenIsQuoted) + ctx.Add(TokenName, ParseElement(Token.ToString(), TokenIsQuoted)); + TokenIsQuoted = false; + TokenName = ""; + Token.Length = 0; + TokenIsQuoted = false; + break; + + case '\r': + case '\n': + break; + + case ' ': + case '\t': + if (QuoteMode) + Token.Append(aJSON[i]); + break; + + case '\\': + ++i; + if (QuoteMode) + { + var C = aJSON[i]; + switch (C) + { + case 't': + Token.Append('\t'); + break; + case 'r': + Token.Append('\r'); + break; + case 'n': + Token.Append('\n'); + break; + case 'b': + Token.Append('\b'); + break; + case 'f': + Token.Append('\f'); + break; + case 'u': + { + var s = aJSON.Substring(i + 1, 4); + Token.Append((char)int.Parse(s, NumberStyles.AllowHexSpecifier)); + i += 4; + break; + } + default: + Token.Append(C); + break; + } + } + break; + case '/': + if (allowLineComments && !QuoteMode && i + 1 < aJSON.Length && aJSON[i + 1] == '/') + { + while (++i < aJSON.Length && aJSON[i] != '\n' && aJSON[i] != '\r') + ; + break; + } + Token.Append(aJSON[i]); + break; + case '\uFEFF': // remove / ignore BOM (Byte Order Mark) + break; + + default: + Token.Append(aJSON[i]); + break; } ++i; } @@ -826,7 +1810,28 @@ public override JSONNode Remove(int aIndex) { if (aIndex < 0 || aIndex >= m_List.Count) return null; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONNode tmp = m_List[aIndex]; +After: + var tmp = m_List[aIndex]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONNode tmp = m_List[aIndex]; +After: + var tmp = m_List[aIndex]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: JSONNode tmp = m_List[aIndex]; +After: + var tmp = m_List[aIndex]; +*/ + + var tmp = m_List[aIndex]; m_List.RemoveAt(aIndex); return tmp; } @@ -841,7 +1846,7 @@ public override IEnumerable Children { get { - foreach (JSONNode N in m_List) + foreach (var N in m_List) yield return N; } } @@ -849,10 +1854,31 @@ public override IEnumerable Children internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('['); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int count = m_List.Count; +After: + var count = m_List.Count; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int count = m_List.Count; +After: + var count = m_List.Count; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int count = m_List.Count; +After: + var count = m_List.Count; +*/ + + var count = m_List.Count; if (inline) aMode = JSONTextMode.Compact; - for (int i = 0; i < count; i++) + for (var i = 0; i < count; i++) { if (i > 0) aSB.Append(','); @@ -921,7 +1947,28 @@ public override JSONNode this[int aIndex] value = JSONNull.CreateOrGet(); if (aIndex < 0 || aIndex >= m_Dict.Count) return; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string key = m_Dict.ElementAt(aIndex).Key; +After: + var key = m_Dict.ElementAt(aIndex).Key; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: string key = m_Dict.ElementAt(aIndex).Key; +After: + var key = m_Dict.ElementAt(aIndex).Key; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string key = m_Dict.ElementAt(aIndex).Key; +After: + var key = m_Dict.ElementAt(aIndex).Key; +*/ + + var key = m_Dict.ElementAt(aIndex).Key; m_Dict[key] = value; } } @@ -951,7 +1998,28 @@ public override JSONNode Remove(string aKey) { if (!m_Dict.ContainsKey(aKey)) return null; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONNode tmp = m_Dict[aKey]; +After: + var tmp = m_Dict[aKey]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONNode tmp = m_Dict[aKey]; +After: + var tmp = m_Dict[aKey]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: JSONNode tmp = m_Dict[aKey]; +After: + var tmp = m_Dict[aKey]; +*/ + + var tmp = m_Dict[aKey]; m_Dict.Remove(aKey); return tmp; } @@ -996,7 +2064,7 @@ public override IEnumerable Children { get { - foreach (KeyValuePair N in m_Dict) + foreach (var N in m_Dict) yield return N.Value; } } @@ -1004,7 +2072,28 @@ public override IEnumerable Children internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('{'); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: bool first = true; +After: + var first = true; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + bool first = true; +After: + var first = true; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + bool first = true; +After: + var first = true; +*/ + + var first = true; if (inline) aMode = JSONTextMode.Compact; foreach (var k in m_Dict) @@ -1065,15 +2154,57 @@ internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int { aSB.Append('\"').Append(Escape(m_Data)).Append('\"'); } - + public override bool Equals(object obj) { if (base.Equals(obj)) return true; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string s = obj as string; +After: + var s = obj as string; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: string s = obj as string; +After: + var s = obj as string; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string s = obj as string; +After: + var s = obj as string; +*/ + + var s = obj as string; if (s != null) return m_Data == s; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONString s2 = obj as JSONString; +After: + var s2 = obj as JSONString; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONString s2 = obj as JSONString; +After: + var s2 = obj as JSONString; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: JSONString s2 = obj as JSONString; +After: + var s2 = obj as JSONString; +*/ + + var s2 = obj as JSONString; if (s2 != null) return m_Data == s2.m_Data; return false; @@ -1085,7 +2216,7 @@ public override int GetHashCode() } // End of JSONString - internal enum JSONNumberType {I, L, U, D, X} + internal enum JSONNumberType { I, L, U, D, X } public partial class JSONNumber : JSONNode { private JSONNumberType numberType = JSONNumberType.X; @@ -1100,25 +2231,29 @@ public partial class JSONNumber : JSONNode public override string Value { - get { + get + { switch (numberType) { - case JSONNumberType.L: return longData.ToString(); - case JSONNumberType.U: return ulongData.ToString(); - case JSONNumberType.D: return doubleData.ToString(CultureInfo.InvariantCulture); + case JSONNumberType.L: + return longData.ToString(); + case JSONNumberType.U: + return ulongData.ToString(); + case JSONNumberType.D: + return doubleData.ToString(CultureInfo.InvariantCulture); } return intData.ToString(); } set => InitString(value); } - + public override int AsInt { get => intData; set => InitInt(value); } - + public override long AsLong { get => longData; @@ -1136,7 +2271,7 @@ public override double AsDouble get => doubleData; set => InitDouble(value); } - + public JSONNumber(int aData) { InitInt(aData); @@ -1167,7 +2302,7 @@ private void InitInt(int aData) numberType = JSONNumberType.I; intData = aData; longData = intData; - ulongData = (ulong) intData; + ulongData = (ulong)intData; doubleData = intData; } @@ -1176,7 +2311,7 @@ private void InitLong(long aData) numberType = JSONNumberType.L; intData = 0; longData = aData; - ulongData = (ulong) longData; + ulongData = (ulong)longData; doubleData = longData; } @@ -1223,7 +2358,7 @@ internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int { aSB.Append(Value); } - + private static bool IsNumeric(object value) { return value is int || value is uint @@ -1233,19 +2368,40 @@ private static bool IsNumeric(object value) || value is short || value is ushort || value is sbyte || value is byte; } - + public override bool Equals(object obj) { if (obj == null) { return false; } - if (base.Equals(obj)) + if (base.Equals(obj)) { return true; - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONNumber o2 = obj as JSONNumber; +After: + var o2 = obj as JSONNumber; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONNumber o2 = obj as JSONNumber; +After: + var o2 = obj as JSONNumber; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: JSONNumber o2 = obj as JSONNumber; +After: + var o2 = obj as JSONNumber; +*/ + + } + + var o2 = obj as JSONNumber; if (o2 != null) { if (o2.numberType != numberType) @@ -1255,23 +2411,29 @@ public override bool Equals(object obj) switch (numberType) { - case JSONNumberType.L: return o2.longData == longData; - case JSONNumberType.U: return o2.ulongData == ulongData; - case JSONNumberType.D: return o2.doubleData == doubleData; + case JSONNumberType.L: + return o2.longData == longData; + case JSONNumberType.U: + return o2.ulongData == ulongData; + case JSONNumberType.D: + return o2.doubleData == doubleData; } return o2.intData == intData; } return IsNumeric(obj) && Convert.ToDouble(obj) == doubleData; } - + public override int GetHashCode() { switch (numberType) { - case JSONNumberType.L: return longData.GetHashCode(); - case JSONNumberType.U: return ulongData.GetHashCode(); - case JSONNumberType.D: return doubleData.GetHashCode(); + case JSONNumberType.L: + return longData.GetHashCode(); + case JSONNumberType.U: + return ulongData.GetHashCode(); + case JSONNumberType.D: + return doubleData.GetHashCode(); } return intData.GetHashCode(); } @@ -1517,4 +2679,4 @@ public static JSONNode Parse(string aJSON) return JSONNode.Parse(aJSON); } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Internals/Token.cs b/src/NATS.Client/v1/Internals/Token.cs index 3eae43b9..732641e4 100644 --- a/src/NATS.Client/v1/Internals/Token.cs +++ b/src/NATS.Client/v1/Internals/Token.cs @@ -15,8 +15,8 @@ namespace NATS.Client.Internals { - public enum TokenType {Space, Crlf, Key, Word, Text} - + public enum TokenType { Space, Crlf, Key, Word, Text } + public class Token { private readonly byte[] _serialized; @@ -26,87 +26,140 @@ public class Token private readonly bool _hasValue; internal Token(byte[] serialized, int len, Token prev, TokenType? required) : - this(serialized, len, prev._end + (prev._type == TokenType.Key ? 2 : 1), required) {} + this(serialized, len, prev._end + (prev._type == TokenType.Key ? 2 : 1), required) + { } - internal Token(byte[] serialized, int len, int cur, TokenType? required) + internal Token(byte[] serialized, int len, int cur, TokenType? required) { _serialized = serialized; - if (cur >= len) { + if (cur >= len) + { throw new NATSInvalidHeaderException(InvalidHeaderComposition); } - if (serialized[cur] == Sp) { + if (serialized[cur] == Sp) + { _type = TokenType.Space; _start = cur; _end = cur; - while (serialized[++cur] == Sp) { + while (serialized[++cur] == Sp) + { _end = cur; } - } else if (serialized[cur] == Cr) { + } + else if (serialized[cur] == Cr) + { MustBeCrlf(len, cur); _type = TokenType.Crlf; _start = cur; _end = cur + 1; - } else if (required == TokenType.Crlf || required == TokenType.Space) { + } + else if (required == TokenType.Crlf || required == TokenType.Space) + { throw new NATSInvalidHeaderException(InvalidHeaderComposition); - } else { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + byte ender1 = Cr; + byte ender2 = Cr; +After: + var ender1 = Cr; + var ender2 = Cr; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + byte ender1 = Cr; + byte ender2 = Cr; +After: + var ender1 = Cr; + var ender2 = Cr; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: byte ender1 = Cr; byte ender2 = Cr; - if (required == null || required == TokenType.Text) { +After: + var ender1 = Cr; + var ender2 = Cr; +*/ + + } + else + { + var ender1 = Cr; + var ender2 = Cr; + if (required == null || required == TokenType.Text) + { _type = TokenType.Text; - } else if (required == TokenType.Word) { + } + else if (required == TokenType.Word) + { ender1 = Sp; ender2 = Cr; _type = TokenType.Word; - } else { // KEY is all that's left if (required == TokenType.KEY) { + } + else + { // KEY is all that's left if (required == TokenType.KEY) { ender1 = Colon; ender2 = Colon; _type = TokenType.Key; } _start = cur; _end = cur; - while (++cur < len && serialized[cur] != ender1 && serialized[cur] != ender2) { + while (++cur < len && serialized[cur] != ender1 && serialized[cur] != ender2) + { _end = cur; } - if (cur >= len) { + if (cur >= len) + { throw new NATSInvalidHeaderException(InvalidHeaderComposition); } - if (serialized[cur] == Cr) { + if (serialized[cur] == Cr) + { MustBeCrlf(len, cur); } _hasValue = true; } } - private void MustBeCrlf(int len, int cur) { - if (cur + 1 >= len || _serialized[cur + 1] != Lf) { - throw new NATSInvalidHeaderException(InvalidHeaderComposition); + private void MustBeCrlf(int len, int cur) + { + if (cur + 1 >= len || _serialized[cur + 1] != Lf) + { + throw new NATSInvalidHeaderException(InvalidHeaderComposition); + } } - } - public void MustBe(TokenType expected) { - if (_type != expected) { - throw new NATSInvalidHeaderException(InvalidHeaderComposition); + public void MustBe(TokenType expected) + { + if (_type != expected) + { + throw new NATSInvalidHeaderException(InvalidHeaderComposition); + } } - } - public bool IsType(TokenType expected) { - return _type == expected; - } + public bool IsType(TokenType expected) + { + return _type == expected; + } - public bool HasValue() { - return _hasValue; - } + public bool HasValue() + { + return _hasValue; + } - public string Value() { - return _hasValue ? System.Text.Encoding.ASCII.GetString(_serialized, _start, _end - _start + 1).Trim() : Empty; - } + public string Value() + { + return _hasValue ? System.Text.Encoding.ASCII.GetString(_serialized, _start, _end - _start + 1).Trim() : Empty; + } + + public bool SamePoint(Token token) + { + return _start == token._start + && _end == token._end + && _type == token._type; + } - public bool SamePoint(Token token) { - return _start == token._start - && _end == token._end - && _type == token._type; - } - } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Internals/Validator.cs b/src/NATS.Client/v1/Internals/Validator.cs index a5209a8b..4422ac27 100644 --- a/src/NATS.Client/v1/Internals/Validator.cs +++ b/src/NATS.Client/v1/Internals/Validator.cs @@ -21,38 +21,65 @@ namespace NATS.Client.Internals { internal static class Validator { - private static readonly char[] WildGt = { '*', '>'}; - private static readonly char[] WildGtDot = { '*', '>', '.'}; - private static readonly char[] WildGtDollar = {'*', '>', '$'}; - private static readonly char[] WildGtDotSlashes = { '*', '>', '.', '\\', '/'}; - - internal static string Required(string s, string label) { - if (EmptyAsNull(s) == null) { + private static readonly char[] WildGt = { '*', '>' }; + private static readonly char[] WildGtDot = { '*', '>', '.' }; + private static readonly char[] WildGtDollar = { '*', '>', '$' }; + private static readonly char[] WildGtDotSlashes = { '*', '>', '.', '\\', '/' }; + + internal static string Required(string s, string label) + { + if (EmptyAsNull(s) == null) + { throw new ArgumentException($"{label} cannot be null or empty."); } return s; } - - internal static void Required(object o, string label) { - if (o == null) { + + internal static void Required(object o, string label) + { + if (o == null) + { throw new ArgumentException($"{label} cannot be null or empty."); } } - - internal static void Required(IDictionary d, string label) { - if (d == null || d.Count == 0) { + + internal static void Required(IDictionary d, string label) + { + if (d == null || d.Count == 0) + { throw new ArgumentException($"{label} cannot be null or empty."); } } - + /* cannot contain spaces \r \n \t cannot start or end with subject token delimiter . some things don't allow it to end greater */ public static string ValidateSubjectTerm(string subject, string label, bool required) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: Tuple t = IsValidSubjectTerm(subject, label, required); +After: + var t = IsValidSubjectTerm(subject, label, required); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Tuple t = IsValidSubjectTerm(subject, label, required); +After: + var t = IsValidSubjectTerm(subject, label, required); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Tuple t = IsValidSubjectTerm(subject, label, required); +After: + var t = IsValidSubjectTerm(subject, label, required); +*/ + + { + var t = IsValidSubjectTerm(subject, label, required); if (t.Item1) { return t.Item2; @@ -64,47 +91,128 @@ public static string ValidateSubjectTerm(string subject, string label, bool requ * If is valid, tuple item1 is true and item2 is the subject * If is not valid, tuple item1 is false and item2 is the error message */ - internal static Tuple IsValidSubjectTerm(string subject, string label, bool required) { + internal static Tuple IsValidSubjectTerm(string subject, string label, bool required) + { subject = EmptyAsNull(subject); - if (subject == null) { - if (required) { + if (subject == null) + { + if (required) + { return new Tuple(false, $"{label} cannot be null or empty."); } return new Tuple(true, null); } - if (subject.EndsWith(".")) { + if (subject.EndsWith(".")) + { return new Tuple(false, $"{label} cannot end with '.'"); - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string[] segments = subject.Split('.'); +After: + var segments = subject.Split('.'); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string[] segments = subject.Split('.'); +After: + var segments = subject.Split('.'); +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string[] segments = subject.Split('.'); - for (int seg = 0; seg < segments.Length; seg++) { +After: + var segments = subject.Split('.'); +*/ + + } + + var segments = subject.Split('.'); + for (var seg = 0; seg < segments.Length; seg++) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string segment = segments[seg]; + int sl = segment.Length; +After: + var segment = segments[seg]; + var sl = segment.Length; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: string segment = segments[seg]; int sl = segment.Length; - if (sl == 0) { - if (seg == 0) { +After: + var segment = segments[seg]; + var sl = segment.Length; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string segment = segments[seg]; + int sl = segment.Length; +After: + var segment = segments[seg]; + var sl = segment.Length; +*/ + + { + var segment = segments[seg]; + var sl = segment.Length; + if (sl == 0) + { + if (seg == 0) + { return new Tuple(false, $"{label} cannot start with '.'"); } return new Tuple(false, $"{label} segment cannot be empty"); } - else { - for (int m = 0; m < sl; m++) { + else + { + for (var m = 0; m < sl; m++) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + char c = segment[m]; +After: + var c = segment[m]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: char c = segment[m]; - switch (c) { - case ' ': - case '\r': - case '\n': - case '\t': - return new Tuple(false, $"{label} cannot contain space, tab, carriage return or linefeed character"); - case '*': - if (sl != 1) { - return new Tuple(false, $"{label} wildcard improperly placed."); - } - break; - case '>': - if (sl != 1 || seg != segments.Length - 1) { - return new Tuple(false, $"{label} wildcard improperly placed."); - } - break; +After: + var c = segment[m]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + char c = segment[m]; +After: + var c = segment[m]; +*/ + + { + var c = segment[m]; + switch (c) + { + case ' ': + case '\r': + case '\n': + case '\t': + return new Tuple(false, $"{label} cannot contain space, tab, carriage return or linefeed character"); + case '*': + if (sl != 1) + { + return new Tuple(false, $"{label} wildcard improperly placed."); + } + break; + case '>': + if (sl != 1 || seg != segments.Length - 1) + { + return new Tuple(false, $"{label} wildcard improperly placed."); + } + break; } } } @@ -116,51 +224,96 @@ public static string ValidateSubject(string s, bool required) { return ValidateSubject(s, "Subject", required, false); } - - public static string ValidateSubject(string subject, string label, bool required, bool cantEndWithGt) { + + public static string ValidateSubject(string subject, string label, bool required, bool cantEndWithGt) + { subject = ValidateSubjectTerm(subject, label, required); - if (subject != null && cantEndWithGt && subject.EndsWith(".>")) { + if (subject != null && cantEndWithGt && subject.EndsWith(".>")) + { throw new ArgumentException($"{label} last segment cannot be '>'"); } return subject; } - public static string ValidateReplyTo(string s, bool required) { + public static string ValidateReplyTo(string s, bool required) + { return ValidatePrintableExceptWildGt(s, "Reply To", required); } - public static string ValidateQueueName(string s, bool required) { + public static string ValidateQueueName(string s, bool required) + { return ValidatePrintableExceptWildDotGt(s, "Queue", required); } - public static string ValidateStreamName(string s, bool required) { + public static string ValidateStreamName(string s, bool required) + { return ValidatePrintableExceptWildDotGtSlashes(s, "Stream", required); } - public static string ValidateDurable(string s, bool required) { + public static string ValidateDurable(string s, bool required) + { return ValidatePrintableExceptWildDotGtSlashes(s, "Durable", required); } - public static string ValidateConsumerName(string s, bool required) { + public static string ValidateConsumerName(string s, bool required) + { return ValidatePrintableExceptWildDotGtSlashes(s, "Name", required); } - public static string ValidatePrefixOrDomain(string s, string label, bool required) { - return Validate(s, required, label, () => { + public static string ValidatePrefixOrDomain(string s, string label, bool required) + { + return Validate(s, required, label, () => + { if (s.StartsWith(".")) { throw new ArgumentException($"{label} cannot start with `.` [{s}]"); } - if (NotPrintableOrHasWildGt(s)) { + if (NotPrintableOrHasWildGt(s)) + { throw new ArgumentException($"{label} must be in the printable ASCII range and cannot include `*`, `>` [{s}]"); } return s; }); } + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: public static IList ValidateKvKeysWildcardAllowedRequired(IList keys) { Required(keys, "Key"); foreach (string key in keys) { +After: + public static IList ValidateKvKeysWildcardAllowedRequired(IList keys) { + Required(keys, "Key"); + foreach (var key in keys) { +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + public static IList ValidateKvKeysWildcardAllowedRequired(IList keys) { + Required(keys, "Key"); + foreach (string key in keys) { +After: + public static IList ValidateKvKeysWildcardAllowedRequired(IList keys) { + Required(keys, "Key"); + foreach (var key in keys) { +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + public static IList ValidateKvKeysWildcardAllowedRequired(IList keys) { + Required(keys, "Key"); + foreach (string key in keys) { +After: + public static IList ValidateKvKeysWildcardAllowedRequired(IList keys) { + Required(keys, "Key"); + foreach (var key in keys) { +*/ + public static IList ValidateKvKeysWildcardAllowedRequired(IList keys) + { + Required(keys, "Key"); + foreach (var key in keys) + { ValidateWildcardKvKey(key, "Key", true); } return keys; @@ -171,17 +324,21 @@ public static string ValidateKvKeyWildcardAllowedRequired(string s) return ValidateWildcardKvKey(s, "Key", true); } - public static string ValidateNonWildcardKvKeyRequired(string s) { + public static string ValidateNonWildcardKvKeyRequired(string s) + { return ValidateNonWildcardKvKey(s, "Key", true); } - public static void ValidateNotSupplied(string s, ClientExDetail detail) { - if (!string.IsNullOrWhiteSpace(s)) { + public static void ValidateNotSupplied(string s, ClientExDetail detail) + { + if (!string.IsNullOrWhiteSpace(s)) + { throw detail.Instance(); } } - internal static string ValidateMustMatchIfBothSupplied(string s1, string s2, ClientExDetail detail) { + internal static string ValidateMustMatchIfBothSupplied(string s1, string s2, ClientExDetail detail) + { // s1 | s2 || result // ---- | ---- || -------------- // null | null || valid, null s2 @@ -191,12 +348,14 @@ internal static string ValidateMustMatchIfBothSupplied(string s1, string s2, Cli // x | y || invalid s1 = EmptyAsNull(s1); s2 = EmptyAsNull(s2); - if (s1 == null) { + if (s1 == null) + { return s2; // s2 can be either null or y } // x / null or x / x - if (s2 == null || s1.Equals(s2)) { + if (s2 == null || s1.Equals(s2)) + { return s1; } @@ -204,11 +363,33 @@ internal static string ValidateMustMatchIfBothSupplied(string s1, string s2, Cli } public static string Validate(string s, bool required, string label, Func check) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string preCheck = EmptyAsNull(s); +After: + var preCheck = EmptyAsNull(s); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string preCheck = EmptyAsNull(s); +After: + var preCheck = EmptyAsNull(s); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string preCheck = EmptyAsNull(s); +After: + var preCheck = EmptyAsNull(s); +*/ + + { + var preCheck = EmptyAsNull(s); if (preCheck == null) { - if (required) { + if (required) + { throw new ArgumentException($"{label} cannot be null or empty [{s}]"); } return null; @@ -217,15 +398,39 @@ public static string Validate(string s, bool required, string label, Func - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: int len = Encoding.UTF8.GetByteCount(s); - if (len > maxLength) { +After: + var len = Encoding.UTF8.GetByteCount(s); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int len = Encoding.UTF8.GetByteCount(s); +After: + var len = Encoding.UTF8.GetByteCount(s); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int len = Encoding.UTF8.GetByteCount(s); +After: + var len = Encoding.UTF8.GetByteCount(s); +*/ + + { + var len = Encoding.UTF8.GetByteCount(s); + if (len > maxLength) + { throw new ArgumentException($"{label} cannot be longer than {maxLength} bytes but was {len} bytes"); } return s; @@ -234,8 +439,10 @@ public static string ValidateMaxLength(string s, int maxLength, bool required, s public static string ValidatePrintable(string s, string label, bool required) { - return Validate(s, required, label, () => { - if (NotPrintable(s)) { + return Validate(s, required, label, () => + { + if (NotPrintable(s)) + { throw new ArgumentException($"{label} must be in the printable ASCII range [{s}]"); } return s; @@ -244,8 +451,10 @@ public static string ValidatePrintable(string s, string label, bool required) public static string ValidatePrintableExceptWildDotGt(string s, string label, bool required) { - return Validate(s, required, label, () => { - if (NotPrintableOrHasWildGtDot(s)) { + return Validate(s, required, label, () => + { + if (NotPrintableOrHasWildGtDot(s)) + { throw new ArgumentException($"{label} must be in the printable ASCII range and cannot include `*` or `.` [{s}]"); } return s; @@ -254,8 +463,10 @@ public static string ValidatePrintableExceptWildDotGt(string s, string label, bo public static string ValidatePrintableExceptWildDotGtSlashes(string s, string label, bool required) { - return Validate(s, required, label, () => { - if (NotPrintableOrHasWildGtDotSlashes(s)) { + return Validate(s, required, label, () => + { + if (NotPrintableOrHasWildGtDotSlashes(s)) + { throw new ArgumentException($"{label} must be in the printable ASCII range and cannot include `*` or `.` [{s}]"); } return s; @@ -264,8 +475,10 @@ public static string ValidatePrintableExceptWildDotGtSlashes(string s, string la public static string ValidatePrintableExceptWildGt(string s, string label, bool required) { - return Validate(s, required, label, () => { - if (NotPrintableOrHasWildGt(s)) { + return Validate(s, required, label, () => + { + if (NotPrintableOrHasWildGt(s)) + { throw new ArgumentException($"{label} must be in the printable ASCII range and cannot include `*`, `>` or `$` [{s}]"); } return s; @@ -274,8 +487,10 @@ public static string ValidatePrintableExceptWildGt(string s, string label, bool public static string ValidatePrintableExceptWildGtDollar(string s, string label, bool required) { - return Validate(s, required, label, () => { - if (NotPrintableOrHasWildGtDollar(s)) { + return Validate(s, required, label, () => + { + if (NotPrintableOrHasWildGtDollar(s)) + { throw new ArgumentException($"{label} must be in the printable ASCII range and cannot include `*`, `>` or `$` [{s}]"); } return s; @@ -284,8 +499,10 @@ public static string ValidatePrintableExceptWildGtDollar(string s, string label, public static string ValidateIsRestrictedTerm(string s, string label, bool required) { - return Validate(s, required, label, () => { - if (NotRestrictedTerm(s)) { + return Validate(s, required, label, () => + { + if (NotRestrictedTerm(s)) + { throw new ArgumentException($"{label} must only contain A-Z, a-z, 0-9, `-` or `_` [{s}]"); } return s; @@ -296,21 +513,25 @@ public static string ValidateBucketName(string s, bool required) { return ValidateIsRestrictedTerm(s, "Bucket Name", required); } - + public static string ValidateWildcardKvKey(string s, string label, bool required) { - return Validate(s, required, label, () => { - if (NotWildcardKvKey(s)) { + return Validate(s, required, label, () => + { + if (NotWildcardKvKey(s)) + { throw new ArgumentException($"{label} must only contain A-Z, a-z, 0-9, `-`, `_`, `/`, `=` or `.` and cannot start with `.` [{s}]"); } return s; }); } - + public static string ValidateNonWildcardKvKey(string s, string label, bool required) { - return Validate(s, required, label, () => { - if (NotNonWildcardKvKey(s)) { + return Validate(s, required, label, () => + { + if (NotNonWildcardKvKey(s)) + { throw new ArgumentException($"{label} must only contain A-Z, a-z, 0-9, `-`, `_`, `/`, `=` or `.` and cannot start with `.` [{s}]"); } return s; @@ -337,8 +558,10 @@ internal static long ValidateMaxMessagesPerSubject(long max) return ValidateGtZeroOrMinus1(max, "Max Messages Per Subject"); } - internal static int ValidateMaxHistory(int max) { - if (max < 1 || max > JetStreamConstants.MaxHistoryPerKey) { + internal static int ValidateMaxHistory(int max) + { + if (max < 1 || max > JetStreamConstants.MaxHistoryPerKey) + { throw new ArgumentException($"Max History Per Key cannot be from 1 to {JetStreamConstants.MaxHistoryPerKey} inclusive."); } return max; @@ -348,20 +571,41 @@ internal static long ValidateMaxHistoryPerKey(long max) { return ValidateGtZeroOrMinus1(max, "Max History Per Key"); } - + internal static long ValidateMaxBytes(long max) { return ValidateGtZeroOrMinus1(max, "Max Bytes"); } - + internal static long ValidateMaxBucketBytes(long max) { return ValidateGtZeroOrMinus1(max, "Max BucketBytes"); // max bucket bytes is a kv alias to max bytes } internal static long ValidateMaxMessageSize(long max, string label) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + long l = ValidateGtZeroOrMinus1(max, label); +After: + var l = ValidateGtZeroOrMinus1(max, label); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: long l = ValidateGtZeroOrMinus1(max, label); +After: + var l = ValidateGtZeroOrMinus1(max, label); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + long l = ValidateGtZeroOrMinus1(max, label); +After: + var l = ValidateGtZeroOrMinus1(max, label); +*/ + + { + var l = ValidateGtZeroOrMinus1(max, label); if (l > int.MaxValue) { throw new ArgumentException($"{label} cannot be larger than {int.MaxValue}"); @@ -400,8 +644,10 @@ internal static Duration ValidateDurationRequired(Duration d) return d; } - internal static void ValidateDurationGtZeroRequired(long millis, string label) { - if (millis <= 0) { + internal static void ValidateDurationGtZeroRequired(long millis, string label) + { + if (millis <= 0) + { throw new ArgumentException($"{label} duration must be supplied and greater than 0."); } } @@ -445,7 +691,7 @@ internal static Duration ValidateDurationNotRequiredNotLessThanMin(long millis, { return ValidateDurationNotRequiredNotLessThanMin(Duration.OfMillis(millis), minimum); } - + internal static object ValidateNotNull(object o, string fieldName) { if (o == null) @@ -506,8 +752,9 @@ internal static long ValidateGtZeroOrMinus1(long l, string label) return l; } - internal static long ValidateNotNegative(long l, string label) { - if (l < 0) + internal static long ValidateNotNegative(long l, string label) + { + if (l < 0) { throw new ArgumentException($"{label} cannot be negative"); } @@ -523,24 +770,74 @@ public static bool NullOrEmpty(string s) return string.IsNullOrWhiteSpace(s); } - public static bool NotPrintable(string s) { - for (int x = 0; x < s.Length; x++) { + public static bool NotPrintable(string s) + { + for (var x = 0; x < s.Length; x++) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: char c = s[x]; - if (c < 33 || c > 126) { +After: + var c = s[x]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + char c = s[x]; +After: + var c = s[x]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + char c = s[x]; +After: + var c = s[x]; +*/ + + { + var c = s[x]; + if (c < 33 || c > 126) + { return true; } } return false; } - public static bool NotPrintableOrHasChars(string s, char[] charsToNotHave) { - for (int x = 0; x < s.Length; x++) { + public static bool NotPrintableOrHasChars(string s, char[] charsToNotHave) + { + for (var x = 0; x < s.Length; x++) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + char c = s[x]; +After: + var c = s[x]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: char c = s[x]; - if (c < 33 || c > 126) { +After: + var c = s[x]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + char c = s[x]; +After: + var c = s[x]; +*/ + + { + var c = s[x]; + if (c < 33 || c > 126) + { return true; } - foreach (char cx in charsToNotHave) { - if (c == cx) { + foreach (var cx in charsToNotHave) + { + if (c == cx) + { return true; } } @@ -553,28 +850,36 @@ public static bool NotRestrictedTerm(string s) { foreach (var c in s) { - if (c < '0') { // before 0 - if (c == '-') { // only dash is accepted + if (c < '0') + { // before 0 + if (c == '-') + { // only dash is accepted continue; } return true; // "not" } - if (c < ':') { + if (c < ':') + { continue; // means it's 0 - 9 } - if (c < 'A') { + if (c < 'A') + { return true; // between 9 and A is "not restricted" } - if (c < '[') { + if (c < '[') + { continue; // means it's A - Z } - if (c < 'a') { // before a - if (c == '_') { // only underscore is accepted + if (c < 'a') + { // before a + if (c == '_') + { // only underscore is accepted continue; } return true; // "not" } - if (c > 'z') { // 122 is z, characters after of them are "not restricted" + if (c > 'z') + { // 122 is z, characters after of them are "not restricted" return true; } } @@ -584,37 +889,48 @@ public static bool NotRestrictedTerm(string s) // limited-term = (A-Z, a-z, 0-9, dash 45, dot 46, fwd-slash 47, equals 61, underscore 95)+ // kv-key-name = limited-term (dot limited-term)* - public static bool NotNonWildcardKvKey(string s) { - if (s[0] == '.') { + public static bool NotNonWildcardKvKey(string s) + { + if (s[0] == '.') + { return true; // can't start with dot } - foreach (char c in s) + foreach (var c in s) { - if (c < '0') { // before 0 - if (c == '-' || c == '.' || c == '/') { // only dash dot and and fwd slash are accepted + if (c < '0') + { // before 0 + if (c == '-' || c == '.' || c == '/') + { // only dash dot and and fwd slash are accepted continue; } return true; // "not" } - if (c < ':') { + if (c < ':') + { continue; // means it's 0 - 9 } - if (c < 'A') { - if (c == '=') { // equals is accepted + if (c < 'A') + { + if (c == '=') + { // equals is accepted continue; } return true; // between 9 and A is "not limited" } - if (c < '[') { + if (c < '[') + { continue; // means it's A - Z } - if (c < 'a') { // before a - if (c == '_') { // only underscore is accepted + if (c < 'a') + { // before a + if (c == '_') + { // only underscore is accepted continue; } return true; // "not" } - if (c > 'z') { // 122 is z, characters after of them are "not limited" + if (c > 'z') + { // 122 is z, characters after of them are "not limited" return true; } } @@ -622,56 +938,71 @@ public static bool NotNonWildcardKvKey(string s) { } // (A-Z, a-z, 0-9, star 42, dash 45, dot 46, fwd-slash 47, equals 61, gt 62, underscore 95)+ - public static bool NotWildcardKvKey(string s) { - if (s[0] == '.') { + public static bool NotWildcardKvKey(string s) + { + if (s[0] == '.') + { return true; // can't start with dot } - foreach (char c in s) + foreach (var c in s) { - if (c < '0') { // before 0 - if (c == '*' || c == '-' || c == '.' || c == '/') { // only star dash dot and fwd slash are accepted + if (c < '0') + { // before 0 + if (c == '*' || c == '-' || c == '.' || c == '/') + { // only star dash dot and fwd slash are accepted continue; } return true; // "not" } - if (c < ':') { + if (c < ':') + { continue; // means it's 0 - 9 } - if (c < 'A') { - if (c == '=' || c == '>') { // equals, gt is accepted + if (c < 'A') + { + if (c == '=' || c == '>') + { // equals, gt is accepted continue; } return true; // between 9 and A is "not limited" } - if (c < '[') { + if (c < '[') + { continue; // means it's A - Z } - if (c < 'a') { // before a - if (c == '_') { // only underscore is accepted + if (c < 'a') + { // before a + if (c == '_') + { // only underscore is accepted continue; } return true; // "not" } - if (c > 'z') { // 122 is z, characters after of them are "not limited" + if (c > 'z') + { // 122 is z, characters after of them are "not limited" return true; } } return false; } - public static bool NotPrintableOrHasWildGt(string s) { + public static bool NotPrintableOrHasWildGt(string s) + { return NotPrintableOrHasChars(s, WildGt); } - public static bool NotPrintableOrHasWildGtDot(string s) { + public static bool NotPrintableOrHasWildGtDot(string s) + { return NotPrintableOrHasChars(s, WildGtDot); } - public static bool NotPrintableOrHasWildGtDotSlashes(string s) { + public static bool NotPrintableOrHasWildGtDotSlashes(string s) + { return NotPrintableOrHasChars(s, WildGtDotSlashes); } - - public static bool NotPrintableOrHasWildGtDollar(string s) { + + public static bool NotPrintableOrHasWildGtDollar(string s) + { return NotPrintableOrHasChars(s, WildGtDollar); } @@ -680,7 +1011,8 @@ public static string EmptyAsNull(string s) return string.IsNullOrWhiteSpace(s) ? null : s; } - public static string EmptyOrNullAs(string s, string ifEmpty) { + public static string EmptyOrNullAs(string s, string ifEmpty) + { return string.IsNullOrWhiteSpace(s) ? ifEmpty : s; } @@ -698,12 +1030,12 @@ public static bool EmptyOrNull(TSource[] list) { return list == null || list.Length == 0; } - + public static bool ZeroOrLtMinus1(long l) { return l == 0 || l < -1; } - + public static Duration EnsureNotNullAndNotLessThanMin(Duration provided, Duration minimum, Duration dflt) { return provided == null || provided.Nanos < minimum.Nanos ? dflt : provided; @@ -713,33 +1045,83 @@ public static Duration EnsureDurationNotLessThanMin(long providedMillis, Duratio { return EnsureNotNullAndNotLessThanMin(Duration.OfMillis(providedMillis), minimum, dflt); } - - public static bool Equal(byte[] a, byte[] a2) { + + public static bool Equal(byte[] a, byte[] a2) + { // exact same object or both null - if (a == a2) { return true; } - if (a == null || a2 == null) { return false; } // only one is null + if (a == a2) + { return true; } + if (a == null || a2 == null) + { return false; } // only one is null +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int length = a.Length; +After: + var length = a.Length; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int length = a.Length; +After: + var length = a.Length; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int length = a.Length; - if (a2.Length != length) { return false; } // diff lengths +After: + var length = a.Length; +*/ + + + var length = a.Length; + if (a2.Length != length) + { return false; } // diff lengths + + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + for (int i=0; i { - if (!IsSemVer(s)) { + return Validate(s, required, label, () => + { + if (!IsSemVer(s)) + { throw new ArgumentException($"{label} must be a valid SemVer [{s}]"); } return s; @@ -762,7 +1144,7 @@ public static bool SequenceEqual(IList l1, IList l2, bool nullSecondEqu { return nullSecondEqualsEmptyFirst && l1.Count == 0; } - + return l1.SequenceEqual(l2); } @@ -781,8 +1163,10 @@ public static bool ConsumerFilterSubjectsAreEquivalent(IList l1, IList return false; } - foreach (T t in l1) { - if (!l2.Contains(t)) { + foreach (var t in l1) + { + if (!l2.Contains(t)) + { return false; } } @@ -795,13 +1179,13 @@ public static bool DictionariesEqual(IDictionary d1, IDictionary { return true; } - + if (d1 == null || d2 == null || d1.Count != d2.Count) { return false; } - foreach (KeyValuePair pair in d1) + foreach (var pair in d1) { if (!d2.TryGetValue(pair.Key, out var value) || !pair.Value.Equals(value)) { diff --git a/src/NATS.Client/v1/JWTHandlerUtils.cs b/src/NATS.Client/v1/JWTHandlerUtils.cs index fd413819..38254e78 100644 --- a/src/NATS.Client/v1/JWTHandlerUtils.cs +++ b/src/NATS.Client/v1/JWTHandlerUtils.cs @@ -24,7 +24,7 @@ public static string LoadUser(string text) try { reader = new StringReader(text); - for (string line = reader.ReadLine(); line != null; line = reader.ReadLine()) + for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) { if (line.Contains("-----BEGIN NATS USER JWT-----")) { @@ -39,7 +39,7 @@ public static string LoadUser(string text) reader?.Dispose(); } } - + public static NkeyPair LoadNkeyPair(string nkeySeed) { StringReader reader = null; @@ -53,7 +53,7 @@ public static NkeyPair LoadNkeyPair(string nkeySeed) // otherwise assume it's a creds file. reader = new StringReader(nkeySeed); - for (string line = reader.ReadLine(); line != null; line = reader.ReadLine()) + for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) { if (line.Contains("-----BEGIN USER NKEY SEED-----")) { diff --git a/src/NATS.Client/v1/JetStream/AccountLimits.cs b/src/NATS.Client/v1/JetStream/AccountLimits.cs index 55054401..ede843a4 100644 --- a/src/NATS.Client/v1/JetStream/AccountLimits.cs +++ b/src/NATS.Client/v1/JetStream/AccountLimits.cs @@ -22,37 +22,37 @@ public sealed class AccountLimits /// The maximum amount of Memory storage Stream Messages may consume. /// public long MaxMemory { get; } - + /// /// The maximum amount of File storage Stream Messages may consume. /// public long MaxStorage { get; } - + /// /// The maximum number of Streams an account can create. /// public long MaxStreams { get; } - + /// /// The maximum number of Consumers an account can create. /// public long MaxConsumers { get; } - + /// /// The maximum number of outstanding ACKs any consumer may configure. /// public long MaxAckPending { get; } - + /// /// The maximum size any single memory stream may be. /// public long MemoryMaxStreamBytes { get; } - + /// /// The maximum size any single storage based stream may be. /// public long StorageMaxStreamBytes { get; } - + /// /// Indicates if streams created in this account requires the max_bytes property set. /// diff --git a/src/NATS.Client/v1/JetStream/AccountStatistics.cs b/src/NATS.Client/v1/JetStream/AccountStatistics.cs index b058c3b8..dd0f15d4 100644 --- a/src/NATS.Client/v1/JetStream/AccountStatistics.cs +++ b/src/NATS.Client/v1/JetStream/AccountStatistics.cs @@ -22,22 +22,22 @@ public sealed class AccountStatistics : ApiResponse { // rollup contains the memory, storage, streams, consumers and limits from the top level private AccountTier _rollup; - + /// /// Gets the amount of memory storage used by the JetStream deployment. /// public long Memory => _rollup.Memory; - + /// /// Gets the amount of file storage used by the JetStream deployment. /// public long Storage => _rollup.Storage; - + /// /// Gets the number of streams used by the JetStream deployment. /// public long Streams => _rollup.Streams; - + /// /// Gets the number of consumers used by the JetStream deployment. /// @@ -49,16 +49,16 @@ public sealed class AccountStatistics : ApiResponse /// See the Account Limits for the specific tier. /// public AccountLimits Limits => _rollup.Limits; - + /// /// Gets the account domain /// - public string Domain { get; private set; } - + public string Domain { get; private set; } + /// /// Gets the account api stats /// - public ApiStats Api { get; private set; } + public ApiStats Api { get; private set; } public IDictionary Tiers; public AccountStatistics(Msg msg, bool throwOnError) : base(msg, throwOnError) @@ -77,8 +77,29 @@ private void Init() Domain = JsonNode[ApiConstants.Domain].Value; Api = new ApiStats(JsonNode[ApiConstants.Api]); IDictionary temp = new Dictionary(); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: JSONNode tnode = JsonNode[ApiConstants.Tiers]; - foreach (string key in tnode.Keys) +After: + var tnode = JsonNode[ApiConstants.Tiers]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONNode tnode = JsonNode[ApiConstants.Tiers]; +After: + var tnode = JsonNode[ApiConstants.Tiers]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONNode tnode = JsonNode[ApiConstants.Tiers]; +After: + var tnode = JsonNode[ApiConstants.Tiers]; +*/ + + var tnode = JsonNode[ApiConstants.Tiers]; + foreach (var key in tnode.Keys) { temp[key] = new AccountTier(tnode[key]); } diff --git a/src/NATS.Client/v1/JetStream/AccountTier.cs b/src/NATS.Client/v1/JetStream/AccountTier.cs index 729a00a6..8135c594 100644 --- a/src/NATS.Client/v1/JetStream/AccountTier.cs +++ b/src/NATS.Client/v1/JetStream/AccountTier.cs @@ -21,28 +21,28 @@ public sealed class AccountTier /// Memory Storage being used for Stream Message storage in this tier. /// public long Memory { get; } - + /// /// File Storage being used for Stream Message storage in this tier. /// public long Storage { get; } - + /// /// Number of active streams in this tier. /// public long Streams { get; } - + /// /// Number of active consumers in this tier. /// public long Consumers { get; } - + /// /// The limits of this tier. /// public AccountLimits Limits { get; } - internal AccountTier(JSONNode jsonNode) + internal AccountTier(JSONNode jsonNode) { Memory = jsonNode[ApiConstants.Memory].AsLong; Storage = jsonNode[ApiConstants.Storage].AsLong; diff --git a/src/NATS.Client/v1/JetStream/ApiConstants.cs b/src/NATS.Client/v1/JetStream/ApiConstants.cs index e96b489d..ee2f615c 100644 --- a/src/NATS.Client/v1/JetStream/ApiConstants.cs +++ b/src/NATS.Client/v1/JetStream/ApiConstants.cs @@ -24,7 +24,7 @@ public static class ApiConstants public const string AllowDirect = "allow_direct"; public const string Api = "api"; public const string AuthRequired = "auth_required"; - public const string AverageProcessingTime = "average_processing_time"; + public const string AverageProcessingTime = "average_processing_time"; public const string Backoff = "backoff"; public const string Batch = "batch"; public const string Bucket = "bucket"; diff --git a/src/NATS.Client/v1/JetStream/ApiEnums.cs b/src/NATS.Client/v1/JetStream/ApiEnums.cs index c65d169f..b34d8bc1 100644 --- a/src/NATS.Client/v1/JetStream/ApiEnums.cs +++ b/src/NATS.Client/v1/JetStream/ApiEnums.cs @@ -35,43 +35,56 @@ public static string GetString(this AckPolicy ackPolicy) { switch (ackPolicy) { - case AckPolicy.None: return "none"; - case AckPolicy.All: return "all"; - case AckPolicy.Explicit: return "explicit"; + case AckPolicy.None: + return "none"; + case AckPolicy.All: + return "all"; + case AckPolicy.Explicit: + return "explicit"; } return null; } - + public static string GetString(this DeliverPolicy deliverPolicy) { switch (deliverPolicy) { - case DeliverPolicy.All: return "all"; - case DeliverPolicy.Last: return "last"; - case DeliverPolicy.New: return "new"; - case DeliverPolicy.ByStartSequence: return "by_start_sequence"; - case DeliverPolicy.ByStartTime: return "by_start_time"; - case DeliverPolicy.LastPerSubject: return "last_per_subject"; + case DeliverPolicy.All: + return "all"; + case DeliverPolicy.Last: + return "last"; + case DeliverPolicy.New: + return "new"; + case DeliverPolicy.ByStartSequence: + return "by_start_sequence"; + case DeliverPolicy.ByStartTime: + return "by_start_time"; + case DeliverPolicy.LastPerSubject: + return "last_per_subject"; } return null; } - + public static string GetString(this DiscardPolicy discardPolicy) { switch (discardPolicy) { - case DiscardPolicy.New: return "new"; - case DiscardPolicy.Old: return "old"; + case DiscardPolicy.New: + return "new"; + case DiscardPolicy.Old: + return "old"; } return null; } - + public static string GetString(this ReplayPolicy replayPolicy) { switch (replayPolicy) { - case ReplayPolicy.Instant: return "instant"; - case ReplayPolicy.Original: return "original"; + case ReplayPolicy.Instant: + return "instant"; + case ReplayPolicy.Original: + return "original"; } return null; } @@ -80,29 +93,36 @@ public static string GetString(this RetentionPolicy retentionPolicy) { switch (retentionPolicy) { - case RetentionPolicy.Limits: return "limits"; - case RetentionPolicy.Interest: return "interest"; - case RetentionPolicy.WorkQueue: return "workqueue"; + case RetentionPolicy.Limits: + return "limits"; + case RetentionPolicy.Interest: + return "interest"; + case RetentionPolicy.WorkQueue: + return "workqueue"; } return null; } - + public static string GetString(this StorageType storageType) { switch (storageType) { - case StorageType.File: return "file"; - case StorageType.Memory: return "memory"; + case StorageType.File: + return "file"; + case StorageType.Memory: + return "memory"; } return null; } - + public static string GetString(this CompressionOption compressionOption) { switch (compressionOption) { - case CompressionOption.None: return "none"; - case CompressionOption.S2: return "s2"; + case CompressionOption.None: + return "none"; + case CompressionOption.S2: + return "s2"; } return null; } @@ -111,9 +131,12 @@ public static string GetString(this ConsumerCreateRequestAction action) { switch (action) { - case ConsumerCreateRequestAction.Create: return "create"; - case ConsumerCreateRequestAction.Update: return "update"; - case ConsumerCreateRequestAction.CreateOrUpdate: return null; + case ConsumerCreateRequestAction.Create: + return "create"; + case ConsumerCreateRequestAction.Update: + return "update"; + case ConsumerCreateRequestAction.CreateOrUpdate: + return null; } return null; } @@ -124,9 +147,12 @@ public static string GetString(this ConsumerCreateRequestAction action) { switch (value) { - case "none": return AckPolicy.None; - case "all": return AckPolicy.All; - case "explicit": return AckPolicy.Explicit; + case "none": + return AckPolicy.None; + case "all": + return AckPolicy.All; + case "explicit": + return AckPolicy.Explicit; } } @@ -139,11 +165,16 @@ public static string GetString(this ConsumerCreateRequestAction action) { switch (value) { - case "all": return DeliverPolicy.All; - case "last": return DeliverPolicy.Last; - case "new": return DeliverPolicy.New; - case "by_start_sequence": return DeliverPolicy.ByStartSequence; - case "by_start_time": return DeliverPolicy.ByStartTime; + case "all": + return DeliverPolicy.All; + case "last": + return DeliverPolicy.Last; + case "new": + return DeliverPolicy.New; + case "by_start_sequence": + return DeliverPolicy.ByStartSequence; + case "by_start_time": + return DeliverPolicy.ByStartTime; } } @@ -156,8 +187,10 @@ public static string GetString(this ConsumerCreateRequestAction action) { switch (value) { - case "instant": return ReplayPolicy.Instant; - case "original": return ReplayPolicy.Original; + case "instant": + return ReplayPolicy.Instant; + case "original": + return ReplayPolicy.Original; } } @@ -170,8 +203,10 @@ public static DiscardPolicy GetValueOrDefault(string value, DiscardPolicy aDefau { switch (value) { - case "new": return DiscardPolicy.New; - case "old": return DiscardPolicy.Old; + case "new": + return DiscardPolicy.New; + case "old": + return DiscardPolicy.Old; } } @@ -184,9 +219,12 @@ public static RetentionPolicy GetValueOrDefault(string value, RetentionPolicy aD { switch (value) { - case "limits": return RetentionPolicy.Limits; - case "interest": return RetentionPolicy.Interest; - case "workqueue": return RetentionPolicy.WorkQueue; + case "limits": + return RetentionPolicy.Limits; + case "interest": + return RetentionPolicy.Interest; + case "workqueue": + return RetentionPolicy.WorkQueue; } } @@ -199,8 +237,10 @@ public static StorageType GetValueOrDefault(string value, StorageType aDefault) { switch (value) { - case "file": return StorageType.File; - case "memory": return StorageType.Memory; + case "file": + return StorageType.File; + case "memory": + return StorageType.Memory; } } @@ -213,8 +253,10 @@ public static CompressionOption GetValueOrDefault(string value, CompressionOptio { switch (value) { - case "none": return CompressionOption.None; - case "s2": return CompressionOption.S2; + case "none": + return CompressionOption.None; + case "s2": + return CompressionOption.S2; } } diff --git a/src/NATS.Client/v1/JetStream/ApiResponse.cs b/src/NATS.Client/v1/JetStream/ApiResponse.cs index 1430fca4..dfaffd93 100644 --- a/src/NATS.Client/v1/JetStream/ApiResponse.cs +++ b/src/NATS.Client/v1/JetStream/ApiResponse.cs @@ -25,7 +25,7 @@ public class ApiResponse internal JSONNode JsonNode { get; private set; } - internal ApiResponse() {} + internal ApiResponse() { } internal ApiResponse(Msg msg, bool throwOnError, bool ignoreMessage = false) { @@ -55,9 +55,11 @@ private void InitJson(string json, bool throwOnError) ThrowOnHasError(); } } - - public void ThrowOnHasError() { - if (HasError) { + + public void ThrowOnHasError() + { + if (HasError) + { throw new NATSJetStreamException(this); } } diff --git a/src/NATS.Client/v1/JetStream/ApiStats.cs b/src/NATS.Client/v1/JetStream/ApiStats.cs index 9334d31a..f6977e5c 100644 --- a/src/NATS.Client/v1/JetStream/ApiStats.cs +++ b/src/NATS.Client/v1/JetStream/ApiStats.cs @@ -22,13 +22,13 @@ public sealed class ApiStats /// Total number of API requests received for this account. /// public long Total { get; } - + /// /// API requests that resulted in an error response. /// public long Errors { get; } - internal ApiStats(JSONNode jsonNode) + internal ApiStats(JSONNode jsonNode) { Total = JsonUtils.AsLongOrZero(jsonNode, ApiConstants.Total); Errors = JsonUtils.AsLongOrZero(jsonNode, ApiConstants.Errors); diff --git a/src/NATS.Client/v1/JetStream/BaseConsumeOptions.cs b/src/NATS.Client/v1/JetStream/BaseConsumeOptions.cs index a9d1b002..8f5b5462 100644 --- a/src/NATS.Client/v1/JetStream/BaseConsumeOptions.cs +++ b/src/NATS.Client/v1/JetStream/BaseConsumeOptions.cs @@ -23,22 +23,22 @@ public class BaseConsumeOptions { /// 500 public const int DefaultMessageCount = 500; - + /// 1_000_000 public const int DefaultMessageCountWhenBytes = 1_000_000; - + /// 25 public const int DefaultThresholdPercent = 25; - + /// 30_000 public const int DefaultExpiresInMillis = 30000; - + /// 1000 public const int MinExpiresMills = 1000; - + /// 30_000 public const int MaxHearbeatMillis = 30000; - + /// 50 public const int MaxIdleHeartbeatPercent = 50; @@ -60,7 +60,8 @@ protected BaseConsumeOptions(IBaseConsumeOptionsBuilder b) { Messages = b.Messages == -1 ? DefaultMessageCountWhenBytes : b.Messages; } - else { + else + { Messages = b.Messages == -1 ? DefaultMessageCount : b.Messages; } @@ -71,7 +72,7 @@ protected BaseConsumeOptions(IBaseConsumeOptionsBuilder b) // calculated IdleHeartbeat = Math.Min(MaxHearbeatMillis, ExpiresInMillis * MaxIdleHeartbeatPercent / 100); } - + public interface IBaseConsumeOptionsBuilder { int Messages { get; } @@ -93,13 +94,36 @@ public abstract class BaseConsumeOptionsBuilder : IBaseConsumeOptionsBu public int ExpiresIn => _expiresIn; protected abstract TB GetThis(); - - protected TB WithMessages(int messages) { + + protected TB WithMessages(int messages) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this._messages = messages < 1 ? -1 : messages; +After: + _messages = messages < 1 ? -1 : messages; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: this._messages = messages < 1 ? -1 : messages; +After: + _messages = messages < 1 ? -1 : messages; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this._messages = messages < 1 ? -1 : messages; +After: + _messages = messages < 1 ? -1 : messages; +*/ + + { + _messages = messages < 1 ? -1 : messages; return GetThis(); } - protected TB WithBytes(long bytes) { + protected TB WithBytes(long bytes) + { _bytes = bytes < 1 ? 0 : bytes; return GetThis(); } @@ -113,15 +137,40 @@ protected TB WithBytes(long bytes) { /// /// the expiration time in milliseconds /// the builder - public TB WithExpiresIn(int expiresInMillis) { + public TB WithExpiresIn(int expiresInMillis) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this._expiresIn = expiresInMillis; +After: + _expiresIn = expiresInMillis; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: this._expiresIn = expiresInMillis; - if (expiresInMillis < 1) { +After: + _expiresIn = expiresInMillis; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this._expiresIn = expiresInMillis; +After: + _expiresIn = expiresInMillis; +*/ + + { + _expiresIn = expiresInMillis; + if (expiresInMillis < 1) + { _expiresIn = DefaultExpiresInMillis; } - else if (expiresInMillis < MinExpiresMills) { + else if (expiresInMillis < MinExpiresMills) + { throw new ArgumentException($"Expires must be greater than or equal to {MinExpiresMills}"); } - else { + else + { _expiresIn = expiresInMillis; } @@ -141,8 +190,30 @@ public TB WithExpiresIn(int expiresInMillis) { /// /// the threshold percent /// the builder - public TB WithThresholdPercent(int thresholdPercent) { + public TB WithThresholdPercent(int thresholdPercent) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this._thresholdPercent = thresholdPercent < 1 ? DefaultThresholdPercent : Math.Min(100, thresholdPercent); +After: + _thresholdPercent = thresholdPercent < 1 ? DefaultThresholdPercent : Math.Min(100, thresholdPercent); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: this._thresholdPercent = thresholdPercent < 1 ? DefaultThresholdPercent : Math.Min(100, thresholdPercent); +After: + _thresholdPercent = thresholdPercent < 1 ? DefaultThresholdPercent : Math.Min(100, thresholdPercent); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this._thresholdPercent = thresholdPercent < 1 ? DefaultThresholdPercent : Math.Min(100, thresholdPercent); +After: + _thresholdPercent = thresholdPercent < 1 ? DefaultThresholdPercent : Math.Min(100, thresholdPercent); +*/ + + { + _thresholdPercent = thresholdPercent < 1 ? DefaultThresholdPercent : Math.Min(100, thresholdPercent); return GetThis(); } diff --git a/src/NATS.Client/v1/JetStream/ClusterInfo.cs b/src/NATS.Client/v1/JetStream/ClusterInfo.cs index 2e94fe0c..16d41834 100644 --- a/src/NATS.Client/v1/JetStream/ClusterInfo.cs +++ b/src/NATS.Client/v1/JetStream/ClusterInfo.cs @@ -33,7 +33,7 @@ private ClusterInfo(JSONNode clusterNode) Leader = clusterNode[ApiConstants.Leader].Value; Replicas = Replica.OptionalListOf(clusterNode[ApiConstants.Replicas]); } - + public override string ToString() { return "ClusterInfo{" + diff --git a/src/NATS.Client/v1/JetStream/ConsumeOptions.cs b/src/NATS.Client/v1/JetStream/ConsumeOptions.cs index 45908ffd..409ae295 100644 --- a/src/NATS.Client/v1/JetStream/ConsumeOptions.cs +++ b/src/NATS.Client/v1/JetStream/ConsumeOptions.cs @@ -1,4 +1,4 @@ -// Copyright 2023 The NATS Authors +// Copyright 2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -24,13 +24,13 @@ public class ConsumeOptions : BaseConsumeOptions /// The initial batch size in messages. /// public int BatchSize => Messages; - + /// /// The initial batch size in bytes. /// public long BatchBytes => Bytes; - protected ConsumeOptions(IBaseConsumeOptionsBuilder b) : base(b) {} + protected ConsumeOptions(IBaseConsumeOptionsBuilder b) : base(b) { } /// /// Gets the ConsumeOptions builder. @@ -48,7 +48,7 @@ protected override ConsumeOptionsBuilder GetThis() { return this; } - + /// /// Set the initial batch size in messages and remove any previously set batch byte constraint. /// Less than 1 will assume the default of when bytes are not specified. @@ -72,7 +72,8 @@ public ConsumeOptionsBuilder WithBatchSize(int batchSize) /// /// the batch size in bytes /// the builder - public ConsumeOptionsBuilder WithBatchBytes(long batchBytes) { + public ConsumeOptionsBuilder WithBatchBytes(long batchBytes) + { base.WithMessages(-1); return base.WithBytes(batchBytes); } diff --git a/src/NATS.Client/v1/JetStream/ConsumerConfiguration.cs b/src/NATS.Client/v1/JetStream/ConsumerConfiguration.cs index efee9758..af1eceb6 100644 --- a/src/NATS.Client/v1/JetStream/ConsumerConfiguration.cs +++ b/src/NATS.Client/v1/JetStream/ConsumerConfiguration.cs @@ -74,7 +74,7 @@ public sealed class ConsumerConfiguration : JsonSerializable public Duration InactiveThreshold { get; } public ulong StartSeq => GetOrUnset(_startSeq); public int MaxDeliver => GetOrUnset(_maxDeliver); - + public ulong RateLimitBps => GetOrUnset(_rateLimitBps); public int MaxAckPending => GetOrUnset(_maxAckPending); public int MaxPullWaiting => GetOrUnset(_maxPullWaiting); @@ -98,7 +98,7 @@ public sealed class ConsumerConfiguration : JsonSerializable [Obsolete("This property is obsolete. Use RateLimitBps.", false)] public long RateLimit => (long)GetOrUnset(_rateLimitBps); - internal ConsumerConfiguration(string json) : this(JSON.Parse(json)) {} + internal ConsumerConfiguration(string json) : this(JSON.Parse(json)) { } internal ConsumerConfiguration(JSONNode ccNode) { @@ -112,7 +112,7 @@ internal ConsumerConfiguration(JSONNode ccNode) DeliverSubject = ccNode[ApiConstants.DeliverSubject].Value; DeliverGroup = ccNode[ApiConstants.DeliverGroup].Value; SampleFrequency = ccNode[ApiConstants.SampleFreq].Value; - + StartTime = AsDate(ccNode[ApiConstants.OptStartTime]); PauseUntil = AsOptionalDate(ccNode[ApiConstants.PauseUntil]); AckWait = AsDuration(ccNode, ApiConstants.AckWait, null); @@ -134,7 +134,28 @@ internal ConsumerConfiguration(JSONNode ccNode) _backoff = DurationList(ccNode, ApiConstants.Backoff, true); _metadata = StringStringDictionary(ccNode, ApiConstants.Metadata, true); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: string tempFs = EmptyAsNull(ccNode[ApiConstants.FilterSubject].Value); +After: + var tempFs = EmptyAsNull(ccNode[ApiConstants.FilterSubject].Value); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string tempFs = EmptyAsNull(ccNode[ApiConstants.FilterSubject].Value); +After: + var tempFs = EmptyAsNull(ccNode[ApiConstants.FilterSubject].Value); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string tempFs = EmptyAsNull(ccNode[ApiConstants.FilterSubject].Value); +After: + var tempFs = EmptyAsNull(ccNode[ApiConstants.FilterSubject].Value); +*/ + + var tempFs = EmptyAsNull(ccNode[ApiConstants.FilterSubject].Value); if (tempFs == null) { _filterSubjects = EmptyAsNull(StringList(ccNode, ApiConstants.FilterSubjects)); @@ -184,8 +205,29 @@ private ConsumerConfiguration(ConsumerConfigurationBuilder builder) } public override JSONNode ToJsonNode() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + + { + var o = new JSONObject(); AddField(o, ApiConstants.Description, Description); AddField(o, ApiConstants.DurableName, Durable); @@ -232,60 +274,104 @@ public override JSONNode ToJsonNode() internal IList GetChanges(ConsumerConfiguration server) { IList changes = new List(); - if (_deliverPolicy != null && _deliverPolicy != server.DeliverPolicy) { changes.Add("DeliverPolicy"); } - if (_ackPolicy != null && _ackPolicy != server.AckPolicy) { changes.Add("AckPolicy"); } - if (_replayPolicy != null && _replayPolicy != server.ReplayPolicy) { changes.Add("ReplayPolicy"); } - - if (_flowControl != null && _flowControl != server.FlowControl) { changes.Add("FlowControl"); } - if (_headersOnly != null && _headersOnly != server.HeadersOnly) { changes.Add("HeadersOnly"); } - if (_memStorage != null && _memStorage != server.MemStorage) { changes.Add("MemStorage"); } - - if (_startSeq != null && !_startSeq.Equals(server.StartSeq)) { changes.Add("StartSequence"); } - if (_rateLimitBps != null && !_rateLimitBps.Equals(server.RateLimitBps)) { changes.Add("RateLimitBps"); } - - if (_maxDeliver != null && !_maxDeliver.Equals(server.MaxDeliver)) { changes.Add("MaxDeliver"); } - if (_maxAckPending != null && !_maxAckPending.Equals(server.MaxAckPending)) { changes.Add("MaxAckPending"); } - if (_maxPullWaiting != null && !_maxPullWaiting.Equals(server.MaxPullWaiting)) { changes.Add("MaxPullWaiting"); } - if (_maxBatch != null && !_maxBatch.Equals(server.MaxBatch)) { changes.Add("MaxBatch"); } - if (_maxBytes != null && !_maxBytes.Equals(server.MaxBytes)) { changes.Add("MaxBytes"); } - if (_numReplicas != null && !_numReplicas.Equals(server.NumReplicas)) { changes.Add("NumReplicas"); } - - if (AckWait != null && !AckWait.Equals(server.AckWait)) { changes.Add("AckWait"); } - if (IdleHeartbeat != null && !IdleHeartbeat.Equals(server.IdleHeartbeat)) { changes.Add("IdleHeartbeat"); } - if (MaxExpires != null && !MaxExpires.Equals(server.MaxExpires)) { changes.Add("MaxExpires"); } - if (InactiveThreshold != null && !InactiveThreshold.Equals(server.InactiveThreshold)) { changes.Add("InactiveThreshold"); } + if (_deliverPolicy != null && _deliverPolicy != server.DeliverPolicy) + { changes.Add("DeliverPolicy"); } + if (_ackPolicy != null && _ackPolicy != server.AckPolicy) + { changes.Add("AckPolicy"); } + if (_replayPolicy != null && _replayPolicy != server.ReplayPolicy) + { changes.Add("ReplayPolicy"); } + + if (_flowControl != null && _flowControl != server.FlowControl) + { changes.Add("FlowControl"); } + if (_headersOnly != null && _headersOnly != server.HeadersOnly) + { changes.Add("HeadersOnly"); } + if (_memStorage != null && _memStorage != server.MemStorage) + { changes.Add("MemStorage"); } + + if (_startSeq != null && !_startSeq.Equals(server.StartSeq)) + { changes.Add("StartSequence"); } + if (_rateLimitBps != null && !_rateLimitBps.Equals(server.RateLimitBps)) + { changes.Add("RateLimitBps"); } + + if (_maxDeliver != null && !_maxDeliver.Equals(server.MaxDeliver)) + { changes.Add("MaxDeliver"); } + if (_maxAckPending != null && !_maxAckPending.Equals(server.MaxAckPending)) + { changes.Add("MaxAckPending"); } + if (_maxPullWaiting != null && !_maxPullWaiting.Equals(server.MaxPullWaiting)) + { changes.Add("MaxPullWaiting"); } + if (_maxBatch != null && !_maxBatch.Equals(server.MaxBatch)) + { changes.Add("MaxBatch"); } + if (_maxBytes != null && !_maxBytes.Equals(server.MaxBytes)) + { changes.Add("MaxBytes"); } + if (_numReplicas != null && !_numReplicas.Equals(server.NumReplicas)) + { changes.Add("NumReplicas"); } + + if (AckWait != null && !AckWait.Equals(server.AckWait)) + { changes.Add("AckWait"); } + if (IdleHeartbeat != null && !IdleHeartbeat.Equals(server.IdleHeartbeat)) + { changes.Add("IdleHeartbeat"); } + if (MaxExpires != null && !MaxExpires.Equals(server.MaxExpires)) + { changes.Add("MaxExpires"); } + if (InactiveThreshold != null && !InactiveThreshold.Equals(server.InactiveThreshold)) + { changes.Add("InactiveThreshold"); } RecordWouldBeChange(StartTime, server.StartTime, "StartTime", changes); RecordWouldBeChange(PauseUntil, server.PauseUntil, "PauseUntil", changes); - + RecordWouldBeChange(Description, server.Description, "Description", changes); RecordWouldBeChange(SampleFrequency, server.SampleFrequency, "SampleFrequency", changes); RecordWouldBeChange(DeliverSubject, server.DeliverSubject, "DeliverSubject", changes); RecordWouldBeChange(DeliverGroup, server.DeliverGroup, "DeliverGroup", changes); - if (_backoff != null && !SequenceEqual(_backoff, server._backoff)) { changes.Add("Backoff"); } - if (_metadata != null && !DictionariesEqual(_metadata, server._metadata)) { changes.Add("Metadata"); } - if (_filterSubjects != null && !SequenceEqual(_filterSubjects, server._filterSubjects)) { changes.Add("FilterSubjects"); } + if (_backoff != null && !SequenceEqual(_backoff, server._backoff)) + { changes.Add("Backoff"); } + if (_metadata != null && !DictionariesEqual(_metadata, server._metadata)) + { changes.Add("Metadata"); } + if (_filterSubjects != null && !SequenceEqual(_filterSubjects, server._filterSubjects)) + { changes.Add("FilterSubjects"); } return changes; } private void RecordWouldBeChange(string request, string server, string field, IList changes) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string r = EmptyAsNull(request); +After: + var r = EmptyAsNull(request); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string r = EmptyAsNull(request); +After: + var r = EmptyAsNull(request); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string r = EmptyAsNull(request); - if (r != null && !r.Equals(EmptyAsNull(server))) { changes.Add(field); } +After: + var r = EmptyAsNull(request); +*/ + + { + var r = EmptyAsNull(request); + if (r != null && !r.Equals(EmptyAsNull(server))) + { changes.Add(field); } } private void RecordWouldBeChange(DateTime request, DateTime server, string field, IList changes) { - if (request != DateTime.MinValue && !request.Equals(server)) { changes.Add(field); } + if (request != DateTime.MinValue && !request.Equals(server)) + { changes.Add(field); } } private void RecordWouldBeChange(DateTime? request, DateTime? server, string field, IList changes) { RecordWouldBeChange(request.GetValueOrDefault(DateTime.MinValue), server.GetValueOrDefault(DateTime.MinValue), field, changes); } - + internal static int GetOrUnset(int? val) { return val ?? IntUnset; @@ -296,16 +382,20 @@ internal static ulong GetOrUnset(ulong? val) return val ?? UlongUnset; } - internal static int? NormalizeToInt(long? l, long min) { - if (l == null) { + internal static int? NormalizeToInt(long? l, long min) + { + if (l == null) + { return null; } - if (l < min) { + if (l < min) + { return IntUnset; } - if (l > int.MaxValue) { + if (l > int.MaxValue) + { return int.MaxValue; } @@ -331,7 +421,7 @@ public static ConsumerConfigurationBuilder Builder() { return new ConsumerConfigurationBuilder(); } - + public static ConsumerConfigurationBuilder Builder(ConsumerConfiguration cc) { return new ConsumerConfigurationBuilder(cc); @@ -342,16 +432,16 @@ public sealed class ConsumerConfigurationBuilder internal DeliverPolicy? _deliverPolicy; internal AckPolicy? _ackPolicy; internal ReplayPolicy? _replayPolicy; - + internal string _description; internal string _durable; internal string _name; internal string _deliverSubject; internal string _deliverGroup; internal string _sampleFrequency; - - internal DateTime _startTime; - internal DateTime? _pauseUntil; + + internal DateTime _startTime; + internal DateTime? _pauseUntil; internal Duration _ackWait; internal Duration _idleHeartbeat; internal Duration _maxExpires; @@ -372,12 +462,13 @@ public sealed class ConsumerConfigurationBuilder internal Dictionary _metadata; internal IList _filterSubjects; - public ConsumerConfigurationBuilder() {} + public ConsumerConfigurationBuilder() { } public ConsumerConfigurationBuilder(ConsumerConfiguration cc) { - if (cc == null) return; - + if (cc == null) + return; + _deliverPolicy = cc._deliverPolicy; _ackPolicy = cc._ackPolicy; _replayPolicy = cc._replayPolicy; @@ -416,7 +507,7 @@ public ConsumerConfigurationBuilder(ConsumerConfiguration cc) if (cc._metadata != null) { _metadata = new Dictionary(); - foreach (string key in cc.Metadata.Keys) + foreach (var key in cc.Metadata.Keys) { _metadata[key] = cc.Metadata[key]; } @@ -547,7 +638,7 @@ public ConsumerConfigurationBuilder WithAckPolicy(AckPolicy? policy) /// The ConsumerConfigurationBuilder public ConsumerConfigurationBuilder WithAckWait(Duration timeout) { - _ackWait = Normalize(timeout); + _ackWait = Normalize(timeout); return this; } @@ -558,7 +649,7 @@ public ConsumerConfigurationBuilder WithAckWait(Duration timeout) /// The ConsumerConfigurationBuilder public ConsumerConfigurationBuilder WithAckWait(long timeoutMillis) { - _ackWait = NormalizeDuration(timeoutMillis); + _ackWait = NormalizeDuration(timeoutMillis); return this; } @@ -581,13 +672,62 @@ public ConsumerConfigurationBuilder WithMaxDeliver(long? maxDeliver) /// The ConsumerConfigurationBuilder public ConsumerConfigurationBuilder WithFilterSubject(string filterSubject) { - if (string.IsNullOrWhiteSpace(filterSubject)) - { + if (string.IsNullOrWhiteSpace(filterSubject)) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: this._filterSubjects = null; - } - else { +After: + _filterSubjects = null; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this._filterSubjects = null; +After: + _filterSubjects = null; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this._filterSubjects = null; +After: + _filterSubjects = null; +*/ + + { + _filterSubjects = null; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this._filterSubjects = new List(); + this._filterSubjects.Add(filterSubject); +After: + _filterSubjects = new List(); + _filterSubjects.Add(filterSubject); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: this._filterSubjects = new List(); this._filterSubjects.Add(filterSubject); +After: + _filterSubjects = new List(); + _filterSubjects.Add(filterSubject); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this._filterSubjects = new List(); + this._filterSubjects.Add(filterSubject); +After: + _filterSubjects = new List(); + _filterSubjects.Add(filterSubject); +*/ + + } + else + { + _filterSubjects = new List(); + _filterSubjects.Add(filterSubject); } return this; } @@ -601,8 +741,29 @@ public ConsumerConfigurationBuilder WithFilterSubject(string filterSubject) public ConsumerConfigurationBuilder WithFilterSubjects(params string[] filterSubjects) { if (filterSubjects == null) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this._filterSubjects = null; +After: + _filterSubjects = null; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this._filterSubjects = null; +After: + _filterSubjects = null; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: this._filterSubjects = null; +After: + _filterSubjects = null; +*/ + + { + _filterSubjects = null; return this; } @@ -616,17 +777,84 @@ public ConsumerConfigurationBuilder WithFilterSubjects(params string[] filterSub /// one or more filter subjects /// The ConsumerConfigurationBuilder public ConsumerConfigurationBuilder WithFilterSubjects(IList filterSubjects) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this._filterSubjects = new List(); +After: + _filterSubjects = new List(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this._filterSubjects = new List(); +After: + _filterSubjects = new List(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: this._filterSubjects = new List(); - if (filterSubjects != null) { - foreach (string fs in filterSubjects) { - if (!string.IsNullOrWhiteSpace(fs)) { +After: + _filterSubjects = new List(); +*/ + + { + _filterSubjects = new List(); + if (filterSubjects != null) + { + foreach (var fs in filterSubjects) + { + if (!string.IsNullOrWhiteSpace(fs)) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this._filterSubjects.Add(fs); +After: + _filterSubjects.Add(fs); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: this._filterSubjects.Add(fs); +After: + _filterSubjects.Add(fs); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this._filterSubjects.Add(fs); +After: + _filterSubjects.Add(fs); +*/ + + { + _filterSubjects.Add(fs); } } } - if (this._filterSubjects.Count == 0) { + if (_filterSubjects.Count == 0) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this._filterSubjects = null; +After: + _filterSubjects = null; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this._filterSubjects = null; +After: + _filterSubjects = null; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: this._filterSubjects = null; +After: + _filterSubjects = null; +*/ + + { + _filterSubjects = null; } return this; } @@ -705,19 +933,107 @@ public ConsumerConfigurationBuilder WithMaxAckPending(long? maxAckPending) /// The ConsumerConfigurationBuilder public ConsumerConfigurationBuilder WithIdleHeartbeat(Duration idleHeartbeat) { - if (idleHeartbeat == null) { + if (idleHeartbeat == null) + { _idleHeartbeat = null; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + long nanos = idleHeartbeat.Nanos; +After: + var nanos = idleHeartbeat.Nanos; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + long nanos = idleHeartbeat.Nanos; +After: + var nanos = idleHeartbeat.Nanos; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + long nanos = idleHeartbeat.Nanos; +After: + var nanos = idleHeartbeat.Nanos; +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + foreach (Duration d in backoffs) +After: + foreach (var d in backoffs) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + foreach (Duration d in backoffs) +After: + foreach (var d in backoffs) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + foreach (Duration d in backoffs) +After: + foreach (var d in backoffs) +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + foreach (long ms in backoffsMillis) { +After: + foreach (var ms in backoffsMillis) { +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + foreach (long ms in backoffsMillis) { +After: + foreach (var ms in backoffsMillis) { +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + foreach (long ms in backoffsMillis) { +After: + foreach (var ms in backoffsMillis) { +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + foreach (string key in metadata.Keys) +After: + foreach (var key in metadata.Keys) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + foreach (string key in metadata.Keys) +After: + foreach (var key in metadata.Keys) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + foreach (string key in metadata.Keys) +After: + foreach (var key in metadata.Keys) +*/ + } else { - long nanos = idleHeartbeat.Nanos; - if (nanos <= DurationUnsetLong) { + var nanos = idleHeartbeat.Nanos; + if (nanos <= DurationUnsetLong) + { _idleHeartbeat = DurationUnset; } - else if (nanos < MinIdleHeartbeatNanos) { + else if (nanos < MinIdleHeartbeatNanos) + { throw new ArgumentException($"Duration must be greater than or equal to {MinIdleHeartbeatNanos} nanos."); } - else { + else + { _idleHeartbeat = idleHeartbeat; } } @@ -732,13 +1048,16 @@ public ConsumerConfigurationBuilder WithIdleHeartbeat(Duration idleHeartbeat) /// The ConsumerConfigurationBuilder public ConsumerConfigurationBuilder WithIdleHeartbeat(long idleHeartbeatMillis) { - if (idleHeartbeatMillis <= DurationUnsetLong) { + if (idleHeartbeatMillis <= DurationUnsetLong) + { _idleHeartbeat = DurationUnset; } - else if (idleHeartbeatMillis < MinIdleHeartbeatMillis) { + else if (idleHeartbeatMillis < MinIdleHeartbeatMillis) + { throw new ArgumentException($"Duration must be greater than or equal to {MinIdleHeartbeatMillis} milliseconds."); } - else { + else + { _idleHeartbeat = Duration.OfMillis(idleHeartbeatMillis); } return this; @@ -749,7 +1068,8 @@ public ConsumerConfigurationBuilder WithIdleHeartbeat(long idleHeartbeatMillis) /// /// the idle heart beat as a Duration /// The ConsumerConfigurationBuilder - public ConsumerConfigurationBuilder WithFlowControl(Duration idleHeartbeat) { + public ConsumerConfigurationBuilder WithFlowControl(Duration idleHeartbeat) + { _flowControl = true; return WithIdleHeartbeat(idleHeartbeat); } @@ -759,7 +1079,8 @@ public ConsumerConfigurationBuilder WithFlowControl(Duration idleHeartbeat) { /// /// the idle heart beat as milliseconds /// The ConsumerConfigurationBuilder - public ConsumerConfigurationBuilder WithFlowControl(long idleHeartbeatMillis) { + public ConsumerConfigurationBuilder WithFlowControl(long idleHeartbeatMillis) + { _flowControl = true; return WithIdleHeartbeat(idleHeartbeatMillis); } @@ -769,7 +1090,8 @@ public ConsumerConfigurationBuilder WithFlowControl(long idleHeartbeatMillis) { /// /// the max amount of expire as a Duration /// The ConsumerConfigurationBuilder - public ConsumerConfigurationBuilder WithMaxExpires(Duration maxExpires) { + public ConsumerConfigurationBuilder WithMaxExpires(Duration maxExpires) + { _maxExpires = Normalize(maxExpires); return this; } @@ -779,7 +1101,8 @@ public ConsumerConfigurationBuilder WithMaxExpires(Duration maxExpires) { /// /// the max amount of expire as milliseconds /// The ConsumerConfigurationBuilder - public ConsumerConfigurationBuilder WithMaxExpires(long maxExpiresMillis) { + public ConsumerConfigurationBuilder WithMaxExpires(long maxExpiresMillis) + { _maxExpires = NormalizeDuration(maxExpiresMillis); return this; } @@ -789,7 +1112,8 @@ public ConsumerConfigurationBuilder WithMaxExpires(long maxExpiresMillis) { /// /// the max amount of expire as a Duration /// The ConsumerConfigurationBuilder - public ConsumerConfigurationBuilder WithInactiveThreshold(Duration inactiveThreshold) { + public ConsumerConfigurationBuilder WithInactiveThreshold(Duration inactiveThreshold) + { _inactiveThreshold = Normalize(inactiveThreshold); return this; } @@ -799,7 +1123,8 @@ public ConsumerConfigurationBuilder WithInactiveThreshold(Duration inactiveThres /// /// the max amount of expire as milliseconds /// The ConsumerConfigurationBuilder - public ConsumerConfigurationBuilder WithInactiveThreshold(long inactiveThresholdMillis) { + public ConsumerConfigurationBuilder WithInactiveThreshold(long inactiveThresholdMillis) + { _inactiveThreshold = NormalizeDuration(inactiveThresholdMillis); return this; } @@ -861,7 +1186,8 @@ public ConsumerConfigurationBuilder WithNumReplicas(int? numReplicas) /// /// true to enable flow control. /// The ConsumerConfigurationBuilder - public ConsumerConfigurationBuilder WithHeadersOnly(bool? headersOnly) { + public ConsumerConfigurationBuilder WithHeadersOnly(bool? headersOnly) + { _headersOnly = headersOnly; return this; } @@ -872,7 +1198,8 @@ public ConsumerConfigurationBuilder WithHeadersOnly(bool? headersOnly) { /// /// true to enable flow control. /// The ConsumerConfigurationBuilder - public ConsumerConfigurationBuilder WithMemStorage(bool? memStorage) { + public ConsumerConfigurationBuilder WithMemStorage(bool? memStorage) + { _memStorage = memStorage; return this; } @@ -891,7 +1218,7 @@ public ConsumerConfigurationBuilder WithBackoff(params Duration[] backoffs) else { _backoff = new List(); - foreach (Duration d in backoffs) + foreach (var d in backoffs) { if (d != null) { @@ -913,7 +1240,8 @@ public ConsumerConfigurationBuilder WithBackoff(params Duration[] backoffs) /// /// zero or more backoff in millis or an array of backoffsMillis /// The ConsumerConfigurationBuilder - public ConsumerConfigurationBuilder WithBackoff(params long[] backoffsMillis) { + public ConsumerConfigurationBuilder WithBackoff(params long[] backoffsMillis) + { if (backoffsMillis == null) { _backoff = null; @@ -921,7 +1249,8 @@ public ConsumerConfigurationBuilder WithBackoff(params long[] backoffsMillis) { else { _backoff = new List(); - foreach (long ms in backoffsMillis) { + foreach (var ms in backoffsMillis) + { if (ms < DurationMinLong) { throw new ArgumentException($"Backoff cannot be less than {DurationMinLong}"); @@ -938,7 +1267,8 @@ public ConsumerConfigurationBuilder WithBackoff(params long[] backoffsMillis) { /// /// the metadata dictionary /// The ConsumerConfigurationBuilder - public ConsumerConfigurationBuilder WithMetadata(Dictionary metadata) { + public ConsumerConfigurationBuilder WithMetadata(Dictionary metadata) + { if (metadata == null) { _metadata = null; @@ -946,7 +1276,7 @@ public ConsumerConfigurationBuilder WithMetadata(Dictionary meta else { _metadata = new Dictionary(); - foreach (string key in metadata.Keys) + foreach (var key in metadata.Keys) { _metadata[key] = metadata[key]; } diff --git a/src/NATS.Client/v1/JetStream/ConsumerContext.cs b/src/NATS.Client/v1/JetStream/ConsumerContext.cs index 0eb08c08..0f6abf93 100644 --- a/src/NATS.Client/v1/JetStream/ConsumerContext.cs +++ b/src/NATS.Client/v1/JetStream/ConsumerContext.cs @@ -18,7 +18,8 @@ namespace NATS.Client.JetStream { - internal interface SimplifiedSubscriptionMaker { + internal interface SimplifiedSubscriptionMaker + { IJetStreamSubscription Subscribe(EventHandler handler, PullMessageManager optionalPmm, long? optionalInactiveThreshold); } @@ -43,11 +44,11 @@ internal class ConsumerContext : IConsumerContext, SimplifiedSubscriptionMaker private readonly ConsumerConfiguration originalOrderedCc; private readonly string subscribeSubject; private readonly PullSubscribeOptions unorderedBindPso; - + private ConsumerInfo cachedConsumerInfo; private MessageConsumerBase lastConsumer; private ulong highestSeq; - + internal ConsumerContext(StreamContext sc, ConsumerInfo ci) { stateLock = new object(); @@ -59,7 +60,7 @@ internal ConsumerContext(StreamContext sc, ConsumerInfo ci) unorderedBindPso = PullSubscribeOptions.FastBindTo(streamCtx.StreamName, ci.Name); cachedConsumerInfo = ci; } - + internal ConsumerContext(StreamContext sc, OrderedConsumerConfiguration config) { stateLock = new object(); @@ -78,42 +79,74 @@ internal ConsumerContext(StreamContext sc, OrderedConsumerConfiguration config) } - public IJetStreamSubscription Subscribe(EventHandler messageHandler, PullMessageManager optionalPmm, long? optionalInactiveThreshold) { + public IJetStreamSubscription Subscribe(EventHandler messageHandler, PullMessageManager optionalPmm, long? optionalInactiveThreshold) + { PullSubscribeOptions pso; - if (ordered) { - if (lastConsumer != null) { + if (ordered) + { + if (lastConsumer != null) + { highestSeq = Math.Max(highestSeq, lastConsumer.pmm.LastStreamSeq); - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: ConsumerConfiguration cc = lastConsumer == null +After: + var cc = lastConsumer == null +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + ConsumerConfiguration cc = lastConsumer == null +After: + var cc = lastConsumer == null +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + ConsumerConfiguration cc = lastConsumer == null +After: + var cc = lastConsumer == null +*/ + + } + var cc = lastConsumer == null ? originalOrderedCc : streamCtx.js.ConsumerConfigurationForOrdered(originalOrderedCc, highestSeq, null, null, optionalInactiveThreshold); pso = new OrderedPullSubscribeOptionsBuilder(streamCtx.StreamName, cc).Build(); } - else { + else + { pso = unorderedBindPso; } - if (messageHandler == null) { - return (JetStreamPullSubscription) streamCtx.js.CreateSubscription(subscribeSubject, null, pso, null, null, false, optionalPmm); + if (messageHandler == null) + { + return (JetStreamPullSubscription)streamCtx.js.CreateSubscription(subscribeSubject, null, pso, null, null, false, optionalPmm); } - + return (JetStreamPullAsyncSubscription)streamCtx.js.CreateSubscription(subscribeSubject, null, pso, null, messageHandler, false, optionalPmm); } - - private void CheckState() { - if (lastConsumer != null) { - if (ordered) { - if (!lastConsumer.Finished) { + + private void CheckState() + { + if (lastConsumer != null) + { + if (ordered) + { + if (!lastConsumer.Finished) + { throw new InvalidOperationException("The ordered consumer is already receiving messages. Ordered Consumer does not allow multiple instances at time."); } } - if (lastConsumer.Finished && !lastConsumer.Stopped) { + if (lastConsumer.Finished && !lastConsumer.Stopped) + { lastConsumer.Dispose(); // finished, might as well make sure the sub is closed. } } } - private MessageConsumerBase TrackConsume(MessageConsumerBase con) { + private MessageConsumerBase TrackConsume(MessageConsumerBase con) + { lastConsumer = con; return con; } @@ -134,7 +167,7 @@ public ConsumerInfo GetCachedConsumerInfo() public Msg Next(int maxWaitMillis = DefaultExpiresInMillis) { - if (maxWaitMillis < MinExpiresMills) + if (maxWaitMillis < MinExpiresMills) { throw new ArgumentException($"Max wait must be at least {MinExpiresMills} milliseconds."); } @@ -190,15 +223,18 @@ public Msg Next(int maxWaitMillis = DefaultExpiresInMillis) } - public IFetchConsumer FetchMessages(int maxMessages) { + public IFetchConsumer FetchMessages(int maxMessages) + { return Fetch(FetchConsumeOptions.Builder().WithMaxMessages(maxMessages).Build()); } - public IFetchConsumer FetchBytes(int maxBytes) { + public IFetchConsumer FetchBytes(int maxBytes) + { return Fetch(FetchConsumeOptions.Builder().WithMaxBytes(maxBytes).Build()); } - public IFetchConsumer Fetch(FetchConsumeOptions fetchConsumeOptions) { + public IFetchConsumer Fetch(FetchConsumeOptions fetchConsumeOptions) + { lock (stateLock) { CheckState(); @@ -207,7 +243,8 @@ public IFetchConsumer Fetch(FetchConsumeOptions fetchConsumeOptions) { } } - public IIterableConsumer Iterate(ConsumeOptions consumeOptions = null) { + public IIterableConsumer Iterate(ConsumeOptions consumeOptions = null) + { lock (stateLock) { CheckState(); @@ -215,7 +252,8 @@ public IIterableConsumer Iterate(ConsumeOptions consumeOptions = null) { } } - public IMessageConsumer Consume(EventHandler handler, ConsumeOptions consumeOptions = null) { + public IMessageConsumer Consume(EventHandler handler, ConsumeOptions consumeOptions = null) + { lock (stateLock) { CheckState(); diff --git a/src/NATS.Client/v1/JetStream/ConsumerCreateRequest.cs b/src/NATS.Client/v1/JetStream/ConsumerCreateRequest.cs index d0d716e4..28aade06 100644 --- a/src/NATS.Client/v1/JetStream/ConsumerCreateRequest.cs +++ b/src/NATS.Client/v1/JetStream/ConsumerCreateRequest.cs @@ -29,10 +29,31 @@ internal ConsumerCreateRequest(string streamName, ConsumerConfiguration config, Config = config; Action = action; } - + public override JSONNode ToJsonNode() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + + { + var o = new JSONObject(); JsonUtils.AddField(o, ApiConstants.StreamName, StreamName); JsonUtils.AddField(o, ApiConstants.Config, Config); JsonUtils.AddField(o, ApiConstants.Action, Action.GetString()); diff --git a/src/NATS.Client/v1/JetStream/ConsumerInfo.cs b/src/NATS.Client/v1/JetStream/ConsumerInfo.cs index 040763a0..fe99f59a 100644 --- a/src/NATS.Client/v1/JetStream/ConsumerInfo.cs +++ b/src/NATS.Client/v1/JetStream/ConsumerInfo.cs @@ -36,7 +36,7 @@ public sealed class ConsumerInfo : ApiResponse public DateTime Timestamp { get; private set; } public bool Paused { get; private set; } public Duration PauseRemaining { get; private set; } - + internal ConsumerInfo(Msg msg, bool throwOnError) : base(msg, throwOnError) { Init(JsonNode); diff --git a/src/NATS.Client/v1/JetStream/ConsumerLimits.cs b/src/NATS.Client/v1/JetStream/ConsumerLimits.cs index 0215fc70..21d7deca 100644 --- a/src/NATS.Client/v1/JetStream/ConsumerLimits.cs +++ b/src/NATS.Client/v1/JetStream/ConsumerLimits.cs @@ -25,7 +25,7 @@ public sealed class ConsumerLimits : JsonSerializable { internal int? _maxAckPending; public int MaxAckPending => GetOrUnset(_maxAckPending); - + public Duration InactiveThreshold { get; } internal static ConsumerLimits OptionalInstance(JSONNode consumerLimitsNode) @@ -46,8 +46,29 @@ private ConsumerLimits(JSONNode clNode) } public override JSONNode ToJsonNode() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + + { + var o = new JSONObject(); AddField(o, ApiConstants.InactiveThreshold, InactiveThreshold); AddField(o, ApiConstants.MaxAckPending, MaxAckPending); @@ -58,23 +79,26 @@ public override JSONNode ToJsonNode() /// Creates a builder for a ConsumerLimits object. /// /// The Builder - public static ConsumerLimitsBuilder Builder() { + public static ConsumerLimitsBuilder Builder() + { return new ConsumerLimitsBuilder(); } /// /// ConsumerLimits can be created using a ConsumerLimitsBuilder. /// - public sealed class ConsumerLimitsBuilder { + public sealed class ConsumerLimitsBuilder + { internal Duration _inactiveThreshold; internal int? _maxAckPending; - + /// /// Set the amount of time before the ephemeral consumer is deemed inactive. /// /// the max amount of expire as a Duration /// The ConsumerLimitsBuilder - public ConsumerLimitsBuilder WithInactiveThreshold(Duration inactiveThreshold) { + public ConsumerLimitsBuilder WithInactiveThreshold(Duration inactiveThreshold) + { _inactiveThreshold = Normalize(inactiveThreshold); return this; } @@ -84,7 +108,8 @@ public ConsumerLimitsBuilder WithInactiveThreshold(Duration inactiveThreshold) { /// /// the max amount of expire as milliseconds /// The ConsumerLimitsBuilder - public ConsumerLimitsBuilder WithInactiveThreshold(long inactiveThresholdMillis) { + public ConsumerLimitsBuilder WithInactiveThreshold(long inactiveThresholdMillis) + { _inactiveThreshold = NormalizeDuration(inactiveThresholdMillis); return this; } @@ -104,7 +129,8 @@ public ConsumerLimitsBuilder WithMaxAckPending(long? maxAckPending) /// Build a ConsumerLimits object /// /// The ConsumerLimits - public ConsumerLimits Build() { + public ConsumerLimits Build() + { return new ConsumerLimits(this); } } diff --git a/src/NATS.Client/v1/JetStream/ConsumerPauseRequest.cs b/src/NATS.Client/v1/JetStream/ConsumerPauseRequest.cs index 207d171c..bc29fcf5 100644 --- a/src/NATS.Client/v1/JetStream/ConsumerPauseRequest.cs +++ b/src/NATS.Client/v1/JetStream/ConsumerPauseRequest.cs @@ -25,10 +25,31 @@ internal ConsumerPauseRequest(DateTime pauseUntil) { PauseUntil = pauseUntil; } - + public override JSONNode ToJsonNode() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + + { + var jso = new JSONObject(); JsonUtils.AddField(jso, ApiConstants.PauseUntil, PauseUntil); return jso; } diff --git a/src/NATS.Client/v1/JetStream/ConsumerPauseResponse.cs b/src/NATS.Client/v1/JetStream/ConsumerPauseResponse.cs index 1168687c..3bddf411 100644 --- a/src/NATS.Client/v1/JetStream/ConsumerPauseResponse.cs +++ b/src/NATS.Client/v1/JetStream/ConsumerPauseResponse.cs @@ -22,7 +22,7 @@ public sealed class ConsumerPauseResponse : ApiResponse public bool Paused { get; private set; } public DateTime? PauseUntil { get; private set; } public Duration PauseRemaining { get; private set; } - + internal ConsumerPauseResponse(Msg msg, bool throwOnError) : base(msg, throwOnError) { Init(); diff --git a/src/NATS.Client/v1/JetStream/Error.cs b/src/NATS.Client/v1/JetStream/Error.cs index 23726cb8..6182b6b7 100644 --- a/src/NATS.Client/v1/JetStream/Error.cs +++ b/src/NATS.Client/v1/JetStream/Error.cs @@ -23,7 +23,7 @@ public sealed class Error public int Code { get; } public int ApiErrorCode { get; } public string Desc { get; } - + internal static Error OptionalInstance(JSONNode error) { return error.Count == 0 ? null : new Error(error); @@ -37,7 +37,8 @@ internal Error(JSONNode node) Desc = temp ?? "Unknown JetStream Error"; } - internal Error(int code, int apiErrorCode, string desc) { + internal Error(int code, int apiErrorCode, string desc) + { Code = code; ApiErrorCode = apiErrorCode; Desc = desc; @@ -45,26 +46,31 @@ internal Error(int code, int apiErrorCode, string desc) { public override string ToString() { - if (ApiErrorCode == NOT_SET) { - if (Code == NOT_SET) { + if (ApiErrorCode == NOT_SET) + { + if (Code == NOT_SET) + { return Desc; } return $"{Desc} ({Code})"; } - if (Code == NOT_SET) { + if (Code == NOT_SET) + { return Desc; } return $"{Desc} [{ApiErrorCode}]"; } - internal static Error Convert(MsgStatus status) { - switch (status.Code) { - case 404: - return JsNoMessageFoundErr; - case 408: - return JsBadRequestErr; + internal static Error Convert(MsgStatus status) + { + switch (status.Code) + { + case 404: + return JsNoMessageFoundErr; + case 408: + return JsBadRequestErr; } return new Error(status.Code, NOT_SET, status.Message); } diff --git a/src/NATS.Client/v1/JetStream/External.cs b/src/NATS.Client/v1/JetStream/External.cs index eeec3524..b31a50ec 100644 --- a/src/NATS.Client/v1/JetStream/External.cs +++ b/src/NATS.Client/v1/JetStream/External.cs @@ -24,7 +24,7 @@ public sealed class External : JsonSerializable /// The subject prefix that imports the other account/domain $JS.API.CONSUMER.> subjects /// public string Api { get; } - + /// /// The delivery subject to use for the push consumer /// @@ -65,7 +65,8 @@ public External(string api, string deliver) /// Creates a builder for an External object. /// /// The Builder - public static ExternalBuilder Builder() { + public static ExternalBuilder Builder() + { return new ExternalBuilder(); } @@ -76,23 +77,25 @@ public sealed class ExternalBuilder { private string _api; private string _deliver; - + /// /// Set the api string. /// /// the api /// - public ExternalBuilder WithApi(string api) { + public ExternalBuilder WithApi(string api) + { _api = api; return this; } - + /// /// Set the deliver string. /// /// the deliver /// - public ExternalBuilder WithDeliver(string deliver) { + public ExternalBuilder WithDeliver(string deliver) + { _deliver = deliver; return this; } @@ -101,7 +104,8 @@ public ExternalBuilder WithDeliver(string deliver) { /// Build a External object /// /// The External - public External Build() { + public External Build() + { return new External(_api, _deliver); } } diff --git a/src/NATS.Client/v1/JetStream/FeatureBase.cs b/src/NATS.Client/v1/JetStream/FeatureBase.cs index 127583db..c4930f05 100644 --- a/src/NATS.Client/v1/JetStream/FeatureBase.cs +++ b/src/NATS.Client/v1/JetStream/FeatureBase.cs @@ -29,7 +29,7 @@ protected FeatureOptions(JetStreamOptions jso) JSOptions = jso; } } - + public abstract class FeatureBase { internal JetStream js; @@ -52,11 +52,14 @@ protected FeatureBase(IConnection connection, FeatureOptions fo) internal MessageInfo _getLast(string subject) { - try { + try + { return jsm.GetLastMessage(StreamName, subject); } - catch (NATSJetStreamException njse) { - if (njse.ApiErrorCode == JetStreamConstants.JsNoMessageFoundErr) { + catch (NATSJetStreamException njse) + { + if (njse.ApiErrorCode == JetStreamConstants.JsNoMessageFoundErr) + { return null; } throw; @@ -65,11 +68,14 @@ internal MessageInfo _getLast(string subject) internal MessageInfo _getBySeq(ulong sequence) { - try { + try + { return jsm.GetMessage(StreamName, sequence); } - catch (NATSJetStreamException njse) { - if (njse.ApiErrorCode == JetStreamConstants.JsNoMessageFoundErr) { + catch (NATSJetStreamException njse) + { + if (njse.ApiErrorCode == JetStreamConstants.JsNoMessageFoundErr) + { return null; } throw; @@ -78,33 +84,144 @@ internal MessageInfo _getBySeq(ulong sequence) internal void VisitSubject(string subject, DeliverPolicy deliverPolicy, bool headersOnly, bool ordered, Action action) { - VisitSubject(new []{subject}, deliverPolicy, headersOnly, ordered, action); + VisitSubject(new[] { subject }, deliverPolicy, headersOnly, ordered, action); } - + internal void VisitSubject(IList subjects, DeliverPolicy deliverPolicy, bool headersOnly, bool ordered, Action action) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: ConsumerConfiguration.ConsumerConfigurationBuilder ccb = ConsumerConfiguration.Builder() +After: + var ccb = ConsumerConfiguration.Builder() +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + ConsumerConfiguration.ConsumerConfigurationBuilder ccb = ConsumerConfiguration.Builder() +After: + var ccb = ConsumerConfiguration.Builder() +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + ConsumerConfiguration.ConsumerConfigurationBuilder ccb = ConsumerConfiguration.Builder() +After: + var ccb = ConsumerConfiguration.Builder() +*/ + + { + var ccb = ConsumerConfiguration.Builder() .WithAckPolicy(AckPolicy.None) .WithDeliverPolicy(deliverPolicy) .WithHeadersOnly(headersOnly) .WithFilterSubjects(subjects); - +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: PushSubscribeOptions pso = PushSubscribeOptions.Builder() +After: + var pso = PushSubscribeOptions.Builder() +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + PushSubscribeOptions pso = PushSubscribeOptions.Builder() +After: + var pso = PushSubscribeOptions.Builder() +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + PushSubscribeOptions pso = PushSubscribeOptions.Builder() +After: + var pso = PushSubscribeOptions.Builder() +*/ + + + var pso = PushSubscribeOptions.Builder() .WithStream(StreamName) .WithOrdered(ordered) .WithConfiguration(ccb.Build()) .Build(); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(null, pso); +After: + var sub = js.PushSubscribeSync(null, pso); +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(null, pso); - try - { +After: + var sub = js.PushSubscribeSync(null, pso); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + IJetStreamPushSyncSubscription sub = js.PushSubscribeSync(null, pso); +After: + var sub = js.PushSubscribeSync(null, pso); +*/ + + + var sub = js.PushSubscribeSync(null, pso); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + bool lastTimedOut = false; + ulong pending = sub.GetConsumerInformation().CalculatedPending; +After: + var lastTimedOut = false; + var pending = sub.GetConsumerInformation().CalculatedPending; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: bool lastTimedOut = false; ulong pending = sub.GetConsumerInformation().CalculatedPending; +After: + var lastTimedOut = false; + var pending = sub.GetConsumerInformation().CalculatedPending; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + bool lastTimedOut = false; + ulong pending = sub.GetConsumerInformation().CalculatedPending; +After: + var lastTimedOut = false; + var pending = sub.GetConsumerInformation().CalculatedPending; +*/ + + try + { + var lastTimedOut = false; + var pending = sub.GetConsumerInformation().CalculatedPending; while (pending > 0) // no need to loop if nothing pending +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Msg m = sub.NextMessage(js.Timeout); +After: + var m = sub.NextMessage(js.Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Msg m = sub.NextMessage(js.Timeout); +After: + var m = sub.NextMessage(js.Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Msg m = sub.NextMessage(js.Timeout); +After: + var m = sub.NextMessage(js.Timeout); +*/ + { try { - Msg m = sub.NextMessage(js.Timeout); + var m = sub.NextMessage(js.Timeout); action.Invoke(m); if (--pending == 0) { @@ -128,4 +245,4 @@ internal void VisitSubject(IList subjects, DeliverPolicy deliverPolicy, } } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/JetStream/FetchConsumeOptions.cs b/src/NATS.Client/v1/JetStream/FetchConsumeOptions.cs index d43718a7..779f4a16 100644 --- a/src/NATS.Client/v1/JetStream/FetchConsumeOptions.cs +++ b/src/NATS.Client/v1/JetStream/FetchConsumeOptions.cs @@ -1,4 +1,4 @@ -// Copyright 2023 The NATS Authors +// Copyright 2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -24,13 +24,13 @@ public class FetchConsumeOptions : BaseConsumeOptions /// The maximum number of messages to fetch. /// public int MaxMessages => Messages; - + /// /// The maximum number of bytes to fetch. /// public long MaxBytes => Bytes; - protected FetchConsumeOptions(IBaseConsumeOptionsBuilder b) : base(b) {} + protected FetchConsumeOptions(IBaseConsumeOptionsBuilder b) : base(b) { } /// /// Gets the FetchConsumeOptions builder. @@ -48,7 +48,7 @@ protected override FetchConsumeOptionsBuilder GetThis() { return this; } - + /// /// Set the maximum number of messages to fetch and remove any previously set {@link #maxBytes(long)} constraint. /// The number of messages fetched will also be constrained by the expiration time. @@ -72,7 +72,8 @@ public FetchConsumeOptionsBuilder WithMaxMessages(int maxMessages) /// /// the maximum bytes /// the builder - public FetchConsumeOptionsBuilder WithMaxBytes(int maxBytes) { + public FetchConsumeOptionsBuilder WithMaxBytes(int maxBytes) + { base.WithMessages(-1); return base.WithBytes(maxBytes); } @@ -90,7 +91,8 @@ public FetchConsumeOptionsBuilder WithMaxBytes(int maxBytes) { /// the maximum bytes /// the maximum number of messages /// the builder - public FetchConsumeOptionsBuilder WithMax(int maxBytes, int maxMessages) { + public FetchConsumeOptionsBuilder WithMax(int maxBytes, int maxMessages) + { base.WithMessages(maxMessages); return base.WithBytes(maxBytes); } diff --git a/src/NATS.Client/v1/JetStream/FetchConsumer.cs b/src/NATS.Client/v1/JetStream/FetchConsumer.cs index feea861f..9d5b7dc9 100644 --- a/src/NATS.Client/v1/JetStream/FetchConsumer.cs +++ b/src/NATS.Client/v1/JetStream/FetchConsumer.cs @@ -26,14 +26,41 @@ internal class FetchConsumer : MessageConsumerBase, IFetchConsumer, IPullManager internal FetchConsumer(SimplifiedSubscriptionMaker subscriptionMaker, ConsumerInfo cachedConsumerInfo, - FetchConsumeOptions fetchConsumeOptions) - : base(cachedConsumerInfo) + FetchConsumeOptions fetchConsumeOptions) + : base(cachedConsumerInfo) { long expiresInMillis = fetchConsumeOptions.ExpiresInMillis; maxWaitTicks = expiresInMillis * TimeSpan.TicksPerMillisecond; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + long inactiveThreshold = expiresInMillis * 110 / 100; // ten % longer than the wait + PullRequestOptions pro = PullRequestOptions.Builder(fetchConsumeOptions.MaxMessages) +After: + var inactiveThreshold = expiresInMillis * 110 / 100; // ten % longer than the wait + var pro = PullRequestOptions.Builder(fetchConsumeOptions.MaxMessages) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + long inactiveThreshold = expiresInMillis * 110 / 100; // ten % longer than the wait + PullRequestOptions pro = PullRequestOptions.Builder(fetchConsumeOptions.MaxMessages) +After: + var inactiveThreshold = expiresInMillis * 110 / 100; // ten % longer than the wait + var pro = PullRequestOptions.Builder(fetchConsumeOptions.MaxMessages) +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: long inactiveThreshold = expiresInMillis * 110 / 100; // ten % longer than the wait PullRequestOptions pro = PullRequestOptions.Builder(fetchConsumeOptions.MaxMessages) +After: + var inactiveThreshold = expiresInMillis * 110 / 100; // ten % longer than the wait + var pro = PullRequestOptions.Builder(fetchConsumeOptions.MaxMessages) +*/ + + + var inactiveThreshold = expiresInMillis * 110 / 100; // ten % longer than the wait + var pro = PullRequestOptions.Builder(fetchConsumeOptions.MaxMessages) .WithMaxBytes(fetchConsumeOptions.MaxBytes) .WithExpiresIn(fetchConsumeOptions.ExpiresInMillis) .WithIdleHeartbeat(fetchConsumeOptions.IdleHeartbeat) @@ -43,7 +70,7 @@ internal FetchConsumer(SimplifiedSubscriptionMaker subscriptionMaker, startTicks = -1; } - public void PendingUpdated() {} + public void PendingUpdated() { } public void HeartbeatError() { @@ -59,14 +86,36 @@ public Msg NextMessage() { return null; } - + // if the manager thinks it has received everything in the pull, it means // that all the messages are already in the internal queue and there is // no waiting necessary if (pmm.NoMorePending()) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Msg m = ((JetStreamPullSubscription)sub)._nextUnmanagedNoWait(pullSubject); +After: + var m = ((JetStreamPullSubscription)sub)._nextUnmanagedNoWait(pullSubject); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: Msg m = ((JetStreamPullSubscription)sub)._nextUnmanagedNoWait(pullSubject); - if (m == null) { +After: + var m = ((JetStreamPullSubscription)sub)._nextUnmanagedNoWait(pullSubject); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Msg m = ((JetStreamPullSubscription)sub)._nextUnmanagedNoWait(pullSubject); +After: + var m = ((JetStreamPullSubscription)sub)._nextUnmanagedNoWait(pullSubject); +*/ + + { + var m = ((JetStreamPullSubscription)sub)._nextUnmanagedNoWait(pullSubject); + if (m == null) + { // if there are no messages in the internal cache AND there are no more pending, // they all have been read and we can go ahead and close the subscription. Finished = true; diff --git a/src/NATS.Client/v1/JetStream/IBaseConsumerContext.cs b/src/NATS.Client/v1/JetStream/IBaseConsumerContext.cs index 013b2be6..9273c0d3 100644 --- a/src/NATS.Client/v1/JetStream/IBaseConsumerContext.cs +++ b/src/NATS.Client/v1/JetStream/IBaseConsumerContext.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace NATS.Client.JetStream { @@ -57,4 +57,4 @@ public interface IBaseConsumerContext /// the IMessageConsumer instance IMessageConsumer Consume(EventHandler handler, ConsumeOptions consumeOptions = null); } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/JetStream/IConsumerContext.cs b/src/NATS.Client/v1/JetStream/IConsumerContext.cs index 55882796..6b359034 100644 --- a/src/NATS.Client/v1/JetStream/IConsumerContext.cs +++ b/src/NATS.Client/v1/JetStream/IConsumerContext.cs @@ -1,4 +1,4 @@ -// Copyright 2023 The NATS Authors +// Copyright 2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/src/NATS.Client/v1/JetStream/IFetchConsumer.cs b/src/NATS.Client/v1/JetStream/IFetchConsumer.cs index 2ace0ae2..0cc5f9c6 100644 --- a/src/NATS.Client/v1/JetStream/IFetchConsumer.cs +++ b/src/NATS.Client/v1/JetStream/IFetchConsumer.cs @@ -1,4 +1,4 @@ -// Copyright 2023 The NATS Authors +// Copyright 2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/src/NATS.Client/v1/JetStream/IIterableConsumer.cs b/src/NATS.Client/v1/JetStream/IIterableConsumer.cs index 2d79c322..65f64d19 100644 --- a/src/NATS.Client/v1/JetStream/IIterableConsumer.cs +++ b/src/NATS.Client/v1/JetStream/IIterableConsumer.cs @@ -1,4 +1,4 @@ -// Copyright 2023 The NATS Authors +// Copyright 2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/src/NATS.Client/v1/JetStream/IJetStream.cs b/src/NATS.Client/v1/JetStream/IJetStream.cs index db587d49..f0c431ae 100644 --- a/src/NATS.Client/v1/JetStream/IJetStream.cs +++ b/src/NATS.Client/v1/JetStream/IJetStream.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2023 The NATS Authors +// Copyright 2021-2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -254,7 +254,7 @@ public interface IJetStream /// Pull Subscribe options for this subscription. /// An IJetStreamPullSubscription IJetStreamPullAsyncSubscription PullSubscribeAsync(string subject, EventHandler handler, PullSubscribeOptions options); - + /// /// Creates a push subscriber on the given , and begins delivering /// messages to the given event handler. @@ -402,7 +402,7 @@ public interface IJetStream /// the name of the stream /// an IStreamContext instance IStreamContext GetStreamContext(string streamName); - + /// /// Create a consumer context for a specific named stream and specific named consumer. /// Verifies that the stream and consumer exist. diff --git a/src/NATS.Client/v1/JetStream/IJetStreamManagement.cs b/src/NATS.Client/v1/JetStream/IJetStreamManagement.cs index da004990..748efbae 100644 --- a/src/NATS.Client/v1/JetStream/IJetStreamManagement.cs +++ b/src/NATS.Client/v1/JetStream/IJetStreamManagement.cs @@ -1,4 +1,4 @@ -// Copyright 2021 The NATS Authors +// Copyright 2021 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -138,7 +138,7 @@ public interface IJetStreamManagement /// The name of the consumer. /// Consumer information ConsumerInfo GetConsumerInfo(string streamName, string consumer); - + /// /// Gets all consumers attached to a stream. /// @@ -165,13 +165,13 @@ public interface IJetStreamManagement /// The subject. Wildcards are allowed. /// IList GetStreamNames(string subjectFilter); - + /// /// Gets stream information about all streams. /// /// An array of stream information objects. IList GetStreams(); - + /// /// Gets stream information about all streams that have subjects matching the filter. /// @@ -229,7 +229,7 @@ public interface IJetStreamManagement /// Whether to erase the message (overwriting with garbage) or only mark it as erased. /// True if the message was deleted. bool DeleteMessage(string streamName, ulong sequence, bool erase); - + /// /// Gets a context for publishing and subscribing to subjects /// backed by Jetstream streams and consumers, using the same connection and JetStreamOptions as the management. diff --git a/src/NATS.Client/v1/JetStream/IJetStreamSubscription.cs b/src/NATS.Client/v1/JetStream/IJetStreamSubscription.cs index f33d4c2a..c084d1b7 100644 --- a/src/NATS.Client/v1/JetStream/IJetStreamSubscription.cs +++ b/src/NATS.Client/v1/JetStream/IJetStreamSubscription.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2023 The NATS Authors +// Copyright 2021-2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -76,14 +76,14 @@ public interface IJetStreamPullSubscription : IJetStreamPullApiSubscription, IJe /// A list of messages IList Fetch(int batchSize, int maxWaitMillis); } - + /// /// Async Pull Subscription on a JetStream context. /// public interface IJetStreamPullAsyncSubscription : IJetStreamPullApiSubscription, IJetStreamSubscription, IAsyncSubscription { } - + public interface IJetStreamPullApiSubscription { /// diff --git a/src/NATS.Client/v1/JetStream/IMessageConsumer.cs b/src/NATS.Client/v1/JetStream/IMessageConsumer.cs index fb4312a9..a51007a5 100644 --- a/src/NATS.Client/v1/JetStream/IMessageConsumer.cs +++ b/src/NATS.Client/v1/JetStream/IMessageConsumer.cs @@ -19,13 +19,34 @@ namespace NATS.Client.JetStream /// Interface definition for a Message Consumer /// public interface IMessageConsumer : IDisposable +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + String GetConsumerName(); +After: + string GetConsumerName(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + String GetConsumerName(); +After: + string GetConsumerName(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + String GetConsumerName(); +After: + string GetConsumerName(); +*/ + { /// /// Gets the consumer name associated with the subscription. /// Some simplified consumer types do not support this, so it might be null. /// /// the consumer name - String GetConsumerName(); + string GetConsumerName(); /// /// Gets information about the consumer behind this subscription. @@ -45,7 +66,7 @@ public interface IMessageConsumer : IDisposable /// The consumer will finish all pull request already in progress, but will not start any new ones. /// void Stop(); - + bool Stopped { get; } bool Finished { get; } diff --git a/src/NATS.Client/v1/JetStream/IOrderedConsumerContext.cs b/src/NATS.Client/v1/JetStream/IOrderedConsumerContext.cs index b48134af..24f7f5c7 100644 --- a/src/NATS.Client/v1/JetStream/IOrderedConsumerContext.cs +++ b/src/NATS.Client/v1/JetStream/IOrderedConsumerContext.cs @@ -1,4 +1,4 @@ -// Copyright 2023 The NATS Authors +// Copyright 2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/src/NATS.Client/v1/JetStream/IPullManagerObserver.cs b/src/NATS.Client/v1/JetStream/IPullManagerObserver.cs index 5fb231db..9943bc50 100644 --- a/src/NATS.Client/v1/JetStream/IPullManagerObserver.cs +++ b/src/NATS.Client/v1/JetStream/IPullManagerObserver.cs @@ -1,4 +1,4 @@ -// Copyright 2023 The NATS Authors +// Copyright 2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: diff --git a/src/NATS.Client/v1/JetStream/IStreamContext.cs b/src/NATS.Client/v1/JetStream/IStreamContext.cs index 94b13234..f0617e43 100644 --- a/src/NATS.Client/v1/JetStream/IStreamContext.cs +++ b/src/NATS.Client/v1/JetStream/IStreamContext.cs @@ -1,4 +1,4 @@ -// Copyright 2023 The NATS Authors +// Copyright 2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -149,4 +149,4 @@ public interface IStreamContext /// true if the delete succeeded bool DeleteMessage(ulong seq, bool erase); } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/JetStream/IterableConsumer.cs b/src/NATS.Client/v1/JetStream/IterableConsumer.cs index 0acdbead..84596ceb 100644 --- a/src/NATS.Client/v1/JetStream/IterableConsumer.cs +++ b/src/NATS.Client/v1/JetStream/IterableConsumer.cs @@ -1,4 +1,4 @@ -// Copyright 2023 The NATS Authors +// Copyright 2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -20,8 +20,8 @@ internal class IterableConsumer : MessageConsumer, IIterableConsumer { internal IterableConsumer(SimplifiedSubscriptionMaker subscriptionMaker, ConsumeOptions consumeOptions, - ConsumerInfo cachedConsumerInfo) - : base(subscriptionMaker, cachedConsumerInfo, consumeOptions, null) {} + ConsumerInfo cachedConsumerInfo) + : base(subscriptionMaker, cachedConsumerInfo, consumeOptions, null) { } public Msg NextMessage(int timeoutMillis) { diff --git a/src/NATS.Client/v1/JetStream/JetStream.cs b/src/NATS.Client/v1/JetStream/JetStream.cs index 0dc69d5f..31bc8e51 100644 --- a/src/NATS.Client/v1/JetStream/JetStream.cs +++ b/src/NATS.Client/v1/JetStream/JetStream.cs @@ -22,14 +22,35 @@ namespace NATS.Client.JetStream { public class JetStream : JetStreamBase, IJetStream { - protected internal JetStream(IConnection connection, JetStreamOptions options) : base(connection, options) {} + protected internal JetStream(IConnection connection, JetStreamOptions options) : base(connection, options) { } - protected internal JetStream(JetStreamBase jetStreamBase) : base(jetStreamBase) {} + protected internal JetStream(JetStreamBase jetStreamBase) : base(jetStreamBase) { } private MsgHeader MergePublishOptions(MsgHeader headers, PublishOptions opts) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + MsgHeader merged = headers == null ? null : new MsgHeader(headers); +After: + var merged = headers == null ? null : new MsgHeader(headers); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + MsgHeader merged = headers == null ? null : new MsgHeader(headers); +After: + var merged = headers == null ? null : new MsgHeader(headers); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + MsgHeader merged = headers == null ? null : new MsgHeader(headers); +After: + var merged = headers == null ? null : new MsgHeader(headers); +*/ + { // never touch the user's original headers - MsgHeader merged = headers == null ? null : new MsgHeader(headers); + var merged = headers == null ? null : new MsgHeader(headers); if (opts != null) { @@ -43,161 +64,2518 @@ private MsgHeader MergePublishOptions(MsgHeader headers, PublishOptions opts) return merged; } - private MsgHeader MergeNum(MsgHeader h, string key, ulong value) + private MsgHeader MergeNum(MsgHeader h, string key, ulong value) + { + return value > 0 ? _MergeString(h, key, value.ToString()) : h; + } + + private MsgHeader MergeString(MsgHeader h, string key, string value) + { + return string.IsNullOrWhiteSpace(value) ? h : _MergeString(h, key, value); + } + + private MsgHeader _MergeString(MsgHeader h, string key, string value) + { + if (h == null) + { + h = new MsgHeader(); + } + h.Set(key, value); + return h; + } + + private PublishAck ProcessPublishResponse(Msg resp, PublishOptions options) + { + if (resp.HasStatus) + { + throw new NATSJetStreamException("Error Publishing: " + resp.Status.Message); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + PublishAck ack = new PublishAck(resp); + string ackStream = ack.Stream; + string pubStream = options?.Stream; +After: + var ack = new PublishAck(resp); + var ackStream = ack.Stream; + var pubStream = options?.Stream; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + PublishAck ack = new PublishAck(resp); + string ackStream = ack.Stream; + string pubStream = options?.Stream; +After: + var ack = new PublishAck(resp); + var ackStream = ack.Stream; + var pubStream = options?.Stream; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + PublishAck ack = new PublishAck(resp); + string ackStream = ack.Stream; + string pubStream = options?.Stream; +After: + var ack = new PublishAck(resp); + var ackStream = ack.Stream; + var pubStream = options?.Stream; +*/ + + } + + var ack = new PublishAck(resp); + var ackStream = ack.Stream; + var pubStream = options?.Stream; + // stream specified in options but different than ack should not happen but... + if (!string.IsNullOrWhiteSpace(pubStream) && pubStream != ackStream) + { + throw new NATSJetStreamException("Expected ack from stream " + pubStream + ", received from: " + ackStream); + } + return ack; + } + + private PublishAck PublishSyncInternal(string subject, byte[] data, MsgHeader hdr, PublishOptions options) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + MsgHeader merged = MergePublishOptions(hdr, options); + Msg msg = new Msg(subject, null, merged, data); +After: + var merged = MergePublishOptions(hdr, options); + var msg = new Msg(subject, null, merged, data); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + MsgHeader merged = MergePublishOptions(hdr, options); + Msg msg = new Msg(subject, null, merged, data); +After: + var merged = MergePublishOptions(hdr, options); + var msg = new Msg(subject, null, merged, data); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + MsgHeader merged = MergePublishOptions(hdr, options); + Msg msg = new Msg(subject, null, merged, data); +After: + var merged = MergePublishOptions(hdr, options); + var msg = new Msg(subject, null, merged, data); +*/ + + { + var merged = MergePublishOptions(hdr, options); + var msg = new Msg(subject, null, merged, data); + + if (JetStreamOptions.IsPublishNoAck) + { + Conn.Publish(msg); + return null; + } + + return ProcessPublishResponse(Conn.Request(msg, Timeout), options); + } + + private async Task PublishAsyncInternal(string subject, byte[] data, MsgHeader hdr, PublishOptions options) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + MsgHeader merged = MergePublishOptions(hdr, options); + Msg msg = new Msg(subject, null, merged, data); +After: + var merged = MergePublishOptions(hdr, options); + var msg = new Msg(subject, null, merged, data); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + MsgHeader merged = MergePublishOptions(hdr, options); + Msg msg = new Msg(subject, null, merged, data); +After: + var merged = MergePublishOptions(hdr, options); + var msg = new Msg(subject, null, merged, data); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + MsgHeader merged = MergePublishOptions(hdr, options); + Msg msg = new Msg(subject, null, merged, data); +After: + var merged = MergePublishOptions(hdr, options); + var msg = new Msg(subject, null, merged, data); +*/ + + { + var merged = MergePublishOptions(hdr, options); + var msg = new Msg(subject, null, merged, data); + + if (JetStreamOptions.IsPublishNoAck) + { + Conn.Publish(msg); + return null; + } + + var result = await Conn.RequestAsync(msg, Timeout).ConfigureAwait(false); + return ProcessPublishResponse(result, options); + } + + public PublishAck Publish(string subject, byte[] data) + => PublishSyncInternal(subject, data, null, null); + + public PublishAck Publish(string subject, MsgHeader headers, byte[] data) + => PublishSyncInternal(subject, data, headers, null); + + public PublishAck Publish(string subject, byte[] data, PublishOptions options) + => PublishSyncInternal(subject, data, null, options); + + public PublishAck Publish(string subject, MsgHeader headers, byte[] data, PublishOptions options) + => PublishSyncInternal(subject, data, headers, options); + + public PublishAck Publish(Msg msg) + => PublishSyncInternal(msg.Subject, msg.Data, msg.Header, null); + + public PublishAck Publish(Msg msg, PublishOptions publishOptions) + => PublishSyncInternal(msg.Subject, msg.Data, msg.Header, publishOptions); + + public Task PublishAsync(string subject, byte[] data) + => PublishAsyncInternal(subject, data, null, null); + + public Task PublishAsync(string subject, MsgHeader headers, byte[] data) + => PublishAsyncInternal(subject, data, headers, null); + + public Task PublishAsync(string subject, byte[] data, PublishOptions publishOptions) + => PublishAsyncInternal(subject, data, null, publishOptions); + + public Task PublishAsync(string subject, MsgHeader headers, byte[] data, PublishOptions publishOptions) + => PublishAsyncInternal(subject, data, headers, publishOptions); + + public Task PublishAsync(Msg msg) + => PublishAsyncInternal(msg.Subject, msg.Data, msg.Header, null); + + public Task PublishAsync(Msg msg, PublishOptions publishOptions) + => PublishAsyncInternal(msg.Subject, msg.Data, msg.Header, publishOptions); + + // ---------------------------------------------------------------------------------------------------- + // Subscribe + // ---------------------------------------------------------------------------------------------------- + + internal delegate MessageManager MessageManagerFactory( + Connection conn, JetStream js, string stream, + SubscribeOptions so, ConsumerConfiguration cc, bool queueMode, bool syncMode); + + internal MessageManagerFactory _pushMessageManagerFactory = + (conn, js, stream, so, cc, queueMode, syncMode) => + new PushMessageManager(conn, js, stream, so, cc, queueMode, syncMode); + + internal MessageManagerFactory _pushOrderedMessageManagerFactory = + (conn, js, stream, so, cc, queueMode, syncMode) => + new OrderedMessageManager(conn, js, stream, so, cc, queueMode, syncMode); + + internal MessageManagerFactory _pullMessageManagerFactory = + (conn, js, stream, so, cc, queueMode, syncMode) => + new PullMessageManager(conn, so, syncMode); + + internal MessageManagerFactory _pullOrderedMessageManagerFactory = + (conn, js, stream, so, cc, queueMode, syncMode) => + new PullOrderedMessageManager(conn, js, stream, so, cc, syncMode); + + internal Subscription CreateSubscription(string userSubscribeSubject, + PushSubscribeOptions pushSubscribeOptions, + PullSubscribeOptions pullSubscribeOptions, + string queueName, + EventHandler userHandler, + bool autoAck, + PullMessageManager pmmInstance) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + bool isPullMode = pullSubscribeOptions != null; +After: + var isPullMode = pullSubscribeOptions != null; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + bool isPullMode = pullSubscribeOptions != null; +After: + var isPullMode = pullSubscribeOptions != null; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + bool isPullMode = pullSubscribeOptions != null; +After: + var isPullMode = pullSubscribeOptions != null; +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + foreach (string fs in userCC.FilterSubjects) +After: + foreach (var fs in userCC.FilterSubjects) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + foreach (string fs in userCC.FilterSubjects) +After: + foreach (var fs in userCC.FilterSubjects) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + foreach (string fs in userCC.FilterSubjects) +After: + foreach (var fs in userCC.FilterSubjects) +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string consumerName = userCC.Durable; + if (consumerName == null) + { + consumerName = userCC.Name; + } + string inboxDeliver = userCC.DeliverSubject; + + // 4. Does this consumer already exist? FastBind bypasses the lookup; + // the dev better know what they are doing... + if (!so.FastBind && consumerName != null) + { + ConsumerInfo serverInfo = LookupConsumerInfo(settledStream, consumerName); + + if (serverInfo != null) { // the consumer for that durable already exists + serverCC = serverInfo.ConsumerConfiguration; + + // check to see if the user sent a different version than the server has + // modifications are not allowed + IList changes = userCC.GetChanges(serverCC); + if (changes.Count > 0) + { + throw JsSubExistingConsumerCannotBeModified.Instance($"[{string.Join(",", changes)}]"); + } + + // deliver subject must be null/empty for pull, defined for push + if (isPullMode) + { + if (!string.IsNullOrWhiteSpace(serverCC.DeliverSubject)) + { + throw JsSubConsumerAlreadyConfiguredAsPush.Instance(); + } + } + else if (string.IsNullOrWhiteSpace(serverCC.DeliverSubject)) + { + throw JsSubConsumerAlreadyConfiguredAsPull.Instance(); + } + + if (string.IsNullOrWhiteSpace(serverCC.DeliverGroup)) + { + // lookedUp was null/empty, means existing consumer is not a queue consumer + if (settledDeliverGroup == null) + { + // ok fine, no queue requested and the existing consumer is also not a queue consumer + // we must check if the consumer is in use though + if (serverInfo.PushBound) + { + throw JsSubConsumerAlreadyBound.Instance(); + } + } + else + { // else they requested a queue but this durable was not configured as queue + throw JsSubExistingConsumerNotQueue.Instance(); + } + } + else if (settledDeliverGroup == null) + { + throw JsSubExistingConsumerIsQueue.Instance(); + } + else if (!serverCC.DeliverGroup.Equals(settledDeliverGroup)) + { + throw JsSubExistingQueueDoesNotMatchRequestedQueue.Instance(); + } + + // consumer already exists, make sure the filter subject matches + // subscribeSubject, if supplied came from the user directly + // or in the userCC or might not have been in either place + if (settledFilterSubjects.Count == 0) + { + // still also might be null, which the server treats as > + if (serverCC.FilterSubjects != null) + { + settledFilterSubjects = serverCC.FilterSubjects; + } + } + else if (!ConsumerFilterSubjectsAreEquivalent(settledFilterSubjects, serverCC.FilterSubjects)) + { + throw JsSubSubjectDoesNotMatchFilter.Instance(); + } + + inboxDeliver = serverCC.DeliverSubject; // use the deliver subject as the inbox. It may be null, that's ok, we'll fix that later + } + else if (so.Bind) { + throw JsSubConsumerNotFoundRequiredInBind.Instance(); + } + } + + // 5. If pull or no deliver subject (inbox) provided or found, make an inbox. + string settledInboxDeliver; + if (isPullMode) + { + settledInboxDeliver = Conn.NewInbox() + ".*"; + } + else if (string.IsNullOrWhiteSpace(inboxDeliver)) { + settledInboxDeliver = Conn.NewInbox(); + } + else + { + settledInboxDeliver = inboxDeliver; + } + + + // 6. If consumer does not exist, create and settle on the config. Name will have to wait + // If the consumer exists, I know what the settled info is + ConsumerConfiguration settledCC; + string settledConsumerName; + if (so.FastBind || serverCC != null) + { + settledCC = serverCC; + settledConsumerName = so.Name; + } + else + { + ConsumerConfiguration.ConsumerConfigurationBuilder ccBuilder = ConsumerConfiguration.Builder(userCC); + + // Pull mode doesn't maintain a deliver subject. It's actually an error if we send it. + if (!isPullMode) { + ccBuilder.WithDeliverSubject(settledInboxDeliver); + } + + // userCC.filterSubjects might have originally been empty + // but there might have been a userSubscribeSubject, + // so this makes sure it's resolved either way + ccBuilder.WithFilterSubjects(settledFilterSubjects); + + ccBuilder.WithDeliverGroup(settledDeliverGroup); + + settledCC = ccBuilder.Build(); + settledConsumerName = null; // the server will give us a name + } + + // 7. create the subscription + bool syncMode = userHandler == null; + MessageManager mm; + Connection.CreateSyncSubscriptionDelegate syncSubDelegate = null; + Connection.CreateAsyncSubscriptionDelegate asyncSubDelegate = null; + if (isPullMode) + { + if (pmmInstance == null) + { + MessageManagerFactory mmFactory = so.Ordered ? _pullOrderedMessageManagerFactory : _pullMessageManagerFactory; + mm = mmFactory((Connection)Conn, this, settledStream, so, settledCC, false, syncMode); + } + else + { + mm = pmmInstance; + } + if (syncMode) + { + syncSubDelegate = (dConn, dSubject, dQueue) => + { + return new JetStreamPullSubscription(dConn, dSubject, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + }; + } + else + { + asyncSubDelegate = (dConn, dSubject, dQueue) => + { + JetStreamPullAsyncSubscription asub = new JetStreamPullAsyncSubscription(dConn, dSubject, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + asub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); + return asub; + }; + } + } + else + { + MessageManagerFactory mmFactory = so.Ordered ? _pushOrderedMessageManagerFactory : _pushMessageManagerFactory; + mm = mmFactory((Connection)Conn, this, settledStream, so, settledCC, settledDeliverGroup != null, syncMode); + if (syncMode) + { + syncSubDelegate = (dConn, dSubject, dQueue) => + { + JetStreamPushSyncSubscription ssub = + new JetStreamPushSyncSubscription(dConn, dSubject, dQueue, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + ssub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); + return ssub; + }; + } + else + { + asyncSubDelegate = (dConn, dSubject, dQueue) => + { + JetStreamPushAsyncSubscription asub = + new JetStreamPushAsyncSubscription(dConn, dSubject, dQueue, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + asub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); + return asub; + }; + } + } + + Subscription sub; + if (syncSubDelegate != null) +After: + var consumerName = userCC.Durable ?? userCC.Name; + var inboxDeliver = userCC.DeliverSubject; + + // 4. Does this consumer already exist? FastBind bypasses the lookup; + // the dev better know what they are doing... + if (!so.FastBind && consumerName != null) + { + var serverInfo = LookupConsumerInfo(settledStream, consumerName); + + if (serverInfo != null) { // the consumer for that durable already exists + serverCC = serverInfo.ConsumerConfiguration; + + // check to see if the user sent a different version than the server has + // modifications are not allowed + var changes = userCC.GetChanges(serverCC); + if (changes.Count > 0) + { + throw JsSubExistingConsumerCannotBeModified.Instance($"[{string.Join(",", changes)}]"); + } + + // deliver subject must be null/empty for pull, defined for push + if (isPullMode) + { + if (!string.IsNullOrWhiteSpace(serverCC.DeliverSubject)) + { + throw JsSubConsumerAlreadyConfiguredAsPush.Instance(); + } + } + else if (string.IsNullOrWhiteSpace(serverCC.DeliverSubject)) + { + throw JsSubConsumerAlreadyConfiguredAsPull.Instance(); + } + + if (string.IsNullOrWhiteSpace(serverCC.DeliverGroup)) + { + // lookedUp was null/empty, means existing consumer is not a queue consumer + if (settledDeliverGroup == null) + { + // ok fine, no queue requested and the existing consumer is also not a queue consumer + // we must check if the consumer is in use though + if (serverInfo.PushBound) + { + throw JsSubConsumerAlreadyBound.Instance(); + } + } + else + { // else they requested a queue but this durable was not configured as queue + throw JsSubExistingConsumerNotQueue.Instance(); + } + } + else if (settledDeliverGroup == null) + { + throw JsSubExistingConsumerIsQueue.Instance(); + } + else if (!serverCC.DeliverGroup.Equals(settledDeliverGroup)) + { + throw JsSubExistingQueueDoesNotMatchRequestedQueue.Instance(); + } + + // consumer already exists, make sure the filter subject matches + // subscribeSubject, if supplied came from the user directly + // or in the userCC or might not have been in either place + if (settledFilterSubjects.Count == 0) + { + // still also might be null, which the server treats as > + if (serverCC.FilterSubjects != null) + { + settledFilterSubjects = serverCC.FilterSubjects; + } + } + else if (!ConsumerFilterSubjectsAreEquivalent(settledFilterSubjects, serverCC.FilterSubjects)) + { + throw JsSubSubjectDoesNotMatchFilter.Instance(); + } + + inboxDeliver = serverCC.DeliverSubject; // use the deliver subject as the inbox. It may be null, that's ok, we'll fix that later + } + else if (so.Bind) { + throw JsSubConsumerNotFoundRequiredInBind.Instance(); + } + } + + // 5. If pull or no deliver subject (inbox) provided or found, make an inbox. + string settledInboxDeliver; + if (isPullMode) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string consumerName = userCC.Durable; + if (consumerName == null) + { + consumerName = userCC.Name; + } + string inboxDeliver = userCC.DeliverSubject; + + // 4. Does this consumer already exist? FastBind bypasses the lookup; + // the dev better know what they are doing... + if (!so.FastBind && consumerName != null) + { + ConsumerInfo serverInfo = LookupConsumerInfo(settledStream, consumerName); + + if (serverInfo != null) { // the consumer for that durable already exists + serverCC = serverInfo.ConsumerConfiguration; + + // check to see if the user sent a different version than the server has + // modifications are not allowed + IList changes = userCC.GetChanges(serverCC); + if (changes.Count > 0) + { + throw JsSubExistingConsumerCannotBeModified.Instance($"[{string.Join(",", changes)}]"); + } + + // deliver subject must be null/empty for pull, defined for push + if (isPullMode) + { + if (!string.IsNullOrWhiteSpace(serverCC.DeliverSubject)) + { + throw JsSubConsumerAlreadyConfiguredAsPush.Instance(); + } + } + else if (string.IsNullOrWhiteSpace(serverCC.DeliverSubject)) + { + throw JsSubConsumerAlreadyConfiguredAsPull.Instance(); + } + + if (string.IsNullOrWhiteSpace(serverCC.DeliverGroup)) + { + // lookedUp was null/empty, means existing consumer is not a queue consumer + if (settledDeliverGroup == null) + { + // ok fine, no queue requested and the existing consumer is also not a queue consumer + // we must check if the consumer is in use though + if (serverInfo.PushBound) + { + throw JsSubConsumerAlreadyBound.Instance(); + } + } + else + { // else they requested a queue but this durable was not configured as queue + throw JsSubExistingConsumerNotQueue.Instance(); + } + } + else if (settledDeliverGroup == null) + { + throw JsSubExistingConsumerIsQueue.Instance(); + } + else if (!serverCC.DeliverGroup.Equals(settledDeliverGroup)) + { + throw JsSubExistingQueueDoesNotMatchRequestedQueue.Instance(); + } + + // consumer already exists, make sure the filter subject matches + // subscribeSubject, if supplied came from the user directly + // or in the userCC or might not have been in either place + if (settledFilterSubjects.Count == 0) + { + // still also might be null, which the server treats as > + if (serverCC.FilterSubjects != null) + { + settledFilterSubjects = serverCC.FilterSubjects; + } + } + else if (!ConsumerFilterSubjectsAreEquivalent(settledFilterSubjects, serverCC.FilterSubjects)) + { + throw JsSubSubjectDoesNotMatchFilter.Instance(); + } + + inboxDeliver = serverCC.DeliverSubject; // use the deliver subject as the inbox. It may be null, that's ok, we'll fix that later + } + else if (so.Bind) { + throw JsSubConsumerNotFoundRequiredInBind.Instance(); + } + } + + // 5. If pull or no deliver subject (inbox) provided or found, make an inbox. + string settledInboxDeliver; + if (isPullMode) + { + settledInboxDeliver = Conn.NewInbox() + ".*"; + } + else if (string.IsNullOrWhiteSpace(inboxDeliver)) { + settledInboxDeliver = Conn.NewInbox(); + } + else + { + settledInboxDeliver = inboxDeliver; + } + + + // 6. If consumer does not exist, create and settle on the config. Name will have to wait + // If the consumer exists, I know what the settled info is + ConsumerConfiguration settledCC; + string settledConsumerName; + if (so.FastBind || serverCC != null) + { + settledCC = serverCC; + settledConsumerName = so.Name; + } + else + { + ConsumerConfiguration.ConsumerConfigurationBuilder ccBuilder = ConsumerConfiguration.Builder(userCC); + + // Pull mode doesn't maintain a deliver subject. It's actually an error if we send it. + if (!isPullMode) { + ccBuilder.WithDeliverSubject(settledInboxDeliver); + } + + // userCC.filterSubjects might have originally been empty + // but there might have been a userSubscribeSubject, + // so this makes sure it's resolved either way + ccBuilder.WithFilterSubjects(settledFilterSubjects); + + ccBuilder.WithDeliverGroup(settledDeliverGroup); + + settledCC = ccBuilder.Build(); + settledConsumerName = null; // the server will give us a name + } + + // 7. create the subscription + bool syncMode = userHandler == null; + MessageManager mm; + Connection.CreateSyncSubscriptionDelegate syncSubDelegate = null; + Connection.CreateAsyncSubscriptionDelegate asyncSubDelegate = null; + if (isPullMode) + { + if (pmmInstance == null) + { + MessageManagerFactory mmFactory = so.Ordered ? _pullOrderedMessageManagerFactory : _pullMessageManagerFactory; + mm = mmFactory((Connection)Conn, this, settledStream, so, settledCC, false, syncMode); + } + else + { + mm = pmmInstance; + } + if (syncMode) + { + syncSubDelegate = (dConn, dSubject, dQueue) => + { + return new JetStreamPullSubscription(dConn, dSubject, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + }; + } + else + { + asyncSubDelegate = (dConn, dSubject, dQueue) => + { + JetStreamPullAsyncSubscription asub = new JetStreamPullAsyncSubscription(dConn, dSubject, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + asub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); + return asub; + }; + } + } + else + { + MessageManagerFactory mmFactory = so.Ordered ? _pushOrderedMessageManagerFactory : _pushMessageManagerFactory; + mm = mmFactory((Connection)Conn, this, settledStream, so, settledCC, settledDeliverGroup != null, syncMode); + if (syncMode) + { + syncSubDelegate = (dConn, dSubject, dQueue) => + { + JetStreamPushSyncSubscription ssub = + new JetStreamPushSyncSubscription(dConn, dSubject, dQueue, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + ssub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); + return ssub; + }; + } + else + { + asyncSubDelegate = (dConn, dSubject, dQueue) => + { + JetStreamPushAsyncSubscription asub = + new JetStreamPushAsyncSubscription(dConn, dSubject, dQueue, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + asub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); + return asub; + }; + } + } + + Subscription sub; + if (syncSubDelegate != null) +After: + var consumerName = userCC.Durable ?? userCC.Name; + var inboxDeliver = userCC.DeliverSubject; + + // 4. Does this consumer already exist? FastBind bypasses the lookup; + // the dev better know what they are doing... + if (!so.FastBind && consumerName != null) + { + var serverInfo = LookupConsumerInfo(settledStream, consumerName); + + if (serverInfo != null) { // the consumer for that durable already exists + serverCC = serverInfo.ConsumerConfiguration; + + // check to see if the user sent a different version than the server has + // modifications are not allowed + var changes = userCC.GetChanges(serverCC); + if (changes.Count > 0) + { + throw JsSubExistingConsumerCannotBeModified.Instance($"[{string.Join(",", changes)}]"); + } + + // deliver subject must be null/empty for pull, defined for push + if (isPullMode) + { + if (!string.IsNullOrWhiteSpace(serverCC.DeliverSubject)) + { + throw JsSubConsumerAlreadyConfiguredAsPush.Instance(); + } + } + else if (string.IsNullOrWhiteSpace(serverCC.DeliverSubject)) + { + throw JsSubConsumerAlreadyConfiguredAsPull.Instance(); + } + + if (string.IsNullOrWhiteSpace(serverCC.DeliverGroup)) + { + // lookedUp was null/empty, means existing consumer is not a queue consumer + if (settledDeliverGroup == null) + { + // ok fine, no queue requested and the existing consumer is also not a queue consumer + // we must check if the consumer is in use though + if (serverInfo.PushBound) + { + throw JsSubConsumerAlreadyBound.Instance(); + } + } + else + { // else they requested a queue but this durable was not configured as queue + throw JsSubExistingConsumerNotQueue.Instance(); + } + } + else if (settledDeliverGroup == null) + { + throw JsSubExistingConsumerIsQueue.Instance(); + } + else if (!serverCC.DeliverGroup.Equals(settledDeliverGroup)) + { + throw JsSubExistingQueueDoesNotMatchRequestedQueue.Instance(); + } + + // consumer already exists, make sure the filter subject matches + // subscribeSubject, if supplied came from the user directly + // or in the userCC or might not have been in either place + if (settledFilterSubjects.Count == 0) + { + // still also might be null, which the server treats as > + if (serverCC.FilterSubjects != null) + { + settledFilterSubjects = serverCC.FilterSubjects; + } + } + else if (!ConsumerFilterSubjectsAreEquivalent(settledFilterSubjects, serverCC.FilterSubjects)) + { + throw JsSubSubjectDoesNotMatchFilter.Instance(); + } + + inboxDeliver = serverCC.DeliverSubject; // use the deliver subject as the inbox. It may be null, that's ok, we'll fix that later + } + else if (so.Bind) { + throw JsSubConsumerNotFoundRequiredInBind.Instance(); + } + } + + // 5. If pull or no deliver subject (inbox) provided or found, make an inbox. + string settledInboxDeliver; + if (isPullMode) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string consumerName = userCC.Durable; + if (consumerName == null) + { + consumerName = userCC.Name; + } + string inboxDeliver = userCC.DeliverSubject; + + // 4. Does this consumer already exist? FastBind bypasses the lookup; + // the dev better know what they are doing... + if (!so.FastBind && consumerName != null) + { + ConsumerInfo serverInfo = LookupConsumerInfo(settledStream, consumerName); + + if (serverInfo != null) { // the consumer for that durable already exists + serverCC = serverInfo.ConsumerConfiguration; + + // check to see if the user sent a different version than the server has + // modifications are not allowed + IList changes = userCC.GetChanges(serverCC); + if (changes.Count > 0) + { + throw JsSubExistingConsumerCannotBeModified.Instance($"[{string.Join(",", changes)}]"); + } + + // deliver subject must be null/empty for pull, defined for push + if (isPullMode) + { + if (!string.IsNullOrWhiteSpace(serverCC.DeliverSubject)) + { + throw JsSubConsumerAlreadyConfiguredAsPush.Instance(); + } + } + else if (string.IsNullOrWhiteSpace(serverCC.DeliverSubject)) + { + throw JsSubConsumerAlreadyConfiguredAsPull.Instance(); + } + + if (string.IsNullOrWhiteSpace(serverCC.DeliverGroup)) + { + // lookedUp was null/empty, means existing consumer is not a queue consumer + if (settledDeliverGroup == null) + { + // ok fine, no queue requested and the existing consumer is also not a queue consumer + // we must check if the consumer is in use though + if (serverInfo.PushBound) + { + throw JsSubConsumerAlreadyBound.Instance(); + } + } + else + { // else they requested a queue but this durable was not configured as queue + throw JsSubExistingConsumerNotQueue.Instance(); + } + } + else if (settledDeliverGroup == null) + { + throw JsSubExistingConsumerIsQueue.Instance(); + } + else if (!serverCC.DeliverGroup.Equals(settledDeliverGroup)) + { + throw JsSubExistingQueueDoesNotMatchRequestedQueue.Instance(); + } + + // consumer already exists, make sure the filter subject matches + // subscribeSubject, if supplied came from the user directly + // or in the userCC or might not have been in either place + if (settledFilterSubjects.Count == 0) + { + // still also might be null, which the server treats as > + if (serverCC.FilterSubjects != null) + { + settledFilterSubjects = serverCC.FilterSubjects; + } + } + else if (!ConsumerFilterSubjectsAreEquivalent(settledFilterSubjects, serverCC.FilterSubjects)) + { + throw JsSubSubjectDoesNotMatchFilter.Instance(); + } + + inboxDeliver = serverCC.DeliverSubject; // use the deliver subject as the inbox. It may be null, that's ok, we'll fix that later + } + else if (so.Bind) { + throw JsSubConsumerNotFoundRequiredInBind.Instance(); + } + } + + // 5. If pull or no deliver subject (inbox) provided or found, make an inbox. + string settledInboxDeliver; + if (isPullMode) + { + settledInboxDeliver = Conn.NewInbox() + ".*"; + } + else if (string.IsNullOrWhiteSpace(inboxDeliver)) { + settledInboxDeliver = Conn.NewInbox(); + } + else + { + settledInboxDeliver = inboxDeliver; + } + + + // 6. If consumer does not exist, create and settle on the config. Name will have to wait + // If the consumer exists, I know what the settled info is + ConsumerConfiguration settledCC; + string settledConsumerName; + if (so.FastBind || serverCC != null) + { + settledCC = serverCC; + settledConsumerName = so.Name; + } + else + { + ConsumerConfiguration.ConsumerConfigurationBuilder ccBuilder = ConsumerConfiguration.Builder(userCC); + + // Pull mode doesn't maintain a deliver subject. It's actually an error if we send it. + if (!isPullMode) { + ccBuilder.WithDeliverSubject(settledInboxDeliver); + } + + // userCC.filterSubjects might have originally been empty + // but there might have been a userSubscribeSubject, + // so this makes sure it's resolved either way + ccBuilder.WithFilterSubjects(settledFilterSubjects); + + ccBuilder.WithDeliverGroup(settledDeliverGroup); + + settledCC = ccBuilder.Build(); + settledConsumerName = null; // the server will give us a name + } + + // 7. create the subscription + bool syncMode = userHandler == null; + MessageManager mm; + Connection.CreateSyncSubscriptionDelegate syncSubDelegate = null; + Connection.CreateAsyncSubscriptionDelegate asyncSubDelegate = null; + if (isPullMode) + { + if (pmmInstance == null) + { + MessageManagerFactory mmFactory = so.Ordered ? _pullOrderedMessageManagerFactory : _pullMessageManagerFactory; + mm = mmFactory((Connection)Conn, this, settledStream, so, settledCC, false, syncMode); + } + else + { + mm = pmmInstance; + } + if (syncMode) + { + syncSubDelegate = (dConn, dSubject, dQueue) => + { + return new JetStreamPullSubscription(dConn, dSubject, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + }; + } + else + { + asyncSubDelegate = (dConn, dSubject, dQueue) => + { + JetStreamPullAsyncSubscription asub = new JetStreamPullAsyncSubscription(dConn, dSubject, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + asub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); + return asub; + }; + } + } + else + { + MessageManagerFactory mmFactory = so.Ordered ? _pushOrderedMessageManagerFactory : _pushMessageManagerFactory; + mm = mmFactory((Connection)Conn, this, settledStream, so, settledCC, settledDeliverGroup != null, syncMode); + if (syncMode) + { + syncSubDelegate = (dConn, dSubject, dQueue) => + { + JetStreamPushSyncSubscription ssub = + new JetStreamPushSyncSubscription(dConn, dSubject, dQueue, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + ssub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); + return ssub; + }; + } + else + { + asyncSubDelegate = (dConn, dSubject, dQueue) => + { + JetStreamPushAsyncSubscription asub = + new JetStreamPushAsyncSubscription(dConn, dSubject, dQueue, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + asub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); + return asub; + }; + } + } + + Subscription sub; + if (syncSubDelegate != null) +After: + var consumerName = userCC.Durable ?? userCC.Name; + var inboxDeliver = userCC.DeliverSubject; + + // 4. Does this consumer already exist? FastBind bypasses the lookup; + // the dev better know what they are doing... + if (!so.FastBind && consumerName != null) + { + var serverInfo = LookupConsumerInfo(settledStream, consumerName); + + if (serverInfo != null) { // the consumer for that durable already exists + serverCC = serverInfo.ConsumerConfiguration; + + // check to see if the user sent a different version than the server has + // modifications are not allowed + var changes = userCC.GetChanges(serverCC); + if (changes.Count > 0) + { + throw JsSubExistingConsumerCannotBeModified.Instance($"[{string.Join(",", changes)}]"); + } + + // deliver subject must be null/empty for pull, defined for push + if (isPullMode) + { + if (!string.IsNullOrWhiteSpace(serverCC.DeliverSubject)) + { + throw JsSubConsumerAlreadyConfiguredAsPush.Instance(); + } + } + else if (string.IsNullOrWhiteSpace(serverCC.DeliverSubject)) + { + throw JsSubConsumerAlreadyConfiguredAsPull.Instance(); + } + + if (string.IsNullOrWhiteSpace(serverCC.DeliverGroup)) + { + // lookedUp was null/empty, means existing consumer is not a queue consumer + if (settledDeliverGroup == null) + { + // ok fine, no queue requested and the existing consumer is also not a queue consumer + // we must check if the consumer is in use though + if (serverInfo.PushBound) + { + throw JsSubConsumerAlreadyBound.Instance(); + } + } + else + { // else they requested a queue but this durable was not configured as queue + throw JsSubExistingConsumerNotQueue.Instance(); + } + } + else if (settledDeliverGroup == null) + { + throw JsSubExistingConsumerIsQueue.Instance(); + } + else if (!serverCC.DeliverGroup.Equals(settledDeliverGroup)) + { + throw JsSubExistingQueueDoesNotMatchRequestedQueue.Instance(); + } + + // consumer already exists, make sure the filter subject matches + // subscribeSubject, if supplied came from the user directly + // or in the userCC or might not have been in either place + if (settledFilterSubjects.Count == 0) + { + // still also might be null, which the server treats as > + if (serverCC.FilterSubjects != null) + { + settledFilterSubjects = serverCC.FilterSubjects; + } + } + else if (!ConsumerFilterSubjectsAreEquivalent(settledFilterSubjects, serverCC.FilterSubjects)) + { + throw JsSubSubjectDoesNotMatchFilter.Instance(); + } + + inboxDeliver = serverCC.DeliverSubject; // use the deliver subject as the inbox. It may be null, that's ok, we'll fix that later + } + else if (so.Bind) { + throw JsSubConsumerNotFoundRequiredInBind.Instance(); + } + } + + // 5. If pull or no deliver subject (inbox) provided or found, make an inbox. + string settledInboxDeliver; + if (isPullMode) +*/ + + { + // Parameter notes. For those relating to the callers, you can see all the callers further down in this source file. + // - pull subscribe callers guarantee that pullSubscribeOptions is not null + // - qgroup is always null with pull callers + // - callers only ever provide one of the subscribe options + + // 1. Initial prep and validation + var isPullMode = pullSubscribeOptions != null; + + SubscribeOptions so; + string stream; + ConsumerConfiguration userCC; + string settledDeliverGroup = null; // push might set this + + if ( +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + sub = ((Connection)Conn).subscribeSync(settledInboxDeliver, settledDeliverGroup, syncSubDelegate); + } + else + { + bool handlerAutoAck = autoAck && settledCC.AckPolicy != AckPolicy.None; + EventHandler handler = (sender, args) => + { + if (mm.Manage(args.Message) == ManageResult.Message) + { + userHandler.Invoke(sender, args); + if (handlerAutoAck) + { + args.Message.Ack(); + } + } + }; + sub = ((Connection)Conn).subscribeAsync(settledInboxDeliver, settledDeliverGroup, handler, asyncSubDelegate); + } + + // 8. The consumer might need to be created, do it here + if (settledConsumerName == null) + { + try + { + ConsumerInfo ci = CreateConsumerInternal(settledStream, settledCC, ConsumerCreateRequestAction.CreateOrUpdate); + if (sub is JetStreamAbstractSyncSubscription syncSub) + { + syncSub.SetConsumerName(ci.Name); + } + else if (sub is JetStreamAbstractAsyncSubscription asyncSub) + { + asyncSub.SetConsumerName(ci.Name); + } + } + catch + { + // create consumer can fail, unsubscribe and then throw the exception to the user + sub.Unsubscribe(); + throw; + } + } + + Conn.FlushBuffer(); + return sub; + } + + // protected internal so can be tested + protected internal ConsumerInfo LookupConsumerInfo(string lookupStream, string lookupConsumer) { + try { + return GetConsumerInfoInternal(lookupStream, lookupConsumer); + } + catch (NATSJetStreamException e) { + if (e.ApiErrorCode == JetStreamConstants.JsConsumerNotFoundErr) { + return null; + } + throw; + } + } + + private string LookupStreamBySubject(string subject) + { + IList list = GetStreamNamesInternal(subject); + return list.Count == 1 ? list[0] : null; + } + + private string LookupStreamSubject(string stream) + { + StreamInfo si = GetStreamInfoInternal(stream, null); + return si.Config.Subjects.Count == 1 ? si.Config.Subjects[0] : null; + } + + private Boolean IsFilterMatch(string subscribeSubject, string filterSubject, string stream) { + + // subscribeSubject guaranteed to not be empty or null + // filterSubject may be null or empty or have value + + if (subscribeSubject.Equals(filterSubject)) { + return true; + } + + if (string.IsNullOrWhiteSpace(filterSubject) || filterSubject.Equals(NatsConstants.GreaterThan)) { + // lookup stream subject returns null if there is not exactly one subject + string streamSubject = LookupStreamSubject(stream); + return subscribeSubject.Equals(streamSubject); + } + + return false; + } + + public IJetStreamPullSubscription PullSubscribe(string subject, PullSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + ValidateNotNull(options, "Pull Subscribe Options"); + return (IJetStreamPullSubscription) CreateSubscription(subject, null, options, null, null, false, null); + } + + public IJetStreamPullAsyncSubscription PullSubscribeAsync(string subject, EventHandler handler, PullSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + ValidateNotNull(handler, "Handler"); + ValidateNotNull(options, "Pull Subscribe Options"); + return (IJetStreamPullAsyncSubscription) CreateSubscription(subject, null, options, null, handler, false, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, EventHandler handler, bool autoAck) + { + subject = ValidateSubject(subject, true); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, null, null, null, handler, autoAck, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, string queue, EventHandler handler, bool autoAck) + { + subject = ValidateSubject(subject, true); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, null, null, queue, handler, autoAck, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, EventHandler handler, bool autoAck, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, options, null, null, handler, autoAck, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, string queue, EventHandler handler, bool autoAck, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, options, null, queue, handler, autoAck, null); + } + + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject) + { + subject = ValidateSubject(subject, true); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, null, null, null, null, false, null); +After: + settledInboxDeliver = Conn.NewInbox() + ".*"; + } + else if (string.IsNullOrWhiteSpace(inboxDeliver)) { + settledInboxDeliver = Conn.NewInbox(); + } + else + { + settledInboxDeliver = inboxDeliver; + } + + + // 6. If consumer does not exist, create and settle on the config. Name will have to wait + // If the consumer exists, I know what the settled info is + ConsumerConfiguration settledCC; + string settledConsumerName; + if (so.FastBind || serverCC != null) + { + settledCC = serverCC; + settledConsumerName = so.Name; + } + else + { + var ccBuilder = ConsumerConfiguration.Builder(userCC); + + // Pull mode doesn't maintain a deliver subject. It's actually an error if we send it. + if (!isPullMode) { + ccBuilder.WithDeliverSubject(settledInboxDeliver); + } + + // userCC.filterSubjects might have originally been empty + // but there might have been a userSubscribeSubject, + // so this makes sure it's resolved either way + ccBuilder.WithFilterSubjects(settledFilterSubjects); + + ccBuilder.WithDeliverGroup(settledDeliverGroup); + + settledCC = ccBuilder.Build(); + settledConsumerName = null; // the server will give us a name + } + + // 7. create the subscription + var syncMode = userHandler == null; + MessageManager mm; + Connection.CreateSyncSubscriptionDelegate syncSubDelegate = null; + Connection.CreateAsyncSubscriptionDelegate asyncSubDelegate = null; + if (isPullMode) + { + if (pmmInstance == null) + { + var mmFactory = so.Ordered ? _pullOrderedMessageManagerFactory : _pullMessageManagerFactory; + mm = mmFactory((Connection)Conn, this, settledStream, so, settledCC, false, syncMode); + } + else + { + mm = pmmInstance; + } + if (syncMode) + { + syncSubDelegate = (dConn, dSubject, dQueue) => + { + return new JetStreamPullSubscription(dConn, dSubject, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + }; + } + else + { + asyncSubDelegate = (dConn, dSubject, dQueue) => + { + var asub = new JetStreamPullAsyncSubscription(dConn, dSubject, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + asub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); + return asub; + }; + } + } + else + { + var mmFactory = so.Ordered ? _pushOrderedMessageManagerFactory : _pushMessageManagerFactory; + mm = mmFactory((Connection)Conn, this, settledStream, so, settledCC, settledDeliverGroup != null, syncMode); + if (syncMode) + { + syncSubDelegate = (dConn, dSubject, dQueue) => + { + var ssub = + new JetStreamPushSyncSubscription(dConn, dSubject, dQueue, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + ssub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); + return ssub; + }; + } + else + { + asyncSubDelegate = (dConn, dSubject, dQueue) => + { + var asub = + new JetStreamPushAsyncSubscription(dConn, dSubject, dQueue, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + asub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); + return asub; + }; + } + } + + Subscription sub; + if (syncSubDelegate != null) + { + sub = ((Connection)Conn).subscribeSync(settledInboxDeliver, settledDeliverGroup, syncSubDelegate); + } + else + { + var handlerAutoAck = autoAck && settledCC.AckPolicy != AckPolicy.None; + EventHandler handler = (sender, args) => + { + if (mm.Manage(args.Message) == ManageResult.Message) + { + userHandler.Invoke(sender, args); + if (handlerAutoAck) + { + args.Message.Ack(); + } + } + }; + sub = ((Connection)Conn).subscribeAsync(settledInboxDeliver, settledDeliverGroup, handler, asyncSubDelegate); + } + + // 8. The consumer might need to be created, do it here + if (settledConsumerName == null) + { + try + { + var ci = CreateConsumerInternal(settledStream, settledCC, ConsumerCreateRequestAction.CreateOrUpdate); + if (sub is JetStreamAbstractSyncSubscription syncSub) + { + syncSub.SetConsumerName(ci.Name); + } + else if (sub is JetStreamAbstractAsyncSubscription asyncSub) + { + asyncSub.SetConsumerName(ci.Name); + } + } + catch + { + // create consumer can fail, unsubscribe and then throw the exception to the user + sub.Unsubscribe(); + throw; + } + } + + Conn.FlushBuffer(); + return sub; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + sub = ((Connection)Conn).subscribeSync(settledInboxDeliver, settledDeliverGroup, syncSubDelegate); + } + else + { + bool handlerAutoAck = autoAck && settledCC.AckPolicy != AckPolicy.None; + EventHandler handler = (sender, args) => + { + if (mm.Manage(args.Message) == ManageResult.Message) + { + userHandler.Invoke(sender, args); + if (handlerAutoAck) + { + args.Message.Ack(); + } + } + }; + sub = ((Connection)Conn).subscribeAsync(settledInboxDeliver, settledDeliverGroup, handler, asyncSubDelegate); + } + + // 8. The consumer might need to be created, do it here + if (settledConsumerName == null) + { + try + { + ConsumerInfo ci = CreateConsumerInternal(settledStream, settledCC, ConsumerCreateRequestAction.CreateOrUpdate); + if (sub is JetStreamAbstractSyncSubscription syncSub) + { + syncSub.SetConsumerName(ci.Name); + } + else if (sub is JetStreamAbstractAsyncSubscription asyncSub) + { + asyncSub.SetConsumerName(ci.Name); + } + } + catch + { + // create consumer can fail, unsubscribe and then throw the exception to the user + sub.Unsubscribe(); + throw; + } + } + + Conn.FlushBuffer(); + return sub; + } + + // protected internal so can be tested + protected internal ConsumerInfo LookupConsumerInfo(string lookupStream, string lookupConsumer) { + try { + return GetConsumerInfoInternal(lookupStream, lookupConsumer); + } + catch (NATSJetStreamException e) { + if (e.ApiErrorCode == JetStreamConstants.JsConsumerNotFoundErr) { + return null; + } + throw; + } + } + + private string LookupStreamBySubject(string subject) + { + IList list = GetStreamNamesInternal(subject); + return list.Count == 1 ? list[0] : null; + } + + private string LookupStreamSubject(string stream) + { + StreamInfo si = GetStreamInfoInternal(stream, null); + return si.Config.Subjects.Count == 1 ? si.Config.Subjects[0] : null; + } + + private Boolean IsFilterMatch(string subscribeSubject, string filterSubject, string stream) { + + // subscribeSubject guaranteed to not be empty or null + // filterSubject may be null or empty or have value + + if (subscribeSubject.Equals(filterSubject)) { + return true; + } + + if (string.IsNullOrWhiteSpace(filterSubject) || filterSubject.Equals(NatsConstants.GreaterThan)) { + // lookup stream subject returns null if there is not exactly one subject + string streamSubject = LookupStreamSubject(stream); + return subscribeSubject.Equals(streamSubject); + } + + return false; + } + + public IJetStreamPullSubscription PullSubscribe(string subject, PullSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + ValidateNotNull(options, "Pull Subscribe Options"); + return (IJetStreamPullSubscription) CreateSubscription(subject, null, options, null, null, false, null); + } + + public IJetStreamPullAsyncSubscription PullSubscribeAsync(string subject, EventHandler handler, PullSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + ValidateNotNull(handler, "Handler"); + ValidateNotNull(options, "Pull Subscribe Options"); + return (IJetStreamPullAsyncSubscription) CreateSubscription(subject, null, options, null, handler, false, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, EventHandler handler, bool autoAck) + { + subject = ValidateSubject(subject, true); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, null, null, null, handler, autoAck, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, string queue, EventHandler handler, bool autoAck) + { + subject = ValidateSubject(subject, true); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, null, null, queue, handler, autoAck, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, EventHandler handler, bool autoAck, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, options, null, null, handler, autoAck, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, string queue, EventHandler handler, bool autoAck, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, options, null, queue, handler, autoAck, null); + } + + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject) + { + subject = ValidateSubject(subject, true); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, null, null, null, null, false, null); +After: + settledInboxDeliver = Conn.NewInbox() + ".*"; + } + else if (string.IsNullOrWhiteSpace(inboxDeliver)) { + settledInboxDeliver = Conn.NewInbox(); + } + else + { + settledInboxDeliver = inboxDeliver; + } + + + // 6. If consumer does not exist, create and settle on the config. Name will have to wait + // If the consumer exists, I know what the settled info is + ConsumerConfiguration settledCC; + string settledConsumerName; + if (so.FastBind || serverCC != null) + { + settledCC = serverCC; + settledConsumerName = so.Name; + } + else + { + var ccBuilder = ConsumerConfiguration.Builder(userCC); + + // Pull mode doesn't maintain a deliver subject. It's actually an error if we send it. + if (!isPullMode) { + ccBuilder.WithDeliverSubject(settledInboxDeliver); + } + + // userCC.filterSubjects might have originally been empty + // but there might have been a userSubscribeSubject, + // so this makes sure it's resolved either way + ccBuilder.WithFilterSubjects(settledFilterSubjects); + + ccBuilder.WithDeliverGroup(settledDeliverGroup); + + settledCC = ccBuilder.Build(); + settledConsumerName = null; // the server will give us a name + } + + // 7. create the subscription + var syncMode = userHandler == null; + MessageManager mm; + Connection.CreateSyncSubscriptionDelegate syncSubDelegate = null; + Connection.CreateAsyncSubscriptionDelegate asyncSubDelegate = null; + if (isPullMode) + { + if (pmmInstance == null) + { + var mmFactory = so.Ordered ? _pullOrderedMessageManagerFactory : _pullMessageManagerFactory; + mm = mmFactory((Connection)Conn, this, settledStream, so, settledCC, false, syncMode); + } + else + { + mm = pmmInstance; + } + if (syncMode) + { + syncSubDelegate = (dConn, dSubject, dQueue) => + { + return new JetStreamPullSubscription(dConn, dSubject, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + }; + } + else + { + asyncSubDelegate = (dConn, dSubject, dQueue) => + { + var asub = new JetStreamPullAsyncSubscription(dConn, dSubject, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + asub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); + return asub; + }; + } + } + else + { + var mmFactory = so.Ordered ? _pushOrderedMessageManagerFactory : _pushMessageManagerFactory; + mm = mmFactory((Connection)Conn, this, settledStream, so, settledCC, settledDeliverGroup != null, syncMode); + if (syncMode) + { + syncSubDelegate = (dConn, dSubject, dQueue) => + { + var ssub = + new JetStreamPushSyncSubscription(dConn, dSubject, dQueue, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + ssub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); + return ssub; + }; + } + else + { + asyncSubDelegate = (dConn, dSubject, dQueue) => + { + var asub = + new JetStreamPushAsyncSubscription(dConn, dSubject, dQueue, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + asub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); + return asub; + }; + } + } + + Subscription sub; + if (syncSubDelegate != null) + { + sub = ((Connection)Conn).subscribeSync(settledInboxDeliver, settledDeliverGroup, syncSubDelegate); + } + else + { + var handlerAutoAck = autoAck && settledCC.AckPolicy != AckPolicy.None; + EventHandler handler = (sender, args) => + { + if (mm.Manage(args.Message) == ManageResult.Message) + { + userHandler.Invoke(sender, args); + if (handlerAutoAck) + { + args.Message.Ack(); + } + } + }; + sub = ((Connection)Conn).subscribeAsync(settledInboxDeliver, settledDeliverGroup, handler, asyncSubDelegate); + } + + // 8. The consumer might need to be created, do it here + if (settledConsumerName == null) + { + try + { + var ci = CreateConsumerInternal(settledStream, settledCC, ConsumerCreateRequestAction.CreateOrUpdate); + if (sub is JetStreamAbstractSyncSubscription syncSub) + { + syncSub.SetConsumerName(ci.Name); + } + else if (sub is JetStreamAbstractAsyncSubscription asyncSub) + { + asyncSub.SetConsumerName(ci.Name); + } + } + catch + { + // create consumer can fail, unsubscribe and then throw the exception to the user + sub.Unsubscribe(); + throw; + } + } + + Conn.FlushBuffer(); + return sub; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + sub = ((Connection)Conn).subscribeSync(settledInboxDeliver, settledDeliverGroup, syncSubDelegate); + } + else + { + bool handlerAutoAck = autoAck && settledCC.AckPolicy != AckPolicy.None; + EventHandler handler = (sender, args) => + { + if (mm.Manage(args.Message) == ManageResult.Message) + { + userHandler.Invoke(sender, args); + if (handlerAutoAck) + { + args.Message.Ack(); + } + } + }; + sub = ((Connection)Conn).subscribeAsync(settledInboxDeliver, settledDeliverGroup, handler, asyncSubDelegate); + } + + // 8. The consumer might need to be created, do it here + if (settledConsumerName == null) + { + try + { + ConsumerInfo ci = CreateConsumerInternal(settledStream, settledCC, ConsumerCreateRequestAction.CreateOrUpdate); + if (sub is JetStreamAbstractSyncSubscription syncSub) + { + syncSub.SetConsumerName(ci.Name); + } + else if (sub is JetStreamAbstractAsyncSubscription asyncSub) + { + asyncSub.SetConsumerName(ci.Name); + } + } + catch + { + // create consumer can fail, unsubscribe and then throw the exception to the user + sub.Unsubscribe(); + throw; + } + } + + Conn.FlushBuffer(); + return sub; + } + + // protected internal so can be tested + protected internal ConsumerInfo LookupConsumerInfo(string lookupStream, string lookupConsumer) { + try { + return GetConsumerInfoInternal(lookupStream, lookupConsumer); + } + catch (NATSJetStreamException e) { + if (e.ApiErrorCode == JetStreamConstants.JsConsumerNotFoundErr) { + return null; + } + throw; + } + } + + private string LookupStreamBySubject(string subject) + { + IList list = GetStreamNamesInternal(subject); + return list.Count == 1 ? list[0] : null; + } + + private string LookupStreamSubject(string stream) + { + StreamInfo si = GetStreamInfoInternal(stream, null); + return si.Config.Subjects.Count == 1 ? si.Config.Subjects[0] : null; + } + + private Boolean IsFilterMatch(string subscribeSubject, string filterSubject, string stream) { + + // subscribeSubject guaranteed to not be empty or null + // filterSubject may be null or empty or have value + + if (subscribeSubject.Equals(filterSubject)) { + return true; + } + + if (string.IsNullOrWhiteSpace(filterSubject) || filterSubject.Equals(NatsConstants.GreaterThan)) { + // lookup stream subject returns null if there is not exactly one subject + string streamSubject = LookupStreamSubject(stream); + return subscribeSubject.Equals(streamSubject); + } + + return false; + } + + public IJetStreamPullSubscription PullSubscribe(string subject, PullSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + ValidateNotNull(options, "Pull Subscribe Options"); + return (IJetStreamPullSubscription) CreateSubscription(subject, null, options, null, null, false, null); + } + + public IJetStreamPullAsyncSubscription PullSubscribeAsync(string subject, EventHandler handler, PullSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + ValidateNotNull(handler, "Handler"); + ValidateNotNull(options, "Pull Subscribe Options"); + return (IJetStreamPullAsyncSubscription) CreateSubscription(subject, null, options, null, handler, false, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, EventHandler handler, bool autoAck) + { + subject = ValidateSubject(subject, true); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, null, null, null, handler, autoAck, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, string queue, EventHandler handler, bool autoAck) + { + subject = ValidateSubject(subject, true); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, null, null, queue, handler, autoAck, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, EventHandler handler, bool autoAck, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, options, null, null, handler, autoAck, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, string queue, EventHandler handler, bool autoAck, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, options, null, queue, handler, autoAck, null); + } + + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject) + { + subject = ValidateSubject(subject, true); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, null, null, null, null, false, null); +After: + settledInboxDeliver = Conn.NewInbox() + ".*"; + } + else if (string.IsNullOrWhiteSpace(inboxDeliver)) { + settledInboxDeliver = Conn.NewInbox(); + } + else + { + settledInboxDeliver = inboxDeliver; + } + + + // 6. If consumer does not exist, create and settle on the config. Name will have to wait + // If the consumer exists, I know what the settled info is + ConsumerConfiguration settledCC; + string settledConsumerName; + if (so.FastBind || serverCC != null) + { + settledCC = serverCC; + settledConsumerName = so.Name; + } + else + { + var ccBuilder = ConsumerConfiguration.Builder(userCC); + + // Pull mode doesn't maintain a deliver subject. It's actually an error if we send it. + if (!isPullMode) { + ccBuilder.WithDeliverSubject(settledInboxDeliver); + } + + // userCC.filterSubjects might have originally been empty + // but there might have been a userSubscribeSubject, + // so this makes sure it's resolved either way + ccBuilder.WithFilterSubjects(settledFilterSubjects); + + ccBuilder.WithDeliverGroup(settledDeliverGroup); + + settledCC = ccBuilder.Build(); + settledConsumerName = null; // the server will give us a name + } + + // 7. create the subscription + var syncMode = userHandler == null; + MessageManager mm; + Connection.CreateSyncSubscriptionDelegate syncSubDelegate = null; + Connection.CreateAsyncSubscriptionDelegate asyncSubDelegate = null; + if (isPullMode) + { + if (pmmInstance == null) + { + var mmFactory = so.Ordered ? _pullOrderedMessageManagerFactory : _pullMessageManagerFactory; + mm = mmFactory((Connection)Conn, this, settledStream, so, settledCC, false, syncMode); + } + else + { + mm = pmmInstance; + } + if (syncMode) + { + syncSubDelegate = (dConn, dSubject, dQueue) => + { + return new JetStreamPullSubscription(dConn, dSubject, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + }; + } + else + { + asyncSubDelegate = (dConn, dSubject, dQueue) => + { + var asub = new JetStreamPullAsyncSubscription(dConn, dSubject, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + asub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); + return asub; + }; + } + } + else + { + var mmFactory = so.Ordered ? _pushOrderedMessageManagerFactory : _pushMessageManagerFactory; + mm = mmFactory((Connection)Conn, this, settledStream, so, settledCC, settledDeliverGroup != null, syncMode); + if (syncMode) + { + syncSubDelegate = (dConn, dSubject, dQueue) => + { + var ssub = + new JetStreamPushSyncSubscription(dConn, dSubject, dQueue, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + ssub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); + return ssub; + }; + } + else + { + asyncSubDelegate = (dConn, dSubject, dQueue) => + { + var asub = + new JetStreamPushAsyncSubscription(dConn, dSubject, dQueue, this, + settledStream, settledConsumerName, settledInboxDeliver, mm); + asub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); + return asub; + }; + } + } + + Subscription sub; + if (syncSubDelegate != null) + { + sub = ((Connection)Conn).subscribeSync(settledInboxDeliver, settledDeliverGroup, syncSubDelegate); + } + else + { + var handlerAutoAck = autoAck && settledCC.AckPolicy != AckPolicy.None; + EventHandler handler = (sender, args) => + { + if (mm.Manage(args.Message) == ManageResult.Message) + { + userHandler.Invoke(sender, args); + if (handlerAutoAck) + { + args.Message.Ack(); + } + } + }; + sub = ((Connection)Conn).subscribeAsync(settledInboxDeliver, settledDeliverGroup, handler, asyncSubDelegate); + } + + // 8. The consumer might need to be created, do it here + if (settledConsumerName == null) + { + try + { + var ci = CreateConsumerInternal(settledStream, settledCC, ConsumerCreateRequestAction.CreateOrUpdate); + if (sub is JetStreamAbstractSyncSubscription syncSub) + { + syncSub.SetConsumerName(ci.Name); + } + else if (sub is JetStreamAbstractAsyncSubscription asyncSub) + { + asyncSub.SetConsumerName(ci.Name); + } + } + catch + { + // create consumer can fail, unsubscribe and then throw the exception to the user + sub.Unsubscribe(); + throw; + } + } + + Conn.FlushBuffer(); + return sub; +*/ +isPullMode) + { + so = pullSubscribeOptions; // options must have already been checked to be non-null + stream = pullSubscribeOptions.Stream; + + userCC = so.ConsumerConfiguration; + + ValidateNotSupplied(userCC.DeliverGroup, JsSubPullCantHaveDeliverGroup); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, options, null, null, null, false, null); + } + + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, string queue) + { + subject = ValidateSubject(subject, true); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, null, null, queue, null, false, null); + } + + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, string queue, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, options, null, queue, null, false, null); +After: + // protected internal so can be tested + protected internal ConsumerInfo LookupConsumerInfo(string lookupStream, string lookupConsumer) { + try { + return GetConsumerInfoInternal(lookupStream, lookupConsumer); + } + catch (NATSJetStreamException e) { + if (e.ApiErrorCode == JetStreamConstants.JsConsumerNotFoundErr) { + return null; + } + throw; + } + } + + private string LookupStreamBySubject(string subject) + { + var list = GetStreamNamesInternal(subject); + return list.Count == 1 ? list[0] : null; + } + + private string LookupStreamSubject(string stream) + { + var si = GetStreamInfoInternal(stream, null); + return si.Config.Subjects.Count == 1 ? si.Config.Subjects[0] : null; + } + + private bool IsFilterMatch(string subscribeSubject, string filterSubject, string stream) { + + // subscribeSubject guaranteed to not be empty or null + // filterSubject may be null or empty or have value + + if (subscribeSubject.Equals(filterSubject)) { + return true; + } + + if (string.IsNullOrWhiteSpace(filterSubject) || filterSubject.Equals(NatsConstants.GreaterThan)) { + // lookup stream subject returns null if there is not exactly one subject + var streamSubject = LookupStreamSubject(stream); + return subscribeSubject.Equals(streamSubject); + } + + return false; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, options, null, null, null, false, null); + } + + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, string queue) + { + subject = ValidateSubject(subject, true); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, null, null, queue, null, false, null); + } + + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, string queue, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, options, null, queue, null, false, null); +After: + // protected internal so can be tested + protected internal ConsumerInfo LookupConsumerInfo(string lookupStream, string lookupConsumer) { + try { + return GetConsumerInfoInternal(lookupStream, lookupConsumer); + } + catch (NATSJetStreamException e) { + if (e.ApiErrorCode == JetStreamConstants.JsConsumerNotFoundErr) { + return null; + } + throw; + } + } + + private string LookupStreamBySubject(string subject) + { + var list = GetStreamNamesInternal(subject); + return list.Count == 1 ? list[0] : null; + } + + private string LookupStreamSubject(string stream) + { + var si = GetStreamInfoInternal(stream, null); + return si.Config.Subjects.Count == 1 ? si.Config.Subjects[0] : null; + } + + private bool IsFilterMatch(string subscribeSubject, string filterSubject, string stream) { + + // subscribeSubject guaranteed to not be empty or null + // filterSubject may be null or empty or have value + + if (subscribeSubject.Equals(filterSubject)) { + return true; + } + + if (string.IsNullOrWhiteSpace(filterSubject) || filterSubject.Equals(NatsConstants.GreaterThan)) { + // lookup stream subject returns null if there is not exactly one subject + var streamSubject = LookupStreamSubject(stream); + return subscribeSubject.Equals(streamSubject); + } + + return false; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, options, null, null, null, false, null); + } + + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, string queue) + { + subject = ValidateSubject(subject, true); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, null, null, queue, null, false, null); + } + + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, string queue, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, options, null, queue, null, false, null); +After: + // protected internal so can be tested + protected internal ConsumerInfo LookupConsumerInfo(string lookupStream, string lookupConsumer) { + try { + return GetConsumerInfoInternal(lookupStream, lookupConsumer); + } + catch (NATSJetStreamException e) { + if (e.ApiErrorCode == JetStreamConstants.JsConsumerNotFoundErr) { + return null; + } + throw; + } + } + + private string LookupStreamBySubject(string subject) + { + var list = GetStreamNamesInternal(subject); + return list.Count == 1 ? list[0] : null; + } + + private string LookupStreamSubject(string stream) + { + var si = GetStreamInfoInternal(stream, null); + return si.Config.Subjects.Count == 1 ? si.Config.Subjects[0] : null; + } + + private bool IsFilterMatch(string subscribeSubject, string filterSubject, string stream) { + + // subscribeSubject guaranteed to not be empty or null + // filterSubject may be null or empty or have value + + if (subscribeSubject.Equals(filterSubject)) { + return true; + } + + if (string.IsNullOrWhiteSpace(filterSubject) || filterSubject.Equals(NatsConstants.GreaterThan)) { + // lookup stream subject returns null if there is not exactly one subject + var streamSubject = LookupStreamSubject(stream); + return subscribeSubject.Equals(streamSubject); + } + + return false; +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + public IStreamContext GetStreamContext(string streamName) + { + Validator.ValidateStreamName(streamName, true); + return new StreamContext(streamName, this, Conn, JetStreamOptions); + } + + public IConsumerContext GetConsumerContext(string streamName, string consumerName) +After: + public IJetStreamPullSubscription PullSubscribe(string subject, PullSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + ValidateNotNull(options, "Pull Subscribe Options"); + return (IJetStreamPullSubscription) CreateSubscription(subject, null, options, null, null, false, null); + } + + public IJetStreamPullAsyncSubscription PullSubscribeAsync(string subject, EventHandler handler, PullSubscribeOptions options) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + public IStreamContext GetStreamContext(string streamName) + { + Validator.ValidateStreamName(streamName, true); + return new StreamContext(streamName, this, Conn, JetStreamOptions); + } + + public IConsumerContext GetConsumerContext(string streamName, string consumerName) +After: + public IJetStreamPullSubscription PullSubscribe(string subject, PullSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + ValidateNotNull(options, "Pull Subscribe Options"); + return (IJetStreamPullSubscription) CreateSubscription(subject, null, options, null, null, false, null); + } + + public IJetStreamPullAsyncSubscription PullSubscribeAsync(string subject, EventHandler handler, PullSubscribeOptions options) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + public IStreamContext GetStreamContext(string streamName) + { + Validator.ValidateStreamName(streamName, true); + return new StreamContext(streamName, this, Conn, JetStreamOptions); + } + + public IConsumerContext GetConsumerContext(string streamName, string consumerName) +After: + public IJetStreamPullSubscription PullSubscribe(string subject, PullSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + ValidateNotNull(options, "Pull Subscribe Options"); + return (IJetStreamPullSubscription) CreateSubscription(subject, null, options, null, null, false, null); + } + + public IJetStreamPullAsyncSubscription PullSubscribeAsync(string subject, EventHandler handler, PullSubscribeOptions options) +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Validator.Required(consumerName, "Consumer Name"); + return GetStreamContext(streamName).GetConsumerContext(consumerName); +After: + subject = ValidateSubject(subject, false); + ValidateNotNull(handler, "Handler"); + ValidateNotNull(options, "Pull Subscribe Options"); + return (IJetStreamPullAsyncSubscription) CreateSubscription(subject, null, options, null, handler, false, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, EventHandler handler, bool autoAck) + { + subject = ValidateSubject(subject, true); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, null, null, null, handler, autoAck, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, string queue, EventHandler handler, bool autoAck) + { + subject = ValidateSubject(subject, true); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, null, null, queue, handler, autoAck, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, EventHandler handler, bool autoAck, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, options, null, null, handler, autoAck, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, string queue, EventHandler handler, bool autoAck, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, options, null, queue, handler, autoAck, null); + } + + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject) + { + subject = ValidateSubject(subject, true); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, null, null, null, null, false, null); + } + + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, options, null, null, null, false, null); + } + + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, string queue) + { + subject = ValidateSubject(subject, true); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, null, null, queue, null, false, null); + } + + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, string queue, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, options, null, queue, null, false, null); + } + + public IStreamContext GetStreamContext(string streamName) + { + Validator.ValidateStreamName(streamName, true); + return new StreamContext(streamName, this, Conn, JetStreamOptions); + } + + public IConsumerContext GetConsumerContext(string streamName, string consumerName) + { + Validator.Required(consumerName, "Consumer Name"); + return GetStreamContext(streamName).GetConsumerContext(consumerName); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Validator.Required(consumerName, "Consumer Name"); + return GetStreamContext(streamName).GetConsumerContext(consumerName); +After: + subject = ValidateSubject(subject, false); + ValidateNotNull(handler, "Handler"); + ValidateNotNull(options, "Pull Subscribe Options"); + return (IJetStreamPullAsyncSubscription) CreateSubscription(subject, null, options, null, handler, false, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, EventHandler handler, bool autoAck) + { + subject = ValidateSubject(subject, true); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, null, null, null, handler, autoAck, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, string queue, EventHandler handler, bool autoAck) + { + subject = ValidateSubject(subject, true); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, null, null, queue, handler, autoAck, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, EventHandler handler, bool autoAck, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, options, null, null, handler, autoAck, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, string queue, EventHandler handler, bool autoAck, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, options, null, queue, handler, autoAck, null); + } + + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject) + { + subject = ValidateSubject(subject, true); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, null, null, null, null, false, null); + } + + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, options, null, null, null, false, null); + } + + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, string queue) + { + subject = ValidateSubject(subject, true); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, null, null, queue, null, false, null); + } + + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, string queue, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, options, null, queue, null, false, null); + } + + public IStreamContext GetStreamContext(string streamName) + { + Validator.ValidateStreamName(streamName, true); + return new StreamContext(streamName, this, Conn, JetStreamOptions); + } + + public IConsumerContext GetConsumerContext(string streamName, string consumerName) + { + Validator.Required(consumerName, "Consumer Name"); + return GetStreamContext(streamName).GetConsumerContext(consumerName); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Validator.Required(consumerName, "Consumer Name"); + return GetStreamContext(streamName).GetConsumerContext(consumerName); +After: + subject = ValidateSubject(subject, false); + ValidateNotNull(handler, "Handler"); + ValidateNotNull(options, "Pull Subscribe Options"); + return (IJetStreamPullAsyncSubscription) CreateSubscription(subject, null, options, null, handler, false, null); + } + + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, EventHandler handler, bool autoAck) { - return value > 0 ? _MergeString(h, key, value.ToString()) : h; + subject = ValidateSubject(subject, true); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, null, null, null, handler, autoAck, null); } - private MsgHeader MergeString(MsgHeader h, string key, string value) + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, string queue, EventHandler handler, bool autoAck) { - return string.IsNullOrWhiteSpace(value) ? h : _MergeString(h, key, value); + subject = ValidateSubject(subject, true); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, null, null, queue, handler, autoAck, null); } - private MsgHeader _MergeString(MsgHeader h, string key, string value) + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, EventHandler handler, bool autoAck, PushSubscribeOptions options) { - if (h == null) { - h = new MsgHeader(); - } - h.Set(key, value); - return h; + subject = ValidateSubject(subject, false); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, options, null, null, handler, autoAck, null); } - private PublishAck ProcessPublishResponse(Msg resp, PublishOptions options) { - if (resp.HasStatus) { - throw new NATSJetStreamException("Error Publishing: " + resp.Status.Message); - } - - PublishAck ack = new PublishAck(resp); - string ackStream = ack.Stream; - string pubStream = options?.Stream; - // stream specified in options but different than ack should not happen but... - if (!string.IsNullOrWhiteSpace(pubStream) && pubStream != ackStream) { - throw new NATSJetStreamException("Expected ack from stream " + pubStream + ", received from: " + ackStream); - } - return ack; + public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, string queue, EventHandler handler, bool autoAck, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + ValidateNotNull(handler, "Handler"); + return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, options, null, queue, handler, autoAck, null); } - private PublishAck PublishSyncInternal(string subject, byte[] data, MsgHeader hdr, PublishOptions options) + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject) { - MsgHeader merged = MergePublishOptions(hdr, options); - Msg msg = new Msg(subject, null, merged, data); - - if (JetStreamOptions.IsPublishNoAck) - { - Conn.Publish(msg); - return null; - } - - return ProcessPublishResponse(Conn.Request(msg, Timeout), options); + subject = ValidateSubject(subject, true); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, null, null, null, null, false, null); } - private async Task PublishAsyncInternal(string subject, byte[] data, MsgHeader hdr, PublishOptions options) + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, PushSubscribeOptions options) { - MsgHeader merged = MergePublishOptions(hdr, options); - Msg msg = new Msg(subject, null, merged, data); - - if (JetStreamOptions.IsPublishNoAck) - { - Conn.Publish(msg); - return null; - } - - var result = await Conn.RequestAsync(msg, Timeout).ConfigureAwait(false); - return ProcessPublishResponse(result, options); + subject = ValidateSubject(subject, false); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, options, null, null, null, false, null); } - public PublishAck Publish(string subject, byte[] data) - => PublishSyncInternal(subject, data, null, null); - - public PublishAck Publish(string subject, MsgHeader headers, byte[] data) - => PublishSyncInternal(subject, data, headers, null); - - public PublishAck Publish(string subject, byte[] data, PublishOptions options) - => PublishSyncInternal(subject, data, null, options); - - public PublishAck Publish(string subject, MsgHeader headers, byte[] data, PublishOptions options) - => PublishSyncInternal(subject, data, headers, options); - - public PublishAck Publish(Msg msg) - => PublishSyncInternal(msg.Subject, msg.Data, msg.Header, null); - - public PublishAck Publish(Msg msg, PublishOptions publishOptions) - => PublishSyncInternal(msg.Subject, msg.Data, msg.Header, publishOptions); - - public Task PublishAsync(string subject, byte[] data) - => PublishAsyncInternal(subject, data, null, null); - - public Task PublishAsync(string subject, MsgHeader headers, byte[] data) - => PublishAsyncInternal(subject, data, headers, null); - - public Task PublishAsync(string subject, byte[] data, PublishOptions publishOptions) - => PublishAsyncInternal(subject, data, null, publishOptions); - - public Task PublishAsync(string subject, MsgHeader headers, byte[] data, PublishOptions publishOptions) - => PublishAsyncInternal(subject, data, headers, publishOptions); - - public Task PublishAsync(Msg msg) - => PublishAsyncInternal(msg.Subject, msg.Data, msg.Header, null); - - public Task PublishAsync(Msg msg, PublishOptions publishOptions) - => PublishAsyncInternal(msg.Subject, msg.Data, msg.Header, publishOptions); - - // ---------------------------------------------------------------------------------------------------- - // Subscribe - // ---------------------------------------------------------------------------------------------------- - - internal delegate MessageManager MessageManagerFactory( - Connection conn, JetStream js, string stream, - SubscribeOptions so, ConsumerConfiguration cc, bool queueMode, bool syncMode); - - internal MessageManagerFactory _pushMessageManagerFactory = - (conn, js, stream, so, cc, queueMode, syncMode) => - new PushMessageManager(conn, js, stream, so, cc, queueMode, syncMode); - - internal MessageManagerFactory _pushOrderedMessageManagerFactory = - (conn, js, stream, so, cc, queueMode, syncMode) => - new OrderedMessageManager(conn, js, stream, so, cc, queueMode, syncMode); + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, string queue) + { + subject = ValidateSubject(subject, true); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, null, null, queue, null, false, null); + } - internal MessageManagerFactory _pullMessageManagerFactory = - (conn, js, stream, so, cc, queueMode, syncMode) => - new PullMessageManager(conn, so, syncMode); + public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, string queue, PushSubscribeOptions options) + { + subject = ValidateSubject(subject, false); + queue = EmptyAsNull(ValidateQueueName(queue, false)); + return (IJetStreamPushSyncSubscription) CreateSubscription(subject, options, null, queue, null, false, null); + } - internal MessageManagerFactory _pullOrderedMessageManagerFactory = - (conn, js, stream, so, cc, queueMode, syncMode) => - new PullOrderedMessageManager(conn, js, stream, so, cc, syncMode); + public IStreamContext GetStreamContext(string streamName) + { + Validator.ValidateStreamName(streamName, true); + return new StreamContext(streamName, this, Conn, JetStreamOptions); + } - internal Subscription CreateSubscription(string userSubscribeSubject, - PushSubscribeOptions pushSubscribeOptions, - PullSubscribeOptions pullSubscribeOptions, - string queueName, - EventHandler userHandler, - bool autoAck, - PullMessageManager pmmInstance) + public IConsumerContext GetConsumerContext(string streamName, string consumerName) { - // Parameter notes. For those relating to the callers, you can see all the callers further down in this source file. - // - pull subscribe callers guarantee that pullSubscribeOptions is not null - // - qgroup is always null with pull callers - // - callers only ever provide one of the subscribe options - - // 1. Initial prep and validation - bool isPullMode = pullSubscribeOptions != null; - - SubscribeOptions so; - string stream; - ConsumerConfiguration userCC; - string settledDeliverGroup = null; // push might set this - - if (isPullMode) - { - so = pullSubscribeOptions; // options must have already been checked to be non-null - stream = pullSubscribeOptions.Stream; - - userCC = so.ConsumerConfiguration; + Validator.Required(consumerName, "Consumer Name"); + return GetStreamContext(streamName).GetConsumerContext(consumerName); +*/ - ValidateNotSupplied(userCC.DeliverGroup, JsSubPullCantHaveDeliverGroup); ValidateNotSupplied(userCC.DeliverSubject, JsSubPullCantHaveDeliverSubject); } - else { + else + { so = pushSubscribeOptions ?? PushSubscribeOptions.DefaultPushOpts; stream = so.Stream; // might be null, that's ok (see directBind) @@ -218,17 +2596,21 @@ internal Subscription CreateSubscription(string userSubscribeSubject, // figure out the queue name settledDeliverGroup = ValidateMustMatchIfBothSupplied(userCC.DeliverGroup, queueName, JsSubQueueDeliverGroupMismatch); - if (so.Ordered && settledDeliverGroup != null) { + if (so.Ordered && settledDeliverGroup != null) + { throw JsSubOrderedNotAllowOnQueues.Instance(); } } - + // 1B. Flow Control / heartbeat not always valid - if (userCC.FlowControl || userCC.IdleHeartbeat != null && userCC.IdleHeartbeat.Millis > 0) { - if (isPullMode) { + if (userCC.FlowControl || userCC.IdleHeartbeat != null && userCC.IdleHeartbeat.Millis > 0) + { + if (isPullMode) + { throw JsSubFcHbNotValidPull.Instance(); } - if (settledDeliverGroup != null) { + if (settledDeliverGroup != null) + { throw JsSubFcHbNotValidQueue.Instance(); } } @@ -239,32 +2621,35 @@ internal Subscription CreateSubscription(string userSubscribeSubject, if (userCC.FilterSubjects == null) // empty filterSubjects gives null { // userCC.filterSubjects empty, populate settledFilterSubjects w/userSubscribeSubject if possible - if (userSubscribeSubject != null) { + if (userSubscribeSubject != null) + { settledFilterSubjects.Add(userSubscribeSubject); } } - else { + else + { // userCC.filterSubjects not empty, validate them - foreach (string fs in userCC.FilterSubjects) + foreach (var fs in userCC.FilterSubjects) { settledFilterSubjects.Add(fs); } // If userSubscribeSubject is provided it must be one of the filter subjects. - if (userSubscribeSubject != null && !settledFilterSubjects.Contains(userSubscribeSubject)) { + if (userSubscribeSubject != null && !settledFilterSubjects.Contains(userSubscribeSubject)) + { throw JsSubSubjectDoesNotMatchFilter.Instance(); } } // 3. Did they tell me what stream? No? look it up. string settledStream; - if (string.IsNullOrWhiteSpace(stream)) + if (string.IsNullOrWhiteSpace(stream)) { - if (settledFilterSubjects.Count == 0) + if (settledFilterSubjects.Count == 0) { throw JsSubSubjectNeededToLookupStream.Instance(); } settledStream = LookupStreamBySubject(settledFilterSubjects[0]); - if (settledStream == null) + if (settledStream == null) { throw JsSubNoMatchingStreamForSubject.Instance(); } @@ -275,65 +2660,62 @@ internal Subscription CreateSubscription(string userSubscribeSubject, } ConsumerConfiguration serverCC = null; - string consumerName = userCC.Durable; - if (consumerName == null) - { - consumerName = userCC.Name; - } - string inboxDeliver = userCC.DeliverSubject; - + var consumerName = userCC.Durable ?? userCC.Name; + var inboxDeliver = userCC.DeliverSubject; + // 4. Does this consumer already exist? FastBind bypasses the lookup; // the dev better know what they are doing... - if (!so.FastBind && consumerName != null) + if (!so.FastBind && consumerName != null) { - ConsumerInfo serverInfo = LookupConsumerInfo(settledStream, consumerName); + var serverInfo = LookupConsumerInfo(settledStream, consumerName); - if (serverInfo != null) { // the consumer for that durable already exists + if (serverInfo != null) + { // the consumer for that durable already exists serverCC = serverInfo.ConsumerConfiguration; // check to see if the user sent a different version than the server has // modifications are not allowed - IList changes = userCC.GetChanges(serverCC); - if (changes.Count > 0) + var changes = userCC.GetChanges(serverCC); + if (changes.Count > 0) { throw JsSubExistingConsumerCannotBeModified.Instance($"[{string.Join(",", changes)}]"); } // deliver subject must be null/empty for pull, defined for push - if (isPullMode) + if (isPullMode) { - if (!string.IsNullOrWhiteSpace(serverCC.DeliverSubject)) + if (!string.IsNullOrWhiteSpace(serverCC.DeliverSubject)) { throw JsSubConsumerAlreadyConfiguredAsPush.Instance(); } } - else if (string.IsNullOrWhiteSpace(serverCC.DeliverSubject)) + else if (string.IsNullOrWhiteSpace(serverCC.DeliverSubject)) { throw JsSubConsumerAlreadyConfiguredAsPull.Instance(); } - if (string.IsNullOrWhiteSpace(serverCC.DeliverGroup)) + if (string.IsNullOrWhiteSpace(serverCC.DeliverGroup)) { // lookedUp was null/empty, means existing consumer is not a queue consumer - if (settledDeliverGroup == null) + if (settledDeliverGroup == null) { // ok fine, no queue requested and the existing consumer is also not a queue consumer // we must check if the consumer is in use though - if (serverInfo.PushBound) + if (serverInfo.PushBound) { throw JsSubConsumerAlreadyBound.Instance(); } } - else + else { // else they requested a queue but this durable was not configured as queue throw JsSubExistingConsumerNotQueue.Instance(); } } - else if (settledDeliverGroup == null) + else if (settledDeliverGroup == null) { throw JsSubExistingConsumerIsQueue.Instance(); } - else if (!serverCC.DeliverGroup.Equals(settledDeliverGroup)) + else if (!serverCC.DeliverGroup.Equals(settledDeliverGroup)) { throw JsSubExistingQueueDoesNotMatchRequestedQueue.Instance(); } @@ -356,7 +2738,8 @@ internal Subscription CreateSubscription(string userSubscribeSubject, inboxDeliver = serverCC.DeliverSubject; // use the deliver subject as the inbox. It may be null, that's ok, we'll fix that later } - else if (so.Bind) { + else if (so.Bind) + { throw JsSubConsumerNotFoundRequiredInBind.Instance(); } } @@ -367,7 +2750,8 @@ internal Subscription CreateSubscription(string userSubscribeSubject, { settledInboxDeliver = Conn.NewInbox() + ".*"; } - else if (string.IsNullOrWhiteSpace(inboxDeliver)) { + else if (string.IsNullOrWhiteSpace(inboxDeliver)) + { settledInboxDeliver = Conn.NewInbox(); } else @@ -385,12 +2769,13 @@ internal Subscription CreateSubscription(string userSubscribeSubject, settledCC = serverCC; settledConsumerName = so.Name; } - else + else { - ConsumerConfiguration.ConsumerConfigurationBuilder ccBuilder = ConsumerConfiguration.Builder(userCC); + var ccBuilder = ConsumerConfiguration.Builder(userCC); // Pull mode doesn't maintain a deliver subject. It's actually an error if we send it. - if (!isPullMode) { + if (!isPullMode) + { ccBuilder.WithDeliverSubject(settledInboxDeliver); } @@ -406,7 +2791,7 @@ internal Subscription CreateSubscription(string userSubscribeSubject, } // 7. create the subscription - bool syncMode = userHandler == null; + var syncMode = userHandler == null; MessageManager mm; Connection.CreateSyncSubscriptionDelegate syncSubDelegate = null; Connection.CreateAsyncSubscriptionDelegate asyncSubDelegate = null; @@ -414,7 +2799,7 @@ internal Subscription CreateSubscription(string userSubscribeSubject, { if (pmmInstance == null) { - MessageManagerFactory mmFactory = so.Ordered ? _pullOrderedMessageManagerFactory : _pullMessageManagerFactory; + var mmFactory = so.Ordered ? _pullOrderedMessageManagerFactory : _pullMessageManagerFactory; mm = mmFactory((Connection)Conn, this, settledStream, so, settledCC, false, syncMode); } else @@ -425,7 +2810,7 @@ internal Subscription CreateSubscription(string userSubscribeSubject, { syncSubDelegate = (dConn, dSubject, dQueue) => { - return new JetStreamPullSubscription(dConn, dSubject, this, + return new JetStreamPullSubscription(dConn, dSubject, this, settledStream, settledConsumerName, settledInboxDeliver, mm); }; } @@ -433,7 +2818,7 @@ internal Subscription CreateSubscription(string userSubscribeSubject, { asyncSubDelegate = (dConn, dSubject, dQueue) => { - JetStreamPullAsyncSubscription asub = new JetStreamPullAsyncSubscription(dConn, dSubject, this, + var asub = new JetStreamPullAsyncSubscription(dConn, dSubject, this, settledStream, settledConsumerName, settledInboxDeliver, mm); asub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); return asub; @@ -442,14 +2827,14 @@ internal Subscription CreateSubscription(string userSubscribeSubject, } else { - MessageManagerFactory mmFactory = so.Ordered ? _pushOrderedMessageManagerFactory : _pushMessageManagerFactory; + var mmFactory = so.Ordered ? _pushOrderedMessageManagerFactory : _pushMessageManagerFactory; mm = mmFactory((Connection)Conn, this, settledStream, so, settledCC, settledDeliverGroup != null, syncMode); if (syncMode) { syncSubDelegate = (dConn, dSubject, dQueue) => { - JetStreamPushSyncSubscription ssub = - new JetStreamPushSyncSubscription(dConn, dSubject, dQueue, this, + var ssub = + new JetStreamPushSyncSubscription(dConn, dSubject, dQueue, this, settledStream, settledConsumerName, settledInboxDeliver, mm); ssub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); return ssub; @@ -459,23 +2844,23 @@ internal Subscription CreateSubscription(string userSubscribeSubject, { asyncSubDelegate = (dConn, dSubject, dQueue) => { - JetStreamPushAsyncSubscription asub = - new JetStreamPushAsyncSubscription(dConn, dSubject, dQueue, this, + var asub = + new JetStreamPushAsyncSubscription(dConn, dSubject, dQueue, this, settledStream, settledConsumerName, settledInboxDeliver, mm); asub.SetPendingLimits(so.PendingMessageLimit, so.PendingByteLimit); return asub; }; } } - + Subscription sub; if (syncSubDelegate != null) { - sub = ((Connection)Conn).subscribeSync(settledInboxDeliver, settledDeliverGroup, syncSubDelegate); + sub = ((Connection)Conn).subscribeSync(settledInboxDeliver, settledDeliverGroup, syncSubDelegate); } else { - bool handlerAutoAck = autoAck && settledCC.AckPolicy != AckPolicy.None; + var handlerAutoAck = autoAck && settledCC.AckPolicy != AckPolicy.None; EventHandler handler = (sender, args) => { if (mm.Manage(args.Message) == ManageResult.Message) @@ -495,7 +2880,7 @@ internal Subscription CreateSubscription(string userSubscribeSubject, { try { - ConsumerInfo ci = CreateConsumerInternal(settledStream, settledCC, ConsumerCreateRequestAction.CreateOrUpdate); + var ci = CreateConsumerInternal(settledStream, settledCC, ConsumerCreateRequestAction.CreateOrUpdate); if (sub is JetStreamAbstractSyncSubscription syncSub) { syncSub.SetConsumerName(ci.Name); @@ -516,14 +2901,18 @@ internal Subscription CreateSubscription(string userSubscribeSubject, Conn.FlushBuffer(); return sub; } - + // protected internal so can be tested - protected internal ConsumerInfo LookupConsumerInfo(string lookupStream, string lookupConsumer) { - try { + protected internal ConsumerInfo LookupConsumerInfo(string lookupStream, string lookupConsumer) + { + try + { return GetConsumerInfoInternal(lookupStream, lookupConsumer); } - catch (NATSJetStreamException e) { - if (e.ApiErrorCode == JetStreamConstants.JsConsumerNotFoundErr) { + catch (NATSJetStreamException e) + { + if (e.ApiErrorCode == JetStreamConstants.JsConsumerNotFoundErr) + { return null; } throw; @@ -532,28 +2921,31 @@ protected internal ConsumerInfo LookupConsumerInfo(string lookupStream, string l private string LookupStreamBySubject(string subject) { - IList list = GetStreamNamesInternal(subject); - return list.Count == 1 ? list[0] : null; + var list = GetStreamNamesInternal(subject); + return list.Count == 1 ? list[0] : null; } - + private string LookupStreamSubject(string stream) { - StreamInfo si = GetStreamInfoInternal(stream, null); + var si = GetStreamInfoInternal(stream, null); return si.Config.Subjects.Count == 1 ? si.Config.Subjects[0] : null; } - private Boolean IsFilterMatch(string subscribeSubject, string filterSubject, string stream) { + private bool IsFilterMatch(string subscribeSubject, string filterSubject, string stream) + { // subscribeSubject guaranteed to not be empty or null // filterSubject may be null or empty or have value - if (subscribeSubject.Equals(filterSubject)) { + if (subscribeSubject.Equals(filterSubject)) + { return true; } - if (string.IsNullOrWhiteSpace(filterSubject) || filterSubject.Equals(NatsConstants.GreaterThan)) { + if (string.IsNullOrWhiteSpace(filterSubject) || filterSubject.Equals(NatsConstants.GreaterThan)) + { // lookup stream subject returns null if there is not exactly one subject - string streamSubject = LookupStreamSubject(stream); + var streamSubject = LookupStreamSubject(stream); return subscribeSubject.Equals(streamSubject); } @@ -564,7 +2956,7 @@ public IJetStreamPullSubscription PullSubscribe(string subject, PullSubscribeOpt { subject = ValidateSubject(subject, false); ValidateNotNull(options, "Pull Subscribe Options"); - return (IJetStreamPullSubscription) CreateSubscription(subject, null, options, null, null, false, null); + return (IJetStreamPullSubscription)CreateSubscription(subject, null, options, null, null, false, null); } public IJetStreamPullAsyncSubscription PullSubscribeAsync(string subject, EventHandler handler, PullSubscribeOptions options) @@ -572,14 +2964,14 @@ public IJetStreamPullAsyncSubscription PullSubscribeAsync(string subject, EventH subject = ValidateSubject(subject, false); ValidateNotNull(handler, "Handler"); ValidateNotNull(options, "Pull Subscribe Options"); - return (IJetStreamPullAsyncSubscription) CreateSubscription(subject, null, options, null, handler, false, null); + return (IJetStreamPullAsyncSubscription)CreateSubscription(subject, null, options, null, handler, false, null); } public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, EventHandler handler, bool autoAck) { subject = ValidateSubject(subject, true); ValidateNotNull(handler, "Handler"); - return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, null, null, null, handler, autoAck, null); + return (IJetStreamPushAsyncSubscription)CreateSubscription(subject, null, null, null, handler, autoAck, null); } public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, string queue, EventHandler handler, bool autoAck) @@ -587,14 +2979,14 @@ public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, string subject = ValidateSubject(subject, true); queue = EmptyAsNull(ValidateQueueName(queue, false)); ValidateNotNull(handler, "Handler"); - return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, null, null, queue, handler, autoAck, null); + return (IJetStreamPushAsyncSubscription)CreateSubscription(subject, null, null, queue, handler, autoAck, null); } public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, EventHandler handler, bool autoAck, PushSubscribeOptions options) { subject = ValidateSubject(subject, false); ValidateNotNull(handler, "Handler"); - return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, options, null, null, handler, autoAck, null); + return (IJetStreamPushAsyncSubscription)CreateSubscription(subject, options, null, null, handler, autoAck, null); } public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, string queue, EventHandler handler, bool autoAck, PushSubscribeOptions options) @@ -602,33 +2994,33 @@ public IJetStreamPushAsyncSubscription PushSubscribeAsync(string subject, string subject = ValidateSubject(subject, false); queue = EmptyAsNull(ValidateQueueName(queue, false)); ValidateNotNull(handler, "Handler"); - return (IJetStreamPushAsyncSubscription) CreateSubscription(subject, options, null, queue, handler, autoAck, null); + return (IJetStreamPushAsyncSubscription)CreateSubscription(subject, options, null, queue, handler, autoAck, null); } public IJetStreamPushSyncSubscription PushSubscribeSync(string subject) { subject = ValidateSubject(subject, true); - return (IJetStreamPushSyncSubscription) CreateSubscription(subject, null, null, null, null, false, null); + return (IJetStreamPushSyncSubscription)CreateSubscription(subject, null, null, null, null, false, null); } public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, PushSubscribeOptions options) { subject = ValidateSubject(subject, false); - return (IJetStreamPushSyncSubscription) CreateSubscription(subject, options, null, null, null, false, null); + return (IJetStreamPushSyncSubscription)CreateSubscription(subject, options, null, null, null, false, null); } public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, string queue) { subject = ValidateSubject(subject, true); queue = EmptyAsNull(ValidateQueueName(queue, false)); - return (IJetStreamPushSyncSubscription) CreateSubscription(subject, null, null, queue, null, false, null); + return (IJetStreamPushSyncSubscription)CreateSubscription(subject, null, null, queue, null, false, null); } public IJetStreamPushSyncSubscription PushSubscribeSync(string subject, string queue, PushSubscribeOptions options) { subject = ValidateSubject(subject, false); queue = EmptyAsNull(ValidateQueueName(queue, false)); - return (IJetStreamPushSyncSubscription) CreateSubscription(subject, options, null, queue, null, false, null); + return (IJetStreamPushSyncSubscription)CreateSubscription(subject, options, null, queue, null, false, null); } public IStreamContext GetStreamContext(string streamName) @@ -636,7 +3028,7 @@ public IStreamContext GetStreamContext(string streamName) Validator.ValidateStreamName(streamName, true); return new StreamContext(streamName, this, Conn, JetStreamOptions); } - + public IConsumerContext GetConsumerContext(string streamName, string consumerName) { Validator.Required(consumerName, "Consumer Name"); diff --git a/src/NATS.Client/v1/JetStream/JetStreamAbstractAsyncSubscription.cs b/src/NATS.Client/v1/JetStream/JetStreamAbstractAsyncSubscription.cs index a452a1a0..42b8f390 100644 --- a/src/NATS.Client/v1/JetStream/JetStreamAbstractAsyncSubscription.cs +++ b/src/NATS.Client/v1/JetStream/JetStreamAbstractAsyncSubscription.cs @@ -1,4 +1,4 @@ -// Copyright 2023 The NATS Authors +// Copyright 2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: diff --git a/src/NATS.Client/v1/JetStream/JetStreamAbstractSyncSubscription.cs b/src/NATS.Client/v1/JetStream/JetStreamAbstractSyncSubscription.cs index f93f4c62..ef8aa5d3 100644 --- a/src/NATS.Client/v1/JetStream/JetStreamAbstractSyncSubscription.cs +++ b/src/NATS.Client/v1/JetStream/JetStreamAbstractSyncSubscription.cs @@ -19,13 +19,13 @@ public abstract class JetStreamAbstractSyncSubscription : SyncSubscription { internal readonly MessageManager MessageManager; internal string _consumer; - + // properties of IJetStreamSubscription, needed in subclass implementation public JetStream Context { get; } public string Stream { get; } public string Consumer => _consumer; public string DeliverSubject { get; } - + internal JetStreamAbstractSyncSubscription(Connection conn, string subject, string queue, JetStream js, string stream, string consumer, string deliver, MessageManager messageManager) : base(conn, subject, queue) @@ -44,7 +44,7 @@ internal virtual void SetConsumerName(string consumer) } public ConsumerInfo GetConsumerInformation() => Context.LookupConsumerInfo(Stream, Consumer); - + public override void Unsubscribe() { MessageManager.Shutdown(); @@ -92,20 +92,41 @@ internal Msg _nextUnmanagedWaitForever(string expectedPullSubject) // this calls is intended to block indefinitely so if there is a managed // message it's like not getting a message at all and we keep waiting while (true) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Msg msg = NextMessageImpl(-1); +After: + var msg = NextMessageImpl(-1); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Msg msg = NextMessageImpl(-1); +After: + var msg = NextMessageImpl(-1); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: Msg msg = NextMessageImpl(-1); +After: + var msg = NextMessageImpl(-1); +*/ + + { + var msg = NextMessageImpl(-1); switch (MessageManager.Manage(msg)) { - case ManageResult.Message: - return msg; - case ManageResult.StatusError: - // if the status applies throw exception, otherwise it's ignored, fall through - if (expectedPullSubject == null || expectedPullSubject.Equals(msg.Subject)) - { - throw new NATSJetStreamStatusException(msg.Status, this); - } - - break; + case ManageResult.Message: + return msg; + case ManageResult.StatusError: + // if the status applies throw exception, otherwise it's ignored, fall through + if (expectedPullSubject == null || expectedPullSubject.Equals(msg.Subject)) + { + throw new NATSJetStreamStatusException(msg.Status, this); + } + + break; } // Check again since waiting forever when: // 1. Any StatusHandled or StatusTerminus @@ -115,57 +136,128 @@ internal Msg _nextUnmanagedWaitForever(string expectedPullSubject) internal Msg _nextUnmanagedNoWait(string expectedPullSubject) { - while (true) { + while (true) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: Msg msg = NextMessageImpl(0); - switch (MessageManager.Manage(msg)) { - case ManageResult.Message: - return msg; - case ManageResult.StatusTerminus: - // if the status applies return null, otherwise it's ignored, fall through - if (expectedPullSubject == null || expectedPullSubject.Equals(msg.Subject)) - { - throw new NATSTimeoutException(); - } - break; - case ManageResult.StatusError: - // if the status applies throw exception, otherwise it's ignored, fall through - if (expectedPullSubject == null || expectedPullSubject.Equals(msg.Subject)) - { - throw new NATSJetStreamStatusException(msg.Status, this); - } - break; +After: + var msg = NextMessageImpl(0); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Msg msg = NextMessageImpl(0); +After: + var msg = NextMessageImpl(0); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Msg msg = NextMessageImpl(0); +After: + var msg = NextMessageImpl(0); +*/ + + { + var msg = NextMessageImpl(0); + switch (MessageManager.Manage(msg)) + { + case ManageResult.Message: + return msg; + case ManageResult.StatusTerminus: + // if the status applies return null, otherwise it's ignored, fall through + if (expectedPullSubject == null || expectedPullSubject.Equals(msg.Subject)) + { + throw new NATSTimeoutException(); + } + break; + case ManageResult.StatusError: + // if the status applies throw exception, otherwise it's ignored, fall through + if (expectedPullSubject == null || expectedPullSubject.Equals(msg.Subject)) + { + throw new NATSJetStreamStatusException(msg.Status, this); + } + break; } // Check again when, regular messages might have arrived // 1. Any StatusHandled // 2. StatusTerminus or StatusError that aren't for expected pullSubject } } - + internal Msg _nextUnmanaged(int timeout, string expectedPullSubject) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int timeLeft = timeout; + Stopwatch sw = Stopwatch.StartNew(); +After: + var timeLeft = timeout; + var sw = Stopwatch.StartNew(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int timeLeft = timeout; + Stopwatch sw = Stopwatch.StartNew(); +After: + var timeLeft = timeout; + var sw = Stopwatch.StartNew(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int timeLeft = timeout; Stopwatch sw = Stopwatch.StartNew(); +After: + var timeLeft = timeout; + var sw = Stopwatch.StartNew(); +*/ + + { + var timeLeft = timeout; + var sw = Stopwatch.StartNew(); while (timeLeft > 0) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Msg msg = NextMessageImpl(timeLeft); +After: + var msg = NextMessageImpl(timeLeft); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: Msg msg = NextMessageImpl(timeLeft); +After: + var msg = NextMessageImpl(timeLeft); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Msg msg = NextMessageImpl(timeLeft); +After: + var msg = NextMessageImpl(timeLeft); +*/ + + { + var msg = NextMessageImpl(timeLeft); switch (MessageManager.Manage(msg)) { - case ManageResult.Message: - return msg; - case ManageResult.StatusTerminus: - // if the status applies return null, otherwise it's ignored, fall through - if (expectedPullSubject == null || expectedPullSubject.Equals(msg.Subject)) - { - throw new NATSTimeoutException(); - } - break; - case ManageResult.StatusError: - // if the status applies throw exception, otherwise it's ignored, fall through - if (expectedPullSubject == null || expectedPullSubject.Equals(msg.Subject)) - { - throw new NATSJetStreamStatusException(msg.Status, this); - } - break; + case ManageResult.Message: + return msg; + case ManageResult.StatusTerminus: + // if the status applies return null, otherwise it's ignored, fall through + if (expectedPullSubject == null || expectedPullSubject.Equals(msg.Subject)) + { + throw new NATSTimeoutException(); + } + break; + case ManageResult.StatusError: + // if the status applies throw exception, otherwise it's ignored, fall through + if (expectedPullSubject == null || expectedPullSubject.Equals(msg.Subject)) + { + throw new NATSJetStreamStatusException(msg.Status, this); + } + break; } // anything else, try again while we have time timeLeft = timeout - (int)sw.ElapsedMilliseconds; diff --git a/src/NATS.Client/v1/JetStream/JetStreamBase.cs b/src/NATS.Client/v1/JetStream/JetStreamBase.cs index 57d1aee7..572ca02a 100644 --- a/src/NATS.Client/v1/JetStream/JetStreamBase.cs +++ b/src/NATS.Client/v1/JetStream/JetStreamBase.cs @@ -26,7 +26,7 @@ internal class CachedStreamInfo internal CachedStreamInfo(StreamInfo si) { AllowDirect = si.Config.AllowDirect; - } + } } public class JetStreamBase @@ -67,7 +67,7 @@ protected JetStreamBase(IConnection connection, JetStreamOptions options) JetStreamOptions = options ?? JetStreamOptions.DefaultJsOptions; Prefix = JetStreamOptions.Prefix; Timeout = JetStreamOptions.RequestTimeout?.Millis ?? Conn.Opts.Timeout; - + } protected JetStreamBase(JetStreamBase jetStreamBase) @@ -81,52 +81,188 @@ protected JetStreamBase(JetStreamBase jetStreamBase) } internal static ServerInfo ServerInfoOrException(IConnection conn) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + ServerInfo si = conn.ServerInfo; + if (si == null) + { + throw new NATSConnectionClosedException(); + } +After: + var si = conn.ServerInfo ?? throw new NATSConnectionClosedException(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + ServerInfo si = conn.ServerInfo; + if (si == null) + { + throw new NATSConnectionClosedException(); + } +After: + var si = conn.ServerInfo ?? throw new NATSConnectionClosedException(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: ServerInfo si = conn.ServerInfo; if (si == null) { throw new NATSConnectionClosedException(); } +After: + var si = conn.ServerInfo ?? throw new NATSConnectionClosedException(); +*/ + + { + var si = conn.ServerInfo ?? throw new NATSConnectionClosedException(); return si; } - + // ---------------------------------------------------------------------------------------------------- // Management that is also needed by regular context // ---------------------------------------------------------------------------------------------------- - internal ConsumerInfo GetConsumerInfoInternal(string streamName, string consumer) { + internal ConsumerInfo GetConsumerInfoInternal(string streamName, string consumer) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string subj = string.Format(JetStreamConstants.JsapiConsumerInfo, streamName, consumer); +After: + var subj = string.Format(JetStreamConstants.JsapiConsumerInfo, streamName, consumer); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: string subj = string.Format(JetStreamConstants.JsapiConsumerInfo, streamName, consumer); +After: + var subj = string.Format(JetStreamConstants.JsapiConsumerInfo, streamName, consumer); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiConsumerInfo, streamName, consumer); +After: + var subj = string.Format(JetStreamConstants.JsapiConsumerInfo, streamName, consumer); +*/ + + { + var subj = string.Format(JetStreamConstants.JsapiConsumerInfo, streamName, consumer); var m = RequestResponseRequired(subj, null, Timeout); return new ConsumerInfo(m, true); } internal ConsumerInfo CreateConsumerInternal(string streamName, ConsumerConfiguration config, ConsumerCreateRequestAction ccrAction) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string consumerName = Validator.EmptyAsNull(config.Name); +After: + var consumerName = Validator.EmptyAsNull(config.Name); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string consumerName = Validator.EmptyAsNull(config.Name); +After: + var consumerName = Validator.EmptyAsNull(config.Name); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string consumerName = Validator.EmptyAsNull(config.Name); +After: + var consumerName = Validator.EmptyAsNull(config.Name); +*/ + { // ConsumerConfiguration validates that name and durable are the same if both are supplied. - string consumerName = Validator.EmptyAsNull(config.Name); + var consumerName = Validator.EmptyAsNull(config.Name); if (consumerName != null && !ConsumerCreate290Available()) { throw ClientExDetail.JsConsumerCreate290NotAvailable.Instance(); - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + bool hasMultipleFilterSubjects = config.HasMultipleFilterSubjects; +After: + var hasMultipleFilterSubjects = config.HasMultipleFilterSubjects; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + bool hasMultipleFilterSubjects = config.HasMultipleFilterSubjects; +After: + var hasMultipleFilterSubjects = config.HasMultipleFilterSubjects; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: bool hasMultipleFilterSubjects = config.HasMultipleFilterSubjects; - +After: + var hasMultipleFilterSubjects = config.HasMultipleFilterSubjects; +*/ + + } + + var hasMultipleFilterSubjects = config.HasMultipleFilterSubjects; + // seems strange that this could happen, but checking anyway... - if (hasMultipleFilterSubjects && !MultipleSubjectFilter210Available()) { + if (hasMultipleFilterSubjects && !MultipleSubjectFilter210Available()) + { throw ClientExDetail.JsMultipleFilterSubjects210NotAvailable.Instance(); - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string durable = Validator.EmptyAsNull(config.Durable); +After: + var durable = Validator.EmptyAsNull(config.Durable); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string durable = Validator.EmptyAsNull(config.Durable); +After: + var durable = Validator.EmptyAsNull(config.Durable); +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string durable = Validator.EmptyAsNull(config.Durable); +After: + var durable = Validator.EmptyAsNull(config.Durable); +*/ + + } + + var durable = Validator.EmptyAsNull(config.Durable); string subj; if (ConsumerCreate290Available() && !hasMultipleFilterSubjects) { - if (consumerName == null) + if (consumerName == null) { // if both consumerName and durable are null, generate a name consumerName = durable ?? GenerateConsumerName(); - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string fs = config.FilterSubject; // we've already determined not multiple so this gives us 1 or null +After: + var fs = config.FilterSubject; // we've already determined not multiple so this gives us 1 or null +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string fs = config.FilterSubject; // we've already determined not multiple so this gives us 1 or null +After: + var fs = config.FilterSubject; // we've already determined not multiple so this gives us 1 or null +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string fs = config.FilterSubject; // we've already determined not multiple so this gives us 1 or null +After: + var fs = config.FilterSubject; // we've already determined not multiple so this gives us 1 or null +*/ + + } + + var fs = config.FilterSubject; // we've already determined not multiple so this gives us 1 or null if (fs == null || fs.Equals(NatsConstants.GreaterThan)) { subj = string.Format(JetStreamConstants.JsapiConsumerCreateV290, streamName, consumerName); @@ -136,11 +272,11 @@ internal ConsumerInfo CreateConsumerInternal(string streamName, ConsumerConfigur subj = string.Format(JetStreamConstants.JsapiConsumerCreateV290WithFilter, streamName, consumerName, fs); } } - else if (durable == null) + else if (durable == null) { subj = string.Format(JetStreamConstants.JsapiConsumerCreate, streamName); } - else + else { subj = string.Format(JetStreamConstants.JsapiDurableCreate, streamName, durable); } @@ -154,15 +290,36 @@ internal string GenerateConsumerName() { return Nuid.NextGlobalSequence(); } - + internal ConsumerConfiguration ConsumerConfigurationForOrdered( ConsumerConfiguration originalCc, ulong lastStreamSeq, - string newDeliverSubject, + string newDeliverSubject, string consumerName, long? inactiveThreshold) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + ConsumerConfiguration.ConsumerConfigurationBuilder builder = ConsumerConfiguration.Builder(originalCc) +After: + var builder = ConsumerConfiguration.Builder(originalCc) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: ConsumerConfiguration.ConsumerConfigurationBuilder builder = ConsumerConfiguration.Builder(originalCc) +After: + var builder = ConsumerConfiguration.Builder(originalCc) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + ConsumerConfiguration.ConsumerConfigurationBuilder builder = ConsumerConfiguration.Builder(originalCc) +After: + var builder = ConsumerConfiguration.Builder(originalCc) +*/ + + { + var builder = ConsumerConfiguration.Builder(originalCc) .WithDeliverSubject(newDeliverSubject) .WithStartTime(DateTime.MinValue); // clear start time in case it was originally set @@ -171,8 +328,9 @@ internal ConsumerConfiguration ConsumerConfigurationForOrdered( builder.WithDeliverPolicy(DeliverPolicy.ByStartSequence) .WithStartSequence(Math.Max(1, lastStreamSeq + 1)); } - - if (consumerName != null && ConsumerCreate290Available()) { + + if (consumerName != null && ConsumerCreate290Available()) + { builder.WithName(consumerName); } @@ -180,33 +338,81 @@ internal ConsumerConfiguration ConsumerConfigurationForOrdered( { builder.WithInactiveThreshold(inactiveThreshold.Value); } - + return builder.Build(); } internal StreamInfo GetStreamInfoInternal(string streamName, StreamInfoOptions options) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string subj = string.Format(JetStreamConstants.JsapiStreamInfo, streamName); + StreamInfoReader sir = new StreamInfoReader(); + while (sir.HasMore()) + { + Msg resp = RequestResponseRequired(subj, sir.NextJson(options), Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiStreamInfo, streamName); + var sir = new StreamInfoReader(); + while (sir.HasMore()) + { + var resp = RequestResponseRequired(subj, sir.NextJson(options), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: string subj = string.Format(JetStreamConstants.JsapiStreamInfo, streamName); StreamInfoReader sir = new StreamInfoReader(); while (sir.HasMore()) { Msg resp = RequestResponseRequired(subj, sir.NextJson(options), Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiStreamInfo, streamName); + var sir = new StreamInfoReader(); + while (sir.HasMore()) + { + var resp = RequestResponseRequired(subj, sir.NextJson(options), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiStreamInfo, streamName); + StreamInfoReader sir = new StreamInfoReader(); + while (sir.HasMore()) + { + Msg resp = RequestResponseRequired(subj, sir.NextJson(options), Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiStreamInfo, streamName); + var sir = new StreamInfoReader(); + while (sir.HasMore()) + { + var resp = RequestResponseRequired(subj, sir.NextJson(options), Timeout); +*/ + + { + var subj = string.Format(JetStreamConstants.JsapiStreamInfo, streamName); + var sir = new StreamInfoReader(); + while (sir.HasMore()) + { + var resp = RequestResponseRequired(subj, sir.NextJson(options), Timeout); sir.Process(resp); } return CacheStreamInfo(streamName, sir.StreamInfo); } - internal StreamInfo CreateAndCacheStreamInfoThrowOnError(string streamName, Msg resp) { + internal StreamInfo CreateAndCacheStreamInfoThrowOnError(string streamName, Msg resp) + { return CacheStreamInfo(streamName, new StreamInfo(resp, true)); } - internal StreamInfo CacheStreamInfo(string streamName, StreamInfo si) { + internal StreamInfo CacheStreamInfo(string streamName, StreamInfo si) + { cachedStreamInfoDictionary[streamName] = new CachedStreamInfo(si); return si; } - - internal IList CacheStreamInfo(IList list) { - foreach (StreamInfo si in list) + + internal IList CacheStreamInfo(IList list) + { + foreach (var si in list) { cachedStreamInfoDictionary[si.Config.Name] = new CachedStreamInfo(si); } @@ -214,10 +420,53 @@ internal IList CacheStreamInfo(IList list) { } internal IList GetStreamNamesInternal(string subjectFilter) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: StreamNamesReader snr = new StreamNamesReader(); - while (snr.HasMore()) { +After: + var snr = new StreamNamesReader(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + StreamNamesReader snr = new StreamNamesReader(); +After: + var snr = new StreamNamesReader(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + StreamNamesReader snr = new StreamNamesReader(); +After: + var snr = new StreamNamesReader(); +*/ + + { + var snr = new StreamNamesReader(); + while (snr.HasMore()) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Msg m = RequestResponseRequired(JetStreamConstants.JsapiStreamNames, snr.NextJson(subjectFilter), Timeout); +After: + var m = RequestResponseRequired(JetStreamConstants.JsapiStreamNames, snr.NextJson(subjectFilter), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: Msg m = RequestResponseRequired(JetStreamConstants.JsapiStreamNames, snr.NextJson(subjectFilter), Timeout); +After: + var m = RequestResponseRequired(JetStreamConstants.JsapiStreamNames, snr.NextJson(subjectFilter), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Msg m = RequestResponseRequired(JetStreamConstants.JsapiStreamNames, snr.NextJson(subjectFilter), Timeout); +After: + var m = RequestResponseRequired(JetStreamConstants.JsapiStreamNames, snr.NextJson(subjectFilter), Timeout); +*/ + + { + var m = RequestResponseRequired(JetStreamConstants.JsapiStreamNames, snr.NextJson(subjectFilter), Timeout); snr.Process(m); } return snr.Strings; @@ -227,22 +476,53 @@ internal IList GetStreamNamesInternal(string subjectFilter) // Request Utils // ---------------------------------------------------------------------------------------------------- internal string PrependPrefix(string subject) => Prefix + subject; - + public Msg RequestResponseRequired(string subject, byte[] bytes, int timeout) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: Msg msg = Conn.Request(PrependPrefix(subject), bytes, timeout); if (msg == null) { throw new NATSJetStreamException("Timeout or no response waiting for NATS JetStream server"); } +After: + var msg = Conn.Request(PrependPrefix(subject), bytes, timeout) ?? throw new NATSJetStreamException("Timeout or no response waiting for NATS JetStream server"); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Msg msg = Conn.Request(PrependPrefix(subject), bytes, timeout); + if (msg == null) + { + throw new NATSJetStreamException("Timeout or no response waiting for NATS JetStream server"); + } +After: + var msg = Conn.Request(PrependPrefix(subject), bytes, timeout) ?? throw new NATSJetStreamException("Timeout or no response waiting for NATS JetStream server"); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Msg msg = Conn.Request(PrependPrefix(subject), bytes, timeout); + if (msg == null) + { + throw new NATSJetStreamException("Timeout or no response waiting for NATS JetStream server"); + } +After: + var msg = Conn.Request(PrependPrefix(subject), bytes, timeout) ?? throw new NATSJetStreamException("Timeout or no response waiting for NATS JetStream server"); +*/ + + { + var msg = Conn.Request(PrependPrefix(subject), bytes, timeout) ?? throw new NATSJetStreamException("Timeout or no response waiting for NATS JetStream server"); return msg; } - - internal CachedStreamInfo GetCachedStreamInfo(string streamName) { + + internal CachedStreamInfo GetCachedStreamInfo(string streamName) + { CachedStreamInfo csi; cachedStreamInfoDictionary.TryGetValue(streamName, out csi); - if (csi != null) { + if (csi != null) + { return csi; } GetStreamInfoInternal(streamName, null); diff --git a/src/NATS.Client/v1/JetStream/JetStreamManagement.cs b/src/NATS.Client/v1/JetStream/JetStreamManagement.cs index f49ceba2..d1b10f44 100644 --- a/src/NATS.Client/v1/JetStream/JetStreamManagement.cs +++ b/src/NATS.Client/v1/JetStream/JetStreamManagement.cs @@ -21,11 +21,32 @@ public class JetStreamManagement : JetStreamBase, IJetStreamManagement { private IJetStream js; // this is lazy init'ed - internal JetStreamManagement(IConnection connection, JetStreamOptions options) : base(connection, options) {} - + internal JetStreamManagement(IConnection connection, JetStreamOptions options) : base(connection, options) { } + public AccountStatistics GetAccountStatistics() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Msg m = RequestResponseRequired(JetStreamConstants.JsapiAccountInfo, null, Timeout); +After: + var m = RequestResponseRequired(JetStreamConstants.JsapiAccountInfo, null, Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Msg m = RequestResponseRequired(JetStreamConstants.JsapiAccountInfo, null, Timeout); +After: + var m = RequestResponseRequired(JetStreamConstants.JsapiAccountInfo, null, Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: Msg m = RequestResponseRequired(JetStreamConstants.JsapiAccountInfo, null, Timeout); +After: + var m = RequestResponseRequired(JetStreamConstants.JsapiAccountInfo, null, Timeout); +*/ + + { + var m = RequestResponseRequired(JetStreamConstants.JsapiAccountInfo, null, Timeout); return new AccountStatistics(m, true); } @@ -38,21 +59,76 @@ public StreamInfo UpdateStream(StreamConfiguration config) private StreamInfo AddOrUpdateStream(StreamConfiguration config, string addUpdateTemplate) { Validator.ValidateNotNull(config, nameof(config)); - - if (string.IsNullOrWhiteSpace(config.Name)) { + + if (string.IsNullOrWhiteSpace(config.Name)) + { throw new ArgumentException("Configuration must have a valid stream name"); - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string subj = string.Format(addUpdateTemplate, config.Name); + Msg m = RequestResponseRequired(subj, config.Serialize(), Timeout); +After: + var subj = string.Format(addUpdateTemplate, config.Name); + var m = RequestResponseRequired(subj, config.Serialize(), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string subj = string.Format(addUpdateTemplate, config.Name); + Msg m = RequestResponseRequired(subj, config.Serialize(), Timeout); +After: + var subj = string.Format(addUpdateTemplate, config.Name); + var m = RequestResponseRequired(subj, config.Serialize(), Timeout); +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string subj = string.Format(addUpdateTemplate, config.Name); Msg m = RequestResponseRequired(subj, config.Serialize(), Timeout); +After: + var subj = string.Format(addUpdateTemplate, config.Name); + var m = RequestResponseRequired(subj, config.Serialize(), Timeout); +*/ + + } + + var subj = string.Format(addUpdateTemplate, config.Name); + var m = RequestResponseRequired(subj, config.Serialize(), Timeout); return CreateAndCacheStreamInfoThrowOnError(config.Name, m); } - + public bool DeleteStream(string streamName) { Validator.ValidateStreamName(streamName, true); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string subj = string.Format(JetStreamConstants.JsapiStreamDelete, streamName); + Msg m = RequestResponseRequired(subj, null, Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiStreamDelete, streamName); + var m = RequestResponseRequired(subj, null, Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: string subj = string.Format(JetStreamConstants.JsapiStreamDelete, streamName); Msg m = RequestResponseRequired(subj, null, Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiStreamDelete, streamName); + var m = RequestResponseRequired(subj, null, Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiStreamDelete, streamName); + Msg m = RequestResponseRequired(subj, null, Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiStreamDelete, streamName); + var m = RequestResponseRequired(subj, null, Timeout); +*/ + + var subj = string.Format(JetStreamConstants.JsapiStreamDelete, streamName); + var m = RequestResponseRequired(subj, null, Timeout); return new SuccessApiResponse(m, true).Success; } @@ -60,6 +136,393 @@ public StreamInfo GetStreamInfo(string streamName) { Validator.ValidateStreamName(streamName, true); return GetStreamInfoInternal(streamName, null); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string subj = string.Format(JetStreamConstants.JsapiStreamPurge, streamName); + Msg m = RequestResponseRequired(subj, null, Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiStreamPurge, streamName); + var m = RequestResponseRequired(subj, null, Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiStreamPurge, streamName); + Msg m = RequestResponseRequired(subj, null, Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiStreamPurge, streamName); + var m = RequestResponseRequired(subj, null, Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiStreamPurge, streamName); + Msg m = RequestResponseRequired(subj, null, Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiStreamPurge, streamName); + var m = RequestResponseRequired(subj, null, Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string subj = string.Format(JetStreamConstants.JsapiStreamPurge, streamName); + Msg m = RequestResponseRequired(subj, options.Serialize(), Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiStreamPurge, streamName); + var m = RequestResponseRequired(subj, options.Serialize(), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiStreamPurge, streamName); + Msg m = RequestResponseRequired(subj, options.Serialize(), Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiStreamPurge, streamName); + var m = RequestResponseRequired(subj, options.Serialize(), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiStreamPurge, streamName); + Msg m = RequestResponseRequired(subj, options.Serialize(), Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiStreamPurge, streamName); + var m = RequestResponseRequired(subj, options.Serialize(), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string subj = string.Format(JetStreamConstants.JsapiConsumerDelete, streamName, consumer); + Msg m = RequestResponseRequired(subj, null, Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiConsumerDelete, streamName, consumer); + var m = RequestResponseRequired(subj, null, Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiConsumerDelete, streamName, consumer); + Msg m = RequestResponseRequired(subj, null, Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiConsumerDelete, streamName, consumer); + var m = RequestResponseRequired(subj, null, Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiConsumerDelete, streamName, consumer); + Msg m = RequestResponseRequired(subj, null, Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiConsumerDelete, streamName, consumer); + var m = RequestResponseRequired(subj, null, Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string subj = string.Format(JetStreamConstants.JsapiConsumerPause, streamName, consumer); + ConsumerPauseRequest cprq = new ConsumerPauseRequest(pauseUntil); + Msg m = RequestResponseRequired(subj, cprq.Serialize(), Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiConsumerPause, streamName, consumer); + var cprq = new ConsumerPauseRequest(pauseUntil); + var m = RequestResponseRequired(subj, cprq.Serialize(), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiConsumerPause, streamName, consumer); + ConsumerPauseRequest cprq = new ConsumerPauseRequest(pauseUntil); + Msg m = RequestResponseRequired(subj, cprq.Serialize(), Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiConsumerPause, streamName, consumer); + var cprq = new ConsumerPauseRequest(pauseUntil); + var m = RequestResponseRequired(subj, cprq.Serialize(), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiConsumerPause, streamName, consumer); + ConsumerPauseRequest cprq = new ConsumerPauseRequest(pauseUntil); + Msg m = RequestResponseRequired(subj, cprq.Serialize(), Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiConsumerPause, streamName, consumer); + var cprq = new ConsumerPauseRequest(pauseUntil); + var m = RequestResponseRequired(subj, cprq.Serialize(), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string subj = string.Format(JetStreamConstants.JsapiConsumerPause, streamName, consumer); + Msg m = RequestResponseRequired(subj, null, Timeout); + ConsumerPauseResponse cpre = new ConsumerPauseResponse(m, true); +After: + var subj = string.Format(JetStreamConstants.JsapiConsumerPause, streamName, consumer); + var m = RequestResponseRequired(subj, null, Timeout); + var cpre = new ConsumerPauseResponse(m, true); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiConsumerPause, streamName, consumer); + Msg m = RequestResponseRequired(subj, null, Timeout); + ConsumerPauseResponse cpre = new ConsumerPauseResponse(m, true); +After: + var subj = string.Format(JetStreamConstants.JsapiConsumerPause, streamName, consumer); + var m = RequestResponseRequired(subj, null, Timeout); + var cpre = new ConsumerPauseResponse(m, true); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiConsumerPause, streamName, consumer); + Msg m = RequestResponseRequired(subj, null, Timeout); + ConsumerPauseResponse cpre = new ConsumerPauseResponse(m, true); +After: + var subj = string.Format(JetStreamConstants.JsapiConsumerPause, streamName, consumer); + var m = RequestResponseRequired(subj, null, Timeout); + var cpre = new ConsumerPauseResponse(m, true); +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + ConsumerNamesReader cnr = new ConsumerNamesReader(); +After: + var cnr = new ConsumerNamesReader(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + ConsumerNamesReader cnr = new ConsumerNamesReader(); +After: + var cnr = new ConsumerNamesReader(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + ConsumerNamesReader cnr = new ConsumerNamesReader(); +After: + var cnr = new ConsumerNamesReader(); +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string subj = string.Format(JetStreamConstants.JsapiConsumerNames, streamName); + Msg m = RequestResponseRequired(subj, cnr.NextJson(), Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiConsumerNames, streamName); + var m = RequestResponseRequired(subj, cnr.NextJson(), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiConsumerNames, streamName); + Msg m = RequestResponseRequired(subj, cnr.NextJson(), Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiConsumerNames, streamName); + var m = RequestResponseRequired(subj, cnr.NextJson(), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiConsumerNames, streamName); + Msg m = RequestResponseRequired(subj, cnr.NextJson(), Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiConsumerNames, streamName); + var m = RequestResponseRequired(subj, cnr.NextJson(), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + ConsumerListReader clr = new ConsumerListReader(); +After: + var clr = new ConsumerListReader(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + ConsumerListReader clr = new ConsumerListReader(); +After: + var clr = new ConsumerListReader(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + ConsumerListReader clr = new ConsumerListReader(); +After: + var clr = new ConsumerListReader(); +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string subj = string.Format(JetStreamConstants.JsapiConsumerList, streamName); + Msg m = RequestResponseRequired(subj, clr.NextJson(), Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiConsumerList, streamName); + var m = RequestResponseRequired(subj, clr.NextJson(), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiConsumerList, streamName); + Msg m = RequestResponseRequired(subj, clr.NextJson(), Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiConsumerList, streamName); + var m = RequestResponseRequired(subj, clr.NextJson(), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiConsumerList, streamName); + Msg m = RequestResponseRequired(subj, clr.NextJson(), Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiConsumerList, streamName); + var m = RequestResponseRequired(subj, clr.NextJson(), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + StreamListReader slr = new StreamListReader(); +After: + var slr = new StreamListReader(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + StreamListReader slr = new StreamListReader(); +After: + var slr = new StreamListReader(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + StreamListReader slr = new StreamListReader(); +After: + var slr = new StreamListReader(); +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Msg m = RequestResponseRequired(JetStreamConstants.JsapiStreamList, slr.NextJson(subjectFilter), Timeout); +After: + var m = RequestResponseRequired(JetStreamConstants.JsapiStreamList, slr.NextJson(subjectFilter), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Msg m = RequestResponseRequired(JetStreamConstants.JsapiStreamList, slr.NextJson(subjectFilter), Timeout); +After: + var m = RequestResponseRequired(JetStreamConstants.JsapiStreamList, slr.NextJson(subjectFilter), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Msg m = RequestResponseRequired(JetStreamConstants.JsapiStreamList, slr.NextJson(subjectFilter), Timeout); +After: + var m = RequestResponseRequired(JetStreamConstants.JsapiStreamList, slr.NextJson(subjectFilter), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + CachedStreamInfo csi = GetCachedStreamInfo(streamName); +After: + var csi = GetCachedStreamInfo(streamName); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + CachedStreamInfo csi = GetCachedStreamInfo(streamName); +After: + var csi = GetCachedStreamInfo(streamName); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + CachedStreamInfo csi = GetCachedStreamInfo(streamName); +After: + var csi = GetCachedStreamInfo(streamName); +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Msg resp = RequestResponseRequired(subj, payload, Timeout); +After: + var resp = RequestResponseRequired(subj, payload, Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Msg resp = RequestResponseRequired(subj, payload, Timeout); +After: + var resp = RequestResponseRequired(subj, payload, Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Msg resp = RequestResponseRequired(subj, payload, Timeout); +After: + var resp = RequestResponseRequired(subj, payload, Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string subj = string.Format(JetStreamConstants.JsapiMsgGet, streamName); + Msg m = RequestResponseRequired(subj, messageGetRequest.Serialize(), Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiMsgGet, streamName); + var m = RequestResponseRequired(subj, messageGetRequest.Serialize(), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiMsgGet, streamName); + Msg m = RequestResponseRequired(subj, messageGetRequest.Serialize(), Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiMsgGet, streamName); + var m = RequestResponseRequired(subj, messageGetRequest.Serialize(), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiMsgGet, streamName); + Msg m = RequestResponseRequired(subj, messageGetRequest.Serialize(), Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiMsgGet, streamName); + var m = RequestResponseRequired(subj, messageGetRequest.Serialize(), Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string subj = string.Format(JetStreamConstants.JsapiMsgDelete, streamName); + byte[] mdr = new MessageDeleteRequest(sequence, erase).Serialize(); + Msg m = RequestResponseRequired(subj, mdr, Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiMsgDelete, streamName); + var mdr = new MessageDeleteRequest(sequence, erase).Serialize(); + var m = RequestResponseRequired(subj, mdr, Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiMsgDelete, streamName); + byte[] mdr = new MessageDeleteRequest(sequence, erase).Serialize(); + Msg m = RequestResponseRequired(subj, mdr, Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiMsgDelete, streamName); + var mdr = new MessageDeleteRequest(sequence, erase).Serialize(); + var m = RequestResponseRequired(subj, mdr, Timeout); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string subj = string.Format(JetStreamConstants.JsapiMsgDelete, streamName); + byte[] mdr = new MessageDeleteRequest(sequence, erase).Serialize(); + Msg m = RequestResponseRequired(subj, mdr, Timeout); +After: + var subj = string.Format(JetStreamConstants.JsapiMsgDelete, streamName); + var mdr = new MessageDeleteRequest(sequence, erase).Serialize(); + var m = RequestResponseRequired(subj, mdr, Timeout); +*/ + } public StreamInfo GetStreamInfo(string streamName, StreamInfoOptions options) @@ -71,8 +534,8 @@ public StreamInfo GetStreamInfo(string streamName, StreamInfoOptions options) public PurgeResponse PurgeStream(string streamName) { Validator.ValidateStreamName(streamName, true); - string subj = string.Format(JetStreamConstants.JsapiStreamPurge, streamName); - Msg m = RequestResponseRequired(subj, null, Timeout); + var subj = string.Format(JetStreamConstants.JsapiStreamPurge, streamName); + var m = RequestResponseRequired(subj, null, Timeout); return new PurgeResponse(m, true); } @@ -80,8 +543,8 @@ public PurgeResponse PurgeStream(string streamName, PurgeOptions options) { Validator.ValidateStreamName(streamName, true); Validator.ValidateNotNull(options, nameof(options)); - string subj = string.Format(JetStreamConstants.JsapiStreamPurge, streamName); - Msg m = RequestResponseRequired(subj, options.Serialize(), Timeout); + var subj = string.Format(JetStreamConstants.JsapiStreamPurge, streamName); + var m = RequestResponseRequired(subj, options.Serialize(), Timeout); return new PurgeResponse(m, true); } @@ -110,8 +573,8 @@ public bool DeleteConsumer(string streamName, string consumer) { Validator.ValidateStreamName(streamName, true); Validator.ValidateNotNull(consumer, nameof(consumer)); - string subj = string.Format(JetStreamConstants.JsapiConsumerDelete, streamName, consumer); - Msg m = RequestResponseRequired(subj, null, Timeout); + var subj = string.Format(JetStreamConstants.JsapiConsumerDelete, streamName, consumer); + var m = RequestResponseRequired(subj, null, Timeout); return new SuccessApiResponse(m, true).Success; } @@ -119,9 +582,9 @@ public ConsumerPauseResponse PauseConsumer(string streamName, string consumer, D { Validator.ValidateStreamName(streamName, true); Validator.ValidateNotNull(consumer, nameof(consumer)); - string subj = string.Format(JetStreamConstants.JsapiConsumerPause, streamName, consumer); - ConsumerPauseRequest cprq = new ConsumerPauseRequest(pauseUntil); - Msg m = RequestResponseRequired(subj, cprq.Serialize(), Timeout); + var subj = string.Format(JetStreamConstants.JsapiConsumerPause, streamName, consumer); + var cprq = new ConsumerPauseRequest(pauseUntil); + var m = RequestResponseRequired(subj, cprq.Serialize(), Timeout); return new ConsumerPauseResponse(m, true); } @@ -129,9 +592,9 @@ public bool ResumeConsumer(string streamName, string consumer) { Validator.ValidateStreamName(streamName, true); Validator.ValidateNotNull(consumer, nameof(consumer)); - string subj = string.Format(JetStreamConstants.JsapiConsumerPause, streamName, consumer); - Msg m = RequestResponseRequired(subj, null, Timeout); - ConsumerPauseResponse cpre = new ConsumerPauseResponse(m, true); + var subj = string.Format(JetStreamConstants.JsapiConsumerPause, streamName, consumer); + var m = RequestResponseRequired(subj, null, Timeout); + var cpre = new ConsumerPauseResponse(m, true); return !cpre.Paused; } @@ -144,10 +607,11 @@ public ConsumerInfo GetConsumerInfo(string streamName, string consumer) public IList GetConsumerNames(string streamName) { - ConsumerNamesReader cnr = new ConsumerNamesReader(); - while (cnr.HasMore()) { - string subj = string.Format(JetStreamConstants.JsapiConsumerNames, streamName); - Msg m = RequestResponseRequired(subj, cnr.NextJson(), Timeout); + var cnr = new ConsumerNamesReader(); + while (cnr.HasMore()) + { + var subj = string.Format(JetStreamConstants.JsapiConsumerNames, streamName); + var m = RequestResponseRequired(subj, cnr.NextJson(), Timeout); cnr.Process(m); } return cnr.Strings; @@ -155,10 +619,11 @@ public IList GetConsumerNames(string streamName) public IList GetConsumers(string streamName) { - ConsumerListReader clr = new ConsumerListReader(); - while (clr.HasMore()) { - string subj = string.Format(JetStreamConstants.JsapiConsumerList, streamName); - Msg m = RequestResponseRequired(subj, clr.NextJson(), Timeout); + var clr = new ConsumerListReader(); + while (clr.HasMore()) + { + var subj = string.Format(JetStreamConstants.JsapiConsumerList, streamName); + var m = RequestResponseRequired(subj, clr.NextJson(), Timeout); clr.Process(m); } return clr.Consumers; @@ -181,9 +646,10 @@ public IList GetStreams() public IList GetStreams(string subjectFilter) { - StreamListReader slr = new StreamListReader(); - while (slr.HasMore()) { - Msg m = RequestResponseRequired(JetStreamConstants.JsapiStreamList, slr.NextJson(subjectFilter), Timeout); + var slr = new StreamListReader(); + while (slr.HasMore()) + { + var m = RequestResponseRequired(JetStreamConstants.JsapiStreamList, slr.NextJson(subjectFilter), Timeout); slr.Process(m); } return CacheStreamInfo(slr.Streams); @@ -212,27 +678,32 @@ public MessageInfo GetNextMessage(string streamName, ulong sequence, string subj internal MessageInfo _GetMessage(string streamName, MessageGetRequest messageGetRequest) { Validator.ValidateStreamName(streamName, true); - CachedStreamInfo csi = GetCachedStreamInfo(streamName); - if (csi.AllowDirect) { + var csi = GetCachedStreamInfo(streamName); + if (csi.AllowDirect) + { string subj; byte[] payload; - if (messageGetRequest.IsLastBySubject) { + if (messageGetRequest.IsLastBySubject) + { subj = string.Format(JetStreamConstants.JsapiDirectGetLast, streamName, messageGetRequest.LastBySubject); payload = null; } - else { + else + { subj = string.Format(JetStreamConstants.JsapiDirectGet, streamName); payload = messageGetRequest.Serialize(); } - Msg resp = RequestResponseRequired(subj, payload, Timeout); - if (resp.HasStatus) { + var resp = RequestResponseRequired(subj, payload, Timeout); + if (resp.HasStatus) + { throw new NATSJetStreamException(Error.Convert(resp.Status)); } return new MessageInfo(resp, streamName, true, true); } - else { - string subj = string.Format(JetStreamConstants.JsapiMsgGet, streamName); - Msg m = RequestResponseRequired(subj, messageGetRequest.Serialize(), Timeout); + else + { + var subj = string.Format(JetStreamConstants.JsapiMsgGet, streamName); + var m = RequestResponseRequired(subj, messageGetRequest.Serialize(), Timeout); return new MessageInfo(m, streamName, false, true); } } @@ -245,9 +716,9 @@ public bool DeleteMessage(string streamName, ulong sequence) public bool DeleteMessage(string streamName, ulong sequence, bool erase) { Validator.ValidateStreamName(streamName, true); - string subj = string.Format(JetStreamConstants.JsapiMsgDelete, streamName); - byte[] mdr = new MessageDeleteRequest(sequence, erase).Serialize(); - Msg m = RequestResponseRequired(subj, mdr, Timeout); + var subj = string.Format(JetStreamConstants.JsapiMsgDelete, streamName); + var mdr = new MessageDeleteRequest(sequence, erase).Serialize(); + var m = RequestResponseRequired(subj, mdr, Timeout); return new SuccessApiResponse(m, true).Success; } diff --git a/src/NATS.Client/v1/JetStream/JetStreamMsg.cs b/src/NATS.Client/v1/JetStream/JetStreamMsg.cs index 20a5c3f1..398b52dc 100644 --- a/src/NATS.Client/v1/JetStream/JetStreamMsg.cs +++ b/src/NATS.Client/v1/JetStream/JetStreamMsg.cs @@ -27,7 +27,7 @@ public sealed class JetStreamMsg : Msg private IConnection Connection { get; } // Take the reply and parse it into the metadata. - internal JetStreamMsg(IConnection conn, MsgArg arg, Subscription s, byte[] payload, long totalLen) : + internal JetStreamMsg(IConnection conn, MsgArg arg, Subscription s, byte[] payload, long totalLen) : base(arg, s, payload, totalLen) { Connection = conn; @@ -52,7 +52,8 @@ private void AckReply(AckType ackType, long delayNanoseconds, int timeout) } } - private bool AckHasntBeenTermed() { + private bool AckHasntBeenTermed() + { return _lastAck == null || !_lastAck.IsTerminal; } @@ -70,7 +71,7 @@ private bool AckHasntBeenTermed() { /// the duration to wait for an ack in milliseconds /// confirmation public override void AckSync(int timeout) => AckReply(AckAck, -1, timeout); - + /// /// Acknowledges a JetStream message has been received but indicates /// that the message is not completely processed and should be sent @@ -126,22 +127,22 @@ public sealed class MetaData /// /// Gets the prefix. /// - public string Prefix { get; } + public string Prefix { get; } /// /// Gets the stream name. /// - public string Stream { get; } + public string Stream { get; } /// /// Gets the domain name. /// - public string Domain { get; } + public string Domain { get; } /// /// Gets the consumer name. /// - public string Consumer { get; } + public string Consumer { get; } /// /// Number of delivered messages @@ -171,19 +172,40 @@ public sealed class MetaData /// /// Number of pending messages /// - public ulong NumPending { get; } + public ulong NumPending { get; } - internal string AccountHash { get; } + internal string AccountHash { get; } // Caller must ensure this is a JS message internal MetaData(string metaData) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string[] parts = metaData?.Split('.'); +After: + var parts = metaData?.Split('.'); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: string[] parts = metaData?.Split('.'); +After: + var parts = metaData?.Split('.'); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string[] parts = metaData?.Split('.'); +After: + var parts = metaData?.Split('.'); +*/ + + { + var parts = metaData?.Split('.'); if (parts == null || parts.Length < 8 || !"ACK".Equals(parts?[1])) { throw new NATSException($"Invalid MetaData: {metaData}"); } - + int streamIndex; bool hasPending; bool hasDomainAndHash; diff --git a/src/NATS.Client/v1/JetStream/JetStreamOptions.cs b/src/NATS.Client/v1/JetStream/JetStreamOptions.cs index 7d8c5ec5..5353599d 100644 --- a/src/NATS.Client/v1/JetStream/JetStreamOptions.cs +++ b/src/NATS.Client/v1/JetStream/JetStreamOptions.cs @@ -23,16 +23,18 @@ public sealed class JetStreamOptions { [Obsolete("This property is obsolete. The connection options request timeout is used as the default", false)] public static readonly Duration DefaultTimeout = Duration.OfMillis(Defaults.Timeout); - + public static readonly JetStreamOptions DefaultJsOptions = Builder().Build(); private JetStreamOptions(JetStreamOptionsBuilder b) { - if (b._jsPrefix == null) { + if (b._jsPrefix == null) + { IsDefaultPrefix = true; Prefix = DefaultApiPrefix; } - else { + else + { IsDefaultPrefix = false; Prefix = b._jsPrefix; } @@ -51,25 +53,47 @@ private JetStreamOptions(JetStreamOptionsBuilder b) /// Gets the request timeout /// public Duration RequestTimeout { get; } - + /// /// Gets is publish should be done in no ack (core) style /// public bool IsPublishNoAck { get; } - + /// /// True if the prefix for this options is the default prefix. /// public bool IsDefaultPrefix { get; } - + /// /// Gets whether the opt-out of the server v2.9.0 consumer create api is set /// public bool IsOptOut290ConsumerCreate { get; } - - internal static string ConvertDomainToPrefix(string domain) { + + internal static string ConvertDomainToPrefix(string domain) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string valid = ValidatePrefixOrDomain(domain, "Domain", false); +After: + var valid = ValidatePrefixOrDomain(domain, "Domain", false); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string valid = ValidatePrefixOrDomain(domain, "Domain", false); +After: + var valid = ValidatePrefixOrDomain(domain, "Domain", false); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string valid = ValidatePrefixOrDomain(domain, "Domain", false); - return valid == null ? null +After: + var valid = ValidatePrefixOrDomain(domain, "Domain", false); +*/ + + { + var valid = ValidatePrefixOrDomain(domain, "Domain", false); + return valid == null ? null : PrefixDollarJsDot + EnsureEndsWithDot(valid) + PrefixApi; } @@ -83,7 +107,7 @@ public static JetStreamOptionsBuilder Builder() { return new JetStreamOptionsBuilder(); } - + /// /// Gets the JetStreamOptions builder based on an existing JetStreamOptions object. /// @@ -104,13 +128,13 @@ public sealed class JetStreamOptionsBuilder /// /// Construct a builder /// - public JetStreamOptionsBuilder() {} + public JetStreamOptionsBuilder() { } /// /// Construct a builder from an existing JetStreamOptions object /// /// an existing JetStreamOptions object - public JetStreamOptionsBuilder(JetStreamOptions jso) + public JetStreamOptionsBuilder(JetStreamOptions jso) { if (jso != null) { @@ -128,7 +152,7 @@ public JetStreamOptionsBuilder(JetStreamOptions jso) _optOut290ConsumerCreate = jso.IsOptOut290ConsumerCreate; } } - + /// /// Sets the prefix for JetStream subjects. A prefix can be used in conjunction with /// user permissions to restrict access to certain JetStream instances. This must @@ -136,12 +160,12 @@ public JetStreamOptionsBuilder(JetStreamOptions jso) /// /// The prefix. /// The JetStreamOptionsBuilder - public JetStreamOptionsBuilder WithPrefix(string prefix) + public JetStreamOptionsBuilder WithPrefix(string prefix) { _jsPrefix = EnsureEndsWithDot(ValidatePrefixOrDomain(prefix, "Prefix", false)); return this; } - + /// /// Sets the domain for JetStream subjects. A domain can be used in conjunction with /// user permissions to restrict access to certain JetStream instances. This must @@ -149,9 +173,51 @@ public JetStreamOptionsBuilder WithPrefix(string prefix) /// /// The domain. /// The JetStreamOptionsBuilder - public JetStreamOptionsBuilder WithDomain(string domain) - { + public JetStreamOptionsBuilder WithDomain(string domain) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string prefix = ConvertDomainToPrefix(domain); +After: + var prefix = ConvertDomainToPrefix(domain); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string prefix = ConvertDomainToPrefix(domain); +After: + var prefix = ConvertDomainToPrefix(domain); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string prefix = ConvertDomainToPrefix(domain); +After: + var prefix = ConvertDomainToPrefix(domain); +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this._optOut290ConsumerCreate = optOut; +After: + _optOut290ConsumerCreate = optOut; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this._optOut290ConsumerCreate = optOut; +After: + _optOut290ConsumerCreate = optOut; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this._optOut290ConsumerCreate = optOut; +After: + _optOut290ConsumerCreate = optOut; +*/ + + { + var prefix = ConvertDomainToPrefix(domain); _jsPrefix = prefix == null ? null : prefix + Dot; return this; } @@ -193,8 +259,9 @@ public JetStreamOptionsBuilder WithPublishNoAck(bool publishNoAck) /// /// /// The JetStreamOptionsBuilder - public JetStreamOptionsBuilder WithOptOut290ConsumerCreate(bool optOut) { - this._optOut290ConsumerCreate = optOut; + public JetStreamOptionsBuilder WithOptOut290ConsumerCreate(bool optOut) + { + _optOut290ConsumerCreate = optOut; return this; } diff --git a/src/NATS.Client/v1/JetStream/JetStreamPullApiImpl.cs b/src/NATS.Client/v1/JetStream/JetStreamPullApiImpl.cs index edb70c4b..b97c73ee 100644 --- a/src/NATS.Client/v1/JetStream/JetStreamPullApiImpl.cs +++ b/src/NATS.Client/v1/JetStream/JetStreamPullApiImpl.cs @@ -25,7 +25,7 @@ internal class JetStreamPullApiImpl private readonly string _subject; private string _consumer; - internal JetStreamPullApiImpl(Connection conn, JetStream js, MessageManager messageManager, + internal JetStreamPullApiImpl(Connection conn, JetStream js, MessageManager messageManager, string stream, string subject, string consumer) { _pullSubjectIdHolder = new InterlockedLong(); @@ -41,11 +41,39 @@ internal void UpdateConsumer(string consumer) { _consumer = consumer; } - - internal string Pull(PullRequestOptions pullRequestOptions, bool raiseStatusWarnings, IPullManagerObserver pullManagerObserver) { + + internal string Pull(PullRequestOptions pullRequestOptions, bool raiseStatusWarnings, IPullManagerObserver pullManagerObserver) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: string publishSubject = _js.PrependPrefix(string.Format(JetStreamConstants.JsapiConsumerMsgNext, _stream, _consumer)); string pullSubject = _subject.Replace("*", _pullSubjectIdHolder.Increment().ToString()); - _mm.StartPullRequest(pullSubject, pullRequestOptions, raiseStatusWarnings, pullManagerObserver); +After: + var publishSubject = _js.PrependPrefix(string.Format(JetStreamConstants.JsapiConsumerMsgNext, _stream, _consumer)); + var pullSubject = _subject.Replace("*", _pullSubjectIdHolder.Increment().ToString()); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string publishSubject = _js.PrependPrefix(string.Format(JetStreamConstants.JsapiConsumerMsgNext, _stream, _consumer)); + string pullSubject = _subject.Replace("*", _pullSubjectIdHolder.Increment().ToString()); +After: + var publishSubject = _js.PrependPrefix(string.Format(JetStreamConstants.JsapiConsumerMsgNext, _stream, _consumer)); + var pullSubject = _subject.Replace("*", _pullSubjectIdHolder.Increment().ToString()); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string publishSubject = _js.PrependPrefix(string.Format(JetStreamConstants.JsapiConsumerMsgNext, _stream, _consumer)); + string pullSubject = _subject.Replace("*", _pullSubjectIdHolder.Increment().ToString()); +After: + var publishSubject = _js.PrependPrefix(string.Format(JetStreamConstants.JsapiConsumerMsgNext, _stream, _consumer)); + var pullSubject = _subject.Replace("*", _pullSubjectIdHolder.Increment().ToString()); +*/ + + { + var publishSubject = _js.PrependPrefix(string.Format(JetStreamConstants.JsapiConsumerMsgNext, _stream, _consumer)); + var pullSubject = _subject.Replace("*", _pullSubjectIdHolder.Increment().ToString()); + _mm.StartPullRequest(pullSubject, pullRequestOptions, raiseStatusWarnings, pullManagerObserver); _conn.Publish(publishSubject, pullSubject, pullRequestOptions.Serialize()); return pullSubject; } diff --git a/src/NATS.Client/v1/JetStream/JetStreamPullAsyncSubscription.cs b/src/NATS.Client/v1/JetStream/JetStreamPullAsyncSubscription.cs index 6a56c7a5..0f40f9e0 100644 --- a/src/NATS.Client/v1/JetStream/JetStreamPullAsyncSubscription.cs +++ b/src/NATS.Client/v1/JetStream/JetStreamPullAsyncSubscription.cs @@ -1,4 +1,4 @@ -// Copyright 2023 The NATS Authors +// Copyright 2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -31,7 +31,7 @@ internal override void SetConsumerName(string consumer) base.SetConsumerName(consumer); pullImpl.UpdateConsumer(consumer); } - + public bool IsPullMode() => true; public void Pull(int batchSize) @@ -39,7 +39,8 @@ public void Pull(int batchSize) pullImpl.Pull(PullRequestOptions.Builder(batchSize).Build(), true, null); } - public void Pull(PullRequestOptions pullRequestOptions) { + public void Pull(PullRequestOptions pullRequestOptions) + { pullImpl.Pull(pullRequestOptions, true, null); } diff --git a/src/NATS.Client/v1/JetStream/JetStreamPullSubscription.cs b/src/NATS.Client/v1/JetStream/JetStreamPullSubscription.cs index d5913c17..85ceae3d 100644 --- a/src/NATS.Client/v1/JetStream/JetStreamPullSubscription.cs +++ b/src/NATS.Client/v1/JetStream/JetStreamPullSubscription.cs @@ -34,7 +34,7 @@ internal override void SetConsumerName(string consumer) base.SetConsumerName(consumer); pullImpl.UpdateConsumer(consumer); } - + public bool IsPullMode() => true; public void Pull(int batchSize) @@ -42,7 +42,8 @@ public void Pull(int batchSize) pullImpl.Pull(PullRequestOptions.Builder(batchSize).Build(), true, null); } - public void Pull(PullRequestOptions pullRequestOptions) { + public void Pull(PullRequestOptions pullRequestOptions) + { pullImpl.Pull(pullRequestOptions, true, null); } @@ -71,6 +72,82 @@ public IList Fetch(int batchSize, int maxWaitMillis) Validator.ValidateDurationGtZeroRequired(maxWaitMillis, "Fetch"); IList messages = new List(); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int batchLeft = batchSize; + + Stopwatch sw = Stopwatch.StartNew(); + + Duration expires = Duration.OfMillis( + maxWaitMillis > ExpireAdjustment ? maxWaitMillis - ExpireAdjustment : maxWaitMillis); + string pullSubject = pullImpl.Pull(PullRequestOptions.Builder(batchLeft).WithExpiresIn(expires).Build(), false, null); + + try + { + // timeout > 0 process as many messages we can in that time period + // If we get a message that either manager handles, we try again, but + // with a shorter timeout based on what we already used up + int timeLeft = maxWaitMillis; + while (batchLeft > 0 && timeLeft > 0) { + Msg msg = NextMessageImpl(timeLeft); +After: + var batchLeft = batchSize; + + var sw = Stopwatch.StartNew(); + + var expires = Duration.OfMillis( + maxWaitMillis > ExpireAdjustment ? maxWaitMillis - ExpireAdjustment : maxWaitMillis); + var pullSubject = pullImpl.Pull(PullRequestOptions.Builder(batchLeft).WithExpiresIn(expires).Build(), false, null); + + try + { + // timeout > 0 process as many messages we can in that time period + // If we get a message that either manager handles, we try again, but + // with a shorter timeout based on what we already used up + var timeLeft = maxWaitMillis; + while (batchLeft > 0 && timeLeft > 0) { + var msg = NextMessageImpl(timeLeft); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int batchLeft = batchSize; + + Stopwatch sw = Stopwatch.StartNew(); + + Duration expires = Duration.OfMillis( + maxWaitMillis > ExpireAdjustment ? maxWaitMillis - ExpireAdjustment : maxWaitMillis); + string pullSubject = pullImpl.Pull(PullRequestOptions.Builder(batchLeft).WithExpiresIn(expires).Build(), false, null); + + try + { + // timeout > 0 process as many messages we can in that time period + // If we get a message that either manager handles, we try again, but + // with a shorter timeout based on what we already used up + int timeLeft = maxWaitMillis; + while (batchLeft > 0 && timeLeft > 0) { + Msg msg = NextMessageImpl(timeLeft); +After: + var batchLeft = batchSize; + + var sw = Stopwatch.StartNew(); + + var expires = Duration.OfMillis( + maxWaitMillis > ExpireAdjustment ? maxWaitMillis - ExpireAdjustment : maxWaitMillis); + var pullSubject = pullImpl.Pull(PullRequestOptions.Builder(batchLeft).WithExpiresIn(expires).Build(), false, null); + + try + { + // timeout > 0 process as many messages we can in that time period + // If we get a message that either manager handles, we try again, but + // with a shorter timeout based on what we already used up + var timeLeft = maxWaitMillis; + while (batchLeft > 0 && timeLeft > 0) { + var msg = NextMessageImpl(timeLeft); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int batchLeft = batchSize; Stopwatch sw = Stopwatch.StartNew(); @@ -87,30 +164,66 @@ public IList Fetch(int batchSize, int maxWaitMillis) int timeLeft = maxWaitMillis; while (batchLeft > 0 && timeLeft > 0) { Msg msg = NextMessageImpl(timeLeft); +After: + var batchLeft = batchSize; + + var sw = Stopwatch.StartNew(); + + var expires = Duration.OfMillis( + maxWaitMillis > ExpireAdjustment ? maxWaitMillis - ExpireAdjustment : maxWaitMillis); + var pullSubject = pullImpl.Pull(PullRequestOptions.Builder(batchLeft).WithExpiresIn(expires).Build(), false, null); + + try + { + // timeout > 0 process as many messages we can in that time period + // If we get a message that either manager handles, we try again, but + // with a shorter timeout based on what we already used up + var timeLeft = maxWaitMillis; + while (batchLeft > 0 && timeLeft > 0) { + var msg = NextMessageImpl(timeLeft); +*/ + + var batchLeft = batchSize; + + var sw = Stopwatch.StartNew(); + + var expires = Duration.OfMillis( + maxWaitMillis > ExpireAdjustment ? maxWaitMillis - ExpireAdjustment : maxWaitMillis); + var pullSubject = pullImpl.Pull(PullRequestOptions.Builder(batchLeft).WithExpiresIn(expires).Build(), false, null); + + try + { + // timeout > 0 process as many messages we can in that time period + // If we get a message that either manager handles, we try again, but + // with a shorter timeout based on what we already used up + var timeLeft = maxWaitMillis; + while (batchLeft > 0 && timeLeft > 0) + { + var msg = NextMessageImpl(timeLeft); if (msg == null) { return messages; } switch (MessageManager.Manage(msg)) { - case ManageResult.Message: - messages.Add(msg); - batchLeft--; - break; - case ManageResult.StatusTerminus: - // if the status applies return null, otherwise it's ignored, fall through - if (pullSubject.Equals(msg.Subject)) - { - return messages; - } - break; - case ManageResult.StatusError: - // if the status applies throw exception, otherwise it's ignored, fall through - if (pullSubject.Equals(msg.Subject)) - { - throw new NATSJetStreamStatusException(msg.Status, this); - } - break; + case ManageResult.Message: + messages.Add(msg); + batchLeft--; + break; + case ManageResult.StatusTerminus: + // if the status applies return null, otherwise it's ignored, fall through + if (pullSubject.Equals(msg.Subject)) + { + return messages; + } + break; + case ManageResult.StatusError: + // if the status applies throw exception, otherwise it's ignored, fall through + if (pullSubject.Equals(msg.Subject)) + { + throw new NATSJetStreamStatusException(msg.Status, this); + } + break; } // case STATUS, try again while we have time timeLeft = maxWaitMillis - (int)sw.ElapsedMilliseconds; diff --git a/src/NATS.Client/v1/JetStream/JetStreamPushAsyncSubscription.cs b/src/NATS.Client/v1/JetStream/JetStreamPushAsyncSubscription.cs index 950598f1..99263a99 100644 --- a/src/NATS.Client/v1/JetStream/JetStreamPushAsyncSubscription.cs +++ b/src/NATS.Client/v1/JetStream/JetStreamPushAsyncSubscription.cs @@ -1,4 +1,4 @@ -// Copyright 2021 The NATS Authors +// Copyright 2021 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -17,8 +17,8 @@ public class JetStreamPushAsyncSubscription : JetStreamAbstractAsyncSubscription { internal JetStreamPushAsyncSubscription(Connection conn, string subject, string queue, JetStream js, string stream, string consumer, string deliver, MessageManager messageManager) - : base(conn, subject, queue, js, stream, consumer, deliver, messageManager) {} - + : base(conn, subject, queue, js, stream, consumer, deliver, messageManager) { } + public bool IsPullMode() => false; } } diff --git a/src/NATS.Client/v1/JetStream/JetStreamPushSyncSubscription.cs b/src/NATS.Client/v1/JetStream/JetStreamPushSyncSubscription.cs index ed526e4d..a54cc09d 100644 --- a/src/NATS.Client/v1/JetStream/JetStreamPushSyncSubscription.cs +++ b/src/NATS.Client/v1/JetStream/JetStreamPushSyncSubscription.cs @@ -1,4 +1,4 @@ -// Copyright 2021 The NATS Authors +// Copyright 2021 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -18,7 +18,7 @@ public class JetStreamPushSyncSubscription : JetStreamAbstractSyncSubscription, internal JetStreamPushSyncSubscription(Connection conn, string subject, string queue, JetStream js, string stream, string consumer, string deliver, MessageManager messageManager) - : base(conn, subject, queue, js, stream, consumer, deliver, messageManager) {} + : base(conn, subject, queue, js, stream, consumer, deliver, messageManager) { } public bool IsPullMode() => false; } diff --git a/src/NATS.Client/v1/JetStream/JsonSerializable.cs b/src/NATS.Client/v1/JetStream/JsonSerializable.cs index 2f5ae544..fd9f8094 100644 --- a/src/NATS.Client/v1/JetStream/JsonSerializable.cs +++ b/src/NATS.Client/v1/JetStream/JsonSerializable.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2023 The NATS Authors +// Copyright 2021-2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: diff --git a/src/NATS.Client/v1/JetStream/ListReaders.cs b/src/NATS.Client/v1/JetStream/ListReaders.cs index db7d059b..5eb2a652 100644 --- a/src/NATS.Client/v1/JetStream/ListReaders.cs +++ b/src/NATS.Client/v1/JetStream/ListReaders.cs @@ -92,10 +92,31 @@ internal abstract class AbstractListReader internal void Process(Msg msg) { Engine = new ListRequestEngine(msg); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: JSONArray nodes = Engine.GetNodes(objectName); +After: + var nodes = Engine.GetNodes(objectName); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONArray nodes = Engine.GetNodes(objectName); +After: + var nodes = Engine.GetNodes(objectName); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONArray nodes = Engine.GetNodes(objectName); +After: + var nodes = Engine.GetNodes(objectName); +*/ + + var nodes = Engine.GetNodes(objectName); if (nodes != null) { - for (int x = 0; x < nodes.Count; x++) + for (var x = 0; x < nodes.Count; x++) { ProcessItem(nodes[x]); } @@ -136,7 +157,7 @@ internal abstract class StringListReader : AbstractListReader { private List _strings = new List(); - protected StringListReader(string objectName, string filterFieldName = null) : base(objectName, filterFieldName) {} + protected StringListReader(string objectName, string filterFieldName = null) : base(objectName, filterFieldName) { } protected override void ProcessItem(JSONNode node) { @@ -148,19 +169,19 @@ protected override void ProcessItem(JSONNode node) internal class ConsumerNamesReader : StringListReader { - internal ConsumerNamesReader() : base(ApiConstants.Consumers) {} + internal ConsumerNamesReader() : base(ApiConstants.Consumers) { } } internal class StreamNamesReader : StringListReader { - internal StreamNamesReader() : base(ApiConstants.Streams, ApiConstants.Subject) {} + internal StreamNamesReader() : base(ApiConstants.Streams, ApiConstants.Subject) { } } internal class ConsumerListReader : AbstractListReader { private List _consumerInfos = new List(); - internal ConsumerListReader() : base(ApiConstants.Consumers) {} + internal ConsumerListReader() : base(ApiConstants.Consumers) { } protected override void ProcessItem(JSONNode node) { @@ -174,7 +195,7 @@ internal class StreamListReader : AbstractListReader { private List _streamInfos = new List(); - internal StreamListReader() : base(ApiConstants.Streams, ApiConstants.Subject) {} + internal StreamListReader() : base(ApiConstants.Streams, ApiConstants.Subject) { } protected override void ProcessItem(JSONNode node) { @@ -197,7 +218,28 @@ public StreamInfoReader() internal void Process(Msg msg) { engine = new ListRequestEngine(msg); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: StreamInfo si = new StreamInfo(msg, true); +After: + var si = new StreamInfo(msg, true); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + StreamInfo si = new StreamInfo(msg, true); +After: + var si = new StreamInfo(msg, true); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + StreamInfo si = new StreamInfo(msg, true); +After: + var si = new StreamInfo(msg, true); +*/ + + var si = new StreamInfo(msg, true); if (StreamInfo == null) { StreamInfo = si; @@ -234,4 +276,4 @@ internal bool HasMore() return engine.HasMore(); } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/JetStream/LostStreamData.cs b/src/NATS.Client/v1/JetStream/LostStreamData.cs index 4c89f383..cdf6be94 100644 --- a/src/NATS.Client/v1/JetStream/LostStreamData.cs +++ b/src/NATS.Client/v1/JetStream/LostStreamData.cs @@ -29,7 +29,28 @@ internal static LostStreamData OptionalInstance(JSONNode lostNode) private LostStreamData(JSONNode lostNode) { Messages = new List(); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: JSONNode.Enumerator e = +After: + var e = +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONNode.Enumerator e = +After: + var e = +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONNode.Enumerator e = +After: + var e = +*/ + + var e = lostNode[ApiConstants.Msgs].AsArray.GetEnumerator(); while (e.MoveNext()) { @@ -46,4 +67,4 @@ public override string ToString() '}'; } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/JetStream/MessageConsumer.cs b/src/NATS.Client/v1/JetStream/MessageConsumer.cs index 128d6c45..75a7b871 100644 --- a/src/NATS.Client/v1/JetStream/MessageConsumer.cs +++ b/src/NATS.Client/v1/JetStream/MessageConsumer.cs @@ -16,7 +16,7 @@ namespace NATS.Client.JetStream { - + /// /// Interface definition for a Message Consumer /// @@ -31,31 +31,73 @@ internal class MessageConsumer : MessageConsumerBase, IPullManagerObserver internal MessageConsumer(SimplifiedSubscriptionMaker subscriptionMaker, ConsumerInfo cachedConsumerInfo, BaseConsumeOptions opts, - EventHandler userMessageHandler) + EventHandler userMessageHandler) : base(cachedConsumerInfo) { this.subscriptionMaker = subscriptionMaker; this.opts = opts; this.userMessageHandler = userMessageHandler; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int bm = opts.Messages; + long bb = opts.Bytes; + int rePullMessages = Math.Max(1, bm * opts.ThresholdPercent / 100); + long rePullBytes = bb == 0 ? 0 : Math.Max(1, bb * opts.ThresholdPercent / 100); +After: + var bm = opts.Messages; + var bb = opts.Bytes; + var rePullMessages = Math.Max(1, bm * opts.ThresholdPercent / 100); + var rePullBytes = bb == 0 ? 0 : Math.Max(1, bb * opts.ThresholdPercent / 100); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int bm = opts.Messages; + long bb = opts.Bytes; + int rePullMessages = Math.Max(1, bm * opts.ThresholdPercent / 100); + long rePullBytes = bb == 0 ? 0 : Math.Max(1, bb * opts.ThresholdPercent / 100); +After: + var bm = opts.Messages; + var bb = opts.Bytes; + var rePullMessages = Math.Max(1, bm * opts.ThresholdPercent / 100); + var rePullBytes = bb == 0 ? 0 : Math.Max(1, bb * opts.ThresholdPercent / 100); +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int bm = opts.Messages; long bb = opts.Bytes; int rePullMessages = Math.Max(1, bm * opts.ThresholdPercent / 100); long rePullBytes = bb == 0 ? 0 : Math.Max(1, bb * opts.ThresholdPercent / 100); +After: + var bm = opts.Messages; + var bb = opts.Bytes; + var rePullMessages = Math.Max(1, bm * opts.ThresholdPercent / 100); + var rePullBytes = bb == 0 ? 0 : Math.Max(1, bb * opts.ThresholdPercent / 100); +*/ + + + var bm = opts.Messages; + var bb = opts.Bytes; + var rePullMessages = Math.Max(1, bm * opts.ThresholdPercent / 100); + var rePullBytes = bb == 0 ? 0 : Math.Max(1, bb * opts.ThresholdPercent / 100); thresholdMessages = bm - rePullMessages; thresholdBytes = bb == 0 ? int.MinValue : bb - rePullBytes; DoSub(); } - public void HeartbeatError() { - try { + public void HeartbeatError() + { + try + { // just close the current sub and make another one. // this could go on endlessly Dispose(); DoSub(); } - catch (Exception) { + catch (Exception) + { SetupHbAlarmToTrigger(); } } @@ -88,7 +130,8 @@ void DoSub() } } - private void SetupHbAlarmToTrigger() { + private void SetupHbAlarmToTrigger() + { pmm.ResetTracking(); pmm.InitOrResetHeartbeatTimer(); } @@ -101,10 +144,44 @@ public void PendingUpdated() } } - private void Repull() { + private void Repull() +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int rePullMessages = Math.Max(1, opts.Messages - pmm.pendingMessages); + long rePullBytes = opts.Bytes == 0 ? 0 : opts.Bytes - pmm.pendingBytes; + PullRequestOptions pro = PullRequestOptions.Builder(rePullMessages) +After: + var rePullMessages = Math.Max(1, opts.Messages - pmm.pendingMessages); + var rePullBytes = opts.Bytes == 0 ? 0 : opts.Bytes - pmm.pendingBytes; + var pro = PullRequestOptions.Builder(rePullMessages) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: int rePullMessages = Math.Max(1, opts.Messages - pmm.pendingMessages); long rePullBytes = opts.Bytes == 0 ? 0 : opts.Bytes - pmm.pendingBytes; PullRequestOptions pro = PullRequestOptions.Builder(rePullMessages) +After: + var rePullMessages = Math.Max(1, opts.Messages - pmm.pendingMessages); + var rePullBytes = opts.Bytes == 0 ? 0 : opts.Bytes - pmm.pendingBytes; + var pro = PullRequestOptions.Builder(rePullMessages) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int rePullMessages = Math.Max(1, opts.Messages - pmm.pendingMessages); + long rePullBytes = opts.Bytes == 0 ? 0 : opts.Bytes - pmm.pendingBytes; + PullRequestOptions pro = PullRequestOptions.Builder(rePullMessages) +After: + var rePullMessages = Math.Max(1, opts.Messages - pmm.pendingMessages); + var rePullBytes = opts.Bytes == 0 ? 0 : opts.Bytes - pmm.pendingBytes; + var pro = PullRequestOptions.Builder(rePullMessages) +*/ + + { + var rePullMessages = Math.Max(1, opts.Messages - pmm.pendingMessages); + var rePullBytes = opts.Bytes == 0 ? 0 : opts.Bytes - pmm.pendingBytes; + var pro = PullRequestOptions.Builder(rePullMessages) .WithMaxBytes(rePullBytes) .WithExpiresIn(opts.ExpiresInMillis) .WithIdleHeartbeat(opts.IdleHeartbeat) diff --git a/src/NATS.Client/v1/JetStream/MessageConsumerBase.cs b/src/NATS.Client/v1/JetStream/MessageConsumerBase.cs index 0ede4919..77dd5455 100644 --- a/src/NATS.Client/v1/JetStream/MessageConsumerBase.cs +++ b/src/NATS.Client/v1/JetStream/MessageConsumerBase.cs @@ -1,4 +1,4 @@ -// Copyright 2023 The NATS Authors +// Copyright 2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -35,7 +35,7 @@ public bool Stopped { return _stopped.IsTrue(); } - + internal set { _stopped.Set(value); @@ -48,13 +48,13 @@ public bool Finished { return _finished.IsTrue(); } - + internal set { _finished.Set(value); } } - + internal MessageConsumerBase(ConsumerInfo cachedConsumerInfo) { this.cachedConsumerInfo = cachedConsumerInfo; diff --git a/src/NATS.Client/v1/JetStream/MessageDeleteRequest.cs b/src/NATS.Client/v1/JetStream/MessageDeleteRequest.cs index 8347aac1..bc632350 100644 --- a/src/NATS.Client/v1/JetStream/MessageDeleteRequest.cs +++ b/src/NATS.Client/v1/JetStream/MessageDeleteRequest.cs @@ -28,8 +28,29 @@ public MessageDeleteRequest(ulong sequence, bool erase) } public override JSONNode ToJsonNode() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + + { + var jso = new JSONObject(); if (Sequence > 0) { jso[ApiConstants.Seq] = Sequence; diff --git a/src/NATS.Client/v1/JetStream/MessageGetRequest.cs b/src/NATS.Client/v1/JetStream/MessageGetRequest.cs index c319b183..e995c8ac 100644 --- a/src/NATS.Client/v1/JetStream/MessageGetRequest.cs +++ b/src/NATS.Client/v1/JetStream/MessageGetRequest.cs @@ -25,19 +25,23 @@ public sealed class MessageGetRequest : JsonSerializable public bool IsLastBySubject => LastBySubject != null; public bool IsNextBySubject => NextBySubject != null; - public static MessageGetRequest ForSequence(ulong sequence) { + public static MessageGetRequest ForSequence(ulong sequence) + { return new MessageGetRequest(sequence, null, null); } - public static MessageGetRequest LastForSubject(string subject) { + public static MessageGetRequest LastForSubject(string subject) + { return new MessageGetRequest(0, subject, null); } - public static MessageGetRequest FirstForSubject(string subject) { + public static MessageGetRequest FirstForSubject(string subject) + { return new MessageGetRequest(0, null, subject); } - public static MessageGetRequest NextForSubject(ulong sequence, string subject) { + public static MessageGetRequest NextForSubject(ulong sequence, string subject) + { return new MessageGetRequest(sequence, null, subject); } @@ -49,8 +53,29 @@ public MessageGetRequest(ulong sequence, string lastBySubject, string nextBySubj } public override JSONNode ToJsonNode() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + + { + var jso = new JSONObject(); if (Sequence > 0) { jso[ApiConstants.Seq] = Sequence; diff --git a/src/NATS.Client/v1/JetStream/MessageInfo.cs b/src/NATS.Client/v1/JetStream/MessageInfo.cs index 607bff1b..4b405b0c 100644 --- a/src/NATS.Client/v1/JetStream/MessageInfo.cs +++ b/src/NATS.Client/v1/JetStream/MessageInfo.cs @@ -50,7 +50,28 @@ private void Init(Msg msg, bool fromDirect, string streamName) Sequence = ulong.Parse(msg.Header.GetLast(JetStreamConstants.NatsSequence)); Time = JsonUtils.AsDate(msg.Header.GetLast(JetStreamConstants.NatsTimestamp)); Stream = msg.Header.GetLast(JetStreamConstants.NatsStream); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: string temp = msg.Header.GetLast(JetStreamConstants.NatsLastSequence); +After: + var temp = msg.Header.GetLast(JetStreamConstants.NatsLastSequence); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string temp = msg.Header.GetLast(JetStreamConstants.NatsLastSequence); +After: + var temp = msg.Header.GetLast(JetStreamConstants.NatsLastSequence); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string temp = msg.Header.GetLast(JetStreamConstants.NatsLastSequence); +After: + var temp = msg.Header.GetLast(JetStreamConstants.NatsLastSequence); +*/ + + var temp = msg.Header.GetLast(JetStreamConstants.NatsLastSequence); if (temp != null) { LastSequence = ulong.Parse(temp); @@ -63,13 +84,55 @@ private void Init(Msg msg, bool fromDirect, string streamName) msg.Header.Remove(JetStreamConstants.NatsLastSequence); } else if (!HasError) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONNode miNode = JsonNode[ApiConstants.Message]; +After: + var miNode = JsonNode[ApiConstants.Message]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: JSONNode miNode = JsonNode[ApiConstants.Message]; +After: + var miNode = JsonNode[ApiConstants.Message]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONNode miNode = JsonNode[ApiConstants.Message]; +After: + var miNode = JsonNode[ApiConstants.Message]; +*/ + + { + var miNode = JsonNode[ApiConstants.Message]; Subject = miNode[ApiConstants.Subject].Value; Sequence = miNode[ApiConstants.Seq].AsUlong; Time = JsonUtils.AsDate(miNode[ApiConstants.Time]); Data = JsonUtils.AsByteArrayFromBase64(miNode[ApiConstants.Data]); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + byte[] bytes = JsonUtils.AsByteArrayFromBase64(miNode[ApiConstants.Hdrs]); +After: + var bytes = JsonUtils.AsByteArrayFromBase64(miNode[ApiConstants.Hdrs]); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + byte[] bytes = JsonUtils.AsByteArrayFromBase64(miNode[ApiConstants.Hdrs]); +After: + var bytes = JsonUtils.AsByteArrayFromBase64(miNode[ApiConstants.Hdrs]); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: byte[] bytes = JsonUtils.AsByteArrayFromBase64(miNode[ApiConstants.Hdrs]); +After: + var bytes = JsonUtils.AsByteArrayFromBase64(miNode[ApiConstants.Hdrs]); +*/ + + var bytes = JsonUtils.AsByteArrayFromBase64(miNode[ApiConstants.Hdrs]); if (bytes != null) { Headers = new HeaderStatusReader(bytes, bytes.Length).Header; diff --git a/src/NATS.Client/v1/JetStream/MessageManager.cs b/src/NATS.Client/v1/JetStream/MessageManager.cs index b59231ca..73817e0b 100644 --- a/src/NATS.Client/v1/JetStream/MessageManager.cs +++ b/src/NATS.Client/v1/JetStream/MessageManager.cs @@ -17,7 +17,7 @@ namespace NATS.Client.JetStream { - public enum ManageResult {Message, StatusHandled, StatusTerminus, StatusError} + public enum ManageResult { Message, StatusHandled, StatusTerminus, StatusError } public abstract class MessageManager { @@ -65,7 +65,8 @@ public virtual void Shutdown() ShutdownHeartbeatTimer(); } - public virtual void StartPullRequest(string pullSubject, PullRequestOptions pullRequestOptions, bool raiseStatusWarnings, IPullManagerObserver pullManagerObserver) { + public virtual void StartPullRequest(string pullSubject, PullRequestOptions pullRequestOptions, bool raiseStatusWarnings, IPullManagerObserver pullManagerObserver) + { // does nothing - only implemented for pulls, but in base class since instance is always referenced as MessageManager, not subclass } @@ -80,18 +81,19 @@ protected virtual bool BeforeChannelAddCheck(Msg msg) } public abstract ManageResult Manage(Msg msg); - - protected void TrackJsMessage(Msg msg) { + + protected void TrackJsMessage(Msg msg) + { lock (StateChangeLock) { LastStreamSeq = msg.MetaData.StreamSequence; LastConsumerSeq++; } } - + internal virtual void HandleHeartbeatError() { - Conn.Opts.HeartbeatAlarmEventHandlerOrDefault.Invoke(this, + Conn.Opts.HeartbeatAlarmEventHandlerOrDefault.Invoke(this, new HeartbeatAlarmEventArgs(Conn, (Subscription)Sub, LastStreamSeq, LastConsumerSeq)); } @@ -127,8 +129,29 @@ internal void InitOrResetHeartbeatTimer() { ShutdownHeartbeatTimer(); heartbeatTimer = new Timer(state => - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: long sinceLast = DateTimeOffset.Now.ToUnixTimeMilliseconds() - LastMsgReceived.Read(); +After: + var sinceLast = DateTimeOffset.Now.ToUnixTimeMilliseconds() - LastMsgReceived.Read(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + long sinceLast = DateTimeOffset.Now.ToUnixTimeMilliseconds() - LastMsgReceived.Read(); +After: + var sinceLast = DateTimeOffset.Now.ToUnixTimeMilliseconds() - LastMsgReceived.Read(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + long sinceLast = DateTimeOffset.Now.ToUnixTimeMilliseconds() - LastMsgReceived.Read(); +After: + var sinceLast = DateTimeOffset.Now.ToUnixTimeMilliseconds() - LastMsgReceived.Read(); +*/ + + { + var sinceLast = DateTimeOffset.Now.ToUnixTimeMilliseconds() - LastMsgReceived.Read(); if (sinceLast > AlarmPeriodSetting) { HandleHeartbeatError(); diff --git a/src/NATS.Client/v1/JetStream/Mirror.cs b/src/NATS.Client/v1/JetStream/Mirror.cs index cf7340fb..b970dac0 100644 --- a/src/NATS.Client/v1/JetStream/Mirror.cs +++ b/src/NATS.Client/v1/JetStream/Mirror.cs @@ -38,17 +38,18 @@ internal static Mirror OptionalInstance(JSONNode mirrorNode) /// the subject transforms, defaults to none public Mirror(string name, ulong startSeq, DateTime startTime, string filterSubject, External external, IList subjectTransforms = null) - : base(name, startSeq, startTime, filterSubject, external, subjectTransforms) {} + : base(name, startSeq, startTime, filterSubject, external, subjectTransforms) { } - internal Mirror(JSONNode mirrorNode) : base(mirrorNode) {} + internal Mirror(JSONNode mirrorNode) : base(mirrorNode) { } - internal Mirror(MirrorBuilder mb) : base(mb) {} + internal Mirror(MirrorBuilder mb) : base(mb) { } /// /// Creates a builder for a mirror object. /// /// The Builder - public static MirrorBuilder Builder() { + public static MirrorBuilder Builder() + { return new MirrorBuilder(); } @@ -56,17 +57,18 @@ public static MirrorBuilder Builder() { /// Creates a builder for a mirror object based on an existing mirror object. /// /// The Builder - public static MirrorBuilder Builder(Mirror mirror) { + public static MirrorBuilder Builder(Mirror mirror) + { return new MirrorBuilder(mirror); } - + /// /// Mirror can be created using a MirrorBuilder. /// public sealed class MirrorBuilder : SourceBaseBuilder { - public MirrorBuilder() {} - public MirrorBuilder(Mirror mirror) : base(mirror) {} + public MirrorBuilder() { } + public MirrorBuilder(Mirror mirror) : base(mirror) { } protected override MirrorBuilder GetThis() { diff --git a/src/NATS.Client/v1/JetStream/NATSJetStreamException.cs b/src/NATS.Client/v1/JetStream/NATSJetStreamException.cs index a1d05910..24867990 100644 --- a/src/NATS.Client/v1/JetStream/NATSJetStreamException.cs +++ b/src/NATS.Client/v1/JetStream/NATSJetStreamException.cs @@ -1,4 +1,4 @@ - + // Copyright 2021 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/src/NATS.Client/v1/JetStream/OrderedConsumerConfiguration.cs b/src/NATS.Client/v1/JetStream/OrderedConsumerConfiguration.cs index 973160c9..e34d7cfc 100644 --- a/src/NATS.Client/v1/JetStream/OrderedConsumerConfiguration.cs +++ b/src/NATS.Client/v1/JetStream/OrderedConsumerConfiguration.cs @@ -20,7 +20,7 @@ namespace NATS.Client.JetStream public sealed class OrderedConsumerConfiguration { public const string DefaultFilterSubject = NatsConstants.GreaterThan; - + public DeliverPolicy? DeliverPolicy { get; private set; } public ulong StartSequence { get; private set; } public DateTime StartTime { get; private set; } @@ -44,13 +44,14 @@ public OrderedConsumerConfiguration() FilterSubjects = new List(); FilterSubjects.Add(DefaultFilterSubject); } - + /// /// Sets the filter subject of the OrderedConsumerConfiguration. /// /// the filter subject /// Builder - public OrderedConsumerConfiguration WithFilterSubject(string filterSubject) { + public OrderedConsumerConfiguration WithFilterSubject(string filterSubject) + { FilterSubjects.Clear(); if (string.IsNullOrEmpty(filterSubject)) { @@ -70,12 +71,12 @@ public OrderedConsumerConfiguration WithFilterSubject(string filterSubject) { /// The ConsumerConfigurationBuilder public OrderedConsumerConfiguration WithFilterSubjects(params string[] filterSubjects) { - return Validator.EmptyOrNull(filterSubjects) - ? WithFilterSubject(null) + return Validator.EmptyOrNull(filterSubjects) + ? WithFilterSubject(null) : WithFilterSubjects(new List(filterSubjects)); } - - + + /// /// Sets the filter subject of the OrderedConsumerConfiguration. /// @@ -84,14 +85,18 @@ public OrderedConsumerConfiguration WithFilterSubjects(params string[] filterSub public OrderedConsumerConfiguration WithFilterSubjects(IList filterSubjects) { FilterSubjects.Clear(); - if (filterSubjects != null) { - foreach (string fs in filterSubjects) { - if (!string.IsNullOrWhiteSpace(fs)) { + if (filterSubjects != null) + { + foreach (var fs in filterSubjects) + { + if (!string.IsNullOrWhiteSpace(fs)) + { FilterSubjects.Add(fs); } } } - if (FilterSubjects.Count == 0) { + if (FilterSubjects.Count == 0) + { FilterSubjects.Add(DefaultFilterSubject); } return this; @@ -103,48 +108,53 @@ public OrderedConsumerConfiguration WithFilterSubjects(IList filterSubje /// /// the delivery policy. /// Builder - public OrderedConsumerConfiguration WithDeliverPolicy(DeliverPolicy? deliverPolicy) { + public OrderedConsumerConfiguration WithDeliverPolicy(DeliverPolicy? deliverPolicy) + { DeliverPolicy = deliverPolicy; return this; } - + /// /// Sets the start sequence of the OrderedConsumerConfiguration. /// /// the start sequence /// Builder - public OrderedConsumerConfiguration WithStartSequence(ulong startSequence) { + public OrderedConsumerConfiguration WithStartSequence(ulong startSequence) + { StartSequence = startSequence; return this; } - + /// /// Sets the start time of the OrderedConsumerConfiguration. /// /// the start time /// Builder - public OrderedConsumerConfiguration WithStartTime(DateTime startTime) { + public OrderedConsumerConfiguration WithStartTime(DateTime startTime) + { StartTime = startTime; return this; } - + /// /// Sets the replay policy of the OrderedConsumerConfiguration. /// /// the replay policy. /// Builder - public OrderedConsumerConfiguration WithReplayPolicy(ReplayPolicy? replayPolicy) { + public OrderedConsumerConfiguration WithReplayPolicy(ReplayPolicy? replayPolicy) + { ReplayPolicy = replayPolicy; return this; } - + /// /// set the headers only flag saying to deliver only the headers of /// messages in the stream and not the bodies /// /// the flag /// Builder - public OrderedConsumerConfiguration WithHeadersOnly(bool? headersOnly) { + public OrderedConsumerConfiguration WithHeadersOnly(bool? headersOnly) + { HeadersOnly = null; if (headersOnly.HasValue && headersOnly.Value) { diff --git a/src/NATS.Client/v1/JetStream/OrderedConsumerContext.cs b/src/NATS.Client/v1/JetStream/OrderedConsumerContext.cs index e031c8a5..014aead6 100644 --- a/src/NATS.Client/v1/JetStream/OrderedConsumerContext.cs +++ b/src/NATS.Client/v1/JetStream/OrderedConsumerContext.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace NATS.Client.JetStream { @@ -11,7 +11,8 @@ internal class OrderedConsumerContext : IOrderedConsumerContext public string ConsumerName => impl.ConsumerName; - internal OrderedConsumerContext(StreamContext streamContext, OrderedConsumerConfiguration config) { + internal OrderedConsumerContext(StreamContext streamContext, OrderedConsumerConfiguration config) + { impl = new ConsumerContext(streamContext, config); } @@ -45,4 +46,4 @@ public IMessageConsumer Consume(EventHandler handler, Consu return impl.Consume(handler, consumeOptions); } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/JetStream/OrderedMessageManager.cs b/src/NATS.Client/v1/JetStream/OrderedMessageManager.cs index 20dcec48..0edecdb2 100644 --- a/src/NATS.Client/v1/JetStream/OrderedMessageManager.cs +++ b/src/NATS.Client/v1/JetStream/OrderedMessageManager.cs @@ -21,12 +21,12 @@ public class OrderedMessageManager : PushMessageManager protected long? TargetSid; public OrderedMessageManager( - Connection conn, - JetStream js, + Connection conn, + JetStream js, string stream, SubscribeOptions so, - ConsumerConfiguration originalCc, - bool queueMode, + ConsumerConfiguration originalCc, + bool queueMode, bool syncMode) : base(conn, js, stream, so, originalCc, queueMode, syncMode) { ExpectedExternalConsumerSeq = 1; // always starts at 1 @@ -45,11 +45,33 @@ public override ManageResult Manage(Msg msg) { return ManageResult.StatusHandled; // wrong sid is throwaway from previous consumer that errored } - + if (msg.IsJetStream) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + ulong receivedConsumerSeq = msg.MetaData.ConsumerSequence; +After: + var receivedConsumerSeq = msg.MetaData.ConsumerSequence; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + ulong receivedConsumerSeq = msg.MetaData.ConsumerSequence; +After: + var receivedConsumerSeq = msg.MetaData.ConsumerSequence; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: ulong receivedConsumerSeq = msg.MetaData.ConsumerSequence; - if (ExpectedExternalConsumerSeq != receivedConsumerSeq) { +After: + var receivedConsumerSeq = msg.MetaData.ConsumerSequence; +*/ + + { + var receivedConsumerSeq = msg.MetaData.ConsumerSequence; + if (ExpectedExternalConsumerSeq != receivedConsumerSeq) + { HandleErrorCondition(); return ManageResult.StatusHandled; // not technically a status } @@ -57,10 +79,10 @@ public override ManageResult Manage(Msg msg) ExpectedExternalConsumerSeq++; return ManageResult.Message; } - + return ManageStatus(msg); } - + internal override void HandleHeartbeatError() { base.HandleHeartbeatError(); @@ -73,26 +95,102 @@ private void HandleErrorCondition() { TargetSid = null; ExpectedExternalConsumerSeq = 1; // consumer always starts with consumer sequence 1 +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + IJetStreamManagement jsm = Conn.CreateJetStreamManagementContext(Js.JetStreamOptions); + String actualConsumerName = Sub.Consumer; +After: + var jsm = Conn.CreateJetStreamManagementContext(Js.JetStreamOptions); + var actualConsumerName = Sub.Consumer; +*/ - // 1. delete the consumer by name so we can recreate it with a different delivery policy - // b/c we cannot edit a push consumer's delivery policy +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + IJetStreamManagement jsm = Conn.CreateJetStreamManagementContext(Js.JetStreamOptions); + String actualConsumerName = Sub.Consumer; +After: + var jsm = Conn.CreateJetStreamManagementContext(Js.JetStreamOptions); + var actualConsumerName = Sub.Consumer; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: IJetStreamManagement jsm = Conn.CreateJetStreamManagementContext(Js.JetStreamOptions); String actualConsumerName = Sub.Consumer; - try { +After: + var jsm = Conn.CreateJetStreamManagementContext(Js.JetStreamOptions); + var actualConsumerName = Sub.Consumer; +*/ + + + // 1. delete the consumer by name so we can recreate it with a different delivery policy + // b/c we cannot edit a push consumer's delivery policy + var jsm = Conn.CreateJetStreamManagementContext(Js.JetStreamOptions); + var actualConsumerName = Sub.Consumer; + try + { jsm.DeleteConsumer(Stream, actualConsumerName); } catch (Exception) { /* ignored */ } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string newDeliverSubject = Sub.Connection.NewInbox(); +After: + var newDeliverSubject = Sub.Connection.NewInbox(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string newDeliverSubject = Sub.Connection.NewInbox(); +After: + var newDeliverSubject = Sub.Connection.NewInbox(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string newDeliverSubject = Sub.Connection.NewInbox(); +After: + var newDeliverSubject = Sub.Connection.NewInbox(); +*/ + // 2. re-subscribe. This means kill the sub then make a new one // New sub needs a new deliver subject - string newDeliverSubject = Sub.Connection.NewInbox(); + var newDeliverSubject = Sub.Connection.NewInbox(); ((Subscription)Sub).ReSubscribe(newDeliverSubject); - TargetSid = ((Subscription)Sub).Sid; + TargetSid = ((Subscription)Sub).Sid; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + ConsumerConfiguration userCc = Js.ConsumerConfigurationForOrdered(OriginalCc, LastStreamSeq, newDeliverSubject, actualConsumerName, null); + ConsumerInfo ci = Js.CreateConsumerInternal(Stream, userCc, ConsumerCreateRequestAction.Create); +After: + var userCc = Js.ConsumerConfigurationForOrdered(OriginalCc, LastStreamSeq, newDeliverSubject, actualConsumerName, null); + var ci = Js.CreateConsumerInternal(Stream, userCc, ConsumerCreateRequestAction.Create); +*/ - // 3. make a new consumer using the same deliver subject but - // with a new starting point +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + ConsumerConfiguration userCc = Js.ConsumerConfigurationForOrdered(OriginalCc, LastStreamSeq, newDeliverSubject, actualConsumerName, null); + ConsumerInfo ci = Js.CreateConsumerInternal(Stream, userCc, ConsumerCreateRequestAction.Create); +After: + var userCc = Js.ConsumerConfigurationForOrdered(OriginalCc, LastStreamSeq, newDeliverSubject, actualConsumerName, null); + var ci = Js.CreateConsumerInternal(Stream, userCc, ConsumerCreateRequestAction.Create); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: ConsumerConfiguration userCc = Js.ConsumerConfigurationForOrdered(OriginalCc, LastStreamSeq, newDeliverSubject, actualConsumerName, null); ConsumerInfo ci = Js.CreateConsumerInternal(Stream, userCc, ConsumerCreateRequestAction.Create); +After: + var userCc = Js.ConsumerConfigurationForOrdered(OriginalCc, LastStreamSeq, newDeliverSubject, actualConsumerName, null); + var ci = Js.CreateConsumerInternal(Stream, userCc, ConsumerCreateRequestAction.Create); +*/ + + + // 3. make a new consumer using the same deliver subject but + // with a new starting point + var userCc = Js.ConsumerConfigurationForOrdered(OriginalCc, LastStreamSeq, newDeliverSubject, actualConsumerName, null); + var ci = Js.CreateConsumerInternal(Stream, userCc, ConsumerCreateRequestAction.Create); if (Sub is JetStreamAbstractSyncSubscription syncSub) { syncSub.SetConsumerName(ci.Name); @@ -106,8 +204,29 @@ private void HandleErrorCondition() Startup(Sub); } catch (Exception e) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: NATSException ne = e is NATSException ? (NATSException)e : new NATSException("Ordered Subscription Error", e); +After: + var ne = e is NATSException ? (NATSException)e : new NATSException("Ordered Subscription Error", e); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + NATSException ne = e is NATSException ? (NATSException)e : new NATSException("Ordered Subscription Error", e); +After: + var ne = e is NATSException ? (NATSException)e : new NATSException("Ordered Subscription Error", e); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + NATSException ne = e is NATSException ? (NATSException)e : new NATSException("Ordered Subscription Error", e); +After: + var ne = e is NATSException ? (NATSException)e : new NATSException("Ordered Subscription Error", e); +*/ + + { + var ne = e is NATSException ? (NATSException)e : new NATSException("Ordered Subscription Error", e); ((Connection)Js.Conn).ScheduleErrorEvent(this, ne); InitOrResetHeartbeatTimer(); } diff --git a/src/NATS.Client/v1/JetStream/PeerInfo.cs b/src/NATS.Client/v1/JetStream/PeerInfo.cs index 06548d1b..f38bf272 100644 --- a/src/NATS.Client/v1/JetStream/PeerInfo.cs +++ b/src/NATS.Client/v1/JetStream/PeerInfo.cs @@ -24,7 +24,8 @@ public abstract class PeerInfo public Duration Active { get; } public long Lag { get; } - internal PeerInfo(JSONNode peerInfoNode) { + internal PeerInfo(JSONNode peerInfoNode) + { Name = peerInfoNode[ApiConstants.Name].Value; Current = peerInfoNode[ApiConstants.Current].AsBool; Offline = peerInfoNode[ApiConstants.Offline].AsBool; diff --git a/src/NATS.Client/v1/JetStream/Placement.cs b/src/NATS.Client/v1/JetStream/Placement.cs index 307d0cbf..1ab63f22 100644 --- a/src/NATS.Client/v1/JetStream/Placement.cs +++ b/src/NATS.Client/v1/JetStream/Placement.cs @@ -23,19 +23,19 @@ namespace NATS.Client.JetStream public sealed class Placement : JsonSerializable { private string cluster; - + /// /// The desired cluster name to place the stream /// public string Cluster { get => cluster; - private set + private set { cluster = string.IsNullOrEmpty(value) ? null : value; } } - + /// /// Tags required on servers hosting this stream /// @@ -96,10 +96,31 @@ public bool HasData() { return cluster != null || Tags != null; } - + public override JSONNode ToJsonNode() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + + { + var o = new JSONObject(); if (cluster != null) { o[ApiConstants.Cluster] = cluster; @@ -115,14 +136,16 @@ public override JSONNode ToJsonNode() /// Creates a builder for a placements object. /// /// The Builder - public static PlacementBuilder Builder() { + public static PlacementBuilder Builder() + { return new PlacementBuilder(); } /// /// Placement can be created using a PlacementBuilder. /// - public sealed class PlacementBuilder { + public sealed class PlacementBuilder + { private string _cluster; private IList _tags; @@ -131,7 +154,8 @@ public sealed class PlacementBuilder { /// /// the cluster /// - public PlacementBuilder WithCluster(string cluster) { + public PlacementBuilder WithCluster(string cluster) + { _cluster = cluster; return this; } @@ -141,7 +165,8 @@ public PlacementBuilder WithCluster(string cluster) { /// /// tags the list of tags /// - public PlacementBuilder WithTags(IList tags) { + public PlacementBuilder WithTags(IList tags) + { _tags = new List(tags); return this; } @@ -151,7 +176,8 @@ public PlacementBuilder WithTags(IList tags) { /// /// tags the list of tags /// - public PlacementBuilder WithTags(params string[] tags) { + public PlacementBuilder WithTags(params string[] tags) + { _tags = new List(tags); return this; } @@ -160,7 +186,8 @@ public PlacementBuilder WithTags(params string[] tags) { /// Build a Placement object /// /// The Placement - public Placement Build() { + public Placement Build() + { return new Placement(_cluster, _tags); } } diff --git a/src/NATS.Client/v1/JetStream/PublishAck.cs b/src/NATS.Client/v1/JetStream/PublishAck.cs index c80ea8bb..a473fda1 100644 --- a/src/NATS.Client/v1/JetStream/PublishAck.cs +++ b/src/NATS.Client/v1/JetStream/PublishAck.cs @@ -39,9 +39,30 @@ private void Init() if (Stream.Length == 0) { throw new NATSException("Invalid JetStream ack."); - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONNode possible = JsonNode[ApiConstants.Seq]; +After: + var possible = JsonNode[ApiConstants.Seq]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONNode possible = JsonNode[ApiConstants.Seq]; +After: + var possible = JsonNode[ApiConstants.Seq]; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: JSONNode possible = JsonNode[ApiConstants.Seq]; +After: + var possible = JsonNode[ApiConstants.Seq]; +*/ + + } + + var possible = JsonNode[ApiConstants.Seq]; if (possible.IsNumber) { Seq = possible.AsUlong; diff --git a/src/NATS.Client/v1/JetStream/PublishOptions.cs b/src/NATS.Client/v1/JetStream/PublishOptions.cs index e2f9b47c..4ae32df7 100644 --- a/src/NATS.Client/v1/JetStream/PublishOptions.cs +++ b/src/NATS.Client/v1/JetStream/PublishOptions.cs @@ -16,7 +16,7 @@ namespace NATS.Client.JetStream { public sealed class PublishOptions - { + { /// /// The default timeout (2000ms) /// @@ -41,27 +41,27 @@ public sealed class PublishOptions /// The stream timeout. /// public Duration StreamTimeout { get; } - + /// /// The Expected Stream. /// public string ExpectedStream { get; } - + /// /// The Expected Last Message Id. /// public string ExpectedLastMsgId { get; } - + /// /// The Expected Last Sequence. /// public ulong ExpectedLastSeq { get; } - + /// /// The Expected Last Sequence. /// public ulong ExpectedLastSubjectSeq { get; } - + /// /// The Expected Message Id. /// @@ -78,7 +78,7 @@ private PublishOptions(string stream, Duration streamTimeout, string expectedStr ExpectedLastSubjectSeq = expectedLastSubjectSeq; MessageId = messageId; } - + /// /// Gets the publish options builder. /// @@ -102,7 +102,7 @@ public sealed class PublishOptionsBuilder private ulong _expectedLastSeq = DefaultLastSequence; private ulong _expectedLastSubjectSeq = DefaultLastSequence; private string _messageId; - + /// /// Set the stream name. /// @@ -141,7 +141,7 @@ public PublishOptionsBuilder WithTimeout(long timeoutMillis) /// /// The message ID of these options. /// The PublishOptionsBuilder - public PublishOptionsBuilder WithMessageId(string msgId) + public PublishOptionsBuilder WithMessageId(string msgId) { _messageId = Validator.ValidateNotEmpty(msgId, nameof(msgId)); return this; @@ -167,7 +167,7 @@ public PublishOptionsBuilder WithExpectedLastMsgId(string lastMessageId) { _expectedLastMsgId = Validator.ValidateNotEmpty(lastMessageId, nameof(lastMessageId)); return this; - } + } /// /// Set the expected sequence. @@ -196,7 +196,7 @@ public PublishOptionsBuilder WithExpectedLastSubjectSequence(ulong sequence) /// Clears the expectedLastId, expectedLastSequence and messageId fields. /// /// The PublishOptionsBuilder - public PublishOptionsBuilder ClearExpected() + public PublishOptionsBuilder ClearExpected() { _expectedLastMsgId = null; _expectedLastSeq = DefaultLastSequence; @@ -209,7 +209,7 @@ public PublishOptionsBuilder ClearExpected() /// Builds the PublishOptions /// /// The PublishOptions object. - public PublishOptions Build() + public PublishOptions Build() { return new PublishOptions(_stream, _streamTimeout, _expectedStream, _expectedLastMsgId, _expectedLastSeq, _expectedLastSubjectSeq, _messageId); } diff --git a/src/NATS.Client/v1/JetStream/PullMessageManager.cs b/src/NATS.Client/v1/JetStream/PullMessageManager.cs index e1986f8e..e42c0831 100644 --- a/src/NATS.Client/v1/JetStream/PullMessageManager.cs +++ b/src/NATS.Client/v1/JetStream/PullMessageManager.cs @@ -55,7 +55,7 @@ public override void StartPullRequest(string pullSubject, PullRequestOptions pro } } } - + internal override void HandleHeartbeatError() { base.HandleHeartbeatError(); @@ -76,7 +76,28 @@ private void TrackIncoming(int m, long b) if (m != Int32.MinValue) { pendingMessages -= m; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + bool zero = pendingMessages < 1; +After: + var zero = pendingMessages < 1; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: bool zero = pendingMessages < 1; +After: + var zero = pendingMessages < 1; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + bool zero = pendingMessages < 1; +After: + var zero = pendingMessages < 1; +*/ + + var zero = pendingMessages < 1; if (trackingBytes) { pendingBytes -= b; @@ -95,8 +116,9 @@ private void TrackIncoming(int m, long b) } } } - - internal void ResetTracking() { + + internal void ResetTracking() + { pendingMessages = 0; pendingBytes = 0; trackingBytes = false; @@ -107,24 +129,79 @@ internal void ResetTracking() { protected override bool BeforeChannelAddCheck(Msg msg) { UpdateLastMessageReceived(); // record message time. Used for heartbeat tracking +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + MsgStatus status = msg.Status; +After: + var status = msg.Status; +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: MsgStatus status = msg.Status; +After: + var status = msg.Status; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + MsgStatus status = msg.Status; +After: + var status = msg.Status; +*/ + + + var status = msg.Status; // normal js message - if (!msg.HasStatus) + if (!msg.HasStatus) { TrackIncoming(1, msg.ConsumeByteCount); return true; } - + // heartbeat just needed to be recorded - if (status.IsHeartbeat()) { + if (status.IsHeartbeat()) + { return false; - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string s = msg.Header[JetStreamConstants.NatsPendingMessages]; + int m = int.MinValue; + long b = long.MaxValue; +After: + var s = msg.Header[JetStreamConstants.NatsPendingMessages]; + var m = int.MinValue; + var b = long.MaxValue; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string s = msg.Header[JetStreamConstants.NatsPendingMessages]; + int m = int.MinValue; + long b = long.MaxValue; +After: + var s = msg.Header[JetStreamConstants.NatsPendingMessages]; + var m = int.MinValue; + var b = long.MaxValue; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string s = msg.Header[JetStreamConstants.NatsPendingMessages]; int m = int.MinValue; long b = long.MaxValue; +After: + var s = msg.Header[JetStreamConstants.NatsPendingMessages]; + var m = int.MinValue; + var b = long.MaxValue; +*/ + + } + + var s = msg.Header[JetStreamConstants.NatsPendingMessages]; + var m = int.MinValue; + var b = long.MaxValue; if (s != null && int.TryParse(s, out m)) { s = msg.Header[JetStreamConstants.NatsPendingBytes]; @@ -142,7 +219,7 @@ protected override bool BeforeChannelAddCheck(Msg msg) public override ManageResult Manage(Msg msg) { // normal js message - if (!msg.HasStatus) + if (!msg.HasStatus) { TrackJsMessage(msg); return ManageResult.Message; @@ -154,34 +231,55 @@ protected ManageResult ManageStatus(Msg msg) { switch (msg.Status.Code) { - case NatsConstants.NotFoundCode: - case NatsConstants.RequestTimeoutCode: + case NatsConstants.NotFoundCode: + case NatsConstants.RequestTimeoutCode: + if (raiseStatusWarnings) + { + Conn.Opts.PullStatusWarningEventHandlerOrDefault.Invoke(this, + new StatusEventArgs(Conn, (Subscription)Sub, msg.Status)); + } + return ManageResult.StatusTerminus; + + case NatsConstants.ConflictCode: +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string statMsg = msg.Status.Message; +After: + var statMsg = msg.Status.Message; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string statMsg = msg.Status.Message; +After: + var statMsg = msg.Status.Message; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string statMsg = msg.Status.Message; +After: + var statMsg = msg.Status.Message; +*/ + + // sometimes just a warning + var statMsg = msg.Status.Message; + if (statMsg.StartsWith("Exceeded Max")) + { if (raiseStatusWarnings) { Conn.Opts.PullStatusWarningEventHandlerOrDefault.Invoke(this, new StatusEventArgs(Conn, (Subscription)Sub, msg.Status)); } - return ManageResult.StatusTerminus; - - case NatsConstants.ConflictCode: - // sometimes just a warning - string statMsg = msg.Status.Message; - if (statMsg.StartsWith("Exceeded Max")) - { - if (raiseStatusWarnings) - { - Conn.Opts.PullStatusWarningEventHandlerOrDefault.Invoke(this, - new StatusEventArgs(Conn, (Subscription)Sub, msg.Status)); - } - return ManageResult.StatusHandled; - } + return ManageResult.StatusHandled; + } - if (statMsg.Equals(JetStreamConstants.BatchCompleted) || - statMsg.Equals(JetStreamConstants.MessageSizeExceedsMaxBytes)) - { - return ManageResult.StatusTerminus; - } - break; + if (statMsg.Equals(JetStreamConstants.BatchCompleted) || + statMsg.Equals(JetStreamConstants.MessageSizeExceedsMaxBytes)) + { + return ManageResult.StatusTerminus; + } + break; } // all others are errors @@ -190,7 +288,8 @@ protected ManageResult ManageStatus(Msg msg) return ManageResult.StatusError; } - internal bool NoMorePending() { + internal bool NoMorePending() + { return pendingMessages < 1 || (trackingBytes && pendingBytes < 1); } } diff --git a/src/NATS.Client/v1/JetStream/PullOrderedMessageManager.cs b/src/NATS.Client/v1/JetStream/PullOrderedMessageManager.cs index 5ca114ee..3bd169ed 100644 --- a/src/NATS.Client/v1/JetStream/PullOrderedMessageManager.cs +++ b/src/NATS.Client/v1/JetStream/PullOrderedMessageManager.cs @@ -45,8 +45,29 @@ public override ManageResult Manage(Msg msg) } if (msg.IsJetStream) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + ulong receivedConsumerSeq = msg.MetaData.ConsumerSequence; +After: + var receivedConsumerSeq = msg.MetaData.ConsumerSequence; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: ulong receivedConsumerSeq = msg.MetaData.ConsumerSequence; +After: + var receivedConsumerSeq = msg.MetaData.ConsumerSequence; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + ulong receivedConsumerSeq = msg.MetaData.ConsumerSequence; +After: + var receivedConsumerSeq = msg.MetaData.ConsumerSequence; +*/ + + { + var receivedConsumerSeq = msg.MetaData.ConsumerSequence; if (ExpectedExternalConsumerSeq != receivedConsumerSeq) { TargetSid = null; diff --git a/src/NATS.Client/v1/JetStream/PullRequestOptions.cs b/src/NATS.Client/v1/JetStream/PullRequestOptions.cs index 5d6a16ad..c6a837a9 100644 --- a/src/NATS.Client/v1/JetStream/PullRequestOptions.cs +++ b/src/NATS.Client/v1/JetStream/PullRequestOptions.cs @@ -26,7 +26,7 @@ public class PullRequestOptions : JsonSerializable /// The size of the batch /// public int BatchSize { get; } - + /// /// The maximum number of bytes in the batch /// @@ -36,12 +36,12 @@ public class PullRequestOptions : JsonSerializable /// The no wait flag /// public bool NoWait { get; } - + /// /// The expires in setting /// public Duration ExpiresIn { get; } - + /// /// The idle heartbeat time /// @@ -57,8 +57,29 @@ protected PullRequestOptions(PullRequestOptionsBuilder pro) } public override JSONNode ToJsonNode() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject jso = new JSONObject {[ApiConstants.Batch] = BatchSize}; +After: + var jso = new JSONObject {[ApiConstants.Batch] = BatchSize}; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONObject jso = new JSONObject {[ApiConstants.Batch] = BatchSize}; +After: + var jso = new JSONObject {[ApiConstants.Batch] = BatchSize}; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: JSONObject jso = new JSONObject {[ApiConstants.Batch] = BatchSize}; +After: + var jso = new JSONObject {[ApiConstants.Batch] = BatchSize}; +*/ + + { + var jso = new JSONObject { [ApiConstants.Batch] = BatchSize }; if (MaxBytes > 0) { jso[ApiConstants.MaxBytes] = MaxBytes; @@ -99,7 +120,7 @@ public sealed class PullRequestOptionsBuilder internal bool _noWait; internal Duration _expiresIn; internal Duration _idleHeartbeat; - + /// /// Set the batch size for the pull /// @@ -110,7 +131,7 @@ public PullRequestOptionsBuilder WithBatchSize(int batchSize) _batchSize = batchSize; return this; } - + /// /// Set the maximum bytes for the pull /// @@ -121,7 +142,7 @@ public PullRequestOptionsBuilder WithMaxBytes(long maxBytes) _maxBytes = maxBytes; return this; } - + /// /// Set the no wait to true /// @@ -131,7 +152,7 @@ public PullRequestOptionsBuilder WithNoWait() _noWait = true; return this; } - + /// /// Set the no wait flag /// @@ -142,7 +163,7 @@ public PullRequestOptionsBuilder WithNoWait(bool noWait) _noWait = noWait; return this; } - + /// /// Set the expires duration time in millis /// @@ -153,7 +174,7 @@ public PullRequestOptionsBuilder WithExpiresIn(long expiresInMillis) _expiresIn = Duration.OfMillis(expiresInMillis); return this; } - + /// /// Set the expires duration /// @@ -164,7 +185,7 @@ public PullRequestOptionsBuilder WithExpiresIn(Duration expiresIn) _expiresIn = expiresIn; return this; } - + /// /// Set the idle heartbeat time in millis /// @@ -175,7 +196,7 @@ public PullRequestOptionsBuilder WithIdleHeartbeat(long idleHeartbeatMillis) _idleHeartbeat = Duration.OfMillis(idleHeartbeatMillis); return this; } - + /// /// Set the idle heartbeat duration /// @@ -191,21 +212,67 @@ public PullRequestOptionsBuilder WithIdleHeartbeat(Duration idleHeartbeat) /// Builds the PullRequestOptions /// /// The PullRequestOptions object. - public PullRequestOptions Build() + public PullRequestOptions Build() { Validator.ValidateGtZero(_batchSize, "Pull batch size"); - if (_idleHeartbeat != null) { + if (_idleHeartbeat != null) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + long idleNanosTemp = _idleHeartbeat.Nanos * 2; +After: + var idleNanosTemp = _idleHeartbeat.Nanos * 2; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + long idleNanosTemp = _idleHeartbeat.Nanos * 2; +After: + var idleNanosTemp = _idleHeartbeat.Nanos * 2; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: long idleNanosTemp = _idleHeartbeat.Nanos * 2; - if (idleNanosTemp > 0) { - if (_expiresIn == null) { +After: + var idleNanosTemp = _idleHeartbeat.Nanos * 2; +*/ + + { + var idleNanosTemp = _idleHeartbeat.Nanos * 2; + if (idleNanosTemp > 0) + { + if (_expiresIn == null) + { throw new ArgumentException("Idle Heartbeat not allowed without expiration."); - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + long expiresNanos = _expiresIn.Nanos; +After: + var expiresNanos = _expiresIn.Nanos; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: long expiresNanos = _expiresIn.Nanos; - if (idleNanosTemp > expiresNanos) { +After: + var expiresNanos = _expiresIn.Nanos; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + long expiresNanos = _expiresIn.Nanos; +After: + var expiresNanos = _expiresIn.Nanos; +*/ + + } + var expiresNanos = _expiresIn.Nanos; + if (idleNanosTemp > expiresNanos) + { throw new ArgumentException("Idle Heartbeat cannot be more than half the expiration."); } } - } + } return new PullRequestOptions(this); } } diff --git a/src/NATS.Client/v1/JetStream/PullSubscribeOptions.cs b/src/NATS.Client/v1/JetStream/PullSubscribeOptions.cs index 8eff87c1..7ee4ca10 100644 --- a/src/NATS.Client/v1/JetStream/PullSubscribeOptions.cs +++ b/src/NATS.Client/v1/JetStream/PullSubscribeOptions.cs @@ -1,4 +1,4 @@ -// Copyright 2021 The NATS Authors +// Copyright 2021 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -18,7 +18,7 @@ public sealed class PullSubscribeOptions : SubscribeOptions public static readonly PullSubscribeOptions DefaultPullOpts = PullSubscribeOptions.Builder().Build(); // Validation is done by base class - private PullSubscribeOptions(ISubscribeOptionsBuilder builder) : base(builder, true, null, null) {} + private PullSubscribeOptions(ISubscribeOptionsBuilder builder) : base(builder, true, null, null) { } /// /// Create PullSubscribeOptions where you are binding to @@ -27,7 +27,8 @@ private PullSubscribeOptions(ISubscribeOptionsBuilder builder) : base(builder, t /// the stream name to bind to /// the consumer name, commonly the durable name /// the PullSubscribeOptions - public static PullSubscribeOptions BindTo(string stream, string name) { + public static PullSubscribeOptions BindTo(string stream, string name) + { return Builder().WithStream(stream).WithName(name).WithBind(true).Build(); } @@ -44,7 +45,8 @@ public static PullSubscribeOptions BindTo(string stream, string name) { /// the stream name to bind to /// the consumer name, commonly the durable name /// the PushSubscribeOptions - public static PullSubscribeOptions FastBindTo(string stream, string name) { + public static PullSubscribeOptions FastBindTo(string stream, string name) + { return Builder().WithStream(stream).WithName(name).WithFastBind(true).Build(); } @@ -62,7 +64,7 @@ public class PullSubscribeOptionsBuilder : PullSubscribeOptionsSubscribeOptionsB /// /// PullSubscribeOptionsSubscribeOptionsBuilder was a naming type. Please use the simpler PullSubscribeOptionsBuilder /// - public class PullSubscribeOptionsSubscribeOptionsBuilder + public class PullSubscribeOptionsSubscribeOptionsBuilder : SubscribeOptionsBuilder { protected override PullSubscribeOptionsSubscribeOptionsBuilder GetThis() diff --git a/src/NATS.Client/v1/JetStream/PurgeOptions.cs b/src/NATS.Client/v1/JetStream/PurgeOptions.cs index 0bb3164f..b1e8c20f 100644 --- a/src/NATS.Client/v1/JetStream/PurgeOptions.cs +++ b/src/NATS.Client/v1/JetStream/PurgeOptions.cs @@ -1,4 +1,4 @@ -using System; +using System; using NATS.Client.Internals; using NATS.Client.Internals.SimpleJSON; @@ -68,7 +68,7 @@ public sealed class PurgeOptionsBuilder private string _subject; private ulong _sequence; private ulong _keep; - + /// /// Set the subject to filter the purge. Wildcards allowed. /// @@ -106,11 +106,12 @@ public PurgeOptionsBuilder WithKeep(ulong keep) /// Builds the PurgeOptions /// /// The PurgeOptions object. - public PurgeOptions Build() + public PurgeOptions Build() { Validator.ValidateSubject(_subject, false); - - if (_sequence > 0 && _keep > 0) { + + if (_sequence > 0 && _keep > 0) + { throw new ArgumentException("seq and keep are mutually exclusive."); } diff --git a/src/NATS.Client/v1/JetStream/PushMessageManager.cs b/src/NATS.Client/v1/JetStream/PushMessageManager.cs index b5bc12db..01e8b851 100644 --- a/src/NATS.Client/v1/JetStream/PushMessageManager.cs +++ b/src/NATS.Client/v1/JetStream/PushMessageManager.cs @@ -24,21 +24,43 @@ public class PushMessageManager : MessageManager protected readonly bool QueueMode; protected readonly bool Fc; protected string LastFcSubject; - - public PushMessageManager(Connection conn, - JetStream js, + + public PushMessageManager(Connection conn, + JetStream js, string stream, SubscribeOptions so, - ConsumerConfiguration originalCc, - bool queueMode, + ConsumerConfiguration originalCc, + bool queueMode, bool syncMode) : base(conn, so, syncMode) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this.Js = js; +After: + Js = js; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: this.Js = js; +After: + Js = js; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this.Js = js; +After: + Js = js; +*/ + + { + Js = js; Stream = stream; OriginalCc = originalCc; QueueMode = queueMode; - if (queueMode) { + if (queueMode) + { Fc = false; } else @@ -52,7 +74,8 @@ public override void Startup(IJetStreamSubscription sub) { base.Startup(sub); ((Subscription)Sub).BeforeChannelAddCheck = BeforeChannelAddCheck; - if (Hb) { + if (Hb) + { InitOrResetHeartbeatTimer(); } } @@ -74,15 +97,18 @@ protected override bool BeforeChannelAddCheck(Msg msg) return true; } - protected bool hasFcSubject(Msg msg) { + protected bool hasFcSubject(Msg msg) + { return msg.Header != null && msg.Header[JetStreamConstants.ConsumerStalledHeader] != null; } - protected string extractFcSubject(Msg msg) { + protected string extractFcSubject(Msg msg) + { return msg.Header == null ? null : msg.Header[JetStreamConstants.ConsumerStalledHeader]; } - public override ManageResult Manage(Msg msg) { + public override ManageResult Manage(Msg msg) + { if (!msg.HasStatus) { TrackJsMessage(msg); @@ -91,14 +117,44 @@ public override ManageResult Manage(Msg msg) { return ManageStatus(msg); } - protected ManageResult ManageStatus(Msg msg) { + protected ManageResult ManageStatus(Msg msg) + { // this checks fc, hb and unknown // only process fc and hb if those flags are set // otherwise they are simply known statuses - if (Fc) { + if (Fc) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: bool isFlowControl = msg.Status.IsFlowControl(); string fcSubject = isFlowControl ? msg.Reply : extractFcSubject(msg); - if (fcSubject != null) { +After: + var isFlowControl = msg.Status.IsFlowControl(); + var fcSubject = isFlowControl ? msg.Reply : extractFcSubject(msg); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + bool isFlowControl = msg.Status.IsFlowControl(); + string fcSubject = isFlowControl ? msg.Reply : extractFcSubject(msg); +After: + var isFlowControl = msg.Status.IsFlowControl(); + var fcSubject = isFlowControl ? msg.Reply : extractFcSubject(msg); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + bool isFlowControl = msg.Status.IsFlowControl(); + string fcSubject = isFlowControl ? msg.Reply : extractFcSubject(msg); +After: + var isFlowControl = msg.Status.IsFlowControl(); + var fcSubject = isFlowControl ? msg.Reply : extractFcSubject(msg); +*/ + + { + var isFlowControl = msg.Status.IsFlowControl(); + var fcSubject = isFlowControl ? msg.Reply : extractFcSubject(msg); + if (fcSubject != null) + { _processFlowControl(fcSubject, isFlowControl ? FlowControlSource.FlowControl : FlowControlSource.Heartbeat); return ManageResult.StatusHandled; } @@ -107,10 +163,12 @@ protected ManageResult ManageStatus(Msg msg) { return ManageResult.StatusError; } - private void _processFlowControl(string fcSubject, FlowControlSource source) { + private void _processFlowControl(string fcSubject, FlowControlSource source) + { // we may get multiple fc/hb messages with the same reply // only need to post to that subject once - if (fcSubject != null && !fcSubject.Equals(LastFcSubject)) { + if (fcSubject != null && !fcSubject.Equals(LastFcSubject)) + { Conn.Publish(fcSubject, null); LastFcSubject = fcSubject; // set after publish in case the pub fails Conn.Opts.FlowControlProcessedEventHandlerOrDefault.Invoke(this, new FlowControlProcessedEventArgs(Conn, (Subscription)Sub, fcSubject, source)); diff --git a/src/NATS.Client/v1/JetStream/PushSubscribeOptions.cs b/src/NATS.Client/v1/JetStream/PushSubscribeOptions.cs index 1fdb0e75..dfa755ce 100644 --- a/src/NATS.Client/v1/JetStream/PushSubscribeOptions.cs +++ b/src/NATS.Client/v1/JetStream/PushSubscribeOptions.cs @@ -18,10 +18,10 @@ public sealed class PushSubscribeOptions : SubscribeOptions public static readonly PushSubscribeOptions DefaultPushOpts = PushSubscribeOptions.Builder().Build(); // Validation is done by base class - private PushSubscribeOptions(ISubscribeOptionsBuilder builder, + private PushSubscribeOptions(ISubscribeOptionsBuilder builder, string deliverSubject, string deliverGroup, - long pendingMessageLimit, long pendingByteLimit) - : base(builder, false, deliverSubject, deliverGroup, pendingMessageLimit, pendingByteLimit) {} + long pendingMessageLimit, long pendingByteLimit) + : base(builder, false, deliverSubject, deliverGroup, pendingMessageLimit, pendingByteLimit) { } /// /// Create PushSubscribeOptions where you are binding to @@ -29,7 +29,8 @@ private PushSubscribeOptions(ISubscribeOptionsBuilder builder, /// /// the stream name to bind to /// the PushSubscribeOptions - public static PushSubscribeOptions ForStream(string stream) { + public static PushSubscribeOptions ForStream(string stream) + { return new PushSubscribeOptionsBuilder().WithStream(stream).Build(); } @@ -51,7 +52,8 @@ public static PushSubscribeOptions BindTo(string stream, string durable) /// /// The builder /// - public static PushSubscribeOptionsBuilder Builder() { + public static PushSubscribeOptionsBuilder Builder() + { return new PushSubscribeOptionsBuilder(); } @@ -112,7 +114,7 @@ public PushSubscribeOptionsBuilder WithPendingMessageLimit(long pendingMessageLi _pendingMessageLimit = pendingMessageLimit; return this; } - + /// /// Set the maximum number of bytes that push subscriptions can hold /// in the internal (pending) message queue. Defaults to 64 * 1024 * 1024 (Nats.SubPendingBytesLimit) diff --git a/src/NATS.Client/v1/JetStream/Replica.cs b/src/NATS.Client/v1/JetStream/Replica.cs index 3ccd19b9..9665ed39 100644 --- a/src/NATS.Client/v1/JetStream/Replica.cs +++ b/src/NATS.Client/v1/JetStream/Replica.cs @@ -23,9 +23,30 @@ internal static List OptionalListOf(JSONNode replicaListNode) if (replicaListNode == null) { return null; - } - +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + List list = new List(); +After: + var list = new List(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + List list = new List(); +After: + var list = new List(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: List list = new List(); +After: + var list = new List(); +*/ + + } + + var list = new List(); foreach (var replicaNode in replicaListNode.Children) { list.Add(new Replica(replicaNode)); @@ -33,6 +54,6 @@ internal static List OptionalListOf(JSONNode replicaListNode) return list.Count == 0 ? null : list; } - internal Replica(JSONNode replicaNode) : base(replicaNode) {} + internal Replica(JSONNode replicaNode) : base(replicaNode) { } } } diff --git a/src/NATS.Client/v1/JetStream/Republish.cs b/src/NATS.Client/v1/JetStream/Republish.cs index f1ecb681..8b165e1f 100644 --- a/src/NATS.Client/v1/JetStream/Republish.cs +++ b/src/NATS.Client/v1/JetStream/Republish.cs @@ -31,7 +31,7 @@ public sealed class Republish : JsonSerializable /// The RePublish Subject template /// public string Destination { get; } - + /// /// Whether to RePublish only headers (no body) /// @@ -65,8 +65,29 @@ public Republish(string source, string destination, bool headersOnly) } public override JSONNode ToJsonNode() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + + { + var o = new JSONObject(); AddField(o, ApiConstants.Src, Source); AddField(o, ApiConstants.Dest, Destination); AddField(o, ApiConstants.HeadersOnly, HeadersOnly); @@ -77,14 +98,16 @@ public override JSONNode ToJsonNode() /// Creates a builder for a republish object. /// /// The Builder - public static RepublishBuilder Builder() { + public static RepublishBuilder Builder() + { return new RepublishBuilder(); } /// /// Republish can be created using a RepublishBuilder. /// - public sealed class RepublishBuilder { + public sealed class RepublishBuilder + { private string _source; private string _destination; private bool _headersOnly; @@ -94,7 +117,8 @@ public sealed class RepublishBuilder { /// /// the source /// - public RepublishBuilder WithSource(string source) { + public RepublishBuilder WithSource(string source) + { _source = source; return this; } @@ -104,17 +128,19 @@ public RepublishBuilder WithSource(string source) { /// /// the destination /// - public RepublishBuilder WithDestination(string destination) { + public RepublishBuilder WithDestination(string destination) + { _destination = destination; return this; } - + /// /// Set Whether to RePublish only headers (no body) /// /// the headers only flag /// - public RepublishBuilder WithHeadersOnly(bool headersOnly) { + public RepublishBuilder WithHeadersOnly(bool headersOnly) + { _headersOnly = headersOnly; return this; } @@ -123,7 +149,8 @@ public RepublishBuilder WithHeadersOnly(bool headersOnly) { /// Build a Republish object /// /// The Republish - public Republish Build() { + public Republish Build() + { return new Republish(_source, _destination, _headersOnly); } } diff --git a/src/NATS.Client/v1/JetStream/SequenceInfo.cs b/src/NATS.Client/v1/JetStream/SequenceInfo.cs index 14ad9b11..9e77eecf 100644 --- a/src/NATS.Client/v1/JetStream/SequenceInfo.cs +++ b/src/NATS.Client/v1/JetStream/SequenceInfo.cs @@ -26,7 +26,7 @@ public sealed class SequenceInfo : SequencePair internal SequenceInfo(JSONNode spNode) : base(spNode) { - LastActive = AsDate(spNode[ApiConstants.LastActive]); + LastActive = AsDate(spNode[ApiConstants.LastActive]); } public override string ToString() diff --git a/src/NATS.Client/v1/JetStream/ServerInfo.cs b/src/NATS.Client/v1/JetStream/ServerInfo.cs index d0de815b..d34fb7a8 100644 --- a/src/NATS.Client/v1/JetStream/ServerInfo.cs +++ b/src/NATS.Client/v1/JetStream/ServerInfo.cs @@ -71,23 +71,28 @@ public ServerInfo(string json) .ToArray(); } - public bool IsNewerVersionThan(string vTarget) { + public bool IsNewerVersionThan(string vTarget) + { return ServerVersion.IsNewer(Version, vTarget); } - public bool IsSameVersion(string vTarget) { + public bool IsSameVersion(string vTarget) + { return ServerVersion.IsSame(Version, vTarget); } - public bool IsOlderThanVersion(string vTarget) { + public bool IsOlderThanVersion(string vTarget) + { return ServerVersion.IsOlder(Version, vTarget); } - public bool IsSameOrOlderThanVersion(string vTarget) { + public bool IsSameOrOlderThanVersion(string vTarget) + { return ServerVersion.IsSameOrOlder(Version, vTarget); } - public bool IsSameOrNewerThanVersion(string vTarget) { + public bool IsSameOrNewerThanVersion(string vTarget) + { return ServerVersion.IsSameOrNewer(Version, vTarget); } diff --git a/src/NATS.Client/v1/JetStream/Source.cs b/src/NATS.Client/v1/JetStream/Source.cs index c2821e15..7b5a5278 100644 --- a/src/NATS.Client/v1/JetStream/Source.cs +++ b/src/NATS.Client/v1/JetStream/Source.cs @@ -27,9 +27,30 @@ internal static List OptionalListOf(JSONNode sourceListNode) if (sourceListNode == null) { return null; - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + List list = new List(); +After: + var list = new List(); +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: List list = new List(); +After: + var list = new List(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + List list = new List(); +After: + var list = new List(); +*/ + + } + + var list = new List(); foreach (var sourceNode in sourceListNode.Children) { list.Add(new Source(sourceNode)); @@ -48,25 +69,27 @@ internal static List OptionalListOf(JSONNode sourceListNode) /// the subject transforms, defaults to none public Source(string name, ulong startSeq, DateTime startTime, string filterSubject, External external, IList subjectTransforms = null) - : base(name, startSeq, startTime, filterSubject, external, subjectTransforms) {} + : base(name, startSeq, startTime, filterSubject, external, subjectTransforms) { } - internal Source(JSONNode sourceBaseNode) : base(sourceBaseNode) {} + internal Source(JSONNode sourceBaseNode) : base(sourceBaseNode) { } - internal Source(SourceBuilder sb) : base(sb) {} + internal Source(SourceBuilder sb) : base(sb) { } /// /// Creates a builder for a source object. /// /// The Builder - public static SourceBuilder Builder() { + public static SourceBuilder Builder() + { return new SourceBuilder(); } - + /// /// Creates a builder for a source object based on an existing source object. /// /// The Builder - public static SourceBuilder Builder(Source source) { + public static SourceBuilder Builder(Source source) + { return new SourceBuilder(source); } @@ -75,8 +98,8 @@ public static SourceBuilder Builder(Source source) { /// public sealed class SourceBuilder : SourceBaseBuilder { - public SourceBuilder() {} - public SourceBuilder(Source source) : base(source) {} + public SourceBuilder() { } + public SourceBuilder(Source source) : base(source) { } protected override SourceBuilder GetThis() { diff --git a/src/NATS.Client/v1/JetStream/SourceBase.cs b/src/NATS.Client/v1/JetStream/SourceBase.cs index cbfb8f9e..972b3921 100644 --- a/src/NATS.Client/v1/JetStream/SourceBase.cs +++ b/src/NATS.Client/v1/JetStream/SourceBase.cs @@ -14,17 +14,17 @@ public class SourceBase : JsonSerializable /// Source stream name. /// public string Name { get; } - + /// /// The sequence to start replicating from. /// public ulong StartSeq { get; } - + /// /// The time stamp to start replicating from. /// public DateTime StartTime { get; } - + /// /// The subject filter to replicate /// @@ -60,7 +60,7 @@ protected SourceBase(string name, ulong startSeq, DateTime startTime, string fil External = external; SubjectTransforms = subjectTransforms; } - + protected SourceBase(ISourceBaseBuilder isbb) { Name = isbb.Name; @@ -72,8 +72,29 @@ protected SourceBase(ISourceBaseBuilder isbb) } public override JSONNode ToJsonNode() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + + { + var jso = new JSONObject(); JsonUtils.AddField(jso, ApiConstants.Name, Name); JsonUtils.AddField(jso, ApiConstants.OptStartSeq, StartSeq); JsonUtils.AddField(jso, ApiConstants.OptStartTime, JsonUtils.ToString(StartTime)); @@ -82,7 +103,7 @@ public override JSONNode ToJsonNode() JsonUtils.AddField(jso, ApiConstants.SubjectTransforms, SubjectTransforms); return jso; } - + public interface ISourceBaseBuilder { string Name { get; } @@ -108,7 +129,7 @@ public abstract class SourceBaseBuilder : ISourceBaseBuil public string FilterSubject => _filterSubject; public External External => _external; public IList SubjectTransforms => _subjectTransforms; - + protected abstract TBuilder GetThis(); protected SourceBaseBuilder() { } @@ -184,8 +205,29 @@ public TBuilder WithExternal(External external) /// the domain /// The Builder public TBuilder WithDomain(string domain) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string prefix = JetStreamOptions.ConvertDomainToPrefix(domain); +After: + var prefix = JetStreamOptions.ConvertDomainToPrefix(domain); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string prefix = JetStreamOptions.ConvertDomainToPrefix(domain); +After: + var prefix = JetStreamOptions.ConvertDomainToPrefix(domain); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string prefix = JetStreamOptions.ConvertDomainToPrefix(domain); +After: + var prefix = JetStreamOptions.ConvertDomainToPrefix(domain); +*/ + + { + var prefix = JetStreamOptions.ConvertDomainToPrefix(domain); _external = prefix == null ? null : External.Builder().WithApi(prefix).Build(); return GetThis(); } @@ -221,19 +263,22 @@ public TBuilder WithSubjectTransforms(IList subjectTransforms) protected bool Equals(SourceBase other) { - return Name == other.Name - && StartSeq == other.StartSeq - && StartTime.Equals(other.StartTime) - && FilterSubject == other.FilterSubject + return Name == other.Name + && StartSeq == other.StartSeq + && StartTime.Equals(other.StartTime) + && FilterSubject == other.FilterSubject && Equals(External, other.External) && Validator.SequenceEqual(SubjectTransforms, other.SubjectTransforms); } public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (ReferenceEquals(null, obj)) + return false; + if (ReferenceEquals(this, obj)) + return true; + if (obj.GetType() != GetType()) + return false; return Equals((SourceBase)obj); } @@ -251,4 +296,4 @@ public override int GetHashCode() } } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/JetStream/SourceInfo.cs b/src/NATS.Client/v1/JetStream/SourceInfo.cs index d36291a5..f4ffb04a 100644 --- a/src/NATS.Client/v1/JetStream/SourceInfo.cs +++ b/src/NATS.Client/v1/JetStream/SourceInfo.cs @@ -23,9 +23,30 @@ internal static List OptionalListOf(JSONNode sourceInfoListNode) if (sourceInfoListNode == null) { return null; - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + List list = new List(); +After: + var list = new List(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + List list = new List(); +After: + var list = new List(); +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: List list = new List(); +After: + var list = new List(); +*/ + + } + + var list = new List(); foreach (var s in sourceInfoListNode.Children) { list.Add(new SourceInfo(s)); diff --git a/src/NATS.Client/v1/JetStream/StreamConfiguration.cs b/src/NATS.Client/v1/JetStream/StreamConfiguration.cs index e05ce505..fa6cf7fb 100644 --- a/src/NATS.Client/v1/JetStream/StreamConfiguration.cs +++ b/src/NATS.Client/v1/JetStream/StreamConfiguration.cs @@ -60,13 +60,13 @@ public sealed class StreamConfiguration : JsonSerializable public long MaxValueSize => MaximumMessageSize; internal StreamConfiguration(string json) : this(JSON.Parse(json)) { } - + internal StreamConfiguration(JSONNode scNode) { - RetentionPolicy = ApiEnums.GetValueOrDefault(scNode[ApiConstants.Retention].Value,RetentionPolicy.Limits); - CompressionOption = ApiEnums.GetValueOrDefault(scNode[ApiConstants.Compression].Value,CompressionOption.None); - StorageType = ApiEnums.GetValueOrDefault(scNode[ApiConstants.Storage].Value,StorageType.File); - DiscardPolicy = ApiEnums.GetValueOrDefault(scNode[ApiConstants.Discard].Value,DiscardPolicy.Old); + RetentionPolicy = ApiEnums.GetValueOrDefault(scNode[ApiConstants.Retention].Value, RetentionPolicy.Limits); + CompressionOption = ApiEnums.GetValueOrDefault(scNode[ApiConstants.Compression].Value, CompressionOption.None); + StorageType = ApiEnums.GetValueOrDefault(scNode[ApiConstants.Storage].Value, StorageType.File); + DiscardPolicy = ApiEnums.GetValueOrDefault(scNode[ApiConstants.Discard].Value, DiscardPolicy.Old); Name = scNode[ApiConstants.Name].Value; Description = scNode[ApiConstants.Description].Value; Subjects = StringList(scNode, ApiConstants.Subjects); @@ -96,11 +96,11 @@ internal StreamConfiguration(JSONNode scNode) Metadata = JsonUtils.StringStringDictionary(scNode, ApiConstants.Metadata); FirstSequence = AsUlongOr(scNode, ApiConstants.FirstSequence, 1U); } - + private StreamConfiguration(StreamConfigurationBuilder builder) { Name = builder._name; - Description = builder._description; + Description = builder._description; Subjects = builder._subjects; RetentionPolicy = builder._retentionPolicy; CompressionOption = builder._compressionOption; @@ -134,8 +134,29 @@ private StreamConfiguration(StreamConfigurationBuilder builder) } public override JSONNode ToJsonNode() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + + { + var o = new JSONObject(); AddField(o, ApiConstants.Retention, RetentionPolicy.GetString()); if (CompressionOption != CompressionOption.None) { @@ -222,8 +243,8 @@ public sealed class StreamConfigurationBuilder internal Dictionary _metadata = new Dictionary(); internal ulong _firstSequence; - public StreamConfigurationBuilder() {} - + public StreamConfigurationBuilder() { } + public StreamConfigurationBuilder(StreamConfiguration sc) { if (sc != null) @@ -259,7 +280,7 @@ public StreamConfigurationBuilder(StreamConfiguration sc) _denyPurge = sc.DenyPurge; _discardNewPerSubject = sc.DiscardNewPerSubject; _firstSequence = sc.FirstSequence; - foreach (string key in sc.Metadata.Keys) + foreach (var key in sc.Metadata.Keys) { _metadata[key] = sc.Metadata[key]; } @@ -271,7 +292,8 @@ public StreamConfigurationBuilder(StreamConfiguration sc) /// /// name of the stream. /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithName(string name) { + public StreamConfigurationBuilder WithName(string name) + { _name = Validator.ValidateStreamName(name, false); return this; } @@ -292,7 +314,8 @@ public StreamConfigurationBuilder WithDescription(string description) /// /// the stream's subjects /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithSubjects(params string[] subjects) { + public StreamConfigurationBuilder WithSubjects(params string[] subjects) + { _subjects.Clear(); return AddSubjects(subjects); } @@ -302,7 +325,8 @@ public StreamConfigurationBuilder WithSubjects(params string[] subjects) { /// /// the stream's subjects /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithSubjects(List subjects) { + public StreamConfigurationBuilder WithSubjects(List subjects) + { _subjects.Clear(); return AddSubjects(subjects); } @@ -312,15 +336,40 @@ public StreamConfigurationBuilder WithSubjects(List subjects) { /// /// the stream's subjects /// The StreamConfigurationBuilder - public StreamConfigurationBuilder AddSubjects(params string[] subjects) { - if (subjects != null) { - foreach (string sub in subjects) { - if (sub != null && !_subjects.Contains(sub)) { + public StreamConfigurationBuilder AddSubjects(params string[] subjects) + { + if (subjects != null) + { + foreach (var sub in subjects) + { + if (sub != null && !_subjects.Contains(sub)) + { _subjects.Add(sub); } } } return this; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + foreach (string sub in subjects) { +After: + foreach (var sub in subjects) { +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + foreach (string sub in subjects) { +After: + foreach (var sub in subjects) { +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + foreach (string sub in subjects) { +After: + foreach (var sub in subjects) { +*/ + } /// @@ -328,10 +377,14 @@ public StreamConfigurationBuilder AddSubjects(params string[] subjects) { /// /// the stream's subjects /// The StreamConfigurationBuilder - public StreamConfigurationBuilder AddSubjects(List subjects) { - if (subjects != null) { - foreach (string sub in subjects) { - if (sub != null && !_subjects.Contains(sub)) { + public StreamConfigurationBuilder AddSubjects(List subjects) + { + if (subjects != null) + { + foreach (var sub in subjects) + { + if (sub != null && !_subjects.Contains(sub)) + { _subjects.Add(sub); } } @@ -344,7 +397,8 @@ public StreamConfigurationBuilder AddSubjects(List subjects) { /// /// the retention policy of the StreamConfiguration /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithRetentionPolicy(RetentionPolicy? policy) { + public StreamConfigurationBuilder WithRetentionPolicy(RetentionPolicy? policy) + { _retentionPolicy = policy ?? RetentionPolicy.Limits; return this; } @@ -354,7 +408,8 @@ public StreamConfigurationBuilder WithRetentionPolicy(RetentionPolicy? policy) { /// /// the compression option of the StreamConfiguration /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithCompressionOption(CompressionOption? option) { + public StreamConfigurationBuilder WithCompressionOption(CompressionOption? option) + { _compressionOption = option ?? CompressionOption.None; return this; } @@ -364,7 +419,7 @@ public StreamConfigurationBuilder WithCompressionOption(CompressionOption? optio /// /// the maximum number of consumers /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithMaxConsumers(long maxConsumers) + public StreamConfigurationBuilder WithMaxConsumers(long maxConsumers) { _maxConsumers = Validator.ValidateMaxConsumers(maxConsumers); return this; @@ -375,7 +430,8 @@ public StreamConfigurationBuilder WithMaxConsumers(long maxConsumers) /// /// the maximum number of messages /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithMaxMessages(long maxMsgs) { + public StreamConfigurationBuilder WithMaxMessages(long maxMsgs) + { _maxMsgs = Validator.ValidateMaxMessages(maxMsgs); return this; } @@ -385,17 +441,19 @@ public StreamConfigurationBuilder WithMaxMessages(long maxMsgs) { /// /// the maximum number of messages /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithMaxMessagesPerSubject(long maxMsgsPerSubject) { + public StreamConfigurationBuilder WithMaxMessagesPerSubject(long maxMsgsPerSubject) + { _maxMsgsPerSubject = Validator.ValidateMaxMessagesPerSubject(maxMsgsPerSubject); return this; } - + /// /// Sets the maximum number of bytes in the StreamConfiguration. /// /// the maximum number of bytes /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithMaxBytes(long maxBytes) { + public StreamConfigurationBuilder WithMaxBytes(long maxBytes) + { _maxBytes = Validator.ValidateMaxBytes(maxBytes); return this; } @@ -405,7 +463,28 @@ public StreamConfigurationBuilder WithMaxBytes(long maxBytes) { /// /// the maximum message age as a Duration /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithMaxAge(Duration maxAge) + public StreamConfigurationBuilder WithMaxAge( +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + foreach (Source source in sources) +After: + foreach (var source in sources) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + foreach (Source source in sources) +After: + foreach (var source in sources) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + foreach (Source source in sources) +After: + foreach (var source in sources) +*/ +Duration maxAge) { _maxAge = Validator.ValidateDurationNotRequiredGtOrEqZero(maxAge); return this; @@ -416,7 +495,29 @@ public StreamConfigurationBuilder WithMaxAge(Duration maxAge) /// /// the maximum message age as millis /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithMaxAge(long maxAgeMillis) { + public StreamConfigurationBuilder WithMaxAge( +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + foreach (Source source in sources) +After: + foreach (var source in sources) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + foreach (Source source in sources) +After: + foreach (var source in sources) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + foreach (Source source in sources) +After: + foreach (var source in sources) +*/ +long maxAgeMillis) + { _maxAge = Validator.ValidateDurationNotRequiredGtOrEqZero(maxAgeMillis); return this; } @@ -427,7 +528,8 @@ public StreamConfigurationBuilder WithMaxAge(long maxAgeMillis) { /// the maximum message size /// The StreamConfigurationBuilder [Obsolete("The server value is a 32-bit signed value. Use WithMaximumMessageSize.", false)] - public StreamConfigurationBuilder WithMaxMsgSize(long maxMsgSize) { + public StreamConfigurationBuilder WithMaxMsgSize(long maxMsgSize) + { _maxMsgSize = (int)Validator.ValidateMaxMessageSize(maxMsgSize); return this; } @@ -437,7 +539,8 @@ public StreamConfigurationBuilder WithMaxMsgSize(long maxMsgSize) { /// /// the maximum message size /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithMaximumMessageSize(int maxMsgSize) { + public StreamConfigurationBuilder WithMaximumMessageSize(int maxMsgSize) + { _maxMsgSize = (int)Validator.ValidateMaxMessageSize(maxMsgSize); return this; } @@ -447,7 +550,8 @@ public StreamConfigurationBuilder WithMaximumMessageSize(int maxMsgSize) { /// /// the storage type /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithStorageType(StorageType? storageType) { + public StreamConfigurationBuilder WithStorageType(StorageType? storageType) + { _storageType = storageType ?? StorageType.File; return this; } @@ -457,7 +561,8 @@ public StreamConfigurationBuilder WithStorageType(StorageType? storageType) { /// /// the number of replicas to store this message on /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithReplicas(int replicas) { + public StreamConfigurationBuilder WithReplicas(int replicas) + { _replicas = Validator.ValidateNumberOfReplicas(replicas); return this; } @@ -468,7 +573,8 @@ public StreamConfigurationBuilder WithReplicas(int replicas) { /// /// true to disable acknowledgements. /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithNoAck(bool noAck) { + public StreamConfigurationBuilder WithNoAck(bool noAck) + { _noAck = noAck; return this; } @@ -478,7 +584,8 @@ public StreamConfigurationBuilder WithNoAck(bool noAck) { /// /// the stream template of the stream. /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithTemplateOwner(string templateOwner) { + public StreamConfigurationBuilder WithTemplateOwner(string templateOwner) + { _templateOwner = Validator.EmptyAsNull(templateOwner); return this; } @@ -488,7 +595,8 @@ public StreamConfigurationBuilder WithTemplateOwner(string templateOwner) { /// /// the discard policy of the StreamConfiguration /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithDiscardPolicy(DiscardPolicy? policy) { + public StreamConfigurationBuilder WithDiscardPolicy(DiscardPolicy? policy) + { _discardPolicy = policy ?? DiscardPolicy.Old; return this; } @@ -499,7 +607,29 @@ public StreamConfigurationBuilder WithDiscardPolicy(DiscardPolicy? policy) { /// /// duration to hold message ids for duplicate checking. /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithDuplicateWindow(Duration window) { + public StreamConfigurationBuilder WithDuplicateWindow( +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + foreach (string key in metadata.Keys) +After: + foreach (var key in metadata.Keys) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + foreach (string key in metadata.Keys) +After: + foreach (var key in metadata.Keys) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + foreach (string key in metadata.Keys) +After: + foreach (var key in metadata.Keys) +*/ +Duration window) + { _duplicateWindow = Validator.ValidateDurationNotRequiredGtOrEqZero(window); return this; } @@ -510,7 +640,8 @@ public StreamConfigurationBuilder WithDuplicateWindow(Duration window) { /// /// duration to hold message ids for duplicate checking. /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithDuplicateWindow(long windowMillis) { + public StreamConfigurationBuilder WithDuplicateWindow(long windowMillis) + { _duplicateWindow = Validator.ValidateDurationNotRequiredGtOrEqZero(windowMillis); return this; } @@ -520,7 +651,8 @@ public StreamConfigurationBuilder WithDuplicateWindow(long windowMillis) { /// /// the placement directive object /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithPlacement(Placement placement) { + public StreamConfigurationBuilder WithPlacement(Placement placement) + { _placement = placement; return this; } @@ -530,7 +662,8 @@ public StreamConfigurationBuilder WithPlacement(Placement placement) { /// /// the republish object /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithRepublish(Republish republish) { + public StreamConfigurationBuilder WithRepublish(Republish republish) + { _republish = republish; return this; } @@ -540,7 +673,8 @@ public StreamConfigurationBuilder WithRepublish(Republish republish) { /// /// the subjectTransform object /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithSubjectTransform(SubjectTransform subjectTransform) { + public StreamConfigurationBuilder WithSubjectTransform(SubjectTransform subjectTransform) + { _subjectTransform = subjectTransform; return this; } @@ -550,7 +684,8 @@ public StreamConfigurationBuilder WithSubjectTransform(SubjectTransform subjectT /// /// the consumerLimits object /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithConsumerLimits(ConsumerLimits consumerLimits) { + public StreamConfigurationBuilder WithConsumerLimits(ConsumerLimits consumerLimits) + { _consumerLimits = consumerLimits; return this; } @@ -560,7 +695,8 @@ public StreamConfigurationBuilder WithConsumerLimits(ConsumerLimits consumerLimi /// /// the mirror object /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithMirror(Mirror mirror) { + public StreamConfigurationBuilder WithMirror(Mirror mirror) + { _mirror = mirror; return this; } @@ -570,7 +706,8 @@ public StreamConfigurationBuilder WithMirror(Mirror mirror) { /// /// the stream's sources /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithSources(params Source[] sources) { + public StreamConfigurationBuilder WithSources(params Source[] sources) + { _sources.Clear(); return AddSources(sources); } @@ -580,7 +717,8 @@ public StreamConfigurationBuilder WithSources(params Source[] sources) { /// /// the stream's sources /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithSources(List sources) { + public StreamConfigurationBuilder WithSources(List sources) + { _sources.Clear(); return AddSources(sources); } @@ -590,12 +728,13 @@ public StreamConfigurationBuilder WithSources(List sources) { /// /// the stream's sources /// The StreamConfigurationBuilder - public StreamConfigurationBuilder AddSources(params Source[] sources) { - if (sources != null) + public StreamConfigurationBuilder AddSources(params Source[] sources) + { + if (sources != null) { - foreach (Source source in sources) + foreach (var source in sources) { - if (source != null && !_sources.Contains(source)) + if (source != null && !_sources.Contains(source)) { _sources.Add(source); } @@ -609,12 +748,13 @@ public StreamConfigurationBuilder AddSources(params Source[] sources) { /// /// the stream's sources /// The StreamConfigurationBuilder - public StreamConfigurationBuilder AddSources(List sources) { - if (sources != null) + public StreamConfigurationBuilder AddSources(List sources) + { + if (sources != null) { - foreach (Source source in sources) + foreach (var source in sources) { - if (source != null && !_sources.Contains(source)) + if (source != null && !_sources.Contains(source)) { _sources.Add(source); } @@ -628,8 +768,10 @@ public StreamConfigurationBuilder AddSources(List sources) { /// /// /// The StreamConfigurationBuilder - public StreamConfigurationBuilder AddSource(Source source) { - if (source != null && !_sources.Contains(source)) { + public StreamConfigurationBuilder AddSource(Source source) + { + if (source != null && !_sources.Contains(source)) + { _sources.Add(source); } return this; @@ -640,7 +782,8 @@ public StreamConfigurationBuilder AddSource(Source source) { /// /// true to allow rollup. /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithAllowRollup(bool allowRollup) { + public StreamConfigurationBuilder WithAllowRollup(bool allowRollup) + { _allowRollup = allowRollup; return this; } @@ -650,7 +793,8 @@ public StreamConfigurationBuilder WithAllowRollup(bool allowRollup) { /// /// the allow direct setting. /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithAllowDirect(bool allowDirect) { + public StreamConfigurationBuilder WithAllowDirect(bool allowDirect) + { _allowDirect = allowDirect; return this; } @@ -660,7 +804,8 @@ public StreamConfigurationBuilder WithAllowDirect(bool allowDirect) { /// /// the mirror direct setting. /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithMirrorDirect(bool mirrorDirect) { + public StreamConfigurationBuilder WithMirrorDirect(bool mirrorDirect) + { _mirrorDirect = mirrorDirect; return this; } @@ -670,7 +815,8 @@ public StreamConfigurationBuilder WithMirrorDirect(bool mirrorDirect) { /// /// true to deny delete. /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithDenyDelete(bool denyDelete) { + public StreamConfigurationBuilder WithDenyDelete(bool denyDelete) + { _denyDelete = denyDelete; return this; } @@ -680,7 +826,8 @@ public StreamConfigurationBuilder WithDenyDelete(bool denyDelete) { /// /// true to deny purge. /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithDenyPurge(bool denyPurge) { + public StreamConfigurationBuilder WithDenyPurge(bool denyPurge) + { _denyPurge = denyPurge; return this; } @@ -690,26 +837,29 @@ public StreamConfigurationBuilder WithDenyPurge(bool denyPurge) { /// /// true to deny purge. /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithDiscardNewPerSubject(bool discardNewPerSubject) { + public StreamConfigurationBuilder WithDiscardNewPerSubject(bool discardNewPerSubject) + { _discardNewPerSubject = discardNewPerSubject; return this; } - + /// /// Sets the first sequence to be used. 1 is the default. 0 is treated as 1. /// /// specify the first_seq in the stream config when creating the stream. /// - public StreamConfigurationBuilder WithFirstSequence(ulong firstSequence) { + public StreamConfigurationBuilder WithFirstSequence(ulong firstSequence) + { _firstSequence = firstSequence == 0 ? 1 : firstSequence; return this; } - + /// /// Set this stream to be sealed. This is irreversible. /// /// The StreamConfigurationBuilder - public StreamConfigurationBuilder Seal() { + public StreamConfigurationBuilder Seal() + { _sealed = true; return this; } @@ -719,11 +869,12 @@ public StreamConfigurationBuilder Seal() { /// /// the metadata dictionary /// The StreamConfigurationBuilder - public StreamConfigurationBuilder WithMetadata(IDictionary metadata) { + public StreamConfigurationBuilder WithMetadata(IDictionary metadata) + { _metadata.Clear(); if (metadata != null) { - foreach (string key in metadata.Keys) + foreach (var key in metadata.Keys) { _metadata[key] = metadata[key]; } diff --git a/src/NATS.Client/v1/JetStream/StreamContext.cs b/src/NATS.Client/v1/JetStream/StreamContext.cs index 8ff84cd1..13586400 100644 --- a/src/NATS.Client/v1/JetStream/StreamContext.cs +++ b/src/NATS.Client/v1/JetStream/StreamContext.cs @@ -1,4 +1,4 @@ -// Copyright 2023 The NATS Authors +// Copyright 2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/src/NATS.Client/v1/JetStream/StreamInfoOptions.cs b/src/NATS.Client/v1/JetStream/StreamInfoOptions.cs index c6b1db2b..d1dae466 100644 --- a/src/NATS.Client/v1/JetStream/StreamInfoOptions.cs +++ b/src/NATS.Client/v1/JetStream/StreamInfoOptions.cs @@ -1,4 +1,4 @@ -// Copyright 2022 The NATS Authors +// Copyright 2022 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -58,7 +58,8 @@ public StreamInfoOptionsBuilder WithFilterSubjects(string subjectsFilter) return this; } - public StreamInfoOptionsBuilder WithAllSubjects() { + public StreamInfoOptionsBuilder WithAllSubjects() + { _subjectsFilter = NatsConstants.GreaterThan; return this; } diff --git a/src/NATS.Client/v1/JetStream/StreamState.cs b/src/NATS.Client/v1/JetStream/StreamState.cs index 2a5a9e88..8f2b345e 100644 --- a/src/NATS.Client/v1/JetStream/StreamState.cs +++ b/src/NATS.Client/v1/JetStream/StreamState.cs @@ -52,13 +52,34 @@ private StreamState(JSONNode streamState) Subjects = Subject.GetList(streamState[ApiConstants.Subjects]); Deleted = new List(); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: JSONNode.Enumerator e = +After: + var e = +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONNode.Enumerator e = +After: + var e = +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONNode.Enumerator e = +After: + var e = +*/ + + var e = streamState[ApiConstants.Deleted].AsArray.GetEnumerator(); while (e.MoveNext()) { Deleted.Add(e.Current.Value.AsUlong); - } - + } + LostStreamData = LostStreamData.OptionalInstance(streamState[ApiConstants.Lost]); } @@ -66,7 +87,7 @@ internal void AddAll(IList optional) { if (optional != null && optional.Count > 0) { - foreach (Subject s in optional) + foreach (var s in optional) { Subjects.Add(s); } diff --git a/src/NATS.Client/v1/JetStream/Subject.cs b/src/NATS.Client/v1/JetStream/Subject.cs index 73359d30..f019c289 100644 --- a/src/NATS.Client/v1/JetStream/Subject.cs +++ b/src/NATS.Client/v1/JetStream/Subject.cs @@ -22,7 +22,27 @@ public sealed class Subject public long Count { get; } internal static IList GetList(JSONNode subjectsNode) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + List list = new List(); + if (subjectsNode != null) + { + JSONNode.Enumerator e = subjectsNode.GetEnumerator(); + while (e.MoveNext()) + { + KeyValuePair pair = e.Current; +After: + var list = new List(); + if (subjectsNode != null) + { + var e = subjectsNode.GetEnumerator(); + while (e.MoveNext()) + { + var pair = e.Current; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: List list = new List(); if (subjectsNode != null) { @@ -30,6 +50,43 @@ internal static IList GetList(JSONNode subjectsNode) while (e.MoveNext()) { KeyValuePair pair = e.Current; +After: + var list = new List(); + if (subjectsNode != null) + { + var e = subjectsNode.GetEnumerator(); + while (e.MoveNext()) + { + var pair = e.Current; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + List list = new List(); + if (subjectsNode != null) + { + JSONNode.Enumerator e = subjectsNode.GetEnumerator(); + while (e.MoveNext()) + { + KeyValuePair pair = e.Current; +After: + var list = new List(); + if (subjectsNode != null) + { + var e = subjectsNode.GetEnumerator(); + while (e.MoveNext()) + { + var pair = e.Current; +*/ + + { + var list = new List(); + if (subjectsNode != null) + { + var e = subjectsNode.GetEnumerator(); + while (e.MoveNext()) + { + var pair = e.Current; list.Add(new Subject(pair.Key, pair.Value.AsLong)); } } diff --git a/src/NATS.Client/v1/JetStream/SubjectTransform.cs b/src/NATS.Client/v1/JetStream/SubjectTransform.cs index d46fb28c..62a610a0 100644 --- a/src/NATS.Client/v1/JetStream/SubjectTransform.cs +++ b/src/NATS.Client/v1/JetStream/SubjectTransform.cs @@ -36,14 +36,14 @@ internal static SubjectTransform OptionalInstance(JSONNode subjectTransformNode) { return subjectTransformNode.Count == 0 ? null : new SubjectTransform(subjectTransformNode); } - + internal static IList OptionalListOf(JSONNode subjectTransformListNode) { if (subjectTransformListNode == null) { return null; } - + IList list = new List(); foreach (var subjectTransformNode in subjectTransformListNode.Children) { @@ -70,8 +70,29 @@ public SubjectTransform(string source, string destination) } public override JSONNode ToJsonNode() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + + { + var o = new JSONObject(); AddField(o, ApiConstants.Src, Source); AddField(o, ApiConstants.Dest, Destination); return o; @@ -81,14 +102,16 @@ public override JSONNode ToJsonNode() /// Creates a builder for a SubjectTransform object. /// /// The Builder - public static SubjectTransformBuilder Builder() { + public static SubjectTransformBuilder Builder() + { return new SubjectTransformBuilder(); } /// /// SubjectTransform can be created using a SubjectTransformBuilder. /// - public sealed class SubjectTransformBuilder { + public sealed class SubjectTransformBuilder + { private string _source; private string _destination; @@ -97,7 +120,8 @@ public sealed class SubjectTransformBuilder { /// /// the source /// The SubjectTransformBuilder - public SubjectTransformBuilder WithSource(string source) { + public SubjectTransformBuilder WithSource(string source) + { _source = source; return this; } @@ -107,16 +131,18 @@ public SubjectTransformBuilder WithSource(string source) { /// /// the destination /// The SubjectTransformBuilder - public SubjectTransformBuilder WithDestination(string destination) { + public SubjectTransformBuilder WithDestination(string destination) + { _destination = destination; return this; } - + /// /// Build a SubjectTransform object /// /// The SubjectTransform object - public SubjectTransform Build() { + public SubjectTransform Build() + { return new SubjectTransform(_source, _destination); } } diff --git a/src/NATS.Client/v1/JetStream/SubscribeOptions.cs b/src/NATS.Client/v1/JetStream/SubscribeOptions.cs index 90aa3f84..461322a3 100644 --- a/src/NATS.Client/v1/JetStream/SubscribeOptions.cs +++ b/src/NATS.Client/v1/JetStream/SubscribeOptions.cs @@ -52,9 +52,9 @@ public abstract class SubscribeOptions /// public string DeliverGroup => ConsumerConfiguration.DeliverGroup; - protected SubscribeOptions(ISubscribeOptionsBuilder builder, bool pull, + protected SubscribeOptions(ISubscribeOptionsBuilder builder, bool pull, string deliverSubject, string deliverGroup, - long pendingMessageLimit = Defaults.SubPendingMsgsLimit, + long pendingMessageLimit = Defaults.SubPendingMsgsLimit, long pendingByteLimit = Defaults.SubPendingBytesLimit) { Pull = pull; @@ -67,24 +67,67 @@ protected SubscribeOptions(ISubscribeOptionsBuilder builder, bool pull, { throw JsSoOrderedNotAllowedWithBind.Instance(); } - + Stream = ValidateStreamName(builder.Stream, builder.Bind); // required when bind mode +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string ccName = ValidateMustMatchIfBothSupplied(builder.Name, builder.Cc?.Name, JsSoNameMismatch); +After: + var ccName = ValidateMustMatchIfBothSupplied(builder.Name, builder.Cc?.Name, JsSoNameMismatch); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string ccName = ValidateMustMatchIfBothSupplied(builder.Name, builder.Cc?.Name, JsSoNameMismatch); +After: + var ccName = ValidateMustMatchIfBothSupplied(builder.Name, builder.Cc?.Name, JsSoNameMismatch); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string ccName = ValidateMustMatchIfBothSupplied(builder.Name, builder.Cc?.Name, JsSoNameMismatch); +After: + var ccName = ValidateMustMatchIfBothSupplied(builder.Name, builder.Cc?.Name, JsSoNameMismatch); +*/ + // read the consumer names and do basic validation // A1. validate name input - string ccName = ValidateMustMatchIfBothSupplied(builder.Name, builder.Cc?.Name, JsSoNameMismatch); + var ccName = ValidateMustMatchIfBothSupplied(builder.Name, builder.Cc?.Name, JsSoNameMismatch); // B1. Must be a valid consumer name if supplied ccName = ValidateConsumerName(ccName, false); - - // A2. validate durable input +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string ccDurable = ValidateMustMatchIfBothSupplied(builder.Durable, builder.Cc?.Durable, JsSoDurableMismatch); +After: + var ccDurable = ValidateMustMatchIfBothSupplied(builder.Durable, builder.Cc?.Durable, JsSoDurableMismatch); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: string ccDurable = ValidateMustMatchIfBothSupplied(builder.Durable, builder.Cc?.Durable, JsSoDurableMismatch); +After: + var ccDurable = ValidateMustMatchIfBothSupplied(builder.Durable, builder.Cc?.Durable, JsSoDurableMismatch); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string ccDurable = ValidateMustMatchIfBothSupplied(builder.Durable, builder.Cc?.Durable, JsSoDurableMismatch); +After: + var ccDurable = ValidateMustMatchIfBothSupplied(builder.Durable, builder.Cc?.Durable, JsSoDurableMismatch); +*/ + + + // A2. validate durable input + var ccDurable = ValidateMustMatchIfBothSupplied(builder.Durable, builder.Cc?.Durable, JsSoDurableMismatch); // B2. Must be a valid consumer name if supplied ccDurable = ValidateDurable(ccDurable, false); // C. name must match durable if both supplied Name = ValidateMustMatchIfBothSupplied(ccName, ccDurable, JsConsumerNameDurableMismatch); - if (Bind && Name == null) { + if (Bind && Name == null) + { throw JsSoNameOrDurableRequiredForBind.Instance(); } @@ -94,44 +137,151 @@ protected SubscribeOptions(ISubscribeOptionsBuilder builder, bool pull, PendingMessageLimit = pendingMessageLimit; PendingByteLimit = pendingByteLimit; - + if (Ordered) { ValidateNotSupplied(deliverGroup, JsSoOrderedNotAllowedWithDeliverGroup); ValidateNotSupplied(ccDurable, JsSoOrderedNotAllowedWithDurable); ValidateNotSupplied(deliverSubject, JsSoOrderedNotAllowedWithDeliverSubject); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + bool? ms = builder.Cc?._memStorage; +After: + var ms = builder.Cc?._memStorage; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + bool? ms = builder.Cc?._memStorage; +After: + var ms = builder.Cc?._memStorage; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: bool? ms = builder.Cc?._memStorage; +After: + var ms = builder.Cc?._memStorage; +*/ + + var ms = builder.Cc?._memStorage; if (ms != null && !ms.Value) { throw JsSoOrderedMemStorageNotSuppliedOrTrue.Instance(); - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int? r = builder.Cc?._numReplicas; +After: + var r = builder.Cc?._numReplicas; +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: int? r = builder.Cc?._numReplicas; +After: + var r = builder.Cc?._numReplicas; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int? r = builder.Cc?._numReplicas; +After: + var r = builder.Cc?._numReplicas; +*/ + + } + + var r = builder.Cc?._numReplicas; if (r != null && r != 1) { throw JsSoOrderedReplicasNotSuppliedOrOne.Instance(); - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + long hb = DefaultOrderedHeartbeat; +After: + var hb = DefaultOrderedHeartbeat; +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: long hb = DefaultOrderedHeartbeat; +After: + var hb = DefaultOrderedHeartbeat; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + long hb = DefaultOrderedHeartbeat; +After: + var hb = DefaultOrderedHeartbeat; +*/ + + } + + var hb = DefaultOrderedHeartbeat; if (builder.Cc != null) { // want to make sure they didn't set it or they didn't set it to something other than none - if (builder.Cc._ackPolicy != null && builder.Cc._ackPolicy != AckPolicy.None) { + if (builder.Cc._ackPolicy != null && builder.Cc._ackPolicy != AckPolicy.None) + { throw JsSoOrderedRequiresAckPolicyNone.Instance(); } - if (builder.Cc.MaxDeliver > 1) { + if (builder.Cc.MaxDeliver > 1) + { throw JsSoOrderedRequiresMaxDeliverOfOne.Instance(); - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Duration ccHb = builder.Cc.IdleHeartbeat; +After: + var ccHb = builder.Cc.IdleHeartbeat; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Duration ccHb = builder.Cc.IdleHeartbeat; +After: + var ccHb = builder.Cc.IdleHeartbeat; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: Duration ccHb = builder.Cc.IdleHeartbeat; +After: + var ccHb = builder.Cc.IdleHeartbeat; +*/ + + } + + var ccHb = builder.Cc.IdleHeartbeat; if (ccHb != null) { hb = ccHb.Millis; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + ConsumerConfigurationBuilder ccbuilder = Builder(builder.Cc) +After: + var ccbuilder = Builder(builder.Cc) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + ConsumerConfigurationBuilder ccbuilder = Builder(builder.Cc) +After: + var ccbuilder = Builder(builder.Cc) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + ConsumerConfigurationBuilder ccbuilder = Builder(builder.Cc) +After: + var ccbuilder = Builder(builder.Cc) +*/ + } } - - ConsumerConfigurationBuilder ccbuilder = Builder(builder.Cc) + + var ccbuilder = Builder(builder.Cc) .WithAckPolicy(AckPolicy.None) .WithMaxDeliver(1) .WithAckWait(Duration.OfHours(22)) @@ -156,7 +306,7 @@ protected SubscribeOptions(ISubscribeOptionsBuilder builder, bool pull, .Build(); } } - + public override string ToString() { return GetType().Name + "{" + @@ -182,7 +332,7 @@ public interface ISubscribeOptionsBuilder int MessageAlarmTime { get; } bool Ordered { get; } } - + public abstract class SubscribeOptionsBuilder : ISubscribeOptionsBuilder { protected string _stream; diff --git a/src/NATS.Client/v1/KeyValue/IKeyValue.cs b/src/NATS.Client/v1/KeyValue/IKeyValue.cs index b0175131..faec89f2 100644 --- a/src/NATS.Client/v1/KeyValue/IKeyValue.cs +++ b/src/NATS.Client/v1/KeyValue/IKeyValue.cs @@ -1,4 +1,4 @@ -// Copyright 2021 The NATS Authors +// Copyright 2021 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -93,13 +93,13 @@ public interface IKeyValue /// the key /// the expected last revision void Delete(string key, ulong expectedRevision); - + /// /// Purge all values/history from the specific key. /// /// the key void Purge(string key); - + /// /// Purge all values/history from the specific key iff the key exists and its last revision matches the expected. /// @@ -208,4 +208,4 @@ public interface IKeyValue /// the status object KeyValueStatus Status(); } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/KeyValue/IKeyValueManagement.cs b/src/NATS.Client/v1/KeyValue/IKeyValueManagement.cs index 74043d7f..7a661eb1 100644 --- a/src/NATS.Client/v1/KeyValue/IKeyValueManagement.cs +++ b/src/NATS.Client/v1/KeyValue/IKeyValueManagement.cs @@ -1,4 +1,4 @@ -// Copyright 2021 The NATS Authors +// Copyright 2021 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -65,4 +65,4 @@ public interface IKeyValueManagement /// void Delete(string bucketName); } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/KeyValue/IKeyValueWatcher.cs b/src/NATS.Client/v1/KeyValue/IKeyValueWatcher.cs index a2b03286..51aa19f2 100644 --- a/src/NATS.Client/v1/KeyValue/IKeyValueWatcher.cs +++ b/src/NATS.Client/v1/KeyValue/IKeyValueWatcher.cs @@ -1,4 +1,4 @@ -// Copyright 2022 The NATS Authors +// Copyright 2022 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: diff --git a/src/NATS.Client/v1/KeyValue/KeyValue.cs b/src/NATS.Client/v1/KeyValue/KeyValue.cs index 6f0c33d7..fd771934 100644 --- a/src/NATS.Client/v1/KeyValue/KeyValue.cs +++ b/src/NATS.Client/v1/KeyValue/KeyValue.cs @@ -27,20 +27,84 @@ public class KeyValue : FeatureBase, IKeyValue internal string StreamSubject { get; } internal string ReadPrefix { get; } internal string WritePrefix { get; } - - internal KeyValue(IConnection connection, string bucketName, KeyValueOptions kvo) : base(connection, kvo) { + + internal KeyValue(IConnection connection, string bucketName, KeyValueOptions kvo) : base(connection, kvo) + { BucketName = Validator.ValidateBucketName(bucketName, true); StreamName = ToStreamName(BucketName); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + StreamInfo si = jsm.GetStreamInfo(StreamName); +After: + var si = jsm.GetStreamInfo(StreamName); +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: StreamInfo si = jsm.GetStreamInfo(StreamName); +After: + var si = jsm.GetStreamInfo(StreamName); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + StreamInfo si = jsm.GetStreamInfo(StreamName); +After: + var si = jsm.GetStreamInfo(StreamName); +*/ + + + var si = jsm.GetStreamInfo(StreamName); StreamSubject = ToStreamSubject(BucketName); ReadPrefix = ToKeyPrefix(bucketName); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Mirror m = si.Config.Mirror; +After: + var m = si.Config.Mirror; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Mirror m = si.Config.Mirror; +After: + var m = si.Config.Mirror; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: Mirror m = si.Config.Mirror; +After: + var m = si.Config.Mirror; +*/ + + + var m = si.Config.Mirror; if (m != null) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string bName = TrimPrefix(m.Name); +After: + var bName = TrimPrefix(m.Name); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string bName = TrimPrefix(m.Name); +After: + var bName = TrimPrefix(m.Name); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string bName = TrimPrefix(m.Name); +After: + var bName = TrimPrefix(m.Name); +*/ + + { + var bName = TrimPrefix(m.Name); if (m.External?.Api == null) { WritePrefix = ToKeyPrefix(bName); @@ -62,12 +126,12 @@ internal KeyValue(IConnection connection, string bucketName, KeyValueOptions kvo } public string BucketName { get; } - + internal string ReadSubject(string key) { return ReadPrefix + key; } - + internal string WriteSubject(string key) { return WritePrefix + key; @@ -83,22 +147,88 @@ public KeyValueEntry Get(string key, ulong revision) return existingOnly(_getBySeq(Validator.ValidateNonWildcardKvKeyRequired(key), revision)); } - private KeyValueEntry existingOnly(KeyValueEntry kve) { + private KeyValueEntry existingOnly(KeyValueEntry kve) + { return kve == null || !kve.Operation.Equals(KeyValueOperation.Put) ? null : kve; } - - KeyValueEntry _get(string key) { + + KeyValueEntry _get(string key) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + MessageInfo mi = _getLast(ReadSubject(key)); +After: + var mi = _getLast(ReadSubject(key)); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: MessageInfo mi = _getLast(ReadSubject(key)); +After: + var mi = _getLast(ReadSubject(key)); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + MessageInfo mi = _getLast(ReadSubject(key)); +After: + var mi = _getLast(ReadSubject(key)); +*/ + + { + var mi = _getLast(ReadSubject(key)); return mi == null ? null : new KeyValueEntry(mi); } KeyValueEntry _getBySeq(string key, ulong revision) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + MessageInfo mi = _getBySeq(revision); +After: + var mi = _getBySeq(revision); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: MessageInfo mi = _getBySeq(revision); +After: + var mi = _getBySeq(revision); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + MessageInfo mi = _getBySeq(revision); +After: + var mi = _getBySeq(revision); +*/ + + { + var mi = _getBySeq(revision); if (mi != null) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + KeyValueEntry kve = new KeyValueEntry(mi); +After: + var kve = new KeyValueEntry(mi); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: KeyValueEntry kve = new KeyValueEntry(mi); - if (key.Equals(kve.Key)) { +After: + var kve = new KeyValueEntry(mi); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + KeyValueEntry kve = new KeyValueEntry(mi); +After: + var kve = new KeyValueEntry(mi); +*/ + + { + var kve = new KeyValueEntry(mi); + if (key.Equals(kve.Key)) + { return kve; } } @@ -114,7 +244,7 @@ public ulong Put(string key, byte[] value) public ulong Put(string key, string value) => Put(key, Encoding.UTF8.GetBytes(value)); public ulong Put(string key, long value) => Put(key, Encoding.UTF8.GetBytes(value.ToString())); - + public ulong Create(string key, byte[] value) { Validator.ValidateNonWildcardKvKeyRequired(key); @@ -125,10 +255,32 @@ public ulong Create(string key, byte[] value) catch (NATSJetStreamException e) { if (e.ApiErrorCode == JetStreamConstants.JsWrongLastSequence) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + KeyValueEntry kve = _get(key); +After: + var kve = _get(key); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + KeyValueEntry kve = _get(key); +After: + var kve = _get(key); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + KeyValueEntry kve = _get(key); +After: + var kve = _get(key); +*/ + { // must check if the last message for this subject is a delete or purge - KeyValueEntry kve = _get(key); - if (kve != null && !kve.Operation.Equals(KeyValueOperation.Put)) { + var kve = _get(key); + if (kve != null && !kve.Operation.Equals(KeyValueOperation.Put)) + { return Update(key, value, kve.Revision); } } @@ -138,8 +290,29 @@ public ulong Create(string key, byte[] value) } public ulong Update(string key, byte[] value, ulong expectedRevision) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: MsgHeader h = new MsgHeader +After: + var h = new MsgHeader +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + MsgHeader h = new MsgHeader +After: + var h = new MsgHeader +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + MsgHeader h = new MsgHeader +After: + var h = new MsgHeader +*/ + + { + var h = new MsgHeader { [JetStreamConstants.ExpLastSubjectSeqHeader] = expectedRevision.ToString() }; @@ -151,41 +324,83 @@ public void Delete(string key) Validator.ValidateKvKeyWildcardAllowedRequired(key); _write(key, null, DeleteHeaders); } - + public void Delete(string key, ulong expectedRevision) { Validator.ValidateKvKeyWildcardAllowedRequired(key); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + MsgHeader h = DeleteHeaders; +After: + var h = DeleteHeaders; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + MsgHeader h = DeleteHeaders; +After: + var h = DeleteHeaders; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: MsgHeader h = DeleteHeaders; +After: + var h = DeleteHeaders; +*/ + + var h = DeleteHeaders; h[JetStreamConstants.ExpLastSubjectSeqHeader] = expectedRevision.ToString(); _write(key, null, h); } - public void Purge(string key) + public void Purge(string key) { Validator.ValidateKvKeyWildcardAllowedRequired(key); _write(key, null, PurgeHeaders); } - + public void Purge(string key, ulong expectedRevision) { Validator.ValidateKvKeyWildcardAllowedRequired(key); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + MsgHeader h = PurgeHeaders; +After: + var h = PurgeHeaders; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: MsgHeader h = PurgeHeaders; +After: + var h = PurgeHeaders; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + MsgHeader h = PurgeHeaders; +After: + var h = PurgeHeaders; +*/ + + var h = PurgeHeaders; h[JetStreamConstants.ExpLastSubjectSeqHeader] = expectedRevision.ToString(); _write(key, null, h); } - + public KeyValueWatchSubscription Watch(string key, IKeyValueWatcher watcher, params KeyValueWatchOption[] watchOptions) { Validator.ValidateKvKeyWildcardAllowedRequired(key); Validator.ValidateNotNull(watcher, "Watcher is required"); - return new KeyValueWatchSubscription(this, new List {key}, watcher, ConsumerConfiguration.UlongUnset, watchOptions); + return new KeyValueWatchSubscription(this, new List { key }, watcher, ConsumerConfiguration.UlongUnset, watchOptions); } - + public KeyValueWatchSubscription Watch(string key, IKeyValueWatcher watcher, ulong fromRevision, params KeyValueWatchOption[] watchOptions) { Validator.ValidateKvKeyWildcardAllowedRequired(key); Validator.ValidateNotNull(watcher, "Watcher is required"); - return new KeyValueWatchSubscription(this, new List {key}, watcher, fromRevision, watchOptions); + return new KeyValueWatchSubscription(this, new List { key }, watcher, fromRevision, watchOptions); } public KeyValueWatchSubscription Watch(IList keys, IKeyValueWatcher watcher, params KeyValueWatchOption[] watchOptions) @@ -205,34 +420,35 @@ public KeyValueWatchSubscription Watch(IList keys, IKeyValueWatcher watc public KeyValueWatchSubscription WatchAll(IKeyValueWatcher watcher, params KeyValueWatchOption[] watchOptions) { Validator.ValidateNotNull(watcher, "Watcher is required"); - return new KeyValueWatchSubscription(this, new List {NatsConstants.GreaterThan}, watcher, ConsumerConfiguration.UlongUnset, watchOptions); + return new KeyValueWatchSubscription(this, new List { NatsConstants.GreaterThan }, watcher, ConsumerConfiguration.UlongUnset, watchOptions); } public KeyValueWatchSubscription WatchAll(IKeyValueWatcher watcher, ulong fromRevision, params KeyValueWatchOption[] watchOptions) { Validator.ValidateNotNull(watcher, "Watcher is required"); - return new KeyValueWatchSubscription(this, new List {NatsConstants.GreaterThan}, watcher, fromRevision, watchOptions); + return new KeyValueWatchSubscription(this, new List { NatsConstants.GreaterThan }, watcher, fromRevision, watchOptions); } - private PublishAck _write(string key, byte[] data, MsgHeader h) { + private PublishAck _write(string key, byte[] data, MsgHeader h) + { Validator.ValidateNonWildcardKvKeyRequired(key); return js.Publish(new Msg(WriteSubject(key), h, data)); } public IList Keys() { - return _keys(new []{ReadSubject(NatsConstants.GreaterThan)}); + return _keys(new[] { ReadSubject(NatsConstants.GreaterThan) }); } public IList Keys(string filter) { - return _keys(new []{ReadSubject(filter)}); + return _keys(new[] { ReadSubject(filter) }); } public IList Keys(IList filters) { IList readSubjectFilters = new List(filters.Count); - foreach (string f in filters) + foreach (var f in filters) { readSubjectFilters.Add(ReadSubject(f)); } @@ -242,9 +458,32 @@ public IList Keys(IList filters) internal IList _keys(IList readSubjectFilters) { IList list = new List(); - VisitSubject(readSubjectFilters, DeliverPolicy.LastPerSubject, true, false, m => { + VisitSubject(readSubjectFilters, DeliverPolicy.LastPerSubject, true, false, m => +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: KeyValueOperation op = GetOperation(m.Header, KeyValueOperation.Put); - if (op.Equals(KeyValueOperation.Put)) { +After: + var op = GetOperation(m.Header, KeyValueOperation.Put); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + KeyValueOperation op = GetOperation(m.Header, KeyValueOperation.Put); +After: + var op = GetOperation(m.Header, KeyValueOperation.Put); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + KeyValueOperation op = GetOperation(m.Header, KeyValueOperation.Put); +After: + var op = GetOperation(m.Header, KeyValueOperation.Put); +*/ + + { + var op = GetOperation(m.Header, KeyValueOperation.Put); + if (op.Equals(KeyValueOperation.Put)) + { list.Add(new BucketAndKey(m).Key); } }); @@ -254,7 +493,8 @@ internal IList _keys(IList readSubjectFilters) public IList History(string key) { IList list = new List(); - VisitSubject(ReadSubject(key), DeliverPolicy.All, false, true, m => { + VisitSubject(ReadSubject(key), DeliverPolicy.All, false, true, m => + { list.Add(new KeyValueEntry(m)); }); return list; @@ -263,28 +503,74 @@ public IList History(string key) public void PurgeDeletes() => PurgeDeletes(null); public void PurgeDeletes(KeyValuePurgeOptions options) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + long dmThresh = options == null +After: + var dmThresh = options == null +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: long dmThresh = options == null +After: + var dmThresh = options == null +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + long dmThresh = options == null +After: + var dmThresh = options == null +*/ + + { + var dmThresh = options == null ? KeyValuePurgeOptions.DefaultThresholdMillis : options.DeleteMarkersThresholdMillis; DateTime limit; - if (dmThresh < 0) { + if (dmThresh < 0) + { limit = DateTime.UtcNow.AddMilliseconds(600000); // long enough in the future to clear all } - else if (dmThresh == 0) { + else if (dmThresh == 0) + { limit = DateTime.UtcNow.AddMilliseconds(KeyValuePurgeOptions.DefaultThresholdMillis); } - else { + else + { limit = DateTime.UtcNow.AddMilliseconds(-dmThresh); } IList noKeepList = new List(); IList keepList = new List(); VisitSubject(ToStreamSubject(BucketName), DeliverPolicy.LastPerSubject, true, false, m => - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: KeyValueEntry kve = new KeyValueEntry(m); - if (!kve.Operation.Equals(KeyValueOperation.Put)) { +After: + var kve = new KeyValueEntry(m); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + KeyValueEntry kve = new KeyValueEntry(m); +After: + var kve = new KeyValueEntry(m); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + KeyValueEntry kve = new KeyValueEntry(m); +After: + var kve = new KeyValueEntry(m); +*/ + + { + var kve = new KeyValueEntry(m); + if (!kve.Operation.Equals(KeyValueOperation.Put)) + { if (kve.Created > limit) // created > limit, so created after { keepList.Add(new BucketAndKey(m).Key); @@ -296,14 +582,35 @@ public void PurgeDeletes(KeyValuePurgeOptions options) } }); - foreach (string key in noKeepList) + foreach (var key in noKeepList) { jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(ReadSubject(key))); } - foreach (string key in keepList) - { + foreach (var key in keepList) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: PurgeOptions po = PurgeOptions.Builder() +After: + var po = PurgeOptions.Builder() +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + PurgeOptions po = PurgeOptions.Builder() +After: + var po = PurgeOptions.Builder() +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + PurgeOptions po = PurgeOptions.Builder() +After: + var po = PurgeOptions.Builder() +*/ + + { + var po = PurgeOptions.Builder() .WithSubject(ReadSubject(key)) .WithKeep(1) .Build(); @@ -316,4 +623,4 @@ public KeyValueStatus Status() return new KeyValueStatus(jsm.GetStreamInfo(ToStreamName(BucketName))); } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/KeyValue/KeyValueConfiguration.cs b/src/NATS.Client/v1/KeyValue/KeyValueConfiguration.cs index 38beb8fd..13af00d8 100644 --- a/src/NATS.Client/v1/KeyValue/KeyValueConfiguration.cs +++ b/src/NATS.Client/v1/KeyValue/KeyValueConfiguration.cs @@ -26,7 +26,7 @@ public class KeyValueConfiguration internal static readonly CompressionOption JsCompressionNo = CompressionOption.None; internal StreamConfiguration BackingConfig { get; } - + /// /// The name of the bucket /// @@ -75,7 +75,7 @@ internal KeyValueConfiguration(StreamConfiguration sc) /// The storage type for this bucket /// public StorageType StorageType => BackingConfig.StorageType; - + /// /// The number of replicas for this bucket /// @@ -114,7 +114,7 @@ public static KeyValueConfigurationBuilder Builder() { return new KeyValueConfigurationBuilder((KeyValueConfiguration)null); } - + /// /// Creates a builder for the KeyValueConfiguration. /// @@ -124,7 +124,7 @@ public static KeyValueConfigurationBuilder Builder(string name) { return new KeyValueConfigurationBuilder(name); } - + /// /// Creates a builder for the KeyValueConfiguration. /// @@ -149,7 +149,7 @@ public sealed class KeyValueConfigurationBuilder /// /// Default builder /// - public KeyValueConfigurationBuilder() : this((KeyValueConfiguration)null) {} + public KeyValueConfigurationBuilder() : this((KeyValueConfiguration)null) { } /// /// Builder accepting the object store bucket name. @@ -164,13 +164,16 @@ public KeyValueConfigurationBuilder(string name) : this((KeyValueConfiguration)n /// Construct the builder by copying another configuration /// /// the other configuration - public KeyValueConfigurationBuilder(KeyValueConfiguration kvc) { - if (kvc == null) { + public KeyValueConfigurationBuilder(KeyValueConfiguration kvc) + { + if (kvc == null) + { scBuilder = new StreamConfigurationBuilder(); WithMaxHistoryPerKey(1); WithReplicas(1); } - else { + else + { scBuilder = new StreamConfigurationBuilder(kvc.BackingConfig); _name = ExtractBucketName(kvc.BackingConfig.Name); } @@ -181,7 +184,8 @@ public KeyValueConfigurationBuilder(KeyValueConfiguration kvc) { /// /// name of the key value bucket /// - public KeyValueConfigurationBuilder WithName(string name) { + public KeyValueConfigurationBuilder WithName(string name) + { _name = Validator.ValidateBucketName(name, true); return this; } @@ -191,7 +195,8 @@ public KeyValueConfigurationBuilder WithName(string name) { /// /// the description of the store. /// - public KeyValueConfigurationBuilder WithDescription(string description) { + public KeyValueConfigurationBuilder WithDescription(string description) + { scBuilder.WithDescription(description); return this; } @@ -201,7 +206,8 @@ public KeyValueConfigurationBuilder WithDescription(string description) { /// /// the maximum history /// - public KeyValueConfigurationBuilder WithMaxHistoryPerKey(int maxHistoryPerKey) { + public KeyValueConfigurationBuilder WithMaxHistoryPerKey(int maxHistoryPerKey) + { scBuilder.WithMaxMessagesPerSubject(Validator.ValidateMaxHistory(maxHistoryPerKey)); return this; } @@ -211,7 +217,8 @@ public KeyValueConfigurationBuilder WithMaxHistoryPerKey(int maxHistoryPerKey) { /// /// the maximum number of bytes /// - public KeyValueConfigurationBuilder WithMaxBucketSize(long maxBucketSize) { + public KeyValueConfigurationBuilder WithMaxBucketSize(long maxBucketSize) + { scBuilder.WithMaxBytes(Validator.ValidateMaxBucketBytes(maxBucketSize)); return this; } @@ -222,7 +229,8 @@ public KeyValueConfigurationBuilder WithMaxBucketSize(long maxBucketSize) { /// the maximum size for a value /// [Obsolete("The server value is a 32-bit signed value. Use WithMaximumValueSize.", false)] - public KeyValueConfigurationBuilder WithMaxValueSize(long maxValueSize) { + public KeyValueConfigurationBuilder WithMaxValueSize(long maxValueSize) + { scBuilder.WithMaximumMessageSize((int)Validator.ValidateMaxValueSize(maxValueSize)); return this; } @@ -232,7 +240,8 @@ public KeyValueConfigurationBuilder WithMaxValueSize(long maxValueSize) { /// /// the maximum size for a value /// - public KeyValueConfigurationBuilder WithMaximumValueSize(int maxValueSize) { + public KeyValueConfigurationBuilder WithMaximumValueSize(int maxValueSize) + { scBuilder.WithMaximumMessageSize((int)Validator.ValidateMaxValueSize(maxValueSize)); return this; } @@ -242,7 +251,8 @@ public KeyValueConfigurationBuilder WithMaximumValueSize(int maxValueSize) { /// /// Sets the maximum age /// - public KeyValueConfigurationBuilder WithTtl(Duration ttl) { + public KeyValueConfigurationBuilder WithTtl(Duration ttl) + { scBuilder.WithMaxAge(ttl); return this; } @@ -252,7 +262,8 @@ public KeyValueConfigurationBuilder WithTtl(Duration ttl) { /// /// the storage type /// - public KeyValueConfigurationBuilder WithStorageType(StorageType storageType) { + public KeyValueConfigurationBuilder WithStorageType(StorageType storageType) + { scBuilder.WithStorageType(storageType); return this; } @@ -262,7 +273,8 @@ public KeyValueConfigurationBuilder WithStorageType(StorageType storageType) { /// /// number of replicas /// the number of replicas - public KeyValueConfigurationBuilder WithReplicas(int replicas) { + public KeyValueConfigurationBuilder WithReplicas(int replicas) + { scBuilder.WithReplicas(replicas); return this; } @@ -272,7 +284,8 @@ public KeyValueConfigurationBuilder WithReplicas(int replicas) { /// /// the placement /// - public KeyValueConfigurationBuilder WithPlacement(Placement placement) { + public KeyValueConfigurationBuilder WithPlacement(Placement placement) + { scBuilder.WithPlacement(placement); return this; } @@ -282,7 +295,8 @@ public KeyValueConfigurationBuilder WithPlacement(Placement placement) { /// /// the republish /// The KeyValueConfigurationBuilder - public KeyValueConfigurationBuilder WithRepublish(Republish republish) { + public KeyValueConfigurationBuilder WithRepublish(Republish republish) + { scBuilder.WithRepublish(republish); return this; } @@ -303,7 +317,8 @@ public KeyValueConfigurationBuilder WithMirror(Mirror mirror) /// /// the KeyValue's sources /// The KeyValueConfigurationBuilder - public KeyValueConfigurationBuilder WithSources(params Source[] sources) { + public KeyValueConfigurationBuilder WithSources(params Source[] sources) + { _sources.Clear(); return AddSources(sources); } @@ -313,7 +328,8 @@ public KeyValueConfigurationBuilder WithSources(params Source[] sources) { /// /// the KeyValue's sources /// The KeyValueConfigurationBuilder - public KeyValueConfigurationBuilder WithSources(List sources) { + public KeyValueConfigurationBuilder WithSources(List sources) + { _sources.Clear(); return AddSources(sources); } @@ -323,10 +339,14 @@ public KeyValueConfigurationBuilder WithSources(List sources) { /// /// the KeyValue's sources /// The KeyValueConfigurationBuilder - public KeyValueConfigurationBuilder AddSources(params Source[] sources) { - if (sources != null) { - foreach (Source source in sources) { - if (source != null && !_sources.Contains(source)) { + public KeyValueConfigurationBuilder AddSources(params Source[] sources) + { + if (sources != null) + { + foreach (var source in sources) + { + if (source != null && !_sources.Contains(source)) + { _sources.Add(source); } } @@ -339,10 +359,14 @@ public KeyValueConfigurationBuilder AddSources(params Source[] sources) { /// /// the KeyValue's sources /// The KeyValueConfigurationBuilder - public KeyValueConfigurationBuilder AddSources(List sources) { - if (sources != null) { - foreach (Source source in sources) { - if (source != null && !_sources.Contains(source)) { + public KeyValueConfigurationBuilder AddSources(List sources) + { + if (sources != null) + { + foreach (var source in sources) + { + if (source != null && !_sources.Contains(source)) + { _sources.Add(source); } } @@ -355,8 +379,10 @@ public KeyValueConfigurationBuilder AddSources(List sources) { /// /// /// The KeyValueConfigurationBuilder - public KeyValueConfigurationBuilder AddSource(Source source) { - if (source != null && !_sources.Contains(source)) { + public KeyValueConfigurationBuilder AddSource(Source source) + { + if (source != null && !_sources.Contains(source)) + { _sources.Add(source); } return this; @@ -370,7 +396,8 @@ public KeyValueConfigurationBuilder AddSource(Source source) { /// /// true to allow direct headers. /// The KeyValueConfigurationBuilder - public KeyValueConfigurationBuilder WithAllowDirect(bool allowDirect) { + public KeyValueConfigurationBuilder WithAllowDirect(bool allowDirect) + { return this; } @@ -400,34 +427,84 @@ public KeyValueConfigurationBuilder WithMetadata(IDictionary met /// Builds the KeyValueConfiguration /// /// the KeyValueConfiguration - public KeyValueConfiguration Build() { + public KeyValueConfiguration Build() + { _name = Validator.Required(_name, "name"); scBuilder.WithName(ToStreamName(_name)) .WithAllowRollup(true) .WithAllowDirect(true) .WithDiscardPolicy(DiscardPolicy.New) .WithDenyDelete(true); - - if (_mirror != null) { + + if (_mirror != null) + { scBuilder.WithMirrorDirect(true); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string name = _mirror.Name; +After: + var name = _mirror.Name; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: string name = _mirror.Name; - if (HasPrefix(name)) { +After: + var name = _mirror.Name; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string name = _mirror.Name; +After: + var name = _mirror.Name; +*/ + + var name = _mirror.Name; + if (HasPrefix(name)) + { scBuilder.WithMirror(_mirror); } - else { + else + { scBuilder.WithMirror( Mirror.Builder(_mirror) .WithName(ToStreamName(name)) .Build()); } } - else if (_sources.Count > 0) { - foreach (Source source in _sources) { + else if (_sources.Count > 0) + { + foreach (var source in _sources) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string name = source.Name; +After: + var name = source.Name; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string name = source.Name; +After: + var name = source.Name; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string name = source.Name; - if (HasPrefix(name)) { +After: + var name = source.Name; +*/ + + { + var name = source.Name; + if (HasPrefix(name)) + { scBuilder.AddSource(source); } - else { + else + { scBuilder.AddSource( Source.Builder(source) .WithName(ToStreamName(name)) @@ -435,10 +512,11 @@ public KeyValueConfiguration Build() { } } } - else { + else + { scBuilder.WithSubjects(ToStreamSubject(_name)); } - + return new KeyValueConfiguration(scBuilder.Build()); } } diff --git a/src/NATS.Client/v1/KeyValue/KeyValueEntry.cs b/src/NATS.Client/v1/KeyValue/KeyValueEntry.cs index a8410b3b..f01da205 100644 --- a/src/NATS.Client/v1/KeyValue/KeyValueEntry.cs +++ b/src/NATS.Client/v1/KeyValue/KeyValueEntry.cs @@ -28,7 +28,8 @@ public class KeyValueEntry public KeyValueOperation Operation { get; } public long DataLength { get; } - public KeyValueEntry(MessageInfo mi) { + public KeyValueEntry(MessageInfo mi) + { bucketAndKey = new BucketAndKey(mi.Subject); Value = ExtractValue(mi.Data); DataLength = CalculateLength(Value, mi.Headers); @@ -38,7 +39,8 @@ public KeyValueEntry(MessageInfo mi) { Operation = KeyValueUtil.GetOperation(mi.Headers, KeyValueOperation.Put); } - public KeyValueEntry(Msg m) { + public KeyValueEntry(Msg m) + { bucketAndKey = new BucketAndKey(m.Subject); Value = ExtractValue(m.Data); DataLength = CalculateLength(Value, m.Header); @@ -58,11 +60,13 @@ public bool TryGetLongValue(out long lvalue) return long.TryParse(ValueAsString(), out lvalue); } - private static byte[] ExtractValue(byte[] data) { + private static byte[] ExtractValue(byte[] data) + { return data == null || data.Length == 0 ? null : data; } - private static long CalculateLength(byte[] value, MsgHeader h) { + private static long CalculateLength(byte[] value, MsgHeader h) + { if (value == null) { long.TryParse(h?[JetStreamConstants.MsgSizeHeader], out var len); @@ -70,7 +74,7 @@ private static long CalculateLength(byte[] value, MsgHeader h) { } return value.Length; } - + public override string ToString() { return $"Bucket: {Bucket}, Key: {Key}, Operation: {Operation}, Revision: {Revision}, Delta: {Delta}, DataLength: {DataLength}, Created: {Created}"; @@ -89,9 +93,12 @@ public bool Equals(KeyValueEntry other) public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (ReferenceEquals(null, obj)) + return false; + if (ReferenceEquals(this, obj)) + return true; + if (obj.GetType() != GetType()) + return false; return Equals((KeyValueEntry)obj); } @@ -110,4 +117,4 @@ public override int GetHashCode() } } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/KeyValue/KeyValueManagement.cs b/src/NATS.Client/v1/KeyValue/KeyValueManagement.cs index 6e43e280..1318c4da 100644 --- a/src/NATS.Client/v1/KeyValue/KeyValueManagement.cs +++ b/src/NATS.Client/v1/KeyValue/KeyValueManagement.cs @@ -27,10 +27,31 @@ internal KeyValueManagement(IConnection connection, KeyValueOptions kvo) { jsm = (JetStreamManagement)connection.CreateJetStreamManagementContext(kvo?.JSOptions); } - + public KeyValueStatus Create(KeyValueConfiguration config) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + StreamConfiguration sc = config.BackingConfig; +After: + var sc = config.BackingConfig; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + StreamConfiguration sc = config.BackingConfig; +After: + var sc = config.BackingConfig; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: StreamConfiguration sc = config.BackingConfig; +After: + var sc = config.BackingConfig; +*/ + + { + var sc = config.BackingConfig; // most validation / KVC setup is done in the KeyValueConfiguration Builder // but this is done here because the context has a connection which has the server info with a version @@ -40,7 +61,7 @@ public KeyValueStatus Create(KeyValueConfiguration config) } return new KeyValueStatus(jsm.AddStream(sc)); } - + public KeyValueStatus Update(KeyValueConfiguration config) { return new KeyValueStatus(jsm.UpdateStream(config.BackingConfig)); @@ -49,9 +70,32 @@ public KeyValueStatus Update(KeyValueConfiguration config) public IList GetBucketNames() { IList buckets = new List(); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: IList names = jsm.GetStreamNames(); - foreach (string name in names) { - if (name.StartsWith(KvStreamPrefix)) { +After: + var names = jsm.GetStreamNames(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + IList names = jsm.GetStreamNames(); +After: + var names = jsm.GetStreamNames(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + IList names = jsm.GetStreamNames(); +After: + var names = jsm.GetStreamNames(); +*/ + + var names = jsm.GetStreamNames(); + foreach (var name in names) + { + if (name.StartsWith(KvStreamPrefix)) + { buckets.Add(ExtractBucketName(name)); } } @@ -67,10 +111,32 @@ public KeyValueStatus GetStatus(string bucketName) } public IList GetStatuses() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + IList bucketNames = GetBucketNames(); +After: + var bucketNames = GetBucketNames(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: IList bucketNames = GetBucketNames(); +After: + var bucketNames = GetBucketNames(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + IList bucketNames = GetBucketNames(); +After: + var bucketNames = GetBucketNames(); +*/ + + { + var bucketNames = GetBucketNames(); IList statuses = new List(); - foreach (string name in bucketNames) { + foreach (var name in bucketNames) + { statuses.Add(new KeyValueStatus(jsm.GetStreamInfo(ToStreamName(name)))); } return statuses; diff --git a/src/NATS.Client/v1/KeyValue/KeyValueOperation.cs b/src/NATS.Client/v1/KeyValue/KeyValueOperation.cs index 3d1d2d1c..842cee89 100644 --- a/src/NATS.Client/v1/KeyValue/KeyValueOperation.cs +++ b/src/NATS.Client/v1/KeyValue/KeyValueOperation.cs @@ -1,4 +1,4 @@ -// Copyright 2021 The NATS Authors +// Copyright 2021 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -27,14 +27,17 @@ private KeyValueOperation(byte id, string headerValue) public static readonly KeyValueOperation Put = new KeyValueOperation(1, "PUT"); public static readonly KeyValueOperation Delete = new KeyValueOperation(2, "DEL"); public static readonly KeyValueOperation Purge = new KeyValueOperation(3, "PURGE"); - + public static KeyValueOperation GetOrDefault(string s, KeyValueOperation dflt) { if (!string.IsNullOrWhiteSpace(s)) { - if (s.Equals(Put.HeaderValue)) return Put; - if (s.Equals(Delete.HeaderValue)) return Delete; - if (s.Equals(Purge.HeaderValue)) return Purge; + if (s.Equals(Put.HeaderValue)) + return Put; + if (s.Equals(Delete.HeaderValue)) + return Delete; + if (s.Equals(Purge.HeaderValue)) + return Purge; } return dflt; } @@ -43,7 +46,8 @@ public static KeyValueOperation GetOrDefault(string s, KeyValueOperation dflt) public override int GetHashCode() => _id.GetHashCode(); - public bool Equals(KeyValueOperation other) { + public bool Equals(KeyValueOperation other) + { return _id.Equals(other?._id); } @@ -52,4 +56,4 @@ public override string ToString() return HeaderValue; } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/KeyValue/KeyValueOptions.cs b/src/NATS.Client/v1/KeyValue/KeyValueOptions.cs index ac3b4e65..acb8de00 100644 --- a/src/NATS.Client/v1/KeyValue/KeyValueOptions.cs +++ b/src/NATS.Client/v1/KeyValue/KeyValueOptions.cs @@ -18,8 +18,8 @@ namespace NATS.Client.KeyValue { public sealed class KeyValueOptions : FeatureOptions { - private KeyValueOptions(JetStreamOptions jso) : base(jso) {} - + private KeyValueOptions(JetStreamOptions jso) : base(jso) { } + /// /// Gets a KeyValueOptionsBuilder builder. /// @@ -30,7 +30,7 @@ public static KeyValueOptionsBuilder Builder() { return new KeyValueOptionsBuilder(); } - + /// /// Gets the KeyValueOptions builder based on an existing KeyValueOptions object. /// @@ -40,7 +40,7 @@ public static KeyValueOptionsBuilder Builder(KeyValueOptions kvo) { return new KeyValueOptionsBuilder(kvo); } - + /// /// Gets the KeyValueOptions builder based on an existing JetStreamOptions object. /// @@ -58,7 +58,7 @@ public sealed class KeyValueOptionsBuilder /// /// Construct a builder /// - public KeyValueOptionsBuilder() : this(null) {} + public KeyValueOptionsBuilder() : this(null) { } /// /// Construct a builder from an existing KeyValueOptions object @@ -68,7 +68,7 @@ public KeyValueOptionsBuilder(KeyValueOptions kvo) { _jsoBuilder = JetStreamOptions.Builder(kvo?.JSOptions); } - + /// /// Sets the JetStreamOptions. /// @@ -85,11 +85,12 @@ public KeyValueOptionsBuilder WithJetStreamOptions(JetStreamOptions jso) /// /// the duration to wait for responses. /// The ObjectStoreOptionsBuilder - public KeyValueOptionsBuilder WithRequestTimeout(Duration requestTimeout) { + public KeyValueOptionsBuilder WithRequestTimeout(Duration requestTimeout) + { _jsoBuilder.WithRequestTimeout(requestTimeout); return this; } - + /// /// Sets the prefix for JetStream subjects. A prefix can be used in conjunction with /// user permissions to restrict access to certain JetStream instances. This must @@ -102,7 +103,7 @@ public KeyValueOptionsBuilder WithJsPrefix(string prefix) _jsoBuilder.WithPrefix(prefix); return this; } - + /// /// Sets the domain for JetStream subjects. A domain can be used in conjunction with /// user permissions to restrict access to certain JetStream instances. This must @@ -110,7 +111,7 @@ public KeyValueOptionsBuilder WithJsPrefix(string prefix) /// /// The domain. /// The JetStreamOptionsBuilder - public KeyValueOptionsBuilder WithJsDomain(string domain) + public KeyValueOptionsBuilder WithJsDomain(string domain) { _jsoBuilder.WithDomain(domain); return this; diff --git a/src/NATS.Client/v1/KeyValue/KeyValuePurgeOptions.cs b/src/NATS.Client/v1/KeyValue/KeyValuePurgeOptions.cs index b019442e..90b1f6f1 100644 --- a/src/NATS.Client/v1/KeyValue/KeyValuePurgeOptions.cs +++ b/src/NATS.Client/v1/KeyValue/KeyValuePurgeOptions.cs @@ -1,4 +1,4 @@ -// Copyright 2022 The NATS Authors +// Copyright 2022 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -25,7 +25,7 @@ private KeyValuePurgeOptions(long deleteMarkersThresholdMillis) { DeleteMarkersThresholdMillis = deleteMarkersThresholdMillis; } - + /// /// Gets a KeyValuePurgeOptions builder. /// @@ -44,8 +44,8 @@ public sealed class KeyValuePurgeOptionsBuilder /// /// Construct a builder /// - public KeyValuePurgeOptionsBuilder() {} - + public KeyValuePurgeOptionsBuilder() { } + /// /// Set the delete marker threshold. /// 0 will assume the default threshold. @@ -58,7 +58,7 @@ public KeyValuePurgeOptionsBuilder WithDeleteMarkersThresholdMillis(long thresho _deleteMarkersThresholdMillis = thresholdMillis; return this; } - + /// /// Set the delete marker threshold. /// null or duration of 0 will assume the default threshold. @@ -71,7 +71,7 @@ public KeyValuePurgeOptionsBuilder WithDeleteMarkersThreshold(Duration threshold _deleteMarkersThresholdMillis = threshold?.Millis ?? DefaultThresholdMillis; return this; } - + /// /// Set the delete marker threshold to -1 so as to not keep any markers /// @@ -88,10 +88,12 @@ public KeyValuePurgeOptionsBuilder WithDeleteMarkersNoThreshold() /// The KeyValueOptions object. public KeyValuePurgeOptions Build() { - if (_deleteMarkersThresholdMillis < 0) { + if (_deleteMarkersThresholdMillis < 0) + { _deleteMarkersThresholdMillis = -1; } - else if (_deleteMarkersThresholdMillis == 0) { + else if (_deleteMarkersThresholdMillis == 0) + { _deleteMarkersThresholdMillis = DefaultThresholdMillis; } return new KeyValuePurgeOptions(_deleteMarkersThresholdMillis); diff --git a/src/NATS.Client/v1/KeyValue/KeyValueStatus.cs b/src/NATS.Client/v1/KeyValue/KeyValueStatus.cs index ec74c64d..3072e0ad 100644 --- a/src/NATS.Client/v1/KeyValue/KeyValueStatus.cs +++ b/src/NATS.Client/v1/KeyValue/KeyValueStatus.cs @@ -1,4 +1,4 @@ -// Copyright 2021 The NATS Authors +// Copyright 2021 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -30,7 +30,8 @@ public class KeyValueStatus /// public KeyValueConfiguration Config { get; } - public KeyValueStatus(StreamInfo si) { + public KeyValueStatus(StreamInfo si) + { BackingStreamInfo = si; Config = new KeyValueConfiguration(si.Config); } @@ -85,7 +86,7 @@ public KeyValueStatus(StreamInfo si) { /// The storage type for this bucket /// public StorageType StorageType => Config.StorageType; - + /// /// The number of replicas for this bucket /// diff --git a/src/NATS.Client/v1/KeyValue/KeyValueUtil.cs b/src/NATS.Client/v1/KeyValue/KeyValueUtil.cs index c794959a..5eb5337f 100644 --- a/src/NATS.Client/v1/KeyValue/KeyValueUtil.cs +++ b/src/NATS.Client/v1/KeyValue/KeyValueUtil.cs @@ -22,7 +22,7 @@ public static class KeyValueUtil internal const string KvSubjectPrefix = "$KV."; internal const string KvSubjectSuffix = ".>"; internal const string KvOperationHeaderKey = "KV-Operation"; - + public static MsgHeader DeleteHeaders => new MsgHeader { { KvOperationHeaderKey, KeyValueOperation.Delete.HeaderValue } @@ -34,51 +34,82 @@ public static class KeyValueUtil { JetStreamConstants.RollupHeader, JetStreamConstants.RollupHeaderSubject } }; - public static string ExtractBucketName(string streamName) { + public static string ExtractBucketName(string streamName) + { return streamName.Substring(KvStreamPrefixLen); } - public static string ToStreamName(string bucketName) { + public static string ToStreamName(string bucketName) + { return KvStreamPrefix + bucketName; } - public static string ToStreamSubject(string bucketName) { + public static string ToStreamSubject(string bucketName) + { return KvSubjectPrefix + bucketName + KvSubjectSuffix; } - public static string ToKeyPrefix(string bucketName) { + public static string ToKeyPrefix(string bucketName) + { return KvSubjectPrefix + bucketName + "."; } - public static bool HasPrefix(string bucketName) { + public static bool HasPrefix(string bucketName) + { return bucketName.StartsWith(KvStreamPrefix); } - public static string TrimPrefix(string bucketName) { - if (bucketName.StartsWith(KvStreamPrefix)) { + public static string TrimPrefix(string bucketName) + { + if (bucketName.StartsWith(KvStreamPrefix)) + { return bucketName.Substring(KvStreamPrefix.Length); } return bucketName; } - public static string GetOperationHeader(MsgHeader h) { + public static string GetOperationHeader(MsgHeader h) + { return h?[KvOperationHeaderKey]; } - public static KeyValueOperation GetOperation(MsgHeader h, KeyValueOperation dflt) { + public static KeyValueOperation GetOperation(MsgHeader h, KeyValueOperation dflt) + { return KeyValueOperation.GetOrDefault(GetOperationHeader(h), dflt); } } - internal class BucketAndKey { + internal class BucketAndKey + { public string Bucket { get; } public string Key { get; } - public BucketAndKey(Msg m) : this(m.Subject) {} + public BucketAndKey(Msg m) : this(m.Subject) { } public BucketAndKey(string subject) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string[] split = subject.Split(new[] { '.' }, 3); +After: + var split = subject.Split(new[] { '.' }, 3); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: string[] split = subject.Split(new[] { '.' }, 3); +After: + var split = subject.Split(new[] { '.' }, 3); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string[] split = subject.Split(new[] { '.' }, 3); +After: + var split = subject.Split(new[] { '.' }, 3); +*/ + + { + var split = subject.Split(new[] { '.' }, 3); Bucket = split[1]; Key = split[2]; } @@ -90,9 +121,12 @@ public bool Equals(BucketAndKey other) public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (ReferenceEquals(null, obj)) + return false; + if (ReferenceEquals(this, obj)) + return true; + if (obj.GetType() != GetType()) + return false; return Equals((BucketAndKey)obj); } @@ -104,4 +138,4 @@ public override int GetHashCode() } } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/KeyValue/KeyValueWatchOption.cs b/src/NATS.Client/v1/KeyValue/KeyValueWatchOption.cs index 788cde05..d887e1a6 100644 --- a/src/NATS.Client/v1/KeyValue/KeyValueWatchOption.cs +++ b/src/NATS.Client/v1/KeyValue/KeyValueWatchOption.cs @@ -1,4 +1,4 @@ -// Copyright 2022 The NATS Authors +// Copyright 2022 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -20,22 +20,22 @@ public enum KeyValueWatchOption /// Default is to include deletes. /// IgnoreDelete, - + /// /// Only get metadata, skip value when retrieving data from the server. /// MetaOnly, - + /// /// Watch starting at the first entry for all keys. /// Default is to start at the last per key. /// IncludeHistory, - + /// /// Watch starting when there are new entries for keys. /// Default is to start at the last per key. /// UpdatesOnly } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/KeyValue/KeyValueWatchSubscription.cs b/src/NATS.Client/v1/KeyValue/KeyValueWatchSubscription.cs index 0cadc0e8..a7d8dbcc 100644 --- a/src/NATS.Client/v1/KeyValue/KeyValueWatchSubscription.cs +++ b/src/NATS.Client/v1/KeyValue/KeyValueWatchSubscription.cs @@ -29,23 +29,64 @@ public KeyValueWatchSubscription(KeyValue kv, IList keyPatterns, { subLock = new object(); IList subscribeSubjects = new List(); - foreach (string keyPattern in keyPatterns) + foreach (var keyPattern in keyPatterns) { subscribeSubjects.Add(kv.ReadSubject(keyPattern)); - } - - // figure out the result options +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + bool headersOnly = false; + bool includeDeletes = true; + DeliverPolicy deliverPolicy = DeliverPolicy.LastPerSubject; +After: + var headersOnly = false; + var includeDeletes = true; + var deliverPolicy = DeliverPolicy.LastPerSubject; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + bool headersOnly = false; + bool includeDeletes = true; + DeliverPolicy deliverPolicy = DeliverPolicy.LastPerSubject; +After: + var headersOnly = false; + var includeDeletes = true; + var deliverPolicy = DeliverPolicy.LastPerSubject; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: bool headersOnly = false; bool includeDeletes = true; DeliverPolicy deliverPolicy = DeliverPolicy.LastPerSubject; - foreach (KeyValueWatchOption wo in watchOptions) +After: + var headersOnly = false; + var includeDeletes = true; + var deliverPolicy = DeliverPolicy.LastPerSubject; +*/ + + } + + // figure out the result options + var headersOnly = false; + var includeDeletes = true; + var deliverPolicy = DeliverPolicy.LastPerSubject; + foreach (var wo in watchOptions) { - switch (wo) + switch (wo) { - case KeyValueWatchOption.MetaOnly: headersOnly = true; break; - case KeyValueWatchOption.IgnoreDelete: includeDeletes = false; break; - case KeyValueWatchOption.UpdatesOnly: deliverPolicy = DeliverPolicy.New; break; - case KeyValueWatchOption.IncludeHistory: deliverPolicy = DeliverPolicy.All; break; + case KeyValueWatchOption.MetaOnly: + headersOnly = true; + break; + case KeyValueWatchOption.IgnoreDelete: + includeDeletes = false; + break; + case KeyValueWatchOption.UpdatesOnly: + deliverPolicy = DeliverPolicy.New; + break; + case KeyValueWatchOption.IncludeHistory: + deliverPolicy = DeliverPolicy.All; + break; } } @@ -57,7 +98,7 @@ public KeyValueWatchSubscription(KeyValue kv, IList keyPatterns, else { fromRevision = ConsumerConfiguration.UlongUnset; // easier on the builder since we aren't starting at a fromRevision - if (deliverPolicy == DeliverPolicy.New) + if (deliverPolicy == DeliverPolicy.New) { endOfDataSent = new InterlockedBoolean(true); watcher.EndOfData(); @@ -65,10 +106,31 @@ public KeyValueWatchSubscription(KeyValue kv, IList keyPatterns, else { endOfDataSent = new InterlockedBoolean(); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + PushSubscribeOptions pso = PushSubscribeOptions.Builder() +After: + var pso = PushSubscribeOptions.Builder() +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + PushSubscribeOptions pso = PushSubscribeOptions.Builder() +After: + var pso = PushSubscribeOptions.Builder() +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + PushSubscribeOptions pso = PushSubscribeOptions.Builder() +After: + var pso = PushSubscribeOptions.Builder() +*/ + } } - - PushSubscribeOptions pso = PushSubscribeOptions.Builder() + + var pso = PushSubscribeOptions.Builder() .WithStream(kv.StreamName) .WithOrdered(true) .WithConfiguration( @@ -82,8 +144,29 @@ public KeyValueWatchSubscription(KeyValue kv, IList keyPatterns, .Build(); void Handler(object sender, MsgHandlerEventArgs args) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + KeyValueEntry kve = new KeyValueEntry(args.Message); +After: + var kve = new KeyValueEntry(args.Message); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + KeyValueEntry kve = new KeyValueEntry(args.Message); +After: + var kve = new KeyValueEntry(args.Message); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: KeyValueEntry kve = new KeyValueEntry(args.Message); +After: + var kve = new KeyValueEntry(args.Message); +*/ + + { + var kve = new KeyValueEntry(args.Message); if (includeDeletes || kve.Operation.Equals(KeyValueOperation.Put)) { watcher.Watch(kve); @@ -98,8 +181,29 @@ void Handler(object sender, MsgHandlerEventArgs args) sub = kv.js.PushSubscribeAsync(null, Handler, false, pso); if (endOfDataSent.IsFalse()) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + ulong pending = sub.GetConsumerInformation().CalculatedPending; +After: + var pending = sub.GetConsumerInformation().CalculatedPending; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: ulong pending = sub.GetConsumerInformation().CalculatedPending; +After: + var pending = sub.GetConsumerInformation().CalculatedPending; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + ulong pending = sub.GetConsumerInformation().CalculatedPending; +After: + var pending = sub.GetConsumerInformation().CalculatedPending; +*/ + + { + var pending = sub.GetConsumerInformation().CalculatedPending; if (pending == 0) { endOfDataSent.Set(true); @@ -135,4 +239,4 @@ public void Dispose() Unsubscribe(); } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Msg.cs b/src/NATS.Client/v1/Msg.cs index 3a2575d5..2a81cb4a 100644 --- a/src/NATS.Client/v1/Msg.cs +++ b/src/NATS.Client/v1/Msg.cs @@ -60,14 +60,53 @@ public Msg(string subject, string reply, MsgHeader header, byte[] data) if (string.IsNullOrWhiteSpace(subject)) { throw new ArgumentException("Subject cannot be null, empty, or whitespace.", nameof(subject)); - } - +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this.Subject = subject; + this.Reply = reply; + this.Header = header; + this.Data = data; +After: + Subject = subject; + Reply = reply; + Header = header; + Data = data; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: this.Subject = subject; this.Reply = reply; this.Header = header; this.Data = data; +After: + Subject = subject; + Reply = reply; + Header = header; + Data = data; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this.Subject = subject; + this.Reply = reply; + this.Header = header; + this.Data = data; +After: + Subject = subject; + Reply = reply; + Header = header; + Data = data; +*/ + + } + + Subject = subject; + Reply = reply; + Header = header; + Data = data; } - + /// /// Initializes a new instance of the class with a subject, header, and data. /// @@ -78,7 +117,7 @@ public Msg(string subject, MsgHeader header, byte[] data) : this(subject, null, header, data) { } - + /// /// Initializes a new instance of the class with a subject, reply, and data. /// @@ -120,7 +159,7 @@ protected internal Msg(Msg msg) status = msg.status; _lastAck = msg._lastAck; } - + internal Msg(MsgArg arg, Subscription s, byte[] payload, long totalLen) { subject = arg.subject; @@ -131,17 +170,59 @@ internal Msg(MsgArg arg, Subscription s, byte[] payload, long totalLen) if (arg.hdr > 0) { headerLen = arg.hdr; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + HeaderStatusReader hsr = new HeaderStatusReader(payload, arg.hdr); +After: + var hsr = new HeaderStatusReader(payload, arg.hdr); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: HeaderStatusReader hsr = new HeaderStatusReader(payload, arg.hdr); +After: + var hsr = new HeaderStatusReader(payload, arg.hdr); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + HeaderStatusReader hsr = new HeaderStatusReader(payload, arg.hdr); +After: + var hsr = new HeaderStatusReader(payload, arg.hdr); +*/ + + var hsr = new HeaderStatusReader(payload, arg.hdr); header = hsr.Header; status = hsr.Status; } else { headerLen = 0; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + long payloadLen = totalLen - arg.hdr; +After: + var payloadLen = totalLen - arg.hdr; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + long payloadLen = totalLen - arg.hdr; +After: + var payloadLen = totalLen - arg.hdr; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + long payloadLen = totalLen - arg.hdr; +After: + var payloadLen = totalLen - arg.hdr; +*/ + } // make a deep copy of the bytes for this message. - long payloadLen = totalLen - arg.hdr; + var payloadLen = totalLen - arg.hdr; if (payloadLen > 0) { data = new byte[payloadLen]; @@ -187,17 +268,89 @@ public byte[] Data set { if (value == null) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: this.data = null; +After: + data = null; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this.data = null; +After: + data = null; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this.data = null; +After: + data = null; +*/ + + { + data = null; return; - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int len = value.Length; + if (len == 0) + this.data = Empty; + else + { + this.data = new byte[len]; +After: + var len = value.Length; + if (len == 0) + data = Empty; + else + { + data = new byte[len]; +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: int len = value.Length; if (len == 0) this.data = Empty; else { this.data = new byte[len]; +After: + var len = value.Length; + if (len == 0) + data = Empty; + else + { + data = new byte[len]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int len = value.Length; + if (len == 0) + this.data = Empty; + else + { + this.data = new byte[len]; +After: + var len = value.Length; + if (len == 0) + data = Empty; + else + { + data = new byte[len]; +*/ + + } + + var len = value.Length; + if (len == 0) + data = Empty; + else + { + data = new byte[len]; Array.Copy(value, 0, data, 0, len); } } @@ -249,15 +402,44 @@ public void Respond(byte[] data) if (string.IsNullOrEmpty(Reply)) { throw new NATSException("No Reply subject"); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Connection conn = ArrivalSubscription?.Connection; + if (conn == null) + { + throw new NATSException("Message is not bound to a subscription"); } +After: + var conn = (ArrivalSubscription?.Connection) ?? throw new NATSException("Message is not bound to a subscription"); +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: Connection conn = ArrivalSubscription?.Connection; if (conn == null) { throw new NATSException("Message is not bound to a subscription"); } +After: + var conn = (ArrivalSubscription?.Connection) ?? throw new NATSException("Message is not bound to a subscription"); +*/ - conn.Publish(this.Reply, data); +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Connection conn = ArrivalSubscription?.Connection; + if (conn == null) + { + throw new NATSException("Message is not bound to a subscription"); + } +After: + var conn = (ArrivalSubscription?.Connection) ?? throw new NATSException("Message is not bound to a subscription"); +*/ + + } + + var conn = (ArrivalSubscription?.Connection) ?? throw new NATSException("Message is not bound to a subscription"); + + conn.Publish(Reply, data); } /// @@ -265,8 +447,29 @@ public void Respond(byte[] data) /// /// A string representation of the messages. public override string ToString() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: StringBuilder sb = new StringBuilder(); +After: + var sb = new StringBuilder(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + StringBuilder sb = new StringBuilder(); +After: + var sb = new StringBuilder(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + StringBuilder sb = new StringBuilder(); +After: + var sb = new StringBuilder(); +*/ + + { + var sb = new StringBuilder(); sb.Append("{"); if (header != null) { @@ -274,8 +477,29 @@ public override string ToString() } sb.AppendFormat("Subject={0};Reply={1};Payload=<", Subject, Reply != null ? _reply : "null"); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int len = data.Length; +After: + var len = data.Length; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int len = data.Length; +After: + var len = data.Length; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int len = data.Length; +After: + var len = data.Length; +*/ + + + var len = data.Length; int i; for (i = 0; i < 32 && i < len; i++) @@ -424,7 +648,7 @@ public virtual void InProgress() { /* noop */ } /// Only applies to JetStream messages received from the server. /// /// the consumption byte count or -1 if the message implementation does not support this method - public long ConsumeByteCount => + public long ConsumeByteCount => subject.Length + headerLen + (data == null ? 0 : data.Length) + (_reply == null ? 0 : _reply.Length); } } diff --git a/src/NATS.Client/v1/MsgHeader.cs b/src/NATS.Client/v1/MsgHeader.cs index adae9bb4..48fa3c39 100644 --- a/src/NATS.Client/v1/MsgHeader.cs +++ b/src/NATS.Client/v1/MsgHeader.cs @@ -106,7 +106,7 @@ private void CheckKeyValue(string key, string value) throw new ArgumentException("key cannot be empty or null."); } - foreach (char c in key) + foreach (var c in key) { // only printable characters and no colon if (c < 32 || c > 126 || c == ':') @@ -115,7 +115,7 @@ private void CheckKeyValue(string key, string value) if (value != null) { - foreach (char c in value) + foreach (var c in value) { // Generally more permissive than HTTP. Allow only printable // characters and include tab (0x9) to cover what's allowed @@ -131,7 +131,8 @@ private void CheckKeyValue(string key, string value) /// public IEnumerable Keys { - get { + get + { return nvc.Keys; } } @@ -141,7 +142,7 @@ public IEnumerable Keys /// public int Count { - get { return nvc.Count; } + get { return nvc.Count; } } /// @@ -210,11 +211,32 @@ public void Clear() } private string ToHeaderString() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + StringBuilder sb = new StringBuilder(NatsConstants.HeaderVersionBytesPlusCrlf); +After: + var sb = new StringBuilder(NatsConstants.HeaderVersionBytesPlusCrlf); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + StringBuilder sb = new StringBuilder(NatsConstants.HeaderVersionBytesPlusCrlf); +After: + var sb = new StringBuilder(NatsConstants.HeaderVersionBytesPlusCrlf); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: StringBuilder sb = new StringBuilder(NatsConstants.HeaderVersionBytesPlusCrlf); +After: + var sb = new StringBuilder(NatsConstants.HeaderVersionBytesPlusCrlf); +*/ + + { + var sb = new StringBuilder(NatsConstants.HeaderVersionBytesPlusCrlf); foreach (string s in nvc.Keys) { - foreach (string v in nvc.GetValues(s)) + foreach (var v in nvc.GetValues(s)) { sb.AppendFormat("{0}:{1}\r\n", s, v); } @@ -256,8 +278,54 @@ public string[] GetValues(string name) /// /// public string GetFirst(string name) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string[] all = nvc.GetValues(name); + return all == null ? null: all[0]; + } + + /// + /// Gets the last value for the specific key. + /// Will be null if the key is not found + /// + /// + /// + public string GetLast(string name) + { + string[] all = nvc.GetValues(name); +After: + var all = nvc.GetValues(name); + return all == null ? null: all[0]; + } + + /// + /// Gets the last value for the specific key. + /// Will be null if the key is not found + /// + /// + /// + public string GetLast(string name) + { + var all = nvc.GetValues(name); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string[] all = nvc.GetValues(name); + return all == null ? null: all[0]; + } + + /// + /// Gets the last value for the specific key. + /// Will be null if the key is not found + /// + /// + /// + public string GetLast(string name) { string[] all = nvc.GetValues(name); +After: + var all = nvc.GetValues(name); return all == null ? null: all[0]; } @@ -269,8 +337,55 @@ public string GetFirst(string name) /// public string GetLast(string name) { + var all = nvc.GetValues(name); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string[] all = nvc.GetValues(name); - return all == null ? null: all[all.Length-1]; + return all == null ? null: all[0]; + } + + /// + /// Gets the last value for the specific key. + /// Will be null if the key is not found + /// + /// + /// + public string GetLast(string name) + { + string[] all = nvc.GetValues(name); +After: + var all = nvc.GetValues(name); + return all == null ? null: all[0]; + } + + /// + /// Gets the last value for the specific key. + /// Will be null if the key is not found + /// + /// + /// + public string GetLast(string name) + { + var all = nvc.GetValues(name); +*/ + + { + var all = nvc.GetValues(name); + return all == null ? null : all[0]; + } + + /// + /// Gets the last value for the specific key. + /// Will be null if the key is not found + /// + /// + /// + public string GetLast(string name) + { + var all = nvc.GetValues(name); + return all == null ? null : all[all.Length - 1]; } /// @@ -285,11 +400,39 @@ public IEnumerator GetEnumerator() private bool Equals(MsgHeader other) { - if (nvc.Count != other.nvc.Count) return false; - foreach (string key in nvc.AllKeys) - { + if (nvc.Count != other.nvc.Count) + return false; + foreach (var key in nvc.AllKeys) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string[] thisValues = nvc.GetValues(key) ?? Array.Empty(); + string[] thatValues = other.nvc.GetValues(key) ?? Array.Empty(); +After: + var thisValues = nvc.GetValues(key) ?? Array.Empty(); + var thatValues = other.nvc.GetValues(key) ?? Array.Empty(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: string[] thisValues = nvc.GetValues(key) ?? Array.Empty(); string[] thatValues = other.nvc.GetValues(key) ?? Array.Empty(); +After: + var thisValues = nvc.GetValues(key) ?? Array.Empty(); + var thatValues = other.nvc.GetValues(key) ?? Array.Empty(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string[] thisValues = nvc.GetValues(key) ?? Array.Empty(); + string[] thatValues = other.nvc.GetValues(key) ?? Array.Empty(); +After: + var thisValues = nvc.GetValues(key) ?? Array.Empty(); + var thatValues = other.nvc.GetValues(key) ?? Array.Empty(); +*/ + + { + var thisValues = nvc.GetValues(key) ?? Array.Empty(); + var thatValues = other.nvc.GetValues(key) ?? Array.Empty(); if (!thisValues.SequenceEqual(thatValues)) { return false; diff --git a/src/NATS.Client/v1/MsgStatus.cs b/src/NATS.Client/v1/MsgStatus.cs index a71c00f5..f08a4a58 100644 --- a/src/NATS.Client/v1/MsgStatus.cs +++ b/src/NATS.Client/v1/MsgStatus.cs @@ -1,4 +1,4 @@ -// Copyright 2015-2023 The NATS Authors +// Copyright 2015-2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -21,31 +21,35 @@ public sealed class MsgStatus private const string FlowControlText = "FlowControl Request"; private const string HeartbeatText = "Idle Heartbeat"; private const string NoRespondersText = "No Responders Available For Request"; - + private readonly int _code; private readonly string _message; - + public MsgStatus(int code, string message) { _code = code; _message = message ?? MakeMessage(code); } - public MsgStatus(Token codeToken, Token messageToken) : this(ExtractCode(codeToken), ExtractMessage(messageToken)) {} + public MsgStatus(Token codeToken, Token messageToken) : this(ExtractCode(codeToken), ExtractMessage(messageToken)) { } public int Code => _code; public string Message => _message; - private static string ExtractMessage(Token messageToken) { + private static string ExtractMessage(Token messageToken) + { return messageToken.HasValue() ? messageToken.Value() : null; } - private static int ExtractCode(Token codeToken) { - try { + private static int ExtractCode(Token codeToken) + { + try + { return int.Parse(codeToken.Value()); } - catch (Exception) { + catch (Exception) + { throw new NATSInvalidHeaderException(NatsConstants.InvalidHeaderStatusCode); } } @@ -54,24 +58,30 @@ private string MakeMessage(int code) { switch (code) { - case NatsConstants.NoRespondersCode: return NoRespondersText; - default: return "Server Status Message: " + code; + case NatsConstants.NoRespondersCode: + return NoRespondersText; + default: + return "Server Status Message: " + code; } } - private bool IsStatus(int code, string text) { + private bool IsStatus(int code, string text) + { return _code == code && _message.Equals(text); } - public bool IsFlowControl() { + public bool IsFlowControl() + { return _code == NatsConstants.FlowOrHeartbeatStatusCode && _message.Equals(FlowControlText); } - public bool IsHeartbeat() { + public bool IsHeartbeat() + { return _code == NatsConstants.FlowOrHeartbeatStatusCode && _message.Equals(HeartbeatText); } - public bool IsNoResponders() { + public bool IsNoResponders() + { return _code == NatsConstants.NoRespondersCode && _message.Equals(NoRespondersText); } diff --git a/src/NATS.Client/v1/NATS.cs b/src/NATS.Client/v1/NATS.cs index 842d97da..1b13793d 100644 --- a/src/NATS.Client/v1/NATS.cs +++ b/src/NATS.Client/v1/NATS.cs @@ -78,52 +78,52 @@ public static class Defaults /// /// The default NATS connect url ("nats://localhost:4222") /// - public const string Url = "nats://localhost:4222"; + public const string Url = "nats://localhost:4222"; /// /// The default NATS connect port. (4222) /// - public const int Port = 4222; + public const int Port = 4222; /// /// Default number of times to attempt a reconnect. (60) /// - public const int MaxReconnect = 60; + public const int MaxReconnect = 60; /// /// Default ReconnectWait time (2 seconds) /// - public const int ReconnectWait = 2000; // 2 seconds. - + public const int ReconnectWait = 2000; // 2 seconds. + /// /// Default timeout (2 seconds). /// - public const int Timeout = 2000; // 2 seconds. + public const int Timeout = 2000; // 2 seconds. /// /// Default ping interval (2 minutes); /// - public const int PingInterval = 120000;// 2 minutes. + public const int PingInterval = 120000;// 2 minutes. /// /// Default MaxPingOut value (2); /// - public const int MaxPingOut = 2; + public const int MaxPingOut = 2; /// /// Default MaxChanLen (65536) /// - public const int MaxChanLen = 65536; + public const int MaxChanLen = 65536; /// /// Default Request Channel Length /// - public const int RequestChanLen = 4; + public const int RequestChanLen = 4; /// /// Language string of this client, ".NET" /// - public const string LangString = ".NET"; + public const string LangString = ".NET"; /// /// Default subscriber pending messages limit. @@ -173,23 +173,23 @@ public static class Defaults // Default server pool size internal const int srvPoolSize = 4; - - public static EventHandler DefaultClosedEventHandler() => + + public static EventHandler DefaultClosedEventHandler() => (sender, e) => WriteEvent("ClosedEvent", e); - - public static EventHandler DefaultServerDiscoveredEventHandler() => + + public static EventHandler DefaultServerDiscoveredEventHandler() => (sender, e) => WriteEvent("ServerDiscoveredEvent", e); - - public static EventHandler DefaultDisconnectedEventHandler() => + + public static EventHandler DefaultDisconnectedEventHandler() => (sender, e) => WriteEvent("DisconnectedEvent", e); - public static EventHandler DefaultReconnectedEventHandler() => + public static EventHandler DefaultReconnectedEventHandler() => (sender, e) => WriteEvent("ReconnectedEvent", e); - public static EventHandler DefaultLameDuckModeEventHandler() => + public static EventHandler DefaultLameDuckModeEventHandler() => (sender, e) => WriteEvent("LameDuckModeEvent", e); - public static EventHandler DefaultAsyncErrorEventHandler() => + public static EventHandler DefaultAsyncErrorEventHandler() => (sender, e) => WriteError("AsyncErrorEvent", e); public static EventHandler DefaultHeartbeatAlarmEventHandler() => @@ -198,26 +198,28 @@ public static EventHandler DefaultHeartbeatAlarmEventHa "lastStreamSequence: ", e?.LastStreamSequence ?? 0U, "lastConsumerSequence: ", e?.LastConsumerSequence ?? 0U); - public static EventHandler DefaultUnhandledStatusEventHandler() => + public static EventHandler DefaultUnhandledStatusEventHandler() => (sender, e) => WriteJsEvent("UnhandledStatus", e, "Status: ", e?.Status); - public static EventHandler DefaultPullStatusWarningEventHandler() => + public static EventHandler DefaultPullStatusWarningEventHandler() => (sender, e) => WriteJsEvent("PullStatusWarning", e, "Status: ", e?.Status); - public static EventHandler DefaultPullStatusErrorEventHandler() => + public static EventHandler DefaultPullStatusErrorEventHandler() => (sender, e) => WriteJsEvent("PullStatusError", e, "Status: ", e?.Status); public static EventHandler DefaultFlowControlProcessedEventHandler() => (sender, e) => WriteJsEvent("FlowControlProcessed", e, "FcSubject: ", e?.FcSubject, "Source: ", e?.Source); - private static void WriteJsEvent(string label, ConnJsSubEventArgs e, params object[] pairs) { + private static void WriteJsEvent(string label, ConnJsSubEventArgs e, params object[] pairs) + { var sb = BeginFormatMessage(label, e?.Conn, e?.Sub, null); if (e?.JetStreamSub != null && e?.JetStreamSub.Consumer != null) { sb.Append(", ConsumerName:").Append(e.JetStreamSub.Consumer); } - for (int x = 0; x < pairs.Length; x++) { + for (var x = 0; x < pairs.Length; x++) + { sb.Append(", ").Append(pairs[x]).Append(pairs[++x]); } Console.Out.WriteLine(sb.ToString()); @@ -233,19 +235,42 @@ private static void WriteEvent(string label, ConnEventArgs e) Console.Error.WriteLine(BeginFormatMessage(label, e.Conn, null, e.Error.Message).ToString()); } - private static void WriteError(string label, ErrEventArgs e) { + private static void WriteError(string label, ErrEventArgs e) + { Console.Error.WriteLine(e == null ? label : BeginFormatMessage(label, e.Conn, e.Subscription, e.Error).ToString()); } private static StringBuilder BeginFormatMessage(string label, Connection conn, Subscription sub, string error) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: StringBuilder sb = new StringBuilder(label); +After: + var sb = new StringBuilder(label); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + StringBuilder sb = new StringBuilder(label); +After: + var sb = new StringBuilder(label); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + StringBuilder sb = new StringBuilder(label); +After: + var sb = new StringBuilder(label); +*/ + + { + var sb = new StringBuilder(label); if (conn != null) { sb.Append(", Connection: ").Append(conn.ClientID); } - if (sub != null) { + if (sub != null) + { sb.Append(", Subscription: ").Append(sub.Sid); } if (error != null) @@ -265,9 +290,36 @@ public enum FlowControlSource { FlowControl, Heartbeat } public class ConnEventArgs : EventArgs { internal ConnEventArgs(Connection c, Exception error = null) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: this.Conn = c; this.Error = error; +After: + Conn = c; + Error = error; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this.Conn = c; + this.Error = error; +After: + Conn = c; + Error = error; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this.Conn = c; + this.Error = error; +After: + Conn = c; + Error = error; +*/ + + { + Conn = c; + Error = error; } /// @@ -319,12 +371,33 @@ public class ErrEventArgs : EventArgs /// /// Gets the associated with the event. /// - public Subscription Subscription { get; } - + public Subscription Subscription { get; } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + public String Error { get; } +After: + public string Error { get; } +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + public String Error { get; } +After: + public string Error { get; } +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + public String Error { get; } +After: + public string Error { get; } +*/ + + /// /// Gets the error message associated with the event. /// - public String Error { get; } + public string Error { get; } public ErrEventArgs(Connection conn, Subscription subscription, string error) { @@ -344,7 +417,7 @@ public class ConnJsSubEventArgs : EventArgs /// The associated with the event. /// public Connection Conn { get; } - + /// /// The associated with the event. /// @@ -353,7 +426,7 @@ public class ConnJsSubEventArgs : EventArgs /// /// The when the associated Subscription is of this type. /// - public IJetStreamSubscription JetStreamSub { get; } + public IJetStreamSubscription JetStreamSub { get; } protected ConnJsSubEventArgs(Connection conn, Subscription sub) { @@ -365,7 +438,7 @@ protected ConnJsSubEventArgs(Connection conn, Subscription sub) } } } - + /// /// Provides details for an heartbeat alarm encountered /// @@ -374,7 +447,7 @@ public class HeartbeatAlarmEventArgs : ConnJsSubEventArgs public ulong LastStreamSequence { get; } public ulong LastConsumerSequence { get; } - public HeartbeatAlarmEventArgs(Connection c, Subscription s, + public HeartbeatAlarmEventArgs(Connection c, Subscription s, ulong lastStreamSequence, ulong lastConsumerSequence) : base(c, s) { LastStreamSequence = lastStreamSequence; @@ -400,9 +473,9 @@ public StatusEventArgs(Connection c, Subscription s, MsgStatus status) : base(c, /// public class UnhandledStatusEventArgs : StatusEventArgs { - public UnhandledStatusEventArgs(Connection c, Subscription s, MsgStatus status) : base(c, s, status) {} + public UnhandledStatusEventArgs(Connection c, Subscription s, MsgStatus status) : base(c, s, status) { } } - + /// /// Provides details for an status message when when a flow control is processed. /// @@ -430,12 +503,13 @@ public class UserJWTEventArgs : EventArgs /// /// Sets the JWT read by the event handler. This MUST be set in the event handler. /// - public string JWT + public string JWT { set { jwt = value; } internal get { - if (jwt == null) { + if (jwt == null) + { throw new NATSConnectionException("JWT was not set in the UserJWT event hander."); } return jwt; @@ -491,26 +565,26 @@ internal get */ internal class IC { - internal const string _CRLF_ = "\r\n"; + internal const string _CRLF_ = "\r\n"; internal const string _EMPTY_ = ""; - internal const string _SPC_ = " "; + internal const string _SPC_ = " "; internal const string _PUB_P_ = "PUB "; internal const string _HPUB_P_ = "HPUB "; - internal const string _OK_OP_ = "+OK"; - internal const string _ERR_OP_ = "-ERR"; - internal const string _MSG_OP_ = "MSG"; + internal const string _OK_OP_ = "+OK"; + internal const string _ERR_OP_ = "-ERR"; + internal const string _MSG_OP_ = "MSG"; internal const string _PING_OP_ = "PING"; internal const string _PONG_OP_ = "PONG"; internal const string _INFO_OP_ = "INFO"; internal const string inboxPrefix = "_INBOX."; - internal const string conProtoNoCRLF = "CONNECT"; - internal const string pingProto = "PING" + IC._CRLF_; - internal const string pongProto = "PONG" + IC._CRLF_; - internal const string pubProto = "PUB {0} {1} {2}" + IC._CRLF_; - internal const string subProto = "SUB {0} {1} {2}" + IC._CRLF_; + internal const string conProtoNoCRLF = "CONNECT"; + internal const string pingProto = "PING" + IC._CRLF_; + internal const string pongProto = "PONG" + IC._CRLF_; + internal const string pubProto = "PUB {0} {1} {2}" + IC._CRLF_; + internal const string subProto = "SUB {0} {1} {2}" + IC._CRLF_; internal const string unsubProto = "UNSUB {0} {1}" + IC._CRLF_; internal const string pongProtoNoCRLF = "PONG"; @@ -529,7 +603,7 @@ public MsgHandlerEventArgs(Msg message) { Message = message; } - + /// /// Retrieves the message. diff --git a/src/NATS.Client/v1/NKeys.cs b/src/NATS.Client/v1/NKeys.cs index b3e19591..06ee540f 100644 --- a/src/NATS.Client/v1/NKeys.cs +++ b/src/NATS.Client/v1/NKeys.cs @@ -55,9 +55,30 @@ internal static class Crc16 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 }; static internal ushort Checksum(byte[] data) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int crc = 0; +After: + var crc = 0; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int crc = 0; +After: + var crc = 0; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int crc = 0; - foreach (byte b in data) +After: + var crc = 0; +*/ + + { + var crc = 0; + foreach (var b in data) { crc = ((crc << 8) & 0xffff) ^ crc16tab[((crc >> 8) ^ (ushort)b & 0x00FF)]; } @@ -76,10 +97,44 @@ public class NkeyPair : IDisposable private byte[] key; public Nkeys.PrefixType Type { get; } - internal NkeyPair(byte[] publicKey, byte[] privateKey, Nkeys.PrefixType type) { + internal NkeyPair(byte[] publicKey, byte[] privateKey, Nkeys.PrefixType type) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: this.key = publicKey; this.expandedPrivateKey = privateKey; this.Type = type; +After: + key = publicKey; + expandedPrivateKey = privateKey; + Type = type; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this.key = publicKey; + this.expandedPrivateKey = privateKey; + this.Type = type; +After: + key = publicKey; + expandedPrivateKey = privateKey; + Type = type; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this.key = publicKey; + this.expandedPrivateKey = privateKey; + this.Type = type; +After: + key = publicKey; + expandedPrivateKey = privateKey; + Type = type; +*/ + + { + key = publicKey; + expandedPrivateKey = privateKey; + Type = type; } internal NkeyPair(byte[] userSeed, Nkeys.PrefixType type) @@ -87,9 +142,30 @@ internal NkeyPair(byte[] userSeed, Nkeys.PrefixType type) if (userSeed == null) { throw new NATSException("seed cannot be null"); - } +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int len = userSeed.Length; +After: + var len = userSeed.Length; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int len = userSeed.Length; +After: + var len = userSeed.Length; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int len = userSeed.Length; +After: + var len = userSeed.Length; +*/ + + } + + var len = userSeed.Length; if (len != Ed25519.PrivateKeySeedSize) { throw new NATSException("invalid seed length"); @@ -130,8 +206,29 @@ public void Wipe() /// /// The signature. public byte[] Sign(byte[] src) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: byte[] rv = Ed25519.Sign(src, expandedPrivateKey); +After: + var rv = Ed25519.Sign(src, expandedPrivateKey); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + byte[] rv = Ed25519.Sign(src, expandedPrivateKey); +After: + var rv = Ed25519.Sign(src, expandedPrivateKey); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + byte[] rv = Ed25519.Sign(src, expandedPrivateKey); +After: + var rv = Ed25519.Sign(src, expandedPrivateKey); +*/ + + { + var rv = Ed25519.Sign(src, expandedPrivateKey); CryptoBytes.Wipe(expandedPrivateKey); return rv; } @@ -211,7 +308,8 @@ public enum PrefixType /// Base 32 encoded Nkey. /// public static byte[] Decode(string src) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: byte[] raw = Base32.Decode(src); byte[] raw2 = Base32.FromBase32String(src); ushort crc = (ushort)(raw[raw.Length - 2] | raw[raw.Length - 1] << 8); @@ -219,6 +317,62 @@ public static byte[] Decode(string src) // trim off the CRC16 int len = raw.Length - 2; byte[] data = new byte[len]; +After: + var raw = Base32.Decode(src); + var raw2 = Base32.FromBase32String(src); + var crc = (ushort)(raw[raw.Length - 2] | raw[raw.Length - 1] << 8); + + // trim off the CRC16 + var len = raw.Length - 2; + var data = new byte[len]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + byte[] raw = Base32.Decode(src); + byte[] raw2 = Base32.FromBase32String(src); + ushort crc = (ushort)(raw[raw.Length - 2] | raw[raw.Length - 1] << 8); + + // trim off the CRC16 + int len = raw.Length - 2; + byte[] data = new byte[len]; +After: + var raw = Base32.Decode(src); + var raw2 = Base32.FromBase32String(src); + var crc = (ushort)(raw[raw.Length - 2] | raw[raw.Length - 1] << 8); + + // trim off the CRC16 + var len = raw.Length - 2; + var data = new byte[len]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + byte[] raw = Base32.Decode(src); + byte[] raw2 = Base32.FromBase32String(src); + ushort crc = (ushort)(raw[raw.Length - 2] | raw[raw.Length - 1] << 8); + + // trim off the CRC16 + int len = raw.Length - 2; + byte[] data = new byte[len]; +After: + var raw = Base32.Decode(src); + var raw2 = Base32.FromBase32String(src); + var crc = (ushort)(raw[raw.Length - 2] | raw[raw.Length - 1] << 8); + + // trim off the CRC16 + var len = raw.Length - 2; + var data = new byte[len]; +*/ + + { + var raw = Base32.Decode(src); + var raw2 = Base32.FromBase32String(src); + var crc = (ushort)(raw[raw.Length - 2] | raw[raw.Length - 1] << 8); + + // trim off the CRC16 + var len = raw.Length - 2; + var data = new byte[len]; Buffer.BlockCopy(raw, 0, data, 0, len); if (crc != Crc16.Checksum(data)) @@ -231,12 +385,12 @@ private static bool IsValidPublicPrefixByte(byte prefixByte) { switch (prefixByte) { - case PrefixByteServer: - case PrefixByteCluster: - case PrefixByteOperator: - case PrefixByteAccount: - case PrefixByteUser: - return true; + case PrefixByteServer: + case PrefixByteCluster: + case PrefixByteOperator: + case PrefixByteAccount: + case PrefixByteUser: + return true; } return false; } @@ -245,11 +399,16 @@ private static bool IsValidPublicPrefixByte(byte prefixByte) { switch (prefixByte) { - case PrefixByteServer: return PrefixType.Server; - case PrefixByteCluster: return PrefixType.Cluster; - case PrefixByteOperator: return PrefixType.Operator; - case PrefixByteAccount: return PrefixType.Account; - case PrefixByteUser: return PrefixType.User; + case PrefixByteServer: + return PrefixType.Server; + case PrefixByteCluster: + return PrefixType.Cluster; + case PrefixByteOperator: + return PrefixType.Operator; + case PrefixByteAccount: + return PrefixType.Account; + case PrefixByteUser: + return PrefixType.User; } return null; } @@ -258,11 +417,16 @@ internal static byte PrefixFromType(PrefixType type) { switch (type) { - case PrefixType.Server: return PrefixByteServer; - case PrefixType.Cluster: return PrefixByteCluster; - case PrefixType.Operator: return PrefixByteOperator; - case PrefixType.Account: return PrefixByteAccount; - case PrefixType.User: return PrefixByteUser; + case PrefixType.Server: + return PrefixByteServer; + case PrefixType.Cluster: + return PrefixByteCluster; + case PrefixType.Operator: + return PrefixByteOperator; + case PrefixType.Account: + return PrefixByteAccount; + case PrefixType.User: + return PrefixByteUser; } return 0; } @@ -295,8 +459,86 @@ internal static byte[] DecodeSeed(byte[] raw) } internal static byte[] DecodeSeed(byte[] raw, out PrefixType type) - { - // Need to do the reverse here to get back to internal representation. +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + byte b1 = (byte)(raw[0] & 248); // 248 = 11111000 + byte prefix = (byte)((raw[0] & 7) << 5 | ((raw[1] & 248) >> 3)); // 7 = 00000111 + + try + { + if (b1 != PrefixByteSeed) + throw new NATSException("Invalid Seed."); + + PrefixType? tfp = TypeFromPrefix(prefix); + if (!tfp.HasValue) + { + throw new NATSException("Invalid Public Prefix Byte."); + } + type = tfp.Value; + + // Trim off the first two bytes + byte[] data = new byte[raw.Length - 2]; +After: + var b1 = (byte)(raw[0] & 248); // 248 = 11111000 + var prefix = (byte)((raw[0] & 7) << 5 | ((raw[1] & 248) >> 3)); // 7 = 00000111 + + try + { + if (b1 != PrefixByteSeed) + throw new NATSException("Invalid Seed."); + + var tfp = TypeFromPrefix(prefix); + if (!tfp.HasValue) + { + throw new NATSException("Invalid Public Prefix Byte."); + } + type = tfp.Value; + + // Trim off the first two bytes + var data = new byte[raw.Length - 2]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + byte b1 = (byte)(raw[0] & 248); // 248 = 11111000 + byte prefix = (byte)((raw[0] & 7) << 5 | ((raw[1] & 248) >> 3)); // 7 = 00000111 + + try + { + if (b1 != PrefixByteSeed) + throw new NATSException("Invalid Seed."); + + PrefixType? tfp = TypeFromPrefix(prefix); + if (!tfp.HasValue) + { + throw new NATSException("Invalid Public Prefix Byte."); + } + type = tfp.Value; + + // Trim off the first two bytes + byte[] data = new byte[raw.Length - 2]; +After: + var b1 = (byte)(raw[0] & 248); // 248 = 11111000 + var prefix = (byte)((raw[0] & 7) << 5 | ((raw[1] & 248) >> 3)); // 7 = 00000111 + + try + { + if (b1 != PrefixByteSeed) + throw new NATSException("Invalid Seed."); + + var tfp = TypeFromPrefix(prefix); + if (!tfp.HasValue) + { + throw new NATSException("Invalid Public Prefix Byte."); + } + type = tfp.Value; + + // Trim off the first two bytes + var data = new byte[raw.Length - 2]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: byte b1 = (byte)(raw[0] & 248); // 248 = 11111000 byte prefix = (byte)((raw[0] & 7) << 5 | ((raw[1] & 248) >> 3)); // 7 = 00000111 @@ -314,6 +556,93 @@ internal static byte[] DecodeSeed(byte[] raw, out PrefixType type) // Trim off the first two bytes byte[] data = new byte[raw.Length - 2]; +After: + var b1 = (byte)(raw[0] & 248); // 248 = 11111000 + var prefix = (byte)((raw[0] & 7) << 5 | ((raw[1] & 248) >> 3)); // 7 = 00000111 + + try + { + if (b1 != PrefixByteSeed) + throw new NATSException("Invalid Seed."); + + var tfp = TypeFromPrefix(prefix); + if (!tfp.HasValue) + { + throw new NATSException("Invalid Public Prefix Byte."); + } + type = tfp.Value; + + // Trim off the first two bytes + var data = new byte[raw.Length - 2]; +*/ + + { + // Need to do the reverse here to get back to internal representation. + var b1 = (byte)(raw[0] & 248); // 248 = 11111000 +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + byte[] raw = Nkeys.Decode(publicKey); + byte prefix = raw[0]; +After: + var raw = Nkeys.Decode(publicKey); + var prefix = raw[0]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + byte[] raw = Nkeys.Decode(publicKey); + byte prefix = raw[0]; +After: + var raw = Nkeys.Decode(publicKey); + var prefix = raw[0]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + byte[] raw = Nkeys.Decode(publicKey); + byte prefix = raw[0]; +After: + var raw = Nkeys.Decode(publicKey); + var prefix = raw[0]; +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + PrefixType? tfp = TypeFromPrefix(prefix); +After: + var tfp = TypeFromPrefix(prefix); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + PrefixType? tfp = TypeFromPrefix(prefix); +After: + var tfp = TypeFromPrefix(prefix); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + PrefixType? tfp = TypeFromPrefix(prefix); +After: + var tfp = TypeFromPrefix(prefix); +*/ + + var prefix = (byte)((raw[0] & 7) << 5 | ((raw[1] & 248) >> 3)); // 7 = 00000111 + + try + { + if (b1 != PrefixByteSeed) + throw new NATSException("Invalid Seed."); + + var tfp = TypeFromPrefix(prefix); + if (!tfp.HasValue) + { + throw new NATSException("Invalid Public Prefix Byte."); + } + type = tfp.Value; + + // Trim off the first two bytes + var data = new byte[raw.Length - 2]; Buffer.BlockCopy(raw, 2, data, 0, data.Length); return data; } @@ -337,12 +666,33 @@ internal static byte[] DecodeSeed(string src, out PrefixType type) return DecodeSeed(Nkeys.Decode(src), out type); } - public static NkeyPair FromPublicKey(string publicKey) + public static NkeyPair FromPublicKey( +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + byte[] userSeed = DecodeSeed(seed, out type); +After: + var userSeed = DecodeSeed(seed, out type); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + byte[] userSeed = DecodeSeed(seed, out type); +After: + var userSeed = DecodeSeed(seed, out type); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + byte[] userSeed = DecodeSeed(seed, out type); +After: + var userSeed = DecodeSeed(seed, out type); +*/ +string publicKey) { - byte[] raw = Nkeys.Decode(publicKey); - byte prefix = raw[0]; + var raw = Nkeys.Decode(publicKey); + var prefix = raw[0]; - PrefixType? tfp = TypeFromPrefix(prefix); + var tfp = TypeFromPrefix(prefix); if (!tfp.HasValue) { throw new NATSException("Not a valid public NKey"); @@ -367,7 +717,7 @@ public static NkeyPair FromPublicKey(char[] publicKey) public static NkeyPair FromSeed(string seed) { PrefixType type; - byte[] userSeed = DecodeSeed(seed, out type); + var userSeed = DecodeSeed(seed, out type); try { var kp = new NkeyPair(userSeed, type); @@ -386,34 +736,127 @@ internal static string Encode(byte prefixbyte, bool seed, byte[] src) if (src.Length != 32) throw new NATSException("Invalid seed size"); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + MemoryStream stream = new MemoryStream(); +After: + var stream = new MemoryStream(); +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: MemoryStream stream = new MemoryStream(); +After: + var stream = new MemoryStream(); +*/ - if (seed) { - // In order to make this human printable for both bytes, we need to do a little - // bit manipulation to setup for base32 encoding which takes 5 bits at a time. +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + MemoryStream stream = new MemoryStream(); +After: + var stream = new MemoryStream(); +*/ + + + var stream = new MemoryStream(); + + if (seed) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: byte b1 = (byte) (PrefixByteSeed | (prefixbyte >> 5)); byte b2 = (byte) ((prefixbyte & 31) << 3); // 31 = 00011111 +After: + var b1 = (byte) (PrefixByteSeed | (prefixbyte >> 5)); + var b2 = (byte) ((prefixbyte & 31) << 3); // 31 = 00011111 +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + byte b1 = (byte) (PrefixByteSeed | (prefixbyte >> 5)); + byte b2 = (byte) ((prefixbyte & 31) << 3); // 31 = 00011111 +After: + var b1 = (byte) (PrefixByteSeed | (prefixbyte >> 5)); + var b2 = (byte) ((prefixbyte & 31) << 3); // 31 = 00011111 +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + byte b1 = (byte) (PrefixByteSeed | (prefixbyte >> 5)); + byte b2 = (byte) ((prefixbyte & 31) << 3); // 31 = 00011111 +After: + var b1 = (byte) (PrefixByteSeed | (prefixbyte >> 5)); + var b2 = (byte) ((prefixbyte & 31) << 3); // 31 = 00011111 +*/ + + { + // In order to make this human printable for both bytes, we need to do a little + // bit manipulation to setup for base32 encoding which takes 5 bits at a time. + var b1 = (byte)(PrefixByteSeed | (prefixbyte >> 5)); + var b2 = (byte)((prefixbyte & 31) << 3); // 31 = 00011111 stream.WriteByte(b1); stream.WriteByte(b2); - } else { + } + else + { stream.WriteByte(prefixbyte); } // write payload stream.Write(src, 0, src.Length); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + byte[] checksum = BitConverter.GetBytes(Crc16.Checksum(stream.ToArray())); +After: + var checksum = BitConverter.GetBytes(Crc16.Checksum(stream.ToArray())); +*/ - // Calculate and write crc16 checksum +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + byte[] checksum = BitConverter.GetBytes(Crc16.Checksum(stream.ToArray())); +After: + var checksum = BitConverter.GetBytes(Crc16.Checksum(stream.ToArray())); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: byte[] checksum = BitConverter.GetBytes(Crc16.Checksum(stream.ToArray())); +After: + var checksum = BitConverter.GetBytes(Crc16.Checksum(stream.ToArray())); +*/ + + + // Calculate and write crc16 checksum + var checksum = BitConverter.GetBytes(Crc16.Checksum(stream.ToArray())); stream.Write(checksum, 0, checksum.Length); return Base32.Encode(stream.ToArray()); } private static string CreateSeed(byte prefixbyte) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + byte[] rawSeed = new byte[32]; +After: + var rawSeed = new byte[32]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + byte[] rawSeed = new byte[32]; +After: + var rawSeed = new byte[32]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: byte[] rawSeed = new byte[32]; +After: + var rawSeed = new byte[32]; +*/ + + { + var rawSeed = new byte[32]; using (var rng = RandomNumberGenerator.Create()) { @@ -456,15 +899,63 @@ public static string CreateOperatorSeed() /// /// A the public key corresponding to Seed public static string PublicKeyFromSeed(string seed) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + byte[] s = Nkeys.Decode(seed); +After: + var s = Nkeys.Decode(seed); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + byte[] s = Nkeys.Decode(seed); +After: + var s = Nkeys.Decode(seed); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: byte[] s = Nkeys.Decode(seed); +After: + var s = Nkeys.Decode(seed); +*/ + + { + var s = Nkeys.Decode(seed); if ((s[0] & (31 << 3)) != PrefixByteSeed) { throw new NATSException("Not a seed"); - } - // reconstruct prefix byte +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + byte prefixByte = (byte) ((s[0] & 7) << 5 | ((s[1] >> 3) & 31)); + byte[] pubKey = Ed25519.PublicKeyFromSeed(DecodeSeed(s)); +After: + var prefixByte = (byte) ((s[0] & 7) << 5 | ((s[1] >> 3) & 31)); + var pubKey = Ed25519.PublicKeyFromSeed(DecodeSeed(s)); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + byte prefixByte = (byte) ((s[0] & 7) << 5 | ((s[1] >> 3) & 31)); + byte[] pubKey = Ed25519.PublicKeyFromSeed(DecodeSeed(s)); +After: + var prefixByte = (byte) ((s[0] & 7) << 5 | ((s[1] >> 3) & 31)); + var pubKey = Ed25519.PublicKeyFromSeed(DecodeSeed(s)); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: byte prefixByte = (byte) ((s[0] & 7) << 5 | ((s[1] >> 3) & 31)); byte[] pubKey = Ed25519.PublicKeyFromSeed(DecodeSeed(s)); +After: + var prefixByte = (byte) ((s[0] & 7) << 5 | ((s[1] >> 3) & 31)); + var pubKey = Ed25519.PublicKeyFromSeed(DecodeSeed(s)); +*/ + + } + // reconstruct prefix byte + var prefixByte = (byte)((s[0] & 7) << 5 | ((s[1] >> 3) & 31)); + var pubKey = Ed25519.PublicKeyFromSeed(DecodeSeed(s)); return Encode(prefixByte, false, pubKey); } } diff --git a/src/NATS.Client/v1/NUID.cs b/src/NATS.Client/v1/NUID.cs index 434f7c16..9e5ab7c8 100644 --- a/src/NATS.Client/v1/NUID.cs +++ b/src/NATS.Client/v1/NUID.cs @@ -25,33 +25,366 @@ namespace NATS.Client [Obsolete("NATS.Client.NUID is deprecated and will be removed in a future version")] public class NUID { - private static char[] digits = + private static char[] digits = { '0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F','G','H','I','J', 'K','L','M','N','O','P','Q','R','S','T', 'U','V','W','X','Y','Z' }; - private static int nuidBase = 36; - private static int preLen = 12; + private static int nuidBase = 36; + private static int preLen = 12; private static long seqLen = 10; /// /// Length of the NUID. /// - public static long LENGTH = preLen + seqLen; + public static long LENGTH = preLen + seqLen; /// /// Maximum value of the prefix. /// - public static long MAXPRE = 4738381338321616896L; // base^preLen == 36^12 + public static +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + private static Object globalLock = new Object(); + + private long nextLong(bool useSecureRand, long min, long max) + { + ulong uRange = (ulong)(max - min); + + ulong ulongRand; + do + { + byte[] buf = new byte[8]; + + if (useSecureRand) + { + srand.GetBytes(buf); + } + else + { + prand.NextBytes(buf); + } + + ulongRand = (ulong)BitConverter.ToInt64(buf, 0); + + } while (ulongRand > ulong.MaxValue - ((ulong.MaxValue % uRange) + 1) % uRange); + + return (long)(ulongRand % uRange) + min; + } + + private long nextLong(bool useSecureRand, long max) + { + return nextLong(useSecureRand, 0, max); + } +After: + private static object globalLock = new object(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + private static Object globalLock = new Object(); + + private long nextLong(bool useSecureRand, long min, long max) + { + ulong uRange = (ulong)(max - min); + + ulong ulongRand; + do + { + byte[] buf = new byte[8]; + + if (useSecureRand) + { + srand.GetBytes(buf); + } + else + { + prand.NextBytes(buf); + } + + ulongRand = (ulong)BitConverter.ToInt64(buf, 0); + + } while (ulongRand > ulong.MaxValue - ((ulong.MaxValue % uRange) + 1) % uRange); + + return (long)(ulongRand % uRange) + min; + } + + private long nextLong(bool useSecureRand, long max) + { + return nextLong(useSecureRand, 0, max); + } +After: + private static object globalLock = new object(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + private static Object globalLock = new Object(); + + private long nextLong(bool useSecureRand, long min, long max) + { + ulong uRange = (ulong)(max - min); + + ulong ulongRand; + do + { + byte[] buf = new byte[8]; + + if (useSecureRand) + { + srand.GetBytes(buf); + } + else + { + prand.NextBytes(buf); + } + + ulongRand = (ulong)BitConverter.ToInt64(buf, 0); + + } while (ulongRand > ulong.MaxValue - ((ulong.MaxValue % uRange) + 1) % uRange); + + return (long)(ulongRand % uRange) + min; + } + + private long nextLong(bool useSecureRand, long max) + { + return nextLong(useSecureRand, 0, max); + } +After: + private static object globalLock = new object(); +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + private long nextLong(bool useSecureRand) +After: + private long nextLong(bool useSecureRand, long min, long max) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + private long nextLong(bool useSecureRand) +After: + private long nextLong(bool useSecureRand, long min, long max) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + private long nextLong(bool useSecureRand) +After: + private long nextLong(bool useSecureRand, long min, long max) +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + return nextLong(useSecureRand, long.MinValue, long.MaxValue); +After: + var uRange = (ulong)(max - min); + + ulong ulongRand; + do + { + var buf = new byte[8]; + + if (useSecureRand) + { + srand.GetBytes(buf); + } + else + { + prand.NextBytes(buf); + } + + ulongRand = (ulong)BitConverter.ToInt64(buf, 0); + + } while (ulongRand > ulong.MaxValue - ((ulong.MaxValue % uRange) + 1) % uRange); + + return (long)(ulongRand % uRange) + min; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + return nextLong(useSecureRand, long.MinValue, long.MaxValue); +After: + var uRange = (ulong)(max - min); + + ulong ulongRand; + do + { + var buf = new byte[8]; + + if (useSecureRand) + { + srand.GetBytes(buf); + } + else + { + prand.NextBytes(buf); + } + + ulongRand = (ulong)BitConverter.ToInt64(buf, 0); + + } while (ulongRand > ulong.MaxValue - ((ulong.MaxValue % uRange) + 1) % uRange); + + return (long)(ulongRand % uRange) + min; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + return nextLong(useSecureRand, long.MinValue, long.MaxValue); +After: + var uRange = (ulong)(max - min); + + ulong ulongRand; + do + { + var buf = new byte[8]; + + if (useSecureRand) + { + srand.GetBytes(buf); + } + else + { + prand.NextBytes(buf); + } + + ulongRand = (ulong)BitConverter.ToInt64(buf, 0); + + } while (ulongRand > ulong.MaxValue - ((ulong.MaxValue % uRange) + 1) % uRange); + + return (long)(ulongRand % uRange) + min; +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Added: + private long nextLong(bool useSecureRand, long max) + { + return nextLong(useSecureRand, 0, max); + } + + private long nextLong(bool useSecureRand) + { + return nextLong(useSecureRand, long.MinValue, long.MaxValue); + } +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Added: + private long nextLong(bool useSecureRand, long max) + { + return nextLong(useSecureRand, 0, max); + } + + private long nextLong(bool useSecureRand) + { + return nextLong(useSecureRand, long.MinValue, long.MaxValue); + } +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Added: + private long nextLong(bool useSecureRand, long max) + { + return nextLong(useSecureRand, 0, max); + } + + private long nextLong(bool useSecureRand) + { + return nextLong(useSecureRand, long.MinValue, long.MaxValue); + } +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + char[] b = new char[totalLen]; +After: + var b = new char[totalLen]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + char[] b = new char[totalLen]; +After: + var b = new char[totalLen]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + char[] b = new char[totalLen]; +After: + var b = new char[totalLen]; +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int i = b.Length; + for (long l = seq; i > preLen; l /= nuidBase) +After: + var i = b.Length; + for (var l = seq; i > preLen; l /= nuidBase) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int i = b.Length; + for (long l = seq; i > preLen; l /= nuidBase) +After: + var i = b.Length; + for (var l = seq; i > preLen; l /= nuidBase) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int i = b.Length; + for (long l = seq; i > preLen; l /= nuidBase) +After: + var i = b.Length; + for (var l = seq; i > preLen; l /= nuidBase) +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + long n = nextLong(true, MAXPRE); + int i = pre.Length; + for (long l = n; l > 0; l /= nuidBase) +After: + var n = nextLong(true, MAXPRE); + var i = pre.Length; + for (var l = n; l > 0; l /= nuidBase) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + long n = nextLong(true, MAXPRE); + int i = pre.Length; + for (long l = n; l > 0; l /= nuidBase) +After: + var n = nextLong(true, MAXPRE); + var i = pre.Length; + for (var l = n; l > 0; l /= nuidBase) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + long n = nextLong(true, MAXPRE); + int i = pre.Length; + for (long l = n; l > 0; l /= nuidBase) +After: + var n = nextLong(true, MAXPRE); + var i = pre.Length; + for (var l = n; l > 0; l /= nuidBase) +*/ +long MAXPRE = 4738381338321616896L; // base^preLen == 36^12 /// /// Maximum value of the sequence. /// - public static long MAXSEQ = 3656158440062976L; // base^seqLen == 36^10 + public static long MAXSEQ = 3656158440062976L; // base^seqLen == 36^10 - private static int minInc = 33; - private static int maxInc = 333; + private static int minInc = 33; + private static int maxInc = 333; private static long totalLen = preLen + seqLen; #if NET46 private RNGCryptoServiceProvider srand = new RNGCryptoServiceProvider(); @@ -67,16 +400,16 @@ public class NUID // Global NUID private static NUID globalNUID = new NUID(); - private static Object globalLock = new Object(); + private static object globalLock = new object(); private long nextLong(bool useSecureRand, long min, long max) { - ulong uRange = (ulong)(max - min); + var uRange = (ulong)(max - min); ulong ulongRand; do { - byte[] buf = new byte[8]; + var buf = new byte[8]; if (useSecureRand) { @@ -86,9 +419,9 @@ private long nextLong(bool useSecureRand, long min, long max) { prand.NextBytes(buf); } - + ulongRand = (ulong)BitConverter.ToInt64(buf, 0); - + } while (ulongRand > ulong.MaxValue - ((ulong.MaxValue % uRange) + 1) % uRange); return (long)(ulongRand % uRange) + min; @@ -113,11 +446,11 @@ private string getNextNuid() resetSequential(); } - char[] b = new char[totalLen]; + var b = new char[totalLen]; Array.Copy(pre, b, preLen); - int i = b.Length; - for (long l = seq; i > preLen; l /= nuidBase) + var i = b.Length; + for (var l = seq; i > preLen; l /= nuidBase) { i--; b[i] = digits[(int)(l % nuidBase)]; @@ -140,9 +473,9 @@ private void resetSequential() /// public void RandomizePrefix() { - long n = nextLong(true, MAXPRE); - int i = pre.Length; - for (long l = n; l > 0; l /= nuidBase) + var n = nextLong(true, MAXPRE); + var i = pre.Length; + for (var l = n; l > 0; l /= nuidBase) { i--; pre[i] = (byte)digits[(int)(l % nuidBase)]; diff --git a/src/NATS.Client/v1/NaCl/CryptoBytes.cs b/src/NATS.Client/v1/NaCl/CryptoBytes.cs index 9c9acf80..cfc9f6ff 100644 --- a/src/NATS.Client/v1/NaCl/CryptoBytes.cs +++ b/src/NATS.Client/v1/NaCl/CryptoBytes.cs @@ -59,7 +59,8 @@ public static bool ConstantTimeEquals(byte[] x, byte[] y) public static bool ConstantTimeEquals(ArraySegment x, ArraySegment y) { // Contract.Requires(x.Array != null && y.Array != null); - if (x.Array == null || y.Array == null) throw new ArgumentNullException(); + if (x.Array == null || y.Array == null) + throw new ArgumentNullException(); if (x.Count != y.Count) return false; return InternalConstantTimeEquals(x.Array, x.Offset, y.Array, y.Offset, x.Count) != 0; @@ -82,21 +83,46 @@ public static bool ConstantTimeEquals(ArraySegment x, ArraySegment y public static bool ConstantTimeEquals(byte[] x, int xOffset, byte[] y, int yOffset, int length) { // Contract.Requires(x != null && y != null); - if (x == null || y == null) throw new ArgumentNullException(); + if (x == null || y == null) + throw new ArgumentNullException(); // Contract.Requires(xOffset >= 0 && yOffset >= 0 && length >= 0); - if (xOffset < 0 || yOffset < 0 || length < 0) throw new ArgumentException(); + if (xOffset < 0 || yOffset < 0 || length < 0) + throw new ArgumentException(); // Contract.Requires(xOffset + length <= x.Length); - if (xOffset + length > x.Length) throw new ArgumentException(); + if (xOffset + length > x.Length) + throw new ArgumentException(); // Contract.Requires(yOffset + length <= y.Length); - if (yOffset + length > y.Length) throw new ArgumentException(); + if (yOffset + length > y.Length) + throw new ArgumentException(); return InternalConstantTimeEquals(x, xOffset, y, yOffset, length) != 0; } private static uint InternalConstantTimeEquals(byte[] x, int xOffset, byte[] y, int yOffset, int length) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int differentbits = 0; +After: + var differentbits = 0; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int differentbits = 0; +After: + var differentbits = 0; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int differentbits = 0; - for (int i = 0; i < length; i++) +After: + var differentbits = 0; +*/ + + { + var differentbits = 0; + for (var i = 0; i < length; i++) differentbits |= x[xOffset + i] ^ y[yOffset + i]; return (1 & (unchecked((uint)differentbits - 1) >> 8)); } @@ -108,7 +134,8 @@ private static uint InternalConstantTimeEquals(byte[] x, int xOffset, byte[] y, public static void Wipe(byte[] data) { // Contract.Requires(data != null); - if (data == null) throw new ArgumentNullException(); + if (data == null) + throw new ArgumentNullException(); InternalWipe(data, 0, data.Length); } @@ -121,11 +148,14 @@ public static void Wipe(byte[] data) public static void Wipe(byte[] data, int offset, int length) { // Contract.Requires(data != null); - if (data == null) throw new ArgumentNullException(); + if (data == null) + throw new ArgumentNullException(); // Contract.Requires(offset >= 0 && length >= 0); - if (offset< 0 || length < 0) throw new ArgumentOutOfRangeException(); + if (offset < 0 || length < 0) + throw new ArgumentOutOfRangeException(); // Contract.Requires(offset + length <= data.Length); - if (offset + length > data.Length) throw new ArgumentException(); + if (offset + length > data.Length) + throw new ArgumentException(); InternalWipe(data, offset, length); } @@ -171,9 +201,30 @@ public static string ToHexStringUpper(byte[] data) { if (data == null) return null; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: char[] c = new char[data.Length * 2]; +After: + var c = new char[data.Length * 2]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + char[] c = new char[data.Length * 2]; +After: + var c = new char[data.Length * 2]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + char[] c = new char[data.Length * 2]; +After: + var c = new char[data.Length * 2]; +*/ + + var c = new char[data.Length * 2]; int b; - for (int i = 0; i < data.Length; i++) + for (var i = 0; i < data.Length; i++) { b = data[i] >> 4; c[i * 2] = (char)(55 + b + (((b - 10) >> 31) & -7)); @@ -193,9 +244,30 @@ public static string ToHexStringLower(byte[] data) { if (data == null) return null; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: char[] c = new char[data.Length * 2]; +After: + var c = new char[data.Length * 2]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + char[] c = new char[data.Length * 2]; +After: + var c = new char[data.Length * 2]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + char[] c = new char[data.Length * 2]; +After: + var c = new char[data.Length * 2]; +*/ + + var c = new char[data.Length * 2]; int b; - for (int i = 0; i < data.Length; i++) + for (var i = 0; i < data.Length; i++) { b = data[i] >> 4; c[i * 2] = (char)(87 + b + (((b - 10) >> 31) & -39)); @@ -217,7 +289,7 @@ public static byte[] FromHexString(string hexString) if (hexString.Length % 2 != 0) throw new FormatException("The hex string is invalid because it has an odd length"); var result = new byte[hexString.Length / 2]; - for (int i = 0; i < result.Length; i++) + for (var i = 0; i < result.Length; i++) result[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); return result; } diff --git a/src/NATS.Client/v1/NaCl/Ed25519.cs b/src/NATS.Client/v1/NaCl/Ed25519.cs index e070fa67..6e021f49 100644 --- a/src/NATS.Client/v1/NaCl/Ed25519.cs +++ b/src/NATS.Client/v1/NaCl/Ed25519.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -48,7 +48,8 @@ internal static class Ed25519 public static bool Verify(ArraySegment signature, ArraySegment message, ArraySegment publicKey) { // Contract.Requires(signature.Count == SignatureSize && publicKey.Count == PublicKeySize); - if (signature.Count != SignatureSize || publicKey.Count != PublicKeySize) throw new ArgumentException(); + if (signature.Count != SignatureSize || publicKey.Count != PublicKeySize) + throw new ArgumentException(); return Ed25519Operations.crypto_sign_verify(signature.Array, signature.Offset, message.Array, message.Offset, message.Count, publicKey.Array, publicKey.Offset); } @@ -63,9 +64,11 @@ public static bool Verify(ArraySegment signature, ArraySegment messa public static bool Verify(byte[] signature, byte[] message, byte[] publicKey) { // Contract.Requires(signature != null && message != null && publicKey != null); - if (signature == null || message == null || publicKey == null) throw new ArgumentException(); + if (signature == null || message == null || publicKey == null) + throw new ArgumentException(); // Contract.Requires(signature.Length == SignatureSize && publicKey.Length == PublicKeySize); - if (signature.Length != SignatureSize || publicKey.Length != PublicKeySize) throw new ArgumentException(); + if (signature.Length != SignatureSize || publicKey.Length != PublicKeySize) + throw new ArgumentException(); return Ed25519Operations.crypto_sign_verify(signature, 0, message, 0, message.Length, publicKey, 0); } @@ -79,9 +82,11 @@ public static bool Verify(byte[] signature, byte[] message, byte[] publicKey) public static void Sign(ArraySegment signature, ArraySegment message, ArraySegment expandedPrivateKey) { // Contract.Requires(signature.Array != null && message.Array != null && expandedPrivateKey.Array != null); - if (signature.Array == null || message.Array == null || expandedPrivateKey.Array == null) throw new ArgumentNullException(); + if (signature.Array == null || message.Array == null || expandedPrivateKey.Array == null) + throw new ArgumentNullException(); // Contract.Requires(expandedPrivateKey.Count == ExpandedPrivateKeySize); - if (expandedPrivateKey.Count != ExpandedPrivateKeySize) throw new ArgumentException(); + if (expandedPrivateKey.Count != ExpandedPrivateKeySize) + throw new ArgumentException(); Ed25519Operations.crypto_sign(signature.Array, signature.Offset, message.Array, message.Offset, message.Count, expandedPrivateKey.Array, expandedPrivateKey.Offset); } @@ -94,9 +99,11 @@ public static void Sign(ArraySegment signature, ArraySegment message public static byte[] Sign(byte[] message, byte[] expandedPrivateKey) { // Contract.Requires(message != null && expandedPrivateKey != null); - if (message == null || expandedPrivateKey == null) throw new ArgumentNullException(); + if (message == null || expandedPrivateKey == null) + throw new ArgumentNullException(); // Contract.Requires(expandedPrivateKey.Length == ExpandedPrivateKeySize); - if (expandedPrivateKey.Length != ExpandedPrivateKeySize) throw new ArgumentException(); + if (expandedPrivateKey.Length != ExpandedPrivateKeySize) + throw new ArgumentException(); var signature = new byte[SignatureSize]; Sign(new ArraySegment(signature), new ArraySegment(message), new ArraySegment(expandedPrivateKey)); @@ -111,9 +118,11 @@ public static byte[] Sign(byte[] message, byte[] expandedPrivateKey) public static byte[] PublicKeyFromSeed(byte[] privateKeySeed) { // Contract.Requires(privateKeySeed != null); - if (privateKeySeed == null) throw new ArgumentNullException(); + if (privateKeySeed == null) + throw new ArgumentNullException(); // Contract.Requires(privateKeySeed.Length == PrivateKeySeedSize); - if (privateKeySeed.Length != PrivateKeySeedSize) throw new ArgumentException(); + if (privateKeySeed.Length != PrivateKeySeedSize) + throw new ArgumentException(); byte[] privateKey; byte[] publicKey; @@ -130,9 +139,11 @@ public static byte[] PublicKeyFromSeed(byte[] privateKeySeed) public static byte[] ExpandedPrivateKeyFromSeed(byte[] privateKeySeed) { // Contract.Requires(privateKeySeed != null); - if (privateKeySeed == null) throw new ArgumentNullException(); + if (privateKeySeed == null) + throw new ArgumentNullException(); // Contract.Requires(privateKeySeed.Length == PrivateKeySeedSize); - if (privateKeySeed.Length != PrivateKeySeedSize) throw new ArgumentException(); + if (privateKeySeed.Length != PrivateKeySeedSize) + throw new ArgumentException(); byte[] privateKey; byte[] publicKey; @@ -150,9 +161,11 @@ public static byte[] ExpandedPrivateKeyFromSeed(byte[] privateKeySeed) public static void KeyPairFromSeed(out byte[] publicKey, out byte[] expandedPrivateKey, byte[] privateKeySeed) { // Contract.Requires(privateKeySeed != null); - if (privateKeySeed == null) throw new ArgumentNullException(); + if (privateKeySeed == null) + throw new ArgumentNullException(); // Contract.Requires(privateKeySeed.Length == PrivateKeySeedSize); - if (privateKeySeed.Length != PrivateKeySeedSize) throw new ArgumentException(); + if (privateKeySeed.Length != PrivateKeySeedSize) + throw new ArgumentException(); var pk = new byte[PublicKeySize]; var sk = new byte[ExpandedPrivateKeySize]; @@ -171,16 +184,19 @@ public static void KeyPairFromSeed(out byte[] publicKey, out byte[] expandedPriv public static void KeyPairFromSeed(ArraySegment publicKey, ArraySegment expandedPrivateKey, ArraySegment privateKeySeed) { // Contract.Requires(publicKey.Array != null && expandedPrivateKey.Array != null && privateKeySeed.Array != null); - if (publicKey.Array == null || expandedPrivateKey.Array == null || privateKeySeed.Array == null) throw new ArgumentNullException(); + if (publicKey.Array == null || expandedPrivateKey.Array == null || privateKeySeed.Array == null) + throw new ArgumentNullException(); // Contract.Requires(expandedPrivateKey.Count == ExpandedPrivateKeySize && privateKeySeed.Count == PrivateKeySeedSize); - if (expandedPrivateKey.Count != ExpandedPrivateKeySize || privateKeySeed.Count != PrivateKeySeedSize) throw new ArgumentException(); + if (expandedPrivateKey.Count != ExpandedPrivateKeySize || privateKeySeed.Count != PrivateKeySeedSize) + throw new ArgumentException(); // Contract.Requires(publicKey.Count == PublicKeySize); - if (publicKey.Count != PublicKeySize) throw new ArgumentException(); + if (publicKey.Count != PublicKeySize) + throw new ArgumentException(); - Ed25519Operations.crypto_sign_keypair( - publicKey.Array, publicKey.Offset, - expandedPrivateKey.Array, expandedPrivateKey.Offset, - privateKeySeed.Array, privateKeySeed.Offset); + Ed25519Operations.crypto_sign_keypair( + publicKey.Array, publicKey.Offset, + expandedPrivateKey.Array, expandedPrivateKey.Offset, + privateKeySeed.Array, privateKeySeed.Offset); } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Array16.cs b/src/NATS.Client/v1/NaCl/Internal/Array16.cs index 77d77d6b..091dbd2d 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Array16.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Array16.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; namespace NATS.Client.NaCl.Internal diff --git a/src/NATS.Client/v1/NaCl/Internal/Array8.cs b/src/NATS.Client/v1/NaCl/Internal/Array8.cs index 6039b340..260a9cd3 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Array8.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Array8.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace NATS.Client.NaCl.Internal { @@ -15,4 +15,4 @@ internal struct Array8 public T x6; public T x7; } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/NaCl/Internal/ByteIntegerConverter.cs b/src/NATS.Client/v1/NaCl/Internal/ByteIntegerConverter.cs index 9d202f37..2069871d 100644 --- a/src/NATS.Client/v1/NaCl/Internal/ByteIntegerConverter.cs +++ b/src/NATS.Client/v1/NaCl/Internal/ByteIntegerConverter.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace NATS.Client.NaCl.Internal { diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/FieldElement.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/FieldElement.cs index f4211428..56976376 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/FieldElement.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/FieldElement.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -24,7 +24,8 @@ internal struct FieldElement internal FieldElement(params int[] elements) { // Contract.Requires(elements.Length == 10); - if (elements.Length != 10) throw new ArgumentException(); + if (elements.Length != 10) + throw new ArgumentException(); x0 = elements[0]; x1 = elements[1]; diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/GroupElement.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/GroupElement.cs index 1ed78b98..1a1cf11a 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/GroupElement.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/GroupElement.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -17,7 +17,7 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - /* + /* ge means group element. Here the group is the set of pairs (x,y) of field elements (see fe.h) @@ -31,48 +31,48 @@ Here the group is the set of pairs (x,y) of field elements (see fe.h) ge_precomp (Duif): (y+x,y-x,2dxy) */ - internal struct GroupElementP2 - { - public FieldElement X; - public FieldElement Y; - public FieldElement Z; - } ; + internal struct GroupElementP2 + { + public FieldElement X; + public FieldElement Y; + public FieldElement Z; + }; - internal struct GroupElementP3 - { - public FieldElement X; - public FieldElement Y; - public FieldElement Z; - public FieldElement T; - } ; + internal struct GroupElementP3 + { + public FieldElement X; + public FieldElement Y; + public FieldElement Z; + public FieldElement T; + }; - internal struct GroupElementP1P1 - { - public FieldElement X; - public FieldElement Y; - public FieldElement Z; - public FieldElement T; - } ; + internal struct GroupElementP1P1 + { + public FieldElement X; + public FieldElement Y; + public FieldElement Z; + public FieldElement T; + }; - internal struct GroupElementPreComp - { - public FieldElement yplusx; - public FieldElement yminusx; - public FieldElement xy2d; + internal struct GroupElementPreComp + { + public FieldElement yplusx; + public FieldElement yminusx; + public FieldElement xy2d; - public GroupElementPreComp(FieldElement yplusx, FieldElement yminusx, FieldElement xy2d) - { - this.yplusx = yplusx; - this.yminusx = yminusx; - this.xy2d = xy2d; - } - } ; + public GroupElementPreComp(FieldElement yplusx, FieldElement yminusx, FieldElement xy2d) + { + this.yplusx = yplusx; + this.yminusx = yminusx; + this.xy2d = xy2d; + } + }; - internal struct GroupElementCached - { - public FieldElement YplusX; - public FieldElement YminusX; - public FieldElement Z; - public FieldElement T2d; - } ; + internal struct GroupElementCached + { + public FieldElement YplusX; + public FieldElement YminusX; + public FieldElement Z; + public FieldElement T2d; + }; } diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/base.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/base.cs index bbd02c35..d43e2d22 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/base.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/base.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -1367,4 +1367,4 @@ internal static partial class LookupTables } }; } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/base2.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/base2.cs index 54b34f5a..49ece27d 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/base2.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/base2.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -60,6 +60,6 @@ internal static partial class LookupTables new FieldElement( -24326370,15950226,-31801215,-14592823,-11662737,-5090925,1573892,-2625887,2198790,-15804619 ), new FieldElement( -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683 ) ) - }; + }; } } diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/d.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/d.cs index 34270241..c13f7d7b 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/d.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/d.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -15,8 +15,8 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - internal static partial class LookupTables - { - internal static FieldElement d = new FieldElement(-10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116); - } -} \ No newline at end of file + internal static partial class LookupTables + { + internal static FieldElement d = new FieldElement(-10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116); + } +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/d2.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/d2.cs index 90915635..e2362b3f 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/d2.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/d2.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -17,8 +17,8 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - internal static partial class LookupTables - { - internal static FieldElement d2 = new FieldElement(-21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199); - } -} \ No newline at end of file + internal static partial class LookupTables + { + internal static FieldElement d2 = new FieldElement(-21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199); + } +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_0.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_0.cs index 111f0982..614fbc9e 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_0.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_0.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -17,11 +17,11 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - internal static partial class FieldOperations - { - public static void fe_0(out FieldElement h) - { - h = default(FieldElement); - } - } -} \ No newline at end of file + internal static partial class FieldOperations + { + public static void fe_0(out FieldElement h) + { + h = default(FieldElement); + } + } +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_1.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_1.cs index a6233f43..a457abd8 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_1.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_1.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -15,12 +15,12 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - internal static partial class FieldOperations - { - public static void fe_1(out FieldElement h) - { - h = default(FieldElement); - h.x0 = 1; - } - } -} \ No newline at end of file + internal static partial class FieldOperations + { + public static void fe_1(out FieldElement h) + { + h = default(FieldElement); + h.x0 = 1; + } + } +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_add.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_add.cs index 868e55c8..03668859 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_add.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_add.cs @@ -17,9 +17,9 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - internal static partial class FieldOperations - { - /* + internal static partial class FieldOperations + { + /* h = f + g Can overlap h with f or g. @@ -30,9 +30,10 @@ Can overlap h with f or g. Postconditions: |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */ - //void fe_add(fe h,const fe f,const fe g) - internal static void fe_add(out FieldElement h, ref FieldElement f, ref FieldElement g) - { + //void fe_add(fe h,const fe f,const fe g) + internal static void fe_add(out FieldElement h, ref FieldElement f, ref FieldElement g) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: int f0 = f.x0; int f1 = f.x1; int f2 = f.x2; @@ -63,17 +64,211 @@ internal static void fe_add(out FieldElement h, ref FieldElement f, ref FieldEle int h7 = f7 + g7; int h8 = f8 + g8; int h9 = f9 + g9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; + var h0 = f0 + g0; + var h1 = f1 + g1; + var h2 = f2 + g2; + var h3 = f3 + g3; + var h4 = f4 + g4; + var h5 = f5 + g5; + var h6 = f6 + g6; + var h7 = f7 + g7; + var h8 = f8 + g8; + var h9 = f9 + g9; +*/ - h.x0 = h0; - h.x1 = h1; - h.x2 = h2; - h.x3 = h3; - h.x4 = h4; - h.x5 = h5; - h.x6 = h6; - h.x7 = h7; - h.x8 = h8; - h.x9 = h9; - } - } -} \ No newline at end of file +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int f0 = f.x0; + int f1 = f.x1; + int f2 = f.x2; + int f3 = f.x3; + int f4 = f.x4; + int f5 = f.x5; + int f6 = f.x6; + int f7 = f.x7; + int f8 = f.x8; + int f9 = f.x9; + int g0 = g.x0; + int g1 = g.x1; + int g2 = g.x2; + int g3 = g.x3; + int g4 = g.x4; + int g5 = g.x5; + int g6 = g.x6; + int g7 = g.x7; + int g8 = g.x8; + int g9 = g.x9; + int h0 = f0 + g0; + int h1 = f1 + g1; + int h2 = f2 + g2; + int h3 = f3 + g3; + int h4 = f4 + g4; + int h5 = f5 + g5; + int h6 = f6 + g6; + int h7 = f7 + g7; + int h8 = f8 + g8; + int h9 = f9 + g9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; + var h0 = f0 + g0; + var h1 = f1 + g1; + var h2 = f2 + g2; + var h3 = f3 + g3; + var h4 = f4 + g4; + var h5 = f5 + g5; + var h6 = f6 + g6; + var h7 = f7 + g7; + var h8 = f8 + g8; + var h9 = f9 + g9; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int f0 = f.x0; + int f1 = f.x1; + int f2 = f.x2; + int f3 = f.x3; + int f4 = f.x4; + int f5 = f.x5; + int f6 = f.x6; + int f7 = f.x7; + int f8 = f.x8; + int f9 = f.x9; + int g0 = g.x0; + int g1 = g.x1; + int g2 = g.x2; + int g3 = g.x3; + int g4 = g.x4; + int g5 = g.x5; + int g6 = g.x6; + int g7 = g.x7; + int g8 = g.x8; + int g9 = g.x9; + int h0 = f0 + g0; + int h1 = f1 + g1; + int h2 = f2 + g2; + int h3 = f3 + g3; + int h4 = f4 + g4; + int h5 = f5 + g5; + int h6 = f6 + g6; + int h7 = f7 + g7; + int h8 = f8 + g8; + int h9 = f9 + g9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; + var h0 = f0 + g0; + var h1 = f1 + g1; + var h2 = f2 + g2; + var h3 = f3 + g3; + var h4 = f4 + g4; + var h5 = f5 + g5; + var h6 = f6 + g6; + var h7 = f7 + g7; + var h8 = f8 + g8; + var h9 = f9 + g9; +*/ + + { + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; + var h0 = f0 + g0; + var h1 = f1 + g1; + var h2 = f2 + g2; + var h3 = f3 + g3; + var h4 = f4 + g4; + var h5 = f5 + g5; + var h6 = f6 + g6; + var h7 = f7 + g7; + var h8 = f8 + g8; + var h9 = f9 + g9; + + h.x0 = h0; + h.x1 = h1; + h.x2 = h2; + h.x3 = h3; + h.x4 = h4; + h.x5 = h5; + h.x6 = h6; + h.x7 = h7; + h.x8 = h8; + h.x9 = h9; + } + } +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_cmov.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_cmov.cs index d30a0a9d..75819934 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_cmov.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_cmov.cs @@ -17,18 +17,19 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - internal static partial class FieldOperations - { - /* + internal static partial class FieldOperations + { + /* Replace (f,g) with (g,g) if b == 1; replace (f,g) with (f,g) if b == 0. Preconditions: b in {0,1}. */ - //void fe_cmov(fe f,const fe g,unsigned int b) - internal static void fe_cmov(ref FieldElement f, ref FieldElement g, int b) - { + //void fe_cmov(fe f,const fe g,unsigned int b) + internal static void fe_cmov(ref FieldElement f, ref FieldElement g, int b) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: int f0 = f.x0; int f1 = f.x1; int f2 = f.x2; @@ -59,28 +60,222 @@ internal static void fe_cmov(ref FieldElement f, ref FieldElement g, int b) int x7 = f7 ^ g7; int x8 = f8 ^ g8; int x9 = f9 ^ g9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; + var x0 = f0 ^ g0; + var x1 = f1 ^ g1; + var x2 = f2 ^ g2; + var x3 = f3 ^ g3; + var x4 = f4 ^ g4; + var x5 = f5 ^ g5; + var x6 = f6 ^ g6; + var x7 = f7 ^ g7; + var x8 = f8 ^ g8; + var x9 = f9 ^ g9; +*/ - b = -b; - x0 &= b; - x1 &= b; - x2 &= b; - x3 &= b; - x4 &= b; - x5 &= b; - x6 &= b; - x7 &= b; - x8 &= b; - x9 &= b; - f.x0 = f0 ^ x0; - f.x1 = f1 ^ x1; - f.x2 = f2 ^ x2; - f.x3 = f3 ^ x3; - f.x4 = f4 ^ x4; - f.x5 = f5 ^ x5; - f.x6 = f6 ^ x6; - f.x7 = f7 ^ x7; - f.x8 = f8 ^ x8; - f.x9 = f9 ^ x9; - } - } -} \ No newline at end of file +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int f0 = f.x0; + int f1 = f.x1; + int f2 = f.x2; + int f3 = f.x3; + int f4 = f.x4; + int f5 = f.x5; + int f6 = f.x6; + int f7 = f.x7; + int f8 = f.x8; + int f9 = f.x9; + int g0 = g.x0; + int g1 = g.x1; + int g2 = g.x2; + int g3 = g.x3; + int g4 = g.x4; + int g5 = g.x5; + int g6 = g.x6; + int g7 = g.x7; + int g8 = g.x8; + int g9 = g.x9; + int x0 = f0 ^ g0; + int x1 = f1 ^ g1; + int x2 = f2 ^ g2; + int x3 = f3 ^ g3; + int x4 = f4 ^ g4; + int x5 = f5 ^ g5; + int x6 = f6 ^ g6; + int x7 = f7 ^ g7; + int x8 = f8 ^ g8; + int x9 = f9 ^ g9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; + var x0 = f0 ^ g0; + var x1 = f1 ^ g1; + var x2 = f2 ^ g2; + var x3 = f3 ^ g3; + var x4 = f4 ^ g4; + var x5 = f5 ^ g5; + var x6 = f6 ^ g6; + var x7 = f7 ^ g7; + var x8 = f8 ^ g8; + var x9 = f9 ^ g9; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int f0 = f.x0; + int f1 = f.x1; + int f2 = f.x2; + int f3 = f.x3; + int f4 = f.x4; + int f5 = f.x5; + int f6 = f.x6; + int f7 = f.x7; + int f8 = f.x8; + int f9 = f.x9; + int g0 = g.x0; + int g1 = g.x1; + int g2 = g.x2; + int g3 = g.x3; + int g4 = g.x4; + int g5 = g.x5; + int g6 = g.x6; + int g7 = g.x7; + int g8 = g.x8; + int g9 = g.x9; + int x0 = f0 ^ g0; + int x1 = f1 ^ g1; + int x2 = f2 ^ g2; + int x3 = f3 ^ g3; + int x4 = f4 ^ g4; + int x5 = f5 ^ g5; + int x6 = f6 ^ g6; + int x7 = f7 ^ g7; + int x8 = f8 ^ g8; + int x9 = f9 ^ g9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; + var x0 = f0 ^ g0; + var x1 = f1 ^ g1; + var x2 = f2 ^ g2; + var x3 = f3 ^ g3; + var x4 = f4 ^ g4; + var x5 = f5 ^ g5; + var x6 = f6 ^ g6; + var x7 = f7 ^ g7; + var x8 = f8 ^ g8; + var x9 = f9 ^ g9; +*/ + + { + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; + var x0 = f0 ^ g0; + var x1 = f1 ^ g1; + var x2 = f2 ^ g2; + var x3 = f3 ^ g3; + var x4 = f4 ^ g4; + var x5 = f5 ^ g5; + var x6 = f6 ^ g6; + var x7 = f7 ^ g7; + var x8 = f8 ^ g8; + var x9 = f9 ^ g9; + + b = -b; + x0 &= b; + x1 &= b; + x2 &= b; + x3 &= b; + x4 &= b; + x5 &= b; + x6 &= b; + x7 &= b; + x8 &= b; + x9 &= b; + f.x0 = f0 ^ x0; + f.x1 = f1 ^ x1; + f.x2 = f2 ^ x2; + f.x3 = f3 ^ x3; + f.x4 = f4 ^ x4; + f.x5 = f5 ^ x5; + f.x6 = f6 ^ x6; + f.x7 = f7 ^ x7; + f.x8 = f8 ^ x8; + f.x9 = f9 ^ x9; + } + } +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_cswap.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_cswap.cs index a5e98ea3..b249813b 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_cswap.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_cswap.cs @@ -26,7 +26,138 @@ internal static partial class FieldOperations Preconditions: b in {0,1}. */ public static void fe_cswap(ref FieldElement f, ref FieldElement g, uint b) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int f0 = f.x0; + int f1 = f.x1; + int f2 = f.x2; + int f3 = f.x3; + int f4 = f.x4; + int f5 = f.x5; + int f6 = f.x6; + int f7 = f.x7; + int f8 = f.x8; + int f9 = f.x9; + int g0 = g.x0; + int g1 = g.x1; + int g2 = g.x2; + int g3 = g.x3; + int g4 = g.x4; + int g5 = g.x5; + int g6 = g.x6; + int g7 = g.x7; + int g8 = g.x8; + int g9 = g.x9; + int x0 = f0 ^ g0; + int x1 = f1 ^ g1; + int x2 = f2 ^ g2; + int x3 = f3 ^ g3; + int x4 = f4 ^ g4; + int x5 = f5 ^ g5; + int x6 = f6 ^ g6; + int x7 = f7 ^ g7; + int x8 = f8 ^ g8; + int x9 = f9 ^ g9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; + var x0 = f0 ^ g0; + var x1 = f1 ^ g1; + var x2 = f2 ^ g2; + var x3 = f3 ^ g3; + var x4 = f4 ^ g4; + var x5 = f5 ^ g5; + var x6 = f6 ^ g6; + var x7 = f7 ^ g7; + var x8 = f8 ^ g8; + var x9 = f9 ^ g9; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int f0 = f.x0; + int f1 = f.x1; + int f2 = f.x2; + int f3 = f.x3; + int f4 = f.x4; + int f5 = f.x5; + int f6 = f.x6; + int f7 = f.x7; + int f8 = f.x8; + int f9 = f.x9; + int g0 = g.x0; + int g1 = g.x1; + int g2 = g.x2; + int g3 = g.x3; + int g4 = g.x4; + int g5 = g.x5; + int g6 = g.x6; + int g7 = g.x7; + int g8 = g.x8; + int g9 = g.x9; + int x0 = f0 ^ g0; + int x1 = f1 ^ g1; + int x2 = f2 ^ g2; + int x3 = f3 ^ g3; + int x4 = f4 ^ g4; + int x5 = f5 ^ g5; + int x6 = f6 ^ g6; + int x7 = f7 ^ g7; + int x8 = f8 ^ g8; + int x9 = f9 ^ g9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; + var x0 = f0 ^ g0; + var x1 = f1 ^ g1; + var x2 = f2 ^ g2; + var x3 = f3 ^ g3; + var x4 = f4 ^ g4; + var x5 = f5 ^ g5; + var x6 = f6 ^ g6; + var x7 = f7 ^ g7; + var x8 = f8 ^ g8; + var x9 = f9 ^ g9; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int f0 = f.x0; int f1 = f.x1; int f2 = f.x2; @@ -57,8 +188,93 @@ public static void fe_cswap(ref FieldElement f, ref FieldElement g, uint b) int x7 = f7 ^ g7; int x8 = f8 ^ g8; int x9 = f9 ^ g9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; + var x0 = f0 ^ g0; + var x1 = f1 ^ g1; + var x2 = f2 ^ g2; + var x3 = f3 ^ g3; + var x4 = f4 ^ g4; + var x5 = f5 ^ g5; + var x6 = f6 ^ g6; + var x7 = f7 ^ g7; + var x8 = f8 ^ g8; + var x9 = f9 ^ g9; +*/ + + { + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; + var x0 = f0 ^ g0; + var x1 = f1 ^ g1; + var x2 = f2 ^ g2; + var x3 = f3 ^ g3; + var x4 = f4 ^ g4; + var x5 = f5 ^ g5; + var x6 = f6 ^ g6; + var x7 = f7 ^ g7; + var x8 = f8 ^ g8; + var x9 = f9 ^ g9; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int negb = unchecked((int)-b); +After: + var negb = unchecked((int)-b); +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: int negb = unchecked((int)-b); +After: + var negb = unchecked((int)-b); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int negb = unchecked((int)-b); +After: + var negb = unchecked((int)-b); +*/ + + + var negb = unchecked((int)-b); x0 &= negb; x1 &= negb; x2 &= negb; @@ -91,4 +307,4 @@ public static void fe_cswap(ref FieldElement f, ref FieldElement g, uint b) g.x9 = g9 ^ x9; } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_frombytes.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_frombytes.cs index 9ac2dd5f..c0e6f265 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_frombytes.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_frombytes.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -52,17 +52,37 @@ internal static void fe_frombytes(out FieldElement h, byte[] data, int offset) var h8 = load_3(data, offset + 26) << 4; var h9 = (load_3(data, offset + 29) & 8388607) << 2; - var carry9 = (h9 + (1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - var carry1 = (h1 + (1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - var carry3 = (h3 + (1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - var carry5 = (h5 + (1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - var carry7 = (h7 + (1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + var carry9 = (h9 + (1 << 24)) >> 25; + h0 += carry9 * 19; + h9 -= carry9 << 25; + var carry1 = (h1 + (1 << 24)) >> 25; + h2 += carry1; + h1 -= carry1 << 25; + var carry3 = (h3 + (1 << 24)) >> 25; + h4 += carry3; + h3 -= carry3 << 25; + var carry5 = (h5 + (1 << 24)) >> 25; + h6 += carry5; + h5 -= carry5 << 25; + var carry7 = (h7 + (1 << 24)) >> 25; + h8 += carry7; + h7 -= carry7 << 25; - var carry0 = (h0 + (1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - var carry2 = (h2 + (1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - var carry4 = (h4 + (1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - var carry6 = (h6 + (1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - var carry8 = (h8 + (1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + var carry0 = (h0 + (1 << 25)) >> 26; + h1 += carry0; + h0 -= carry0 << 26; + var carry2 = (h2 + (1 << 25)) >> 26; + h3 += carry2; + h2 -= carry2 << 26; + var carry4 = (h4 + (1 << 25)) >> 26; + h5 += carry4; + h4 -= carry4 << 26; + var carry6 = (h6 + (1 << 25)) >> 26; + h7 += carry6; + h6 -= carry6 << 26; + var carry8 = (h8 + (1 << 25)) >> 26; + h9 += carry8; + h8 -= carry8 << 26; h.x0 = (int)h0; h.x1 = (int)h1; @@ -90,17 +110,37 @@ internal static void fe_frombytes2(out FieldElement h, byte[] data, int offset) var h8 = load_3(data, offset + 26) << 4; var h9 = load_3(data, offset + 29) << 2; - var carry9 = (h9 + (1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - var carry1 = (h1 + (1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - var carry3 = (h3 + (1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - var carry5 = (h5 + (1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - var carry7 = (h7 + (1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + var carry9 = (h9 + (1 << 24)) >> 25; + h0 += carry9 * 19; + h9 -= carry9 << 25; + var carry1 = (h1 + (1 << 24)) >> 25; + h2 += carry1; + h1 -= carry1 << 25; + var carry3 = (h3 + (1 << 24)) >> 25; + h4 += carry3; + h3 -= carry3 << 25; + var carry5 = (h5 + (1 << 24)) >> 25; + h6 += carry5; + h5 -= carry5 << 25; + var carry7 = (h7 + (1 << 24)) >> 25; + h8 += carry7; + h7 -= carry7 << 25; - var carry0 = (h0 + (1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - var carry2 = (h2 + (1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - var carry4 = (h4 + (1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - var carry6 = (h6 + (1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - var carry8 = (h8 + (1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + var carry0 = (h0 + (1 << 25)) >> 26; + h1 += carry0; + h0 -= carry0 << 26; + var carry2 = (h2 + (1 << 25)) >> 26; + h3 += carry2; + h2 -= carry2 << 26; + var carry4 = (h4 + (1 << 25)) >> 26; + h5 += carry4; + h4 -= carry4 << 26; + var carry6 = (h6 + (1 << 25)) >> 26; + h7 += carry6; + h6 -= carry6 << 26; + var carry8 = (h8 + (1 << 25)) >> 26; + h9 += carry8; + h8 -= carry8 << 26; h.x0 = (int)h0; h.x1 = (int)h1; diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_invert.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_invert.cs index c29db69a..1bc11ee5 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_invert.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_invert.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -17,127 +17,145 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - internal static partial class FieldOperations - { - internal static void fe_invert(out FieldElement result, ref FieldElement z) - { - FieldElement t0, t1, t2, t3; - int i; - - /* qhasm: z2 = z1^2^1 */ - /* asm 1: fe_sq(>z2=fe#1,z2=fe#1,>z2=fe#1); */ - /* asm 2: fe_sq(>z2=t0,z2=t0,>z2=t0); */ - fe_sq(out t0, ref z); //for (i = 1; i < 1; ++i) fe_sq(out t0, ref t0); - - /* qhasm: z8 = z2^2^2 */ - /* asm 1: fe_sq(>z8=fe#2,z8=fe#2,>z8=fe#2); */ - /* asm 2: fe_sq(>z8=t1,z8=t1,>z8=t1); */ - fe_sq(out t1, ref t0); for (i = 1; i < 2; ++i) fe_sq(out t1, ref t1); - - /* qhasm: z9 = z1*z8 */ - /* asm 1: fe_mul(>z9=fe#2,z9=t1,z11=fe#1,z11=t0,z22=fe#3,z22=fe#3,>z22=fe#3); */ - /* asm 2: fe_sq(>z22=t2,z22=t2,>z22=t2); */ - fe_sq(out t2, ref t0); //for (i = 1; i < 1; ++i) fe_sq(out t2, ref t2); - - /* qhasm: z_5_0 = z9*z22 */ - /* asm 1: fe_mul(>z_5_0=fe#2,z_5_0=t1,z_10_5=fe#3,z_10_5=fe#3,>z_10_5=fe#3); */ - /* asm 2: fe_sq(>z_10_5=t2,z_10_5=t2,>z_10_5=t2); */ - fe_sq(out t2, ref t1); for (i = 1; i < 5; ++i) fe_sq(out t2, ref t2); - - /* qhasm: z_10_0 = z_10_5*z_5_0 */ - /* asm 1: fe_mul(>z_10_0=fe#2,z_10_0=t1,z_20_10=fe#3,z_20_10=fe#3,>z_20_10=fe#3); */ - /* asm 2: fe_sq(>z_20_10=t2,z_20_10=t2,>z_20_10=t2); */ - fe_sq(out t2, ref t1); for (i = 1; i < 10; ++i) fe_sq(out t2, ref t2); - - /* qhasm: z_20_0 = z_20_10*z_10_0 */ - /* asm 1: fe_mul(>z_20_0=fe#3,z_20_0=t2,z_40_20=fe#4,z_40_20=fe#4,>z_40_20=fe#4); */ - /* asm 2: fe_sq(>z_40_20=t3,z_40_20=t3,>z_40_20=t3); */ - fe_sq(out t3, ref t2); for (i = 1; i < 20; ++i) fe_sq(out t3, ref t3); - - /* qhasm: z_40_0 = z_40_20*z_20_0 */ - /* asm 1: fe_mul(>z_40_0=fe#3,z_40_0=t2,z_50_10=fe#3,z_50_10=fe#3,>z_50_10=fe#3); */ - /* asm 2: fe_sq(>z_50_10=t2,z_50_10=t2,>z_50_10=t2); */ - fe_sq(out t2, ref t2); for (i = 1; i < 10; ++i) fe_sq(out t2, ref t2); - - /* qhasm: z_50_0 = z_50_10*z_10_0 */ - /* asm 1: fe_mul(>z_50_0=fe#2,z_50_0=t1,z_100_50=fe#3,z_100_50=fe#3,>z_100_50=fe#3); */ - /* asm 2: fe_sq(>z_100_50=t2,z_100_50=t2,>z_100_50=t2); */ - fe_sq(out t2, ref t1); for (i = 1; i < 50; ++i) fe_sq(out t2, ref t2); - - /* qhasm: z_100_0 = z_100_50*z_50_0 */ - /* asm 1: fe_mul(>z_100_0=fe#3,z_100_0=t2,z_200_100=fe#4,z_200_100=fe#4,>z_200_100=fe#4); */ - /* asm 2: fe_sq(>z_200_100=t3,z_200_100=t3,>z_200_100=t3); */ - fe_sq(out t3, ref t2); for (i = 1; i < 100; ++i) fe_sq(out t3, ref t3); - - /* qhasm: z_200_0 = z_200_100*z_100_0 */ - /* asm 1: fe_mul(>z_200_0=fe#3,z_200_0=t2,z_250_50=fe#3,z_250_50=fe#3,>z_250_50=fe#3); */ - /* asm 2: fe_sq(>z_250_50=t2,z_250_50=t2,>z_250_50=t2); */ - fe_sq(out t2, ref t2); for (i = 1; i < 50; ++i) fe_sq(out t2, ref t2); - - /* qhasm: z_250_0 = z_250_50*z_50_0 */ - /* asm 1: fe_mul(>z_250_0=fe#2,z_250_0=t1,z_255_5=fe#2,z_255_5=fe#2,>z_255_5=fe#2); */ - /* asm 2: fe_sq(>z_255_5=t1,z_255_5=t1,>z_255_5=t1); */ - fe_sq(out t1, ref t1); for (i = 1; i < 5; ++i) fe_sq(out t1, ref t1); - - /* qhasm: z_255_21 = z_255_5*z11 */ - /* asm 1: fe_mul(>z_255_21=fe#12,z_255_21=out,z2=fe#1,z2=fe#1,>z2=fe#1); */ + /* asm 2: fe_sq(>z2=t0,z2=t0,>z2=t0); */ + fe_sq(out t0, ref z); //for (i = 1; i < 1; ++i) fe_sq(out t0, ref t0); + + /* qhasm: z8 = z2^2^2 */ + /* asm 1: fe_sq(>z8=fe#2,z8=fe#2,>z8=fe#2); */ + /* asm 2: fe_sq(>z8=t1,z8=t1,>z8=t1); */ + fe_sq(out t1, ref t0); + for (i = 1; i < 2; ++i) + fe_sq(out t1, ref t1); + + /* qhasm: z9 = z1*z8 */ + /* asm 1: fe_mul(>z9=fe#2,z9=t1,z11=fe#1,z11=t0,z22=fe#3,z22=fe#3,>z22=fe#3); */ + /* asm 2: fe_sq(>z22=t2,z22=t2,>z22=t2); */ + fe_sq(out t2, ref t0); //for (i = 1; i < 1; ++i) fe_sq(out t2, ref t2); + + /* qhasm: z_5_0 = z9*z22 */ + /* asm 1: fe_mul(>z_5_0=fe#2,z_5_0=t1,z_10_5=fe#3,z_10_5=fe#3,>z_10_5=fe#3); */ + /* asm 2: fe_sq(>z_10_5=t2,z_10_5=t2,>z_10_5=t2); */ + fe_sq(out t2, ref t1); + for (i = 1; i < 5; ++i) + fe_sq(out t2, ref t2); + + /* qhasm: z_10_0 = z_10_5*z_5_0 */ + /* asm 1: fe_mul(>z_10_0=fe#2,z_10_0=t1,z_20_10=fe#3,z_20_10=fe#3,>z_20_10=fe#3); */ + /* asm 2: fe_sq(>z_20_10=t2,z_20_10=t2,>z_20_10=t2); */ + fe_sq(out t2, ref t1); + for (i = 1; i < 10; ++i) + fe_sq(out t2, ref t2); + + /* qhasm: z_20_0 = z_20_10*z_10_0 */ + /* asm 1: fe_mul(>z_20_0=fe#3,z_20_0=t2,z_40_20=fe#4,z_40_20=fe#4,>z_40_20=fe#4); */ + /* asm 2: fe_sq(>z_40_20=t3,z_40_20=t3,>z_40_20=t3); */ + fe_sq(out t3, ref t2); + for (i = 1; i < 20; ++i) + fe_sq(out t3, ref t3); + + /* qhasm: z_40_0 = z_40_20*z_20_0 */ + /* asm 1: fe_mul(>z_40_0=fe#3,z_40_0=t2,z_50_10=fe#3,z_50_10=fe#3,>z_50_10=fe#3); */ + /* asm 2: fe_sq(>z_50_10=t2,z_50_10=t2,>z_50_10=t2); */ + fe_sq(out t2, ref t2); + for (i = 1; i < 10; ++i) + fe_sq(out t2, ref t2); + + /* qhasm: z_50_0 = z_50_10*z_10_0 */ + /* asm 1: fe_mul(>z_50_0=fe#2,z_50_0=t1,z_100_50=fe#3,z_100_50=fe#3,>z_100_50=fe#3); */ + /* asm 2: fe_sq(>z_100_50=t2,z_100_50=t2,>z_100_50=t2); */ + fe_sq(out t2, ref t1); + for (i = 1; i < 50; ++i) + fe_sq(out t2, ref t2); + + /* qhasm: z_100_0 = z_100_50*z_50_0 */ + /* asm 1: fe_mul(>z_100_0=fe#3,z_100_0=t2,z_200_100=fe#4,z_200_100=fe#4,>z_200_100=fe#4); */ + /* asm 2: fe_sq(>z_200_100=t3,z_200_100=t3,>z_200_100=t3); */ + fe_sq(out t3, ref t2); + for (i = 1; i < 100; ++i) + fe_sq(out t3, ref t3); + + /* qhasm: z_200_0 = z_200_100*z_100_0 */ + /* asm 1: fe_mul(>z_200_0=fe#3,z_200_0=t2,z_250_50=fe#3,z_250_50=fe#3,>z_250_50=fe#3); */ + /* asm 2: fe_sq(>z_250_50=t2,z_250_50=t2,>z_250_50=t2); */ + fe_sq(out t2, ref t2); + for (i = 1; i < 50; ++i) + fe_sq(out t2, ref t2); + + /* qhasm: z_250_0 = z_250_50*z_50_0 */ + /* asm 1: fe_mul(>z_250_0=fe#2,z_250_0=t1,z_255_5=fe#2,z_255_5=fe#2,>z_255_5=fe#2); */ + /* asm 2: fe_sq(>z_255_5=t1,z_255_5=t1,>z_255_5=t1); */ + fe_sq(out t1, ref t1); + for (i = 1; i < 5; ++i) + fe_sq(out t1, ref t1); + + /* qhasm: z_255_21 = z_255_5*z11 */ + /* asm 1: fe_mul(>z_255_21=fe#12,z_255_21=out,> 31) ^ 1); } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_mul.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_mul.cs index 216572f2..4ef0af18 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_mul.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_mul.cs @@ -17,9 +17,9 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - internal static partial class FieldOperations - { - /* + internal static partial class FieldOperations + { + /* h = f * g Can overlap h with f or g. @@ -31,7 +31,7 @@ Can overlap h with f or g. |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. */ - /* + /* Notes on implementation strategy: Using schoolbook multiplication. @@ -51,8 +51,9 @@ 10 of them are 2-way parallelizable and vectorizable. With tighter constraints on inputs can squeeze carries into int32. */ - internal static void fe_mul(out FieldElement h, ref FieldElement f, ref FieldElement g) - { + internal static void fe_mul(out FieldElement h, ref FieldElement f, ref FieldElement g) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: int f0 = f.x0; int f1 = f.x1; int f2 = f.x2; @@ -73,7 +74,165 @@ internal static void fe_mul(out FieldElement h, ref FieldElement f, ref FieldEle int g7 = g.x7; int g8 = g.x8; int g9 = g.x9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int f0 = f.x0; + int f1 = f.x1; + int f2 = f.x2; + int f3 = f.x3; + int f4 = f.x4; + int f5 = f.x5; + int f6 = f.x6; + int f7 = f.x7; + int f8 = f.x8; + int f9 = f.x9; + int g0 = g.x0; + int g1 = g.x1; + int g2 = g.x2; + int g3 = g.x3; + int g4 = g.x4; + int g5 = g.x5; + int g6 = g.x6; + int g7 = g.x7; + int g8 = g.x8; + int g9 = g.x9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int f0 = f.x0; + int f1 = f.x1; + int f2 = f.x2; + int f3 = f.x3; + int f4 = f.x4; + int f5 = f.x5; + int f6 = f.x6; + int f7 = f.x7; + int f8 = f.x8; + int f9 = f.x9; + int g0 = g.x0; + int g1 = g.x1; + int g2 = g.x2; + int g3 = g.x3; + int g4 = g.x4; + int g5 = g.x5; + int g6 = g.x6; + int g7 = g.x7; + int g8 = g.x8; + int g9 = g.x9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; +*/ + + { + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int g1_19 = 19 * g1; /* 1.959375*2^29 */ + int g2_19 = 19 * g2; /* 1.959375*2^30; still ok */ + int g3_19 = 19 * g3; + int g4_19 = 19 * g4; + int g5_19 = 19 * g5; + int g6_19 = 19 * g6; + int g7_19 = 19 * g7; + int g8_19 = 19 * g8; + int g9_19 = 19 * g9; +After: + var g1_19 = 19 * g1; /* 1.959375*2^29 */ + var g2_19 = 19 * g2; /* 1.959375*2^30; still ok */ + var g3_19 = 19 * g3; + var g4_19 = 19 * g4; + var g5_19 = 19 * g5; + var g6_19 = 19 * g6; + var g7_19 = 19 * g7; + var g8_19 = 19 * g8; + var g9_19 = 19 * g9; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: int g1_19 = 19 * g1; /* 1.959375*2^29 */ int g2_19 = 19 * g2; /* 1.959375*2^30; still ok */ int g3_19 = 19 * g3; @@ -83,13 +242,309 @@ internal static void fe_mul(out FieldElement h, ref FieldElement f, ref FieldEle int g7_19 = 19 * g7; int g8_19 = 19 * g8; int g9_19 = 19 * g9; +After: + var g1_19 = 19 * g1; /* 1.959375*2^29 */ + var g2_19 = 19 * g2; /* 1.959375*2^30; still ok */ + var g3_19 = 19 * g3; + var g4_19 = 19 * g4; + var g5_19 = 19 * g5; + var g6_19 = 19 * g6; + var g7_19 = 19 * g7; + var g8_19 = 19 * g8; + var g9_19 = 19 * g9; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int g1_19 = 19 * g1; /* 1.959375*2^29 */ + int g2_19 = 19 * g2; /* 1.959375*2^30; still ok */ + int g3_19 = 19 * g3; + int g4_19 = 19 * g4; + int g5_19 = 19 * g5; + int g6_19 = 19 * g6; + int g7_19 = 19 * g7; + int g8_19 = 19 * g8; + int g9_19 = 19 * g9; +After: + var g1_19 = 19 * g1; /* 1.959375*2^29 */ + var g2_19 = 19 * g2; /* 1.959375*2^30; still ok */ + var g3_19 = 19 * g3; + var g4_19 = 19 * g4; + var g5_19 = 19 * g5; + var g6_19 = 19 * g6; + var g7_19 = 19 * g7; + var g8_19 = 19 * g8; + var g9_19 = 19 * g9; +*/ + + + var g1_19 = 19 * g1; /* 1.959375*2^29 */ + var g2_19 = 19 * g2; /* 1.959375*2^30; still ok */ + var g3_19 = 19 * g3; + var g4_19 = 19 * g4; + var g5_19 = 19 * g5; + var g6_19 = 19 * g6; + var g7_19 = 19 * g7; + var g8_19 = 19 * g8; + var g9_19 = 19 * g9; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int f1_2 = 2 * f1; + int f3_2 = 2 * f3; + int f5_2 = 2 * f5; + int f7_2 = 2 * f7; + int f9_2 = 2 * f9; +After: + var f1_2 = 2 * f1; + var f3_2 = 2 * f3; + var f5_2 = 2 * f5; + var f7_2 = 2 * f7; + var f9_2 = 2 * f9; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: int f1_2 = 2 * f1; int f3_2 = 2 * f3; int f5_2 = 2 * f5; int f7_2 = 2 * f7; int f9_2 = 2 * f9; +After: + var f1_2 = 2 * f1; + var f3_2 = 2 * f3; + var f5_2 = 2 * f5; + var f7_2 = 2 * f7; + var f9_2 = 2 * f9; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int f1_2 = 2 * f1; + int f3_2 = 2 * f3; + int f5_2 = 2 * f5; + int f7_2 = 2 * f7; + int f9_2 = 2 * f9; +After: + var f1_2 = 2 * f1; + var f3_2 = 2 * f3; + var f5_2 = 2 * f5; + var f7_2 = 2 * f7; + var f9_2 = 2 * f9; +*/ + + + var f1_2 = 2 * f1; + var f3_2 = 2 * f3; + var f5_2 = 2 * f5; + var f7_2 = 2 * f7; + var f9_2 = 2 * f9; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + long f0g0 = f0 * (long)g0; + long f0g1 = f0 * (long)g1; + long f0g2 = f0 * (long)g2; + long f0g3 = f0 * (long)g3; + long f0g4 = f0 * (long)g4; + long f0g5 = f0 * (long)g5; + long f0g6 = f0 * (long)g6; + long f0g7 = f0 * (long)g7; + long f0g8 = f0 * (long)g8; + long f0g9 = f0 * (long)g9; + long f1g0 = f1 * (long)g0; + long f1g1_2 = f1_2 * (long)g1; + long f1g2 = f1 * (long)g2; + long f1g3_2 = f1_2 * (long)g3; + long f1g4 = f1 * (long)g4; + long f1g5_2 = f1_2 * (long)g5; + long f1g6 = f1 * (long)g6; + long f1g7_2 = f1_2 * (long)g7; + long f1g8 = f1 * (long)g8; + long f1g9_38 = f1_2 * (long)g9_19; + long f2g0 = f2 * (long)g0; + long f2g1 = f2 * (long)g1; + long f2g2 = f2 * (long)g2; + long f2g3 = f2 * (long)g3; + long f2g4 = f2 * (long)g4; + long f2g5 = f2 * (long)g5; + long f2g6 = f2 * (long)g6; + long f2g7 = f2 * (long)g7; + long f2g8_19 = f2 * (long)g8_19; + long f2g9_19 = f2 * (long)g9_19; + long f3g0 = f3 * (long)g0; + long f3g1_2 = f3_2 * (long)g1; + long f3g2 = f3 * (long)g2; + long f3g3_2 = f3_2 * (long)g3; + long f3g4 = f3 * (long)g4; + long f3g5_2 = f3_2 * (long)g5; + long f3g6 = f3 * (long)g6; + long f3g7_38 = f3_2 * (long)g7_19; + long f3g8_19 = f3 * (long)g8_19; + long f3g9_38 = f3_2 * (long)g9_19; + long f4g0 = f4 * (long)g0; + long f4g1 = f4 * (long)g1; + long f4g2 = f4 * (long)g2; + long f4g3 = f4 * (long)g3; + long f4g4 = f4 * (long)g4; + long f4g5 = f4 * (long)g5; + long f4g6_19 = f4 * (long)g6_19; + long f4g7_19 = f4 * (long)g7_19; + long f4g8_19 = f4 * (long)g8_19; + long f4g9_19 = f4 * (long)g9_19; + long f5g0 = f5 * (long)g0; + long f5g1_2 = f5_2 * (long)g1; + long f5g2 = f5 * (long)g2; + long f5g3_2 = f5_2 * (long)g3; + long f5g4 = f5 * (long)g4; + long f5g5_38 = f5_2 * (long)g5_19; + long f5g6_19 = f5 * (long)g6_19; + long f5g7_38 = f5_2 * (long)g7_19; + long f5g8_19 = f5 * (long)g8_19; + long f5g9_38 = f5_2 * (long)g9_19; + long f6g0 = f6 * (long)g0; + long f6g1 = f6 * (long)g1; + long f6g2 = f6 * (long)g2; + long f6g3 = f6 * (long)g3; + long f6g4_19 = f6 * (long)g4_19; + long f6g5_19 = f6 * (long)g5_19; + long f6g6_19 = f6 * (long)g6_19; + long f6g7_19 = f6 * (long)g7_19; + long f6g8_19 = f6 * (long)g8_19; + long f6g9_19 = f6 * (long)g9_19; + long f7g0 = f7 * (long)g0; + long f7g1_2 = f7_2 * (long)g1; + long f7g2 = f7 * (long)g2; + long f7g3_38 = f7_2 * (long)g3_19; + long f7g4_19 = f7 * (long)g4_19; + long f7g5_38 = f7_2 * (long)g5_19; + long f7g6_19 = f7 * (long)g6_19; + long f7g7_38 = f7_2 * (long)g7_19; + long f7g8_19 = f7 * (long)g8_19; + long f7g9_38 = f7_2 * (long)g9_19; + long f8g0 = f8 * (long)g0; + long f8g1 = f8 * (long)g1; + long f8g2_19 = f8 * (long)g2_19; + long f8g3_19 = f8 * (long)g3_19; + long f8g4_19 = f8 * (long)g4_19; + long f8g5_19 = f8 * (long)g5_19; + long f8g6_19 = f8 * (long)g6_19; + long f8g7_19 = f8 * (long)g7_19; + long f8g8_19 = f8 * (long)g8_19; + long f8g9_19 = f8 * (long)g9_19; + long f9g0 = f9 * (long)g0; + long f9g1_38 = f9_2 * (long)g1_19; + long f9g2_19 = f9 * (long)g2_19; + long f9g3_38 = f9_2 * (long)g3_19; + long f9g4_19 = f9 * (long)g4_19; + long f9g5_38 = f9_2 * (long)g5_19; + long f9g6_19 = f9 * (long)g6_19; + long f9g7_38 = f9_2 * (long)g7_19; + long f9g8_19 = f9 * (long)g8_19; + long f9g9_38 = f9_2 * (long)g9_19; +After: + var f0g0 = f0 * (long)g0; + var f0g1 = f0 * (long)g1; + var f0g2 = f0 * (long)g2; + var f0g3 = f0 * (long)g3; + var f0g4 = f0 * (long)g4; + var f0g5 = f0 * (long)g5; + var f0g6 = f0 * (long)g6; + var f0g7 = f0 * (long)g7; + var f0g8 = f0 * (long)g8; + var f0g9 = f0 * (long)g9; + var f1g0 = f1 * (long)g0; + var f1g1_2 = f1_2 * (long)g1; + var f1g2 = f1 * (long)g2; + var f1g3_2 = f1_2 * (long)g3; + var f1g4 = f1 * (long)g4; + var f1g5_2 = f1_2 * (long)g5; + var f1g6 = f1 * (long)g6; + var f1g7_2 = f1_2 * (long)g7; + var f1g8 = f1 * (long)g8; + var f1g9_38 = f1_2 * (long)g9_19; + var f2g0 = f2 * (long)g0; + var f2g1 = f2 * (long)g1; + var f2g2 = f2 * (long)g2; + var f2g3 = f2 * (long)g3; + var f2g4 = f2 * (long)g4; + var f2g5 = f2 * (long)g5; + var f2g6 = f2 * (long)g6; + var f2g7 = f2 * (long)g7; + var f2g8_19 = f2 * (long)g8_19; + var f2g9_19 = f2 * (long)g9_19; + var f3g0 = f3 * (long)g0; + var f3g1_2 = f3_2 * (long)g1; + var f3g2 = f3 * (long)g2; + var f3g3_2 = f3_2 * (long)g3; + var f3g4 = f3 * (long)g4; + var f3g5_2 = f3_2 * (long)g5; + var f3g6 = f3 * (long)g6; + var f3g7_38 = f3_2 * (long)g7_19; + var f3g8_19 = f3 * (long)g8_19; + var f3g9_38 = f3_2 * (long)g9_19; + var f4g0 = f4 * (long)g0; + var f4g1 = f4 * (long)g1; + var f4g2 = f4 * (long)g2; + var f4g3 = f4 * (long)g3; + var f4g4 = f4 * (long)g4; + var f4g5 = f4 * (long)g5; + var f4g6_19 = f4 * (long)g6_19; + var f4g7_19 = f4 * (long)g7_19; + var f4g8_19 = f4 * (long)g8_19; + var f4g9_19 = f4 * (long)g9_19; + var f5g0 = f5 * (long)g0; + var f5g1_2 = f5_2 * (long)g1; + var f5g2 = f5 * (long)g2; + var f5g3_2 = f5_2 * (long)g3; + var f5g4 = f5 * (long)g4; + var f5g5_38 = f5_2 * (long)g5_19; + var f5g6_19 = f5 * (long)g6_19; + var f5g7_38 = f5_2 * (long)g7_19; + var f5g8_19 = f5 * (long)g8_19; + var f5g9_38 = f5_2 * (long)g9_19; + var f6g0 = f6 * (long)g0; + var f6g1 = f6 * (long)g1; + var f6g2 = f6 * (long)g2; + var f6g3 = f6 * (long)g3; + var f6g4_19 = f6 * (long)g4_19; + var f6g5_19 = f6 * (long)g5_19; + var f6g6_19 = f6 * (long)g6_19; + var f6g7_19 = f6 * (long)g7_19; + var f6g8_19 = f6 * (long)g8_19; + var f6g9_19 = f6 * (long)g9_19; + var f7g0 = f7 * (long)g0; + var f7g1_2 = f7_2 * (long)g1; + var f7g2 = f7 * (long)g2; + var f7g3_38 = f7_2 * (long)g3_19; + var f7g4_19 = f7 * (long)g4_19; + var f7g5_38 = f7_2 * (long)g5_19; + var f7g6_19 = f7 * (long)g6_19; + var f7g7_38 = f7_2 * (long)g7_19; + var f7g8_19 = f7 * (long)g8_19; + var f7g9_38 = f7_2 * (long)g9_19; + var f8g0 = f8 * (long)g0; + var f8g1 = f8 * (long)g1; + var f8g2_19 = f8 * (long)g2_19; + var f8g3_19 = f8 * (long)g3_19; + var f8g4_19 = f8 * (long)g4_19; + var f8g5_19 = f8 * (long)g5_19; + var f8g6_19 = f8 * (long)g6_19; + var f8g7_19 = f8 * (long)g7_19; + var f8g8_19 = f8 * (long)g8_19; + var f8g9_19 = f8 * (long)g9_19; + var f9g0 = f9 * (long)g0; + var f9g1_38 = f9_2 * (long)g1_19; + var f9g2_19 = f9 * (long)g2_19; + var f9g3_38 = f9_2 * (long)g3_19; + var f9g4_19 = f9 * (long)g4_19; + var f9g5_38 = f9_2 * (long)g5_19; + var f9g6_19 = f9 * (long)g6_19; + var f9g7_38 = f9_2 * (long)g7_19; + var f9g8_19 = f9 * (long)g8_19; + var f9g9_38 = f9_2 * (long)g9_19; +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: long f0g0 = f0 * (long)g0; long f0g1 = f0 * (long)g1; long f0g2 = f0 * (long)g2; @@ -190,7 +645,467 @@ internal static void fe_mul(out FieldElement h, ref FieldElement f, ref FieldEle long f9g7_38 = f9_2 * (long)g7_19; long f9g8_19 = f9 * (long)g8_19; long f9g9_38 = f9_2 * (long)g9_19; +After: + var f0g0 = f0 * (long)g0; + var f0g1 = f0 * (long)g1; + var f0g2 = f0 * (long)g2; + var f0g3 = f0 * (long)g3; + var f0g4 = f0 * (long)g4; + var f0g5 = f0 * (long)g5; + var f0g6 = f0 * (long)g6; + var f0g7 = f0 * (long)g7; + var f0g8 = f0 * (long)g8; + var f0g9 = f0 * (long)g9; + var f1g0 = f1 * (long)g0; + var f1g1_2 = f1_2 * (long)g1; + var f1g2 = f1 * (long)g2; + var f1g3_2 = f1_2 * (long)g3; + var f1g4 = f1 * (long)g4; + var f1g5_2 = f1_2 * (long)g5; + var f1g6 = f1 * (long)g6; + var f1g7_2 = f1_2 * (long)g7; + var f1g8 = f1 * (long)g8; + var f1g9_38 = f1_2 * (long)g9_19; + var f2g0 = f2 * (long)g0; + var f2g1 = f2 * (long)g1; + var f2g2 = f2 * (long)g2; + var f2g3 = f2 * (long)g3; + var f2g4 = f2 * (long)g4; + var f2g5 = f2 * (long)g5; + var f2g6 = f2 * (long)g6; + var f2g7 = f2 * (long)g7; + var f2g8_19 = f2 * (long)g8_19; + var f2g9_19 = f2 * (long)g9_19; + var f3g0 = f3 * (long)g0; + var f3g1_2 = f3_2 * (long)g1; + var f3g2 = f3 * (long)g2; + var f3g3_2 = f3_2 * (long)g3; + var f3g4 = f3 * (long)g4; + var f3g5_2 = f3_2 * (long)g5; + var f3g6 = f3 * (long)g6; + var f3g7_38 = f3_2 * (long)g7_19; + var f3g8_19 = f3 * (long)g8_19; + var f3g9_38 = f3_2 * (long)g9_19; + var f4g0 = f4 * (long)g0; + var f4g1 = f4 * (long)g1; + var f4g2 = f4 * (long)g2; + var f4g3 = f4 * (long)g3; + var f4g4 = f4 * (long)g4; + var f4g5 = f4 * (long)g5; + var f4g6_19 = f4 * (long)g6_19; + var f4g7_19 = f4 * (long)g7_19; + var f4g8_19 = f4 * (long)g8_19; + var f4g9_19 = f4 * (long)g9_19; + var f5g0 = f5 * (long)g0; + var f5g1_2 = f5_2 * (long)g1; + var f5g2 = f5 * (long)g2; + var f5g3_2 = f5_2 * (long)g3; + var f5g4 = f5 * (long)g4; + var f5g5_38 = f5_2 * (long)g5_19; + var f5g6_19 = f5 * (long)g6_19; + var f5g7_38 = f5_2 * (long)g7_19; + var f5g8_19 = f5 * (long)g8_19; + var f5g9_38 = f5_2 * (long)g9_19; + var f6g0 = f6 * (long)g0; + var f6g1 = f6 * (long)g1; + var f6g2 = f6 * (long)g2; + var f6g3 = f6 * (long)g3; + var f6g4_19 = f6 * (long)g4_19; + var f6g5_19 = f6 * (long)g5_19; + var f6g6_19 = f6 * (long)g6_19; + var f6g7_19 = f6 * (long)g7_19; + var f6g8_19 = f6 * (long)g8_19; + var f6g9_19 = f6 * (long)g9_19; + var f7g0 = f7 * (long)g0; + var f7g1_2 = f7_2 * (long)g1; + var f7g2 = f7 * (long)g2; + var f7g3_38 = f7_2 * (long)g3_19; + var f7g4_19 = f7 * (long)g4_19; + var f7g5_38 = f7_2 * (long)g5_19; + var f7g6_19 = f7 * (long)g6_19; + var f7g7_38 = f7_2 * (long)g7_19; + var f7g8_19 = f7 * (long)g8_19; + var f7g9_38 = f7_2 * (long)g9_19; + var f8g0 = f8 * (long)g0; + var f8g1 = f8 * (long)g1; + var f8g2_19 = f8 * (long)g2_19; + var f8g3_19 = f8 * (long)g3_19; + var f8g4_19 = f8 * (long)g4_19; + var f8g5_19 = f8 * (long)g5_19; + var f8g6_19 = f8 * (long)g6_19; + var f8g7_19 = f8 * (long)g7_19; + var f8g8_19 = f8 * (long)g8_19; + var f8g9_19 = f8 * (long)g9_19; + var f9g0 = f9 * (long)g0; + var f9g1_38 = f9_2 * (long)g1_19; + var f9g2_19 = f9 * (long)g2_19; + var f9g3_38 = f9_2 * (long)g3_19; + var f9g4_19 = f9 * (long)g4_19; + var f9g5_38 = f9_2 * (long)g5_19; + var f9g6_19 = f9 * (long)g6_19; + var f9g7_38 = f9_2 * (long)g7_19; + var f9g8_19 = f9 * (long)g8_19; + var f9g9_38 = f9_2 * (long)g9_19; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + long f0g0 = f0 * (long)g0; + long f0g1 = f0 * (long)g1; + long f0g2 = f0 * (long)g2; + long f0g3 = f0 * (long)g3; + long f0g4 = f0 * (long)g4; + long f0g5 = f0 * (long)g5; + long f0g6 = f0 * (long)g6; + long f0g7 = f0 * (long)g7; + long f0g8 = f0 * (long)g8; + long f0g9 = f0 * (long)g9; + long f1g0 = f1 * (long)g0; + long f1g1_2 = f1_2 * (long)g1; + long f1g2 = f1 * (long)g2; + long f1g3_2 = f1_2 * (long)g3; + long f1g4 = f1 * (long)g4; + long f1g5_2 = f1_2 * (long)g5; + long f1g6 = f1 * (long)g6; + long f1g7_2 = f1_2 * (long)g7; + long f1g8 = f1 * (long)g8; + long f1g9_38 = f1_2 * (long)g9_19; + long f2g0 = f2 * (long)g0; + long f2g1 = f2 * (long)g1; + long f2g2 = f2 * (long)g2; + long f2g3 = f2 * (long)g3; + long f2g4 = f2 * (long)g4; + long f2g5 = f2 * (long)g5; + long f2g6 = f2 * (long)g6; + long f2g7 = f2 * (long)g7; + long f2g8_19 = f2 * (long)g8_19; + long f2g9_19 = f2 * (long)g9_19; + long f3g0 = f3 * (long)g0; + long f3g1_2 = f3_2 * (long)g1; + long f3g2 = f3 * (long)g2; + long f3g3_2 = f3_2 * (long)g3; + long f3g4 = f3 * (long)g4; + long f3g5_2 = f3_2 * (long)g5; + long f3g6 = f3 * (long)g6; + long f3g7_38 = f3_2 * (long)g7_19; + long f3g8_19 = f3 * (long)g8_19; + long f3g9_38 = f3_2 * (long)g9_19; + long f4g0 = f4 * (long)g0; + long f4g1 = f4 * (long)g1; + long f4g2 = f4 * (long)g2; + long f4g3 = f4 * (long)g3; + long f4g4 = f4 * (long)g4; + long f4g5 = f4 * (long)g5; + long f4g6_19 = f4 * (long)g6_19; + long f4g7_19 = f4 * (long)g7_19; + long f4g8_19 = f4 * (long)g8_19; + long f4g9_19 = f4 * (long)g9_19; + long f5g0 = f5 * (long)g0; + long f5g1_2 = f5_2 * (long)g1; + long f5g2 = f5 * (long)g2; + long f5g3_2 = f5_2 * (long)g3; + long f5g4 = f5 * (long)g4; + long f5g5_38 = f5_2 * (long)g5_19; + long f5g6_19 = f5 * (long)g6_19; + long f5g7_38 = f5_2 * (long)g7_19; + long f5g8_19 = f5 * (long)g8_19; + long f5g9_38 = f5_2 * (long)g9_19; + long f6g0 = f6 * (long)g0; + long f6g1 = f6 * (long)g1; + long f6g2 = f6 * (long)g2; + long f6g3 = f6 * (long)g3; + long f6g4_19 = f6 * (long)g4_19; + long f6g5_19 = f6 * (long)g5_19; + long f6g6_19 = f6 * (long)g6_19; + long f6g7_19 = f6 * (long)g7_19; + long f6g8_19 = f6 * (long)g8_19; + long f6g9_19 = f6 * (long)g9_19; + long f7g0 = f7 * (long)g0; + long f7g1_2 = f7_2 * (long)g1; + long f7g2 = f7 * (long)g2; + long f7g3_38 = f7_2 * (long)g3_19; + long f7g4_19 = f7 * (long)g4_19; + long f7g5_38 = f7_2 * (long)g5_19; + long f7g6_19 = f7 * (long)g6_19; + long f7g7_38 = f7_2 * (long)g7_19; + long f7g8_19 = f7 * (long)g8_19; + long f7g9_38 = f7_2 * (long)g9_19; + long f8g0 = f8 * (long)g0; + long f8g1 = f8 * (long)g1; + long f8g2_19 = f8 * (long)g2_19; + long f8g3_19 = f8 * (long)g3_19; + long f8g4_19 = f8 * (long)g4_19; + long f8g5_19 = f8 * (long)g5_19; + long f8g6_19 = f8 * (long)g6_19; + long f8g7_19 = f8 * (long)g7_19; + long f8g8_19 = f8 * (long)g8_19; + long f8g9_19 = f8 * (long)g9_19; + long f9g0 = f9 * (long)g0; + long f9g1_38 = f9_2 * (long)g1_19; + long f9g2_19 = f9 * (long)g2_19; + long f9g3_38 = f9_2 * (long)g3_19; + long f9g4_19 = f9 * (long)g4_19; + long f9g5_38 = f9_2 * (long)g5_19; + long f9g6_19 = f9 * (long)g6_19; + long f9g7_38 = f9_2 * (long)g7_19; + long f9g8_19 = f9 * (long)g8_19; + long f9g9_38 = f9_2 * (long)g9_19; +After: + var f0g0 = f0 * (long)g0; + var f0g1 = f0 * (long)g1; + var f0g2 = f0 * (long)g2; + var f0g3 = f0 * (long)g3; + var f0g4 = f0 * (long)g4; + var f0g5 = f0 * (long)g5; + var f0g6 = f0 * (long)g6; + var f0g7 = f0 * (long)g7; + var f0g8 = f0 * (long)g8; + var f0g9 = f0 * (long)g9; + var f1g0 = f1 * (long)g0; + var f1g1_2 = f1_2 * (long)g1; + var f1g2 = f1 * (long)g2; + var f1g3_2 = f1_2 * (long)g3; + var f1g4 = f1 * (long)g4; + var f1g5_2 = f1_2 * (long)g5; + var f1g6 = f1 * (long)g6; + var f1g7_2 = f1_2 * (long)g7; + var f1g8 = f1 * (long)g8; + var f1g9_38 = f1_2 * (long)g9_19; + var f2g0 = f2 * (long)g0; + var f2g1 = f2 * (long)g1; + var f2g2 = f2 * (long)g2; + var f2g3 = f2 * (long)g3; + var f2g4 = f2 * (long)g4; + var f2g5 = f2 * (long)g5; + var f2g6 = f2 * (long)g6; + var f2g7 = f2 * (long)g7; + var f2g8_19 = f2 * (long)g8_19; + var f2g9_19 = f2 * (long)g9_19; + var f3g0 = f3 * (long)g0; + var f3g1_2 = f3_2 * (long)g1; + var f3g2 = f3 * (long)g2; + var f3g3_2 = f3_2 * (long)g3; + var f3g4 = f3 * (long)g4; + var f3g5_2 = f3_2 * (long)g5; + var f3g6 = f3 * (long)g6; + var f3g7_38 = f3_2 * (long)g7_19; + var f3g8_19 = f3 * (long)g8_19; + var f3g9_38 = f3_2 * (long)g9_19; + var f4g0 = f4 * (long)g0; + var f4g1 = f4 * (long)g1; + var f4g2 = f4 * (long)g2; + var f4g3 = f4 * (long)g3; + var f4g4 = f4 * (long)g4; + var f4g5 = f4 * (long)g5; + var f4g6_19 = f4 * (long)g6_19; + var f4g7_19 = f4 * (long)g7_19; + var f4g8_19 = f4 * (long)g8_19; + var f4g9_19 = f4 * (long)g9_19; + var f5g0 = f5 * (long)g0; + var f5g1_2 = f5_2 * (long)g1; + var f5g2 = f5 * (long)g2; + var f5g3_2 = f5_2 * (long)g3; + var f5g4 = f5 * (long)g4; + var f5g5_38 = f5_2 * (long)g5_19; + var f5g6_19 = f5 * (long)g6_19; + var f5g7_38 = f5_2 * (long)g7_19; + var f5g8_19 = f5 * (long)g8_19; + var f5g9_38 = f5_2 * (long)g9_19; + var f6g0 = f6 * (long)g0; + var f6g1 = f6 * (long)g1; + var f6g2 = f6 * (long)g2; + var f6g3 = f6 * (long)g3; + var f6g4_19 = f6 * (long)g4_19; + var f6g5_19 = f6 * (long)g5_19; + var f6g6_19 = f6 * (long)g6_19; + var f6g7_19 = f6 * (long)g7_19; + var f6g8_19 = f6 * (long)g8_19; + var f6g9_19 = f6 * (long)g9_19; + var f7g0 = f7 * (long)g0; + var f7g1_2 = f7_2 * (long)g1; + var f7g2 = f7 * (long)g2; + var f7g3_38 = f7_2 * (long)g3_19; + var f7g4_19 = f7 * (long)g4_19; + var f7g5_38 = f7_2 * (long)g5_19; + var f7g6_19 = f7 * (long)g6_19; + var f7g7_38 = f7_2 * (long)g7_19; + var f7g8_19 = f7 * (long)g8_19; + var f7g9_38 = f7_2 * (long)g9_19; + var f8g0 = f8 * (long)g0; + var f8g1 = f8 * (long)g1; + var f8g2_19 = f8 * (long)g2_19; + var f8g3_19 = f8 * (long)g3_19; + var f8g4_19 = f8 * (long)g4_19; + var f8g5_19 = f8 * (long)g5_19; + var f8g6_19 = f8 * (long)g6_19; + var f8g7_19 = f8 * (long)g7_19; + var f8g8_19 = f8 * (long)g8_19; + var f8g9_19 = f8 * (long)g9_19; + var f9g0 = f9 * (long)g0; + var f9g1_38 = f9_2 * (long)g1_19; + var f9g2_19 = f9 * (long)g2_19; + var f9g3_38 = f9_2 * (long)g3_19; + var f9g4_19 = f9 * (long)g4_19; + var f9g5_38 = f9_2 * (long)g5_19; + var f9g6_19 = f9 * (long)g6_19; + var f9g7_38 = f9_2 * (long)g7_19; + var f9g8_19 = f9 * (long)g8_19; + var f9g9_38 = f9_2 * (long)g9_19; +*/ + + + var f0g0 = f0 * (long)g0; + var f0g1 = f0 * (long)g1; + var f0g2 = f0 * (long)g2; + var f0g3 = f0 * (long)g3; + var f0g4 = f0 * (long)g4; + var f0g5 = f0 * (long)g5; + var f0g6 = f0 * (long)g6; + var f0g7 = f0 * (long)g7; + var f0g8 = f0 * (long)g8; + var f0g9 = f0 * (long)g9; + var f1g0 = f1 * (long)g0; + var f1g1_2 = f1_2 * (long)g1; + var f1g2 = f1 * (long)g2; + var f1g3_2 = f1_2 * (long)g3; + var f1g4 = f1 * (long)g4; + var f1g5_2 = f1_2 * (long)g5; + var f1g6 = f1 * (long)g6; + var f1g7_2 = f1_2 * (long)g7; + var f1g8 = f1 * (long)g8; + var f1g9_38 = f1_2 * (long)g9_19; + var f2g0 = f2 * (long)g0; + var f2g1 = f2 * (long)g1; + var f2g2 = f2 * (long)g2; + var f2g3 = f2 * (long)g3; + var f2g4 = f2 * (long)g4; + var f2g5 = f2 * (long)g5; + var f2g6 = f2 * (long)g6; + var f2g7 = f2 * (long)g7; + var f2g8_19 = f2 * (long)g8_19; + var f2g9_19 = f2 * (long)g9_19; + var f3g0 = f3 * (long)g0; + var f3g1_2 = f3_2 * (long)g1; + var f3g2 = f3 * (long)g2; + var f3g3_2 = f3_2 * (long)g3; + var f3g4 = f3 * (long)g4; + var f3g5_2 = f3_2 * (long)g5; + var f3g6 = f3 * (long)g6; + var f3g7_38 = f3_2 * (long)g7_19; + var f3g8_19 = f3 * (long)g8_19; + var f3g9_38 = f3_2 * (long)g9_19; + var f4g0 = f4 * (long)g0; + var f4g1 = f4 * (long)g1; + var f4g2 = f4 * (long)g2; + var f4g3 = f4 * (long)g3; + var f4g4 = f4 * (long)g4; + var f4g5 = f4 * (long)g5; + var f4g6_19 = f4 * (long)g6_19; + var f4g7_19 = f4 * (long)g7_19; + var f4g8_19 = f4 * (long)g8_19; + var f4g9_19 = f4 * (long)g9_19; + var f5g0 = f5 * (long)g0; + var f5g1_2 = f5_2 * (long)g1; + var f5g2 = f5 * (long)g2; + var f5g3_2 = f5_2 * (long)g3; + var f5g4 = f5 * (long)g4; + var f5g5_38 = f5_2 * (long)g5_19; + var f5g6_19 = f5 * (long)g6_19; + var f5g7_38 = f5_2 * (long)g7_19; + var f5g8_19 = f5 * (long)g8_19; + var f5g9_38 = f5_2 * (long)g9_19; + var f6g0 = f6 * (long)g0; + var f6g1 = f6 * (long)g1; + var f6g2 = f6 * (long)g2; + var f6g3 = f6 * (long)g3; + var f6g4_19 = f6 * (long)g4_19; + var f6g5_19 = f6 * (long)g5_19; + var f6g6_19 = f6 * (long)g6_19; + var f6g7_19 = f6 * (long)g7_19; + var f6g8_19 = f6 * (long)g8_19; + var f6g9_19 = f6 * (long)g9_19; + var f7g0 = f7 * (long)g0; + var f7g1_2 = f7_2 * (long)g1; + var f7g2 = f7 * (long)g2; + var f7g3_38 = f7_2 * (long)g3_19; + var f7g4_19 = f7 * (long)g4_19; + var f7g5_38 = f7_2 * (long)g5_19; + var f7g6_19 = f7 * (long)g6_19; + var f7g7_38 = f7_2 * (long)g7_19; + var f7g8_19 = f7 * (long)g8_19; + var f7g9_38 = f7_2 * (long)g9_19; + var f8g0 = f8 * (long)g0; + var f8g1 = f8 * (long)g1; + var f8g2_19 = f8 * (long)g2_19; + var f8g3_19 = f8 * (long)g3_19; + var f8g4_19 = f8 * (long)g4_19; + var f8g5_19 = f8 * (long)g5_19; + var f8g6_19 = f8 * (long)g6_19; + var f8g7_19 = f8 * (long)g7_19; + var f8g8_19 = f8 * (long)g8_19; + var f8g9_19 = f8 * (long)g9_19; + var f9g0 = f9 * (long)g0; + var f9g1_38 = f9_2 * (long)g1_19; + var f9g2_19 = f9 * (long)g2_19; + var f9g3_38 = f9_2 * (long)g3_19; + var f9g4_19 = f9 * (long)g4_19; + var f9g5_38 = f9_2 * (long)g5_19; + var f9g6_19 = f9 * (long)g6_19; + var f9g7_38 = f9_2 * (long)g7_19; + var f9g8_19 = f9 * (long)g8_19; + var f9g9_38 = f9_2 * (long)g9_19; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + long h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38; + long h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19; + long h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38; + long h3 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19; + long h4 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38; + long h5 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19; + long h6 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38; + long h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19; + long h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38; + long h9 = f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0; +After: + var h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38; + var h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19; + var h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38; + var h3 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19; + var h4 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38; + var h5 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19; + var h6 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38; + var h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19; + var h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38; + var h9 = f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + long h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38; + long h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19; + long h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38; + long h3 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19; + long h4 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38; + long h5 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19; + long h6 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38; + long h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19; + long h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38; + long h9 = f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0; +After: + var h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38; + var h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19; + var h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38; + var h3 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19; + var h4 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38; + var h5 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19; + var h6 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38; + var h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19; + var h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38; + var h9 = f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: long h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38; long h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19; long h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38; @@ -201,6 +1116,30 @@ internal static void fe_mul(out FieldElement h, ref FieldElement f, ref FieldEle long h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19; long h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38; long h9 = f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0; +After: + var h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38; + var h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19; + var h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38; + var h3 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19; + var h4 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38; + var h5 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19; + var h6 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38; + var h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19; + var h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38; + var h9 = f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0; +*/ + + + var h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38; + var h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19; + var h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38; + var h3 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19; + var h4 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38; + var h5 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19; + var h6 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38; + var h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19; + var h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38; + var h9 = f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0; long carry0; long carry1; @@ -213,66 +1152,90 @@ internal static void fe_mul(out FieldElement h, ref FieldElement f, ref FieldEle long carry8; long carry9; - /* + /* |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38)) i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8 |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19)) i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9 */ - carry0 = (h0 + (long)(1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - carry4 = (h4 + (long)(1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - /* |h0| <= 2^25 */ - /* |h4| <= 2^25 */ - /* |h1| <= 1.71*2^59 */ - /* |h5| <= 1.71*2^59 */ - - carry1 = (h1 + (long)(1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - carry5 = (h5 + (long)(1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - /* |h1| <= 2^24; from now on fits into int32 */ - /* |h5| <= 2^24; from now on fits into int32 */ - /* |h2| <= 1.41*2^60 */ - /* |h6| <= 1.41*2^60 */ - - carry2 = (h2 + (long)(1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - carry6 = (h6 + (long)(1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - /* |h2| <= 2^25; from now on fits into int32 unchanged */ - /* |h6| <= 2^25; from now on fits into int32 unchanged */ - /* |h3| <= 1.71*2^59 */ - /* |h7| <= 1.71*2^59 */ - - carry3 = (h3 + (long)(1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - carry7 = (h7 + (long)(1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - /* |h3| <= 2^24; from now on fits into int32 unchanged */ - /* |h7| <= 2^24; from now on fits into int32 unchanged */ - /* |h4| <= 1.72*2^34 */ - /* |h8| <= 1.41*2^60 */ - - carry4 = (h4 + (long)(1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - carry8 = (h8 + (long)(1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - /* |h4| <= 2^25; from now on fits into int32 unchanged */ - /* |h8| <= 2^25; from now on fits into int32 unchanged */ - /* |h5| <= 1.01*2^24 */ - /* |h9| <= 1.71*2^59 */ - - carry9 = (h9 + (long)(1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - /* |h9| <= 2^24; from now on fits into int32 unchanged */ - /* |h0| <= 1.1*2^39 */ - - carry0 = (h0 + (long)(1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - /* |h0| <= 2^25; from now on fits into int32 unchanged */ - /* |h1| <= 1.01*2^24 */ - - h.x0 = (int)h0; - h.x1 = (int)h1; - h.x2 = (int)h2; - h.x3 = (int)h3; - h.x4 = (int)h4; - h.x5 = (int)h5; - h.x6 = (int)h6; - h.x7 = (int)h7; - h.x8 = (int)h8; - h.x9 = (int)h9; - } - } -} \ No newline at end of file + carry0 = (h0 + (long)(1 << 25)) >> 26; + h1 += carry0; + h0 -= carry0 << 26; + carry4 = (h4 + (long)(1 << 25)) >> 26; + h5 += carry4; + h4 -= carry4 << 26; + /* |h0| <= 2^25 */ + /* |h4| <= 2^25 */ + /* |h1| <= 1.71*2^59 */ + /* |h5| <= 1.71*2^59 */ + + carry1 = (h1 + (long)(1 << 24)) >> 25; + h2 += carry1; + h1 -= carry1 << 25; + carry5 = (h5 + (long)(1 << 24)) >> 25; + h6 += carry5; + h5 -= carry5 << 25; + /* |h1| <= 2^24; from now on fits into int32 */ + /* |h5| <= 2^24; from now on fits into int32 */ + /* |h2| <= 1.41*2^60 */ + /* |h6| <= 1.41*2^60 */ + + carry2 = (h2 + (long)(1 << 25)) >> 26; + h3 += carry2; + h2 -= carry2 << 26; + carry6 = (h6 + (long)(1 << 25)) >> 26; + h7 += carry6; + h6 -= carry6 << 26; + /* |h2| <= 2^25; from now on fits into int32 unchanged */ + /* |h6| <= 2^25; from now on fits into int32 unchanged */ + /* |h3| <= 1.71*2^59 */ + /* |h7| <= 1.71*2^59 */ + + carry3 = (h3 + (long)(1 << 24)) >> 25; + h4 += carry3; + h3 -= carry3 << 25; + carry7 = (h7 + (long)(1 << 24)) >> 25; + h8 += carry7; + h7 -= carry7 << 25; + /* |h3| <= 2^24; from now on fits into int32 unchanged */ + /* |h7| <= 2^24; from now on fits into int32 unchanged */ + /* |h4| <= 1.72*2^34 */ + /* |h8| <= 1.41*2^60 */ + + carry4 = (h4 + (long)(1 << 25)) >> 26; + h5 += carry4; + h4 -= carry4 << 26; + carry8 = (h8 + (long)(1 << 25)) >> 26; + h9 += carry8; + h8 -= carry8 << 26; + /* |h4| <= 2^25; from now on fits into int32 unchanged */ + /* |h8| <= 2^25; from now on fits into int32 unchanged */ + /* |h5| <= 1.01*2^24 */ + /* |h9| <= 1.71*2^59 */ + + carry9 = (h9 + (long)(1 << 24)) >> 25; + h0 += carry9 * 19; + h9 -= carry9 << 25; + /* |h9| <= 2^24; from now on fits into int32 unchanged */ + /* |h0| <= 1.1*2^39 */ + + carry0 = (h0 + (long)(1 << 25)) >> 26; + h1 += carry0; + h0 -= carry0 << 26; + /* |h0| <= 2^25; from now on fits into int32 unchanged */ + /* |h1| <= 1.01*2^24 */ + + h.x0 = (int)h0; + h.x1 = (int)h1; + h.x2 = (int)h2; + h.x3 = (int)h3; + h.x4 = (int)h4; + h.x5 = (int)h5; + h.x6 = (int)h6; + h.x7 = (int)h7; + h.x8 = (int)h8; + h.x9 = (int)h9; + } + } +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_mul121666.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_mul121666.cs index 8b923d90..c0501691 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_mul121666.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_mul121666.cs @@ -17,10 +17,10 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - internal static partial class FieldOperations - { + internal static partial class FieldOperations + { - /* + /* h = f * 121666 Can overlap h with f. @@ -31,8 +31,9 @@ Can overlap h with f. |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. */ - public static void fe_mul121666(out FieldElement h, ref FieldElement f) - { + public static void fe_mul121666(out FieldElement h, ref FieldElement f) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: int f0 = f.x0; int f1 = f.x1; int f2 = f.x2; @@ -43,6 +44,80 @@ public static void fe_mul121666(out FieldElement h, ref FieldElement f) int f7 = f.x7; int f8 = f.x8; int f9 = f.x9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int f0 = f.x0; + int f1 = f.x1; + int f2 = f.x2; + int f3 = f.x3; + int f4 = f.x4; + int f5 = f.x5; + int f6 = f.x6; + int f7 = f.x7; + int f8 = f.x8; + int f9 = f.x9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int f0 = f.x0; + int f1 = f.x1; + int f2 = f.x2; + int f3 = f.x3; + int f4 = f.x4; + int f5 = f.x5; + int f6 = f.x6; + int f7 = f.x7; + int f8 = f.x8; + int f9 = f.x9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; +*/ + + { + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; var h0 = f0 * 121666L; var h1 = f1 * 121666L; @@ -55,28 +130,48 @@ public static void fe_mul121666(out FieldElement h, ref FieldElement f) var h8 = f8 * 121666L; var h9 = f9 * 121666L; - var carry9 = (h9 + (1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - var carry1 = (h1 + (1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - var carry3 = (h3 + (1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - var carry5 = (h5 + (1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - var carry7 = (h7 + (1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + var carry9 = (h9 + (1 << 24)) >> 25; + h0 += carry9 * 19; + h9 -= carry9 << 25; + var carry1 = (h1 + (1 << 24)) >> 25; + h2 += carry1; + h1 -= carry1 << 25; + var carry3 = (h3 + (1 << 24)) >> 25; + h4 += carry3; + h3 -= carry3 << 25; + var carry5 = (h5 + (1 << 24)) >> 25; + h6 += carry5; + h5 -= carry5 << 25; + var carry7 = (h7 + (1 << 24)) >> 25; + h8 += carry7; + h7 -= carry7 << 25; - var carry0 = (h0 + (1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - var carry2 = (h2 + (1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - var carry4 = (h4 + (1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - var carry6 = (h6 + (1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - var carry8 = (h8 + (1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + var carry0 = (h0 + (1 << 25)) >> 26; + h1 += carry0; + h0 -= carry0 << 26; + var carry2 = (h2 + (1 << 25)) >> 26; + h3 += carry2; + h2 -= carry2 << 26; + var carry4 = (h4 + (1 << 25)) >> 26; + h5 += carry4; + h4 -= carry4 << 26; + var carry6 = (h6 + (1 << 25)) >> 26; + h7 += carry6; + h6 -= carry6 << 26; + var carry8 = (h8 + (1 << 25)) >> 26; + h9 += carry8; + h8 -= carry8 << 26; - h.x0 = (int)h0; - h.x1 = (int)h1; - h.x2 = (int)h2; - h.x3 = (int)h3; - h.x4 = (int)h4; - h.x5 = (int)h5; - h.x6 = (int)h6; - h.x7 = (int)h7; - h.x8 = (int)h8; - h.x9 = (int)h9; - } - } -} \ No newline at end of file + h.x0 = (int)h0; + h.x1 = (int)h1; + h.x2 = (int)h2; + h.x3 = (int)h3; + h.x4 = (int)h4; + h.x5 = (int)h5; + h.x6 = (int)h6; + h.x7 = (int)h7; + h.x8 = (int)h8; + h.x9 = (int)h9; + } + } +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_neg.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_neg.cs index c7866e66..51350ca3 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_neg.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_neg.cs @@ -17,9 +17,9 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - internal static partial class FieldOperations - { - /* + internal static partial class FieldOperations + { + /* h = -f Preconditions: @@ -28,8 +28,9 @@ internal static partial class FieldOperations Postconditions: |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. */ - internal static void fe_neg(out FieldElement h, ref FieldElement f) - { + internal static void fe_neg(out FieldElement h, ref FieldElement f) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: int f0 = f.x0; int f1 = f.x1; int f2 = f.x2; @@ -50,17 +51,151 @@ internal static void fe_neg(out FieldElement h, ref FieldElement f) int h7 = -f7; int h8 = -f8; int h9 = -f9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var h0 = -f0; + var h1 = -f1; + var h2 = -f2; + var h3 = -f3; + var h4 = -f4; + var h5 = -f5; + var h6 = -f6; + var h7 = -f7; + var h8 = -f8; + var h9 = -f9; +*/ - h.x0 = h0; - h.x1 = h1; - h.x2 = h2; - h.x3 = h3; - h.x4 = h4; - h.x5 = h5; - h.x6 = h6; - h.x7 = h7; - h.x8 = h8; - h.x9 = h9; - } - } -} \ No newline at end of file +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int f0 = f.x0; + int f1 = f.x1; + int f2 = f.x2; + int f3 = f.x3; + int f4 = f.x4; + int f5 = f.x5; + int f6 = f.x6; + int f7 = f.x7; + int f8 = f.x8; + int f9 = f.x9; + int h0 = -f0; + int h1 = -f1; + int h2 = -f2; + int h3 = -f3; + int h4 = -f4; + int h5 = -f5; + int h6 = -f6; + int h7 = -f7; + int h8 = -f8; + int h9 = -f9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var h0 = -f0; + var h1 = -f1; + var h2 = -f2; + var h3 = -f3; + var h4 = -f4; + var h5 = -f5; + var h6 = -f6; + var h7 = -f7; + var h8 = -f8; + var h9 = -f9; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int f0 = f.x0; + int f1 = f.x1; + int f2 = f.x2; + int f3 = f.x3; + int f4 = f.x4; + int f5 = f.x5; + int f6 = f.x6; + int f7 = f.x7; + int f8 = f.x8; + int f9 = f.x9; + int h0 = -f0; + int h1 = -f1; + int h2 = -f2; + int h3 = -f3; + int h4 = -f4; + int h5 = -f5; + int h6 = -f6; + int h7 = -f7; + int h8 = -f8; + int h9 = -f9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var h0 = -f0; + var h1 = -f1; + var h2 = -f2; + var h3 = -f3; + var h4 = -f4; + var h5 = -f5; + var h6 = -f6; + var h7 = -f7; + var h8 = -f8; + var h9 = -f9; +*/ + + { + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; + var h0 = -f0; + var h1 = -f1; + var h2 = -f2; + var h3 = -f3; + var h4 = -f4; + var h5 = -f5; + var h6 = -f6; + var h7 = -f7; + var h8 = -f8; + var h9 = -f9; + + h.x0 = h0; + h.x1 = h1; + h.x2 = h2; + h.x3 = h3; + h.x4 = h4; + h.x5 = h5; + h.x6 = h6; + h.x7 = h7; + h.x8 = h8; + h.x9 = h9; + } + } +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_pow22523.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_pow22523.cs index 0d7a9927..4b1da690 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_pow22523.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_pow22523.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -17,124 +17,142 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - internal static partial class FieldOperations - { - internal static void fe_pow22523(out FieldElement result, ref FieldElement z) - { - FieldElement t0, t1, t2; - int i; - - /* qhasm: z2 = z1^2^1 */ - /* asm 1: fe_sq(>z2=fe#1,z2=fe#1,>z2=fe#1); */ - /* asm 2: fe_sq(>z2=t0,z2=t0,>z2=t0); */ - fe_sq(out t0, ref z); //for (i = 1; i < 1; ++i) fe_sq(out t0, ref t0); - - /* qhasm: z8 = z2^2^2 */ - /* asm 1: fe_sq(>z8=fe#2,z8=fe#2,>z8=fe#2); */ - /* asm 2: fe_sq(>z8=t1,z8=t1,>z8=t1); */ - fe_sq(out t1, ref t0); for (i = 1; i < 2; ++i) fe_sq(out t1, ref t1); - - /* qhasm: z9 = z1*z8 */ - /* asm 1: fe_mul(>z9=fe#2,z9=t1,z11=fe#1,z11=t0,z22=fe#1,z22=fe#1,>z22=fe#1); */ - /* asm 2: fe_sq(>z22=t0,z22=t0,>z22=t0); */ - fe_sq(out t0, ref t0); //for (i = 1; i < 1; ++i) fe_sq(out t0, ref t0); - - /* qhasm: z_5_0 = z9*z22 */ - /* asm 1: fe_mul(>z_5_0=fe#1,z_5_0=t0,z_10_5=fe#2,z_10_5=fe#2,>z_10_5=fe#2); */ - /* asm 2: fe_sq(>z_10_5=t1,z_10_5=t1,>z_10_5=t1); */ - fe_sq(out t1, ref t0); for (i = 1; i < 5; ++i) fe_sq(out t1, ref t1); - - /* qhasm: z_10_0 = z_10_5*z_5_0 */ - /* asm 1: fe_mul(>z_10_0=fe#1,z_10_0=t0,z_20_10=fe#2,z_20_10=fe#2,>z_20_10=fe#2); */ - /* asm 2: fe_sq(>z_20_10=t1,z_20_10=t1,>z_20_10=t1); */ - fe_sq(out t1, ref t0); for (i = 1; i < 10; ++i) fe_sq(out t1, ref t1); - - /* qhasm: z_20_0 = z_20_10*z_10_0 */ - /* asm 1: fe_mul(>z_20_0=fe#2,z_20_0=t1,z_40_20=fe#3,z_40_20=fe#3,>z_40_20=fe#3); */ - /* asm 2: fe_sq(>z_40_20=t2,z_40_20=t2,>z_40_20=t2); */ - fe_sq(out t2, ref t1); for (i = 1; i < 20; ++i) fe_sq(out t2, ref t2); - - /* qhasm: z_40_0 = z_40_20*z_20_0 */ - /* asm 1: fe_mul(>z_40_0=fe#2,z_40_0=t1,z_50_10=fe#2,z_50_10=fe#2,>z_50_10=fe#2); */ - /* asm 2: fe_sq(>z_50_10=t1,z_50_10=t1,>z_50_10=t1); */ - fe_sq(out t1, ref t1); for (i = 1; i < 10; ++i) fe_sq(out t1, ref t1); - - /* qhasm: z_50_0 = z_50_10*z_10_0 */ - /* asm 1: fe_mul(>z_50_0=fe#1,z_50_0=t0,z_100_50=fe#2,z_100_50=fe#2,>z_100_50=fe#2); */ - /* asm 2: fe_sq(>z_100_50=t1,z_100_50=t1,>z_100_50=t1); */ - fe_sq(out t1, ref t0); for (i = 1; i < 50; ++i) fe_sq(out t1, ref t1); - - /* qhasm: z_100_0 = z_100_50*z_50_0 */ - /* asm 1: fe_mul(>z_100_0=fe#2,z_100_0=t1,z_200_100=fe#3,z_200_100=fe#3,>z_200_100=fe#3); */ - /* asm 2: fe_sq(>z_200_100=t2,z_200_100=t2,>z_200_100=t2); */ - fe_sq(out t2, ref t1); for (i = 1; i < 100; ++i) fe_sq(out t2, ref t2); - - /* qhasm: z_200_0 = z_200_100*z_100_0 */ - /* asm 1: fe_mul(>z_200_0=fe#2,z_200_0=t1,z_250_50=fe#2,z_250_50=fe#2,>z_250_50=fe#2); */ - /* asm 2: fe_sq(>z_250_50=t1,z_250_50=t1,>z_250_50=t1); */ - fe_sq(out t1, ref t1); for (i = 1; i < 50; ++i) fe_sq(out t1, ref t1); - - /* qhasm: z_250_0 = z_250_50*z_50_0 */ - /* asm 1: fe_mul(>z_250_0=fe#1,z_250_0=t0,z_252_2=fe#1,z_252_2=fe#1,>z_252_2=fe#1); */ - /* asm 2: fe_sq(>z_252_2=t0,z_252_2=t0,>z_252_2=t0); */ - fe_sq(out t0, ref t0); for (i = 1; i < 2; ++i) fe_sq(out t0, ref t0); - - /* qhasm: z_252_3 = z_252_2*z1 */ - /* asm 1: fe_mul(>z_252_3=fe#12,z_252_3=out,z2=fe#1,z2=fe#1,>z2=fe#1); */ + /* asm 2: fe_sq(>z2=t0,z2=t0,>z2=t0); */ + fe_sq(out t0, ref z); //for (i = 1; i < 1; ++i) fe_sq(out t0, ref t0); + + /* qhasm: z8 = z2^2^2 */ + /* asm 1: fe_sq(>z8=fe#2,z8=fe#2,>z8=fe#2); */ + /* asm 2: fe_sq(>z8=t1,z8=t1,>z8=t1); */ + fe_sq(out t1, ref t0); + for (i = 1; i < 2; ++i) + fe_sq(out t1, ref t1); + + /* qhasm: z9 = z1*z8 */ + /* asm 1: fe_mul(>z9=fe#2,z9=t1,z11=fe#1,z11=t0,z22=fe#1,z22=fe#1,>z22=fe#1); */ + /* asm 2: fe_sq(>z22=t0,z22=t0,>z22=t0); */ + fe_sq(out t0, ref t0); //for (i = 1; i < 1; ++i) fe_sq(out t0, ref t0); + + /* qhasm: z_5_0 = z9*z22 */ + /* asm 1: fe_mul(>z_5_0=fe#1,z_5_0=t0,z_10_5=fe#2,z_10_5=fe#2,>z_10_5=fe#2); */ + /* asm 2: fe_sq(>z_10_5=t1,z_10_5=t1,>z_10_5=t1); */ + fe_sq(out t1, ref t0); + for (i = 1; i < 5; ++i) + fe_sq(out t1, ref t1); + + /* qhasm: z_10_0 = z_10_5*z_5_0 */ + /* asm 1: fe_mul(>z_10_0=fe#1,z_10_0=t0,z_20_10=fe#2,z_20_10=fe#2,>z_20_10=fe#2); */ + /* asm 2: fe_sq(>z_20_10=t1,z_20_10=t1,>z_20_10=t1); */ + fe_sq(out t1, ref t0); + for (i = 1; i < 10; ++i) + fe_sq(out t1, ref t1); + + /* qhasm: z_20_0 = z_20_10*z_10_0 */ + /* asm 1: fe_mul(>z_20_0=fe#2,z_20_0=t1,z_40_20=fe#3,z_40_20=fe#3,>z_40_20=fe#3); */ + /* asm 2: fe_sq(>z_40_20=t2,z_40_20=t2,>z_40_20=t2); */ + fe_sq(out t2, ref t1); + for (i = 1; i < 20; ++i) + fe_sq(out t2, ref t2); + + /* qhasm: z_40_0 = z_40_20*z_20_0 */ + /* asm 1: fe_mul(>z_40_0=fe#2,z_40_0=t1,z_50_10=fe#2,z_50_10=fe#2,>z_50_10=fe#2); */ + /* asm 2: fe_sq(>z_50_10=t1,z_50_10=t1,>z_50_10=t1); */ + fe_sq(out t1, ref t1); + for (i = 1; i < 10; ++i) + fe_sq(out t1, ref t1); + + /* qhasm: z_50_0 = z_50_10*z_10_0 */ + /* asm 1: fe_mul(>z_50_0=fe#1,z_50_0=t0,z_100_50=fe#2,z_100_50=fe#2,>z_100_50=fe#2); */ + /* asm 2: fe_sq(>z_100_50=t1,z_100_50=t1,>z_100_50=t1); */ + fe_sq(out t1, ref t0); + for (i = 1; i < 50; ++i) + fe_sq(out t1, ref t1); + + /* qhasm: z_100_0 = z_100_50*z_50_0 */ + /* asm 1: fe_mul(>z_100_0=fe#2,z_100_0=t1,z_200_100=fe#3,z_200_100=fe#3,>z_200_100=fe#3); */ + /* asm 2: fe_sq(>z_200_100=t2,z_200_100=t2,>z_200_100=t2); */ + fe_sq(out t2, ref t1); + for (i = 1; i < 100; ++i) + fe_sq(out t2, ref t2); + + /* qhasm: z_200_0 = z_200_100*z_100_0 */ + /* asm 1: fe_mul(>z_200_0=fe#2,z_200_0=t1,z_250_50=fe#2,z_250_50=fe#2,>z_250_50=fe#2); */ + /* asm 2: fe_sq(>z_250_50=t1,z_250_50=t1,>z_250_50=t1); */ + fe_sq(out t1, ref t1); + for (i = 1; i < 50; ++i) + fe_sq(out t1, ref t1); + + /* qhasm: z_250_0 = z_250_50*z_50_0 */ + /* asm 1: fe_mul(>z_250_0=fe#1,z_250_0=t0,z_252_2=fe#1,z_252_2=fe#1,>z_252_2=fe#1); */ + /* asm 2: fe_sq(>z_252_2=t0,z_252_2=t0,>z_252_2=t0); */ + fe_sq(out t0, ref t0); + for (i = 1; i < 2; ++i) + fe_sq(out t0, ref t0); + + /* qhasm: z_252_3 = z_252_2*z1 */ + /* asm 1: fe_mul(>z_252_3=fe#12,z_252_3=out,> 26; h1 += carry0; h0 -= carry0 << 26; - var carry4 = (h4 + (1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - var carry1 = (h1 + (1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - var carry5 = (h5 + (1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - var carry2 = (h2 + (1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - var carry6 = (h6 + (1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - var carry3 = (h3 + (1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - var carry7 = (h7 + (1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - - carry4 = (h4 + (1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - - var carry8 = (h8 + (1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - var carry9 = (h9 + (1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - - carry0 = (h0 + (1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - - h.x0 = (int)h0; - h.x1 = (int)h1; - h.x2 = (int)h2; - h.x3 = (int)h3; - h.x4 = (int)h4; - h.x5 = (int)h5; - h.x6 = (int)h6; - h.x7 = (int)h7; - h.x8 = (int)h8; - h.x9 = (int)h9; - } - } -} \ No newline at end of file + var carry0 = (h0 + (1 << 25)) >> 26; + h1 += carry0; + h0 -= carry0 << 26; + var carry4 = (h4 + (1 << 25)) >> 26; + h5 += carry4; + h4 -= carry4 << 26; + var carry1 = (h1 + (1 << 24)) >> 25; + h2 += carry1; + h1 -= carry1 << 25; + var carry5 = (h5 + (1 << 24)) >> 25; + h6 += carry5; + h5 -= carry5 << 25; + var carry2 = (h2 + (1 << 25)) >> 26; + h3 += carry2; + h2 -= carry2 << 26; + var carry6 = (h6 + (1 << 25)) >> 26; + h7 += carry6; + h6 -= carry6 << 26; + var carry3 = (h3 + (1 << 24)) >> 25; + h4 += carry3; + h3 -= carry3 << 25; + var carry7 = (h7 + (1 << 24)) >> 25; + h8 += carry7; + h7 -= carry7 << 25; + + carry4 = (h4 + (1 << 25)) >> 26; + h5 += carry4; + h4 -= carry4 << 26; + + var carry8 = (h8 + (1 << 25)) >> 26; + h9 += carry8; + h8 -= carry8 << 26; + var carry9 = (h9 + (1 << 24)) >> 25; + h0 += carry9 * 19; + h9 -= carry9 << 25; + + carry0 = (h0 + (1 << 25)) >> 26; + h1 += carry0; + h0 -= carry0 << 26; + + h.x0 = (int)h0; + h.x1 = (int)h1; + h.x2 = (int)h2; + h.x3 = (int)h3; + h.x4 = (int)h4; + h.x5 = (int)h5; + h.x6 = (int)h6; + h.x7 = (int)h7; + h.x8 = (int)h8; + h.x9 = (int)h9; + } + } +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_sq2.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_sq2.cs index 9dbfed52..d8415871 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_sq2.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_sq2.cs @@ -17,9 +17,9 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - internal static partial class FieldOperations - { - /* + internal static partial class FieldOperations + { + /* h = 2 * f * f Can overlap h with f. @@ -30,11 +30,12 @@ Can overlap h with f. |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. */ - /* + /* See fe_mul.c for discussion of implementation strategy. */ - internal static void fe_sq2(out FieldElement h, ref FieldElement f) - { + internal static void fe_sq2(out FieldElement h, ref FieldElement f) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: int f0 = f.x0; int f1 = f.x1; int f2 = f.x2; @@ -45,7 +46,82 @@ internal static void fe_sq2(out FieldElement h, ref FieldElement f) int f7 = f.x7; int f8 = f.x8; int f9 = f.x9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int f0 = f.x0; + int f1 = f.x1; + int f2 = f.x2; + int f3 = f.x3; + int f4 = f.x4; + int f5 = f.x5; + int f6 = f.x6; + int f7 = f.x7; + int f8 = f.x8; + int f9 = f.x9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int f0 = f.x0; + int f1 = f.x1; + int f2 = f.x2; + int f3 = f.x3; + int f4 = f.x4; + int f5 = f.x5; + int f6 = f.x6; + int f7 = f.x7; + int f8 = f.x8; + int f9 = f.x9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; +*/ + { + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: int f0_2 = 2 * f0; int f1_2 = 2 * f1; int f2_2 = 2 * f2; @@ -59,6 +135,98 @@ internal static void fe_sq2(out FieldElement h, ref FieldElement f) int f7_38 = 38 * f7; /* 1.959375*2^30 */ int f8_19 = 19 * f8; /* 1.959375*2^30 */ int f9_38 = 38 * f9; /* 1.959375*2^30 */ +After: + var f0_2 = 2 * f0; + var f1_2 = 2 * f1; + var f2_2 = 2 * f2; + var f3_2 = 2 * f3; + var f4_2 = 2 * f4; + var f5_2 = 2 * f5; + var f6_2 = 2 * f6; + var f7_2 = 2 * f7; + var f5_38 = 38 * f5; /* 1.959375*2^30 */ + var f6_19 = 19 * f6; /* 1.959375*2^30 */ + var f7_38 = 38 * f7; /* 1.959375*2^30 */ + var f8_19 = 19 * f8; /* 1.959375*2^30 */ + var f9_38 = 38 * f9; /* 1.959375*2^30 */ +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int f0_2 = 2 * f0; + int f1_2 = 2 * f1; + int f2_2 = 2 * f2; + int f3_2 = 2 * f3; + int f4_2 = 2 * f4; + int f5_2 = 2 * f5; + int f6_2 = 2 * f6; + int f7_2 = 2 * f7; + int f5_38 = 38 * f5; /* 1.959375*2^30 */ + int f6_19 = 19 * f6; /* 1.959375*2^30 */ + int f7_38 = 38 * f7; /* 1.959375*2^30 */ + int f8_19 = 19 * f8; /* 1.959375*2^30 */ + int f9_38 = 38 * f9; /* 1.959375*2^30 */ +After: + var f0_2 = 2 * f0; + var f1_2 = 2 * f1; + var f2_2 = 2 * f2; + var f3_2 = 2 * f3; + var f4_2 = 2 * f4; + var f5_2 = 2 * f5; + var f6_2 = 2 * f6; + var f7_2 = 2 * f7; + var f5_38 = 38 * f5; /* 1.959375*2^30 */ + var f6_19 = 19 * f6; /* 1.959375*2^30 */ + var f7_38 = 38 * f7; /* 1.959375*2^30 */ + var f8_19 = 19 * f8; /* 1.959375*2^30 */ + var f9_38 = 38 * f9; /* 1.959375*2^30 */ +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int f0_2 = 2 * f0; + int f1_2 = 2 * f1; + int f2_2 = 2 * f2; + int f3_2 = 2 * f3; + int f4_2 = 2 * f4; + int f5_2 = 2 * f5; + int f6_2 = 2 * f6; + int f7_2 = 2 * f7; + int f5_38 = 38 * f5; /* 1.959375*2^30 */ + int f6_19 = 19 * f6; /* 1.959375*2^30 */ + int f7_38 = 38 * f7; /* 1.959375*2^30 */ + int f8_19 = 19 * f8; /* 1.959375*2^30 */ + int f9_38 = 38 * f9; /* 1.959375*2^30 */ +After: + var f0_2 = 2 * f0; + var f1_2 = 2 * f1; + var f2_2 = 2 * f2; + var f3_2 = 2 * f3; + var f4_2 = 2 * f4; + var f5_2 = 2 * f5; + var f6_2 = 2 * f6; + var f7_2 = 2 * f7; + var f5_38 = 38 * f5; /* 1.959375*2^30 */ + var f6_19 = 19 * f6; /* 1.959375*2^30 */ + var f7_38 = 38 * f7; /* 1.959375*2^30 */ + var f8_19 = 19 * f8; /* 1.959375*2^30 */ + var f9_38 = 38 * f9; /* 1.959375*2^30 */ +*/ + + + var f0_2 = 2 * f0; + var f1_2 = 2 * f1; + var f2_2 = 2 * f2; + var f3_2 = 2 * f3; + var f4_2 = 2 * f4; + var f5_2 = 2 * f5; + var f6_2 = 2 * f6; + var f7_2 = 2 * f7; + var f5_38 = 38 * f5; /* 1.959375*2^30 */ + var f6_19 = 19 * f6; /* 1.959375*2^30 */ + var f7_38 = 38 * f7; /* 1.959375*2^30 */ + var f8_19 = 19 * f8; /* 1.959375*2^30 */ + var f9_38 = 38 * f9; /* 1.959375*2^30 */ var f0f0 = f0 * (long)f0; var f0f1_2 = f0_2 * (long)f1; @@ -127,43 +295,67 @@ internal static void fe_sq2(out FieldElement h, ref FieldElement f) var h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38; var h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2; - h0 += h0; - h1 += h1; - h2 += h2; - h3 += h3; - h4 += h4; - h5 += h5; - h6 += h6; - h7 += h7; - h8 += h8; - h9 += h9; - - var carry0 = (h0 + (1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - var carry4 = (h4 + (1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - var carry1 = (h1 + (1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25; - var carry5 = (h5 + (1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25; - var carry2 = (h2 + (1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26; - var carry6 = (h6 + (1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26; - var carry3 = (h3 + (1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25; - var carry7 = (h7 + (1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25; - - carry4 = (h4 + (1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26; - - var carry8 = (h8 + (1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26; - var carry9 = (h9 + (1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; - - carry0 = (h0 + (1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26; - - h.x0 = (int)h0; - h.x1 = (int)h1; - h.x2 = (int)h2; - h.x3 = (int)h3; - h.x4 = (int)h4; - h.x5 = (int)h5; - h.x6 = (int)h6; - h.x7 = (int)h7; - h.x8 = (int)h8; - h.x9 = (int)h9; - } - } -} \ No newline at end of file + h0 += h0; + h1 += h1; + h2 += h2; + h3 += h3; + h4 += h4; + h5 += h5; + h6 += h6; + h7 += h7; + h8 += h8; + h9 += h9; + + var carry0 = (h0 + (1 << 25)) >> 26; + h1 += carry0; + h0 -= carry0 << 26; + var carry4 = (h4 + (1 << 25)) >> 26; + h5 += carry4; + h4 -= carry4 << 26; + var carry1 = (h1 + (1 << 24)) >> 25; + h2 += carry1; + h1 -= carry1 << 25; + var carry5 = (h5 + (1 << 24)) >> 25; + h6 += carry5; + h5 -= carry5 << 25; + var carry2 = (h2 + (1 << 25)) >> 26; + h3 += carry2; + h2 -= carry2 << 26; + var carry6 = (h6 + (1 << 25)) >> 26; + h7 += carry6; + h6 -= carry6 << 26; + var carry3 = (h3 + (1 << 24)) >> 25; + h4 += carry3; + h3 -= carry3 << 25; + var carry7 = (h7 + (1 << 24)) >> 25; + h8 += carry7; + h7 -= carry7 << 25; + + carry4 = (h4 + (1 << 25)) >> 26; + h5 += carry4; + h4 -= carry4 << 26; + + var carry8 = (h8 + (1 << 25)) >> 26; + h9 += carry8; + h8 -= carry8 << 26; + var carry9 = (h9 + (1 << 24)) >> 25; + h0 += carry9 * 19; + h9 -= carry9 << 25; + + carry0 = (h0 + (1 << 25)) >> 26; + h1 += carry0; + h0 -= carry0 << 26; + + h.x0 = (int)h0; + h.x1 = (int)h1; + h.x2 = (int)h2; + h.x3 = (int)h3; + h.x4 = (int)h4; + h.x5 = (int)h5; + h.x6 = (int)h6; + h.x7 = (int)h7; + h.x8 = (int)h8; + h.x9 = (int)h9; + } + } +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_sub.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_sub.cs index 4ebdcd9d..d20a8ccc 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_sub.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_sub.cs @@ -17,9 +17,9 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - internal static partial class FieldOperations - { - /* + internal static partial class FieldOperations + { + /* h = f - g Can overlap h with f or g. @@ -31,8 +31,9 @@ Can overlap h with f or g. |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */ - internal static void fe_sub(out FieldElement h, ref FieldElement f, ref FieldElement g) - { + internal static void fe_sub(out FieldElement h, ref FieldElement f, ref FieldElement g) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: int f0 = f.x0; int f1 = f.x1; int f2 = f.x2; @@ -43,7 +44,82 @@ internal static void fe_sub(out FieldElement h, ref FieldElement f, ref FieldEle int f7 = f.x7; int f8 = f.x8; int f9 = f.x9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int f0 = f.x0; + int f1 = f.x1; + int f2 = f.x2; + int f3 = f.x3; + int f4 = f.x4; + int f5 = f.x5; + int f6 = f.x6; + int f7 = f.x7; + int f8 = f.x8; + int f9 = f.x9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int f0 = f.x0; + int f1 = f.x1; + int f2 = f.x2; + int f3 = f.x3; + int f4 = f.x4; + int f5 = f.x5; + int f6 = f.x6; + int f7 = f.x7; + int f8 = f.x8; + int f9 = f.x9; +After: + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; +*/ + + { + var f0 = f.x0; + var f1 = f.x1; + var f2 = f.x2; + var f3 = f.x3; + var f4 = f.x4; + var f5 = f.x5; + var f6 = f.x6; + var f7 = f.x7; + var f8 = f.x8; + var f9 = f.x9; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: int g0 = g.x0; int g1 = g.x1; int g2 = g.x2; @@ -54,7 +130,107 @@ internal static void fe_sub(out FieldElement h, ref FieldElement f, ref FieldEle int g7 = g.x7; int g8 = g.x8; int g9 = g.x9; +After: + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int g0 = g.x0; + int g1 = g.x1; + int g2 = g.x2; + int g3 = g.x3; + int g4 = g.x4; + int g5 = g.x5; + int g6 = g.x6; + int g7 = g.x7; + int g8 = g.x8; + int g9 = g.x9; +After: + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int g0 = g.x0; + int g1 = g.x1; + int g2 = g.x2; + int g3 = g.x3; + int g4 = g.x4; + int g5 = g.x5; + int g6 = g.x6; + int g7 = g.x7; + int g8 = g.x8; + int g9 = g.x9; +After: + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; +*/ + + + var g0 = g.x0; + var g1 = g.x1; + var g2 = g.x2; + var g3 = g.x3; + var g4 = g.x4; + var g5 = g.x5; + var g6 = g.x6; + var g7 = g.x7; + var g8 = g.x8; + var g9 = g.x9; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int h0 = f0 - g0; + int h1 = f1 - g1; + int h2 = f2 - g2; + int h3 = f3 - g3; + int h4 = f4 - g4; + int h5 = f5 - g5; + int h6 = f6 - g6; + int h7 = f7 - g7; + int h8 = f8 - g8; + int h9 = f9 - g9; +After: + var h0 = f0 - g0; + var h1 = f1 - g1; + var h2 = f2 - g2; + var h3 = f3 - g3; + var h4 = f4 - g4; + var h5 = f5 - g5; + var h6 = f6 - g6; + var h7 = f7 - g7; + var h8 = f8 - g8; + var h9 = f9 - g9; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: int h0 = f0 - g0; int h1 = f1 - g1; int h2 = f2 - g2; @@ -65,17 +241,66 @@ internal static void fe_sub(out FieldElement h, ref FieldElement f, ref FieldEle int h7 = f7 - g7; int h8 = f8 - g8; int h9 = f9 - g9; +After: + var h0 = f0 - g0; + var h1 = f1 - g1; + var h2 = f2 - g2; + var h3 = f3 - g3; + var h4 = f4 - g4; + var h5 = f5 - g5; + var h6 = f6 - g6; + var h7 = f7 - g7; + var h8 = f8 - g8; + var h9 = f9 - g9; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int h0 = f0 - g0; + int h1 = f1 - g1; + int h2 = f2 - g2; + int h3 = f3 - g3; + int h4 = f4 - g4; + int h5 = f5 - g5; + int h6 = f6 - g6; + int h7 = f7 - g7; + int h8 = f8 - g8; + int h9 = f9 - g9; +After: + var h0 = f0 - g0; + var h1 = f1 - g1; + var h2 = f2 - g2; + var h3 = f3 - g3; + var h4 = f4 - g4; + var h5 = f5 - g5; + var h6 = f6 - g6; + var h7 = f7 - g7; + var h8 = f8 - g8; + var h9 = f9 - g9; +*/ + + + var h0 = f0 - g0; + var h1 = f1 - g1; + var h2 = f2 - g2; + var h3 = f3 - g3; + var h4 = f4 - g4; + var h5 = f5 - g5; + var h6 = f6 - g6; + var h7 = f7 - g7; + var h8 = f8 - g8; + var h9 = f9 - g9; - h.x0 = h0; - h.x1 = h1; - h.x2 = h2; - h.x3 = h3; - h.x4 = h4; - h.x5 = h5; - h.x6 = h6; - h.x7 = h7; - h.x8 = h8; - h.x9 = h9; - } - } -} \ No newline at end of file + h.x0 = h0; + h.x1 = h1; + h.x2 = h2; + h.x3 = h3; + h.x4 = h4; + h.x5 = h5; + h.x6 = h6; + h.x7 = h7; + h.x8 = h8; + h.x9 = h9; + } + } +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_tobytes.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_tobytes.cs index 48771d1b..45b71308 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_tobytes.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/fe_tobytes.cs @@ -47,7 +47,58 @@ internal static void fe_tobytes(byte[] s, int offset, ref FieldElement h) { FieldElement hr; fe_reduce(out hr, ref h); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int h0 = hr.x0; + int h1 = hr.x1; + int h2 = hr.x2; + int h3 = hr.x3; + int h4 = hr.x4; + int h5 = hr.x5; + int h6 = hr.x6; + int h7 = hr.x7; + int h8 = hr.x8; + int h9 = hr.x9; +After: + var h0 = hr.x0; + var h1 = hr.x1; + var h2 = hr.x2; + var h3 = hr.x3; + var h4 = hr.x4; + var h5 = hr.x5; + var h6 = hr.x6; + var h7 = hr.x7; + var h8 = hr.x8; + var h9 = hr.x9; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int h0 = hr.x0; + int h1 = hr.x1; + int h2 = hr.x2; + int h3 = hr.x3; + int h4 = hr.x4; + int h5 = hr.x5; + int h6 = hr.x6; + int h7 = hr.x7; + int h8 = hr.x8; + int h9 = hr.x9; +After: + var h0 = hr.x0; + var h1 = hr.x1; + var h2 = hr.x2; + var h3 = hr.x3; + var h4 = hr.x4; + var h5 = hr.x5; + var h6 = hr.x6; + var h7 = hr.x7; + var h8 = hr.x8; + var h9 = hr.x9; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int h0 = hr.x0; int h1 = hr.x1; int h2 = hr.x2; @@ -58,6 +109,30 @@ internal static void fe_tobytes(byte[] s, int offset, ref FieldElement h) int h7 = hr.x7; int h8 = hr.x8; int h9 = hr.x9; +After: + var h0 = hr.x0; + var h1 = hr.x1; + var h2 = hr.x2; + var h3 = hr.x3; + var h4 = hr.x4; + var h5 = hr.x5; + var h6 = hr.x6; + var h7 = hr.x7; + var h8 = hr.x8; + var h9 = hr.x9; +*/ + + + var h0 = hr.x0; + var h1 = hr.x1; + var h2 = hr.x2; + var h3 = hr.x3; + var h4 = hr.x4; + var h5 = hr.x5; + var h6 = hr.x6; + var h7 = hr.x7; + var h8 = hr.x8; + var h9 = hr.x9; /* Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. @@ -67,43 +142,44 @@ internal static void fe_tobytes(byte[] s, int offset, ref FieldElement h) */ unchecked { - s[offset + 0] = (byte) (h0 >> 0); - s[offset + 1] = (byte) (h0 >> 8); - s[offset + 2] = (byte) (h0 >> 16); - s[offset + 3] = (byte) ((h0 >> 24) | (h1 << 2)); - s[offset + 4] = (byte) (h1 >> 6); - s[offset + 5] = (byte) (h1 >> 14); - s[offset + 6] = (byte) ((h1 >> 22) | (h2 << 3)); - s[offset + 7] = (byte) (h2 >> 5); - s[offset + 8] = (byte) (h2 >> 13); - s[offset + 9] = (byte) ((h2 >> 21) | (h3 << 5)); - s[offset + 10] = (byte) (h3 >> 3); - s[offset + 11] = (byte) (h3 >> 11); - s[offset + 12] = (byte) ((h3 >> 19) | (h4 << 6)); - s[offset + 13] = (byte) (h4 >> 2); - s[offset + 14] = (byte) (h4 >> 10); - s[offset + 15] = (byte) (h4 >> 18); - s[offset + 16] = (byte) (h5 >> 0); - s[offset + 17] = (byte) (h5 >> 8); - s[offset + 18] = (byte) (h5 >> 16); - s[offset + 19] = (byte) ((h5 >> 24) | (h6 << 1)); - s[offset + 20] = (byte) (h6 >> 7); - s[offset + 21] = (byte) (h6 >> 15); - s[offset + 22] = (byte) ((h6 >> 23) | (h7 << 3)); - s[offset + 23] = (byte) (h7 >> 5); - s[offset + 24] = (byte) (h7 >> 13); - s[offset + 25] = (byte) ((h7 >> 21) | (h8 << 4)); - s[offset + 26] = (byte) (h8 >> 4); - s[offset + 27] = (byte) (h8 >> 12); - s[offset + 28] = (byte) ((h8 >> 20) | (h9 << 6)); - s[offset + 29] = (byte) (h9 >> 2); - s[offset + 30] = (byte) (h9 >> 10); - s[offset + 31] = (byte) (h9 >> 18); + s[offset + 0] = (byte)(h0 >> 0); + s[offset + 1] = (byte)(h0 >> 8); + s[offset + 2] = (byte)(h0 >> 16); + s[offset + 3] = (byte)((h0 >> 24) | (h1 << 2)); + s[offset + 4] = (byte)(h1 >> 6); + s[offset + 5] = (byte)(h1 >> 14); + s[offset + 6] = (byte)((h1 >> 22) | (h2 << 3)); + s[offset + 7] = (byte)(h2 >> 5); + s[offset + 8] = (byte)(h2 >> 13); + s[offset + 9] = (byte)((h2 >> 21) | (h3 << 5)); + s[offset + 10] = (byte)(h3 >> 3); + s[offset + 11] = (byte)(h3 >> 11); + s[offset + 12] = (byte)((h3 >> 19) | (h4 << 6)); + s[offset + 13] = (byte)(h4 >> 2); + s[offset + 14] = (byte)(h4 >> 10); + s[offset + 15] = (byte)(h4 >> 18); + s[offset + 16] = (byte)(h5 >> 0); + s[offset + 17] = (byte)(h5 >> 8); + s[offset + 18] = (byte)(h5 >> 16); + s[offset + 19] = (byte)((h5 >> 24) | (h6 << 1)); + s[offset + 20] = (byte)(h6 >> 7); + s[offset + 21] = (byte)(h6 >> 15); + s[offset + 22] = (byte)((h6 >> 23) | (h7 << 3)); + s[offset + 23] = (byte)(h7 >> 5); + s[offset + 24] = (byte)(h7 >> 13); + s[offset + 25] = (byte)((h7 >> 21) | (h8 << 4)); + s[offset + 26] = (byte)(h8 >> 4); + s[offset + 27] = (byte)(h8 >> 12); + s[offset + 28] = (byte)((h8 >> 20) | (h9 << 6)); + s[offset + 29] = (byte)(h9 >> 2); + s[offset + 30] = (byte)(h9 >> 10); + s[offset + 31] = (byte)(h9 >> 18); } } internal static void fe_reduce(out FieldElement hr, ref FieldElement h) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: int h0 = h.x0; int h1 = h.x1; int h2 = h.x2; @@ -114,6 +190,80 @@ internal static void fe_reduce(out FieldElement hr, ref FieldElement h) int h7 = h.x7; int h8 = h.x8; int h9 = h.x9; +After: + var h0 = h.x0; + var h1 = h.x1; + var h2 = h.x2; + var h3 = h.x3; + var h4 = h.x4; + var h5 = h.x5; + var h6 = h.x6; + var h7 = h.x7; + var h8 = h.x8; + var h9 = h.x9; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int h0 = h.x0; + int h1 = h.x1; + int h2 = h.x2; + int h3 = h.x3; + int h4 = h.x4; + int h5 = h.x5; + int h6 = h.x6; + int h7 = h.x7; + int h8 = h.x8; + int h9 = h.x9; +After: + var h0 = h.x0; + var h1 = h.x1; + var h2 = h.x2; + var h3 = h.x3; + var h4 = h.x4; + var h5 = h.x5; + var h6 = h.x6; + var h7 = h.x7; + var h8 = h.x8; + var h9 = h.x9; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int h0 = h.x0; + int h1 = h.x1; + int h2 = h.x2; + int h3 = h.x3; + int h4 = h.x4; + int h5 = h.x5; + int h6 = h.x6; + int h7 = h.x7; + int h8 = h.x8; + int h9 = h.x9; +After: + var h0 = h.x0; + var h1 = h.x1; + var h2 = h.x2; + var h3 = h.x3; + var h4 = h.x4; + var h5 = h.x5; + var h6 = h.x6; + var h7 = h.x7; + var h8 = h.x8; + var h9 = h.x9; +*/ + + { + var h0 = h.x0; + var h1 = h.x1; + var h2 = h.x2; + var h3 = h.x3; + var h4 = h.x4; + var h5 = h.x5; + var h6 = h.x6; + var h7 = h.x7; + var h8 = h.x8; + var h9 = h.x9; int q; @@ -133,16 +283,35 @@ internal static void fe_reduce(out FieldElement hr, ref FieldElement h) h0 += 19 * q; /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */ - var carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26; - var carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25; - var carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26; - var carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25; - var carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26; - var carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25; - var carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26; - var carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25; - var carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26; - var carry9 = h9 >> 25; h9 -= carry9 << 25; + var carry0 = h0 >> 26; + h1 += carry0; + h0 -= carry0 << 26; + var carry1 = h1 >> 25; + h2 += carry1; + h1 -= carry1 << 25; + var carry2 = h2 >> 26; + h3 += carry2; + h2 -= carry2 << 26; + var carry3 = h3 >> 25; + h4 += carry3; + h3 -= carry3 << 25; + var carry4 = h4 >> 26; + h5 += carry4; + h4 -= carry4 << 26; + var carry5 = h5 >> 25; + h6 += carry5; + h5 -= carry5 << 25; + var carry6 = h6 >> 26; + h7 += carry6; + h6 -= carry6 << 26; + var carry7 = h7 >> 25; + h8 += carry7; + h7 -= carry7 << 25; + var carry8 = h8 >> 26; + h9 += carry8; + h8 -= carry8 << 26; + var carry9 = h9 >> 25; + h9 -= carry9 << 25; /* h10 = carry9 */ hr.x0 = h0; @@ -157,4 +326,4 @@ internal static void fe_reduce(out FieldElement hr, ref FieldElement h) hr.x9 = h9; } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/ge_add.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/ge_add.cs index 8a077fb4..90e256fc 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/ge_add.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/ge_add.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -17,72 +17,72 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - internal static partial class GroupOperations - { - /* + internal static partial class GroupOperations + { + /* r = p + q */ - internal static void ge_add(out GroupElementP1P1 r, ref GroupElementP3 p, ref GroupElementCached q) - { - FieldElement t0; - - /* qhasm: YpX1 = Y1+X1 */ - /* asm 1: fe_add(>YpX1=fe#1,YpX1=r.X,YmX1=fe#2,YmX1=r.Y,A=fe#3,A=r.Z,B=fe#2,B=r.Y,C=fe#4,C=r.T,ZZ=fe#1,ZZ=r.X,D=fe#5,D=t0,X3=fe#1,X3=r.X,Y3=fe#2,Y3=r.Y,Z3=fe#3,Z3=r.Z,T3=fe#4,T3=r.T,YpX1=fe#1,YpX1=r.X,YmX1=fe#2,YmX1=r.Y,A=fe#3,A=r.Z,B=fe#2,B=r.Y,C=fe#4,C=r.T,ZZ=fe#1,ZZ=r.X,D=fe#5,D=t0,X3=fe#1,X3=r.X,Y3=fe#2,Y3=r.Y,Z3=fe#3,Z3=r.Z,T3=fe#4,T3=r.T,> 3] >> (i & 7))); +After: + for (var i = 0; i < 256; ++i) +*/ - for (int i = 0; i < 256; ++i) +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + for (int i = 0; i < 256; ++i) +After: + for (var i = 0; i < 256; ++i) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + for (int i = 0; i < 256; ++i) +After: + for (var i = 0; i < 256; ++i) +*/ + + { + for (var i = 0; i < 256; ++i) + r[i] = (sbyte)(1 & (a[i >> 3] >> (i & 7))); + + for (var i = 0; i < 256; ++i) { if (r[i] != 0) { - for (int b = 1; b <= 6 && (i + b) < 256; ++b) + for (var b = 1; b <= 6 && (i + b) < 256; ++b) { if (r[i + b] != 0) { if (r[i] + (r[i + b] << b) <= 15) { - r[i] += (sbyte)(r[i + b] << b); r[i + b] = 0; + r[i] += (sbyte)(r[i + b] << b); + r[i + b] = 0; } else if (r[i] - (r[i + b] << b) >= -15) { r[i] -= (sbyte)(r[i + b] << b); - for (int k = i + b; k < 256; ++k) + for (var k = i + b; k < 256; ++k) { if (r[k] == 0) { @@ -55,76 +77,146 @@ private static void slide(sbyte[] r, byte[] a) } } } - } + } - /* + /* r = a * A + b * B where a = a[0]+256*a[1]+...+256^31 a[31]. and b = b[0]+256*b[1]+...+256^31 b[31]. B is the Ed25519 base point (x,4/5) with x positive. */ - public static void ge_double_scalarmult_vartime(out GroupElementP2 r, byte[] a, ref GroupElementP3 A, byte[] b) - { + public static void ge_double_scalarmult_vartime(out GroupElementP2 r, byte[] a, ref GroupElementP3 A, byte[] b) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: GroupElementPreComp[] Bi = LookupTables.Base2; - // todo: Perhaps remove these allocations? +After: + var Bi = LookupTables.Base2; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + GroupElementPreComp[] Bi = LookupTables.Base2; +After: + var Bi = LookupTables.Base2; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + GroupElementPreComp[] Bi = LookupTables.Base2; +After: + var Bi = LookupTables.Base2; +*/ + + { + var Bi = LookupTables.Base2; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: sbyte[] aslide = new sbyte[256]; sbyte[] bslide = new sbyte[256]; GroupElementCached[] Ai = new GroupElementCached[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ - GroupElementP1P1 t; - GroupElementP3 u; - GroupElementP3 A2; - int i; - - slide(aslide, a); - slide(bslide, b); - - ge_p3_to_cached(out Ai[0], ref A); - ge_p3_dbl(out t, ref A); ge_p1p1_to_p3(out A2, ref t); - ge_add(out t, ref A2, ref Ai[0]); ge_p1p1_to_p3(out u, ref t); ge_p3_to_cached(out Ai[1], ref u); - ge_add(out t, ref A2, ref Ai[1]); ge_p1p1_to_p3(out u, ref t); ge_p3_to_cached(out Ai[2], ref u); - ge_add(out t, ref A2, ref Ai[2]); ge_p1p1_to_p3(out u, ref t); ge_p3_to_cached(out Ai[3], ref u); - ge_add(out t, ref A2, ref Ai[3]); ge_p1p1_to_p3(out u, ref t); ge_p3_to_cached(out Ai[4], ref u); - ge_add(out t, ref A2, ref Ai[4]); ge_p1p1_to_p3(out u, ref t); ge_p3_to_cached(out Ai[5], ref u); - ge_add(out t, ref A2, ref Ai[5]); ge_p1p1_to_p3(out u, ref t); ge_p3_to_cached(out Ai[6], ref u); - ge_add(out t, ref A2, ref Ai[6]); ge_p1p1_to_p3(out u, ref t); ge_p3_to_cached(out Ai[7], ref u); - - ge_p2_0(out r); - - for (i = 255; i >= 0; --i) - { - if ((aslide[i] != 0) || (bslide[i] != 0)) break; - } - - for (; i >= 0; --i) - { - ge_p2_dbl(out t, ref r); - - if (aslide[i] > 0) - { - ge_p1p1_to_p3(out u, ref t); - ge_add(out t, ref u, ref Ai[aslide[i] / 2]); - } - else if (aslide[i] < 0) - { - ge_p1p1_to_p3(out u, ref t); - ge_sub(out t, ref u, ref Ai[(-aslide[i]) / 2]); - } - - if (bslide[i] > 0) - { - ge_p1p1_to_p3(out u, ref t); - ge_madd(out t, ref u, ref Bi[bslide[i] / 2]); - } - else if (bslide[i] < 0) - { - ge_p1p1_to_p3(out u, ref t); - ge_msub(out t, ref u, ref Bi[(-bslide[i]) / 2]); - } - - ge_p1p1_to_p2(out r, ref t); - } - } - - } -} \ No newline at end of file +After: + var aslide = new sbyte[256]; + var bslide = new sbyte[256]; + var Ai = new GroupElementCached[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + sbyte[] aslide = new sbyte[256]; + sbyte[] bslide = new sbyte[256]; + GroupElementCached[] Ai = new GroupElementCached[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ +After: + var aslide = new sbyte[256]; + var bslide = new sbyte[256]; + var Ai = new GroupElementCached[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + sbyte[] aslide = new sbyte[256]; + sbyte[] bslide = new sbyte[256]; + GroupElementCached[] Ai = new GroupElementCached[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ +After: + var aslide = new sbyte[256]; + var bslide = new sbyte[256]; + var Ai = new GroupElementCached[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ +*/ + + // todo: Perhaps remove these allocations? + var aslide = new sbyte[256]; + var bslide = new sbyte[256]; + var Ai = new GroupElementCached[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ + GroupElementP1P1 t; + GroupElementP3 u; + GroupElementP3 A2; + int i; + + slide(aslide, a); + slide(bslide, b); + + ge_p3_to_cached(out Ai[0], ref A); + ge_p3_dbl(out t, ref A); + ge_p1p1_to_p3(out A2, ref t); + ge_add(out t, ref A2, ref Ai[0]); + ge_p1p1_to_p3(out u, ref t); + ge_p3_to_cached(out Ai[1], ref u); + ge_add(out t, ref A2, ref Ai[1]); + ge_p1p1_to_p3(out u, ref t); + ge_p3_to_cached(out Ai[2], ref u); + ge_add(out t, ref A2, ref Ai[2]); + ge_p1p1_to_p3(out u, ref t); + ge_p3_to_cached(out Ai[3], ref u); + ge_add(out t, ref A2, ref Ai[3]); + ge_p1p1_to_p3(out u, ref t); + ge_p3_to_cached(out Ai[4], ref u); + ge_add(out t, ref A2, ref Ai[4]); + ge_p1p1_to_p3(out u, ref t); + ge_p3_to_cached(out Ai[5], ref u); + ge_add(out t, ref A2, ref Ai[5]); + ge_p1p1_to_p3(out u, ref t); + ge_p3_to_cached(out Ai[6], ref u); + ge_add(out t, ref A2, ref Ai[6]); + ge_p1p1_to_p3(out u, ref t); + ge_p3_to_cached(out Ai[7], ref u); + + ge_p2_0(out r); + + for (i = 255; i >= 0; --i) + { + if ((aslide[i] != 0) || (bslide[i] != 0)) + break; + } + + for (; i >= 0; --i) + { + ge_p2_dbl(out t, ref r); + + if (aslide[i] > 0) + { + ge_p1p1_to_p3(out u, ref t); + ge_add(out t, ref u, ref Ai[aslide[i] / 2]); + } + else if (aslide[i] < 0) + { + ge_p1p1_to_p3(out u, ref t); + ge_sub(out t, ref u, ref Ai[(-aslide[i]) / 2]); + } + + if (bslide[i] > 0) + { + ge_p1p1_to_p3(out u, ref t); + ge_madd(out t, ref u, ref Bi[bslide[i] / 2]); + } + else if (bslide[i] < 0) + { + ge_p1p1_to_p3(out u, ref t); + ge_msub(out t, ref u, ref Bi[(-bslide[i]) / 2]); + } + + ge_p1p1_to_p2(out r, ref t); + } + } + + } +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/ge_frombytes.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/ge_frombytes.cs index 6fb4025f..b74e57f1 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/ge_frombytes.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/ge_frombytes.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -17,49 +17,49 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - internal static partial class GroupOperations - { - public static int ge_frombytes_negate_vartime(out GroupElementP3 h, byte[] data, int offset) - { - FieldElement u, v, v3, vxx, check; + internal static partial class GroupOperations + { + public static int ge_frombytes_negate_vartime(out GroupElementP3 h, byte[] data, int offset) + { + FieldElement u, v, v3, vxx, check; - FieldOperations.fe_frombytes(out h.Y, data, offset); - FieldOperations.fe_1(out h.Z); - FieldOperations.fe_sq(out u, ref h.Y); - FieldOperations.fe_mul(out v, ref u, ref LookupTables.d); - FieldOperations.fe_sub(out u, ref u, ref h.Z); /* u = y^2-1 */ - FieldOperations.fe_add(out v, ref v, ref h.Z); /* v = dy^2+1 */ + FieldOperations.fe_frombytes(out h.Y, data, offset); + FieldOperations.fe_1(out h.Z); + FieldOperations.fe_sq(out u, ref h.Y); + FieldOperations.fe_mul(out v, ref u, ref LookupTables.d); + FieldOperations.fe_sub(out u, ref u, ref h.Z); /* u = y^2-1 */ + FieldOperations.fe_add(out v, ref v, ref h.Z); /* v = dy^2+1 */ - FieldOperations.fe_sq(out v3, ref v); - FieldOperations.fe_mul(out v3, ref v3, ref v); /* v3 = v^3 */ - FieldOperations.fe_sq(out h.X, ref v3); - FieldOperations.fe_mul(out h.X, ref h.X, ref v); - FieldOperations.fe_mul(out h.X, ref h.X, ref u); /* x = uv^7 */ + FieldOperations.fe_sq(out v3, ref v); + FieldOperations.fe_mul(out v3, ref v3, ref v); /* v3 = v^3 */ + FieldOperations.fe_sq(out h.X, ref v3); + FieldOperations.fe_mul(out h.X, ref h.X, ref v); + FieldOperations.fe_mul(out h.X, ref h.X, ref u); /* x = uv^7 */ - FieldOperations.fe_pow22523(out h.X, ref h.X); /* x = (uv^7)^((q-5)/8) */ - FieldOperations.fe_mul(out h.X, ref h.X, ref v3); - FieldOperations.fe_mul(out h.X, ref h.X, ref u); /* x = uv^3(uv^7)^((q-5)/8) */ + FieldOperations.fe_pow22523(out h.X, ref h.X); /* x = (uv^7)^((q-5)/8) */ + FieldOperations.fe_mul(out h.X, ref h.X, ref v3); + FieldOperations.fe_mul(out h.X, ref h.X, ref u); /* x = uv^3(uv^7)^((q-5)/8) */ - FieldOperations.fe_sq(out vxx, ref h.X); - FieldOperations.fe_mul(out vxx, ref vxx, ref v); - FieldOperations.fe_sub(out check, ref vxx, ref u); /* vx^2-u */ - if (FieldOperations.fe_isnonzero(ref check) != 0) - { - FieldOperations.fe_add(out check, ref vxx, ref u); /* vx^2+u */ - if (FieldOperations.fe_isnonzero(ref check) != 0) - { - h = default(GroupElementP3); - return -1; - } - FieldOperations.fe_mul(out h.X, ref h.X, ref LookupTables.sqrtm1); - } + FieldOperations.fe_sq(out vxx, ref h.X); + FieldOperations.fe_mul(out vxx, ref vxx, ref v); + FieldOperations.fe_sub(out check, ref vxx, ref u); /* vx^2-u */ + if (FieldOperations.fe_isnonzero(ref check) != 0) + { + FieldOperations.fe_add(out check, ref vxx, ref u); /* vx^2+u */ + if (FieldOperations.fe_isnonzero(ref check) != 0) + { + h = default(GroupElementP3); + return -1; + } + FieldOperations.fe_mul(out h.X, ref h.X, ref LookupTables.sqrtm1); + } - if (FieldOperations.fe_isnegative(ref h.X) == (data[offset + 31] >> 7)) - FieldOperations.fe_neg(out h.X, ref h.X); + if (FieldOperations.fe_isnegative(ref h.X) == (data[offset + 31] >> 7)) + FieldOperations.fe_neg(out h.X, ref h.X); - FieldOperations.fe_mul(out h.T, ref h.X, ref h.Y); - return 0; - } + FieldOperations.fe_mul(out h.T, ref h.X, ref h.Y); + return 0; + } - } -} \ No newline at end of file + } +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/ge_madd.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/ge_madd.cs index 607ace71..d7f3c1e9 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/ge_madd.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/ge_madd.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -17,68 +17,68 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - internal static partial class GroupOperations - { - /* + internal static partial class GroupOperations + { + /* r = p + q */ - public static void ge_madd(out GroupElementP1P1 r, ref GroupElementP3 p, ref GroupElementPreComp q) - { - FieldElement t0; - - /* qhasm: YpX1 = Y1+X1 */ - /* asm 1: fe_add(>YpX1=fe#1,YpX1=r.X,YmX1=fe#2,YmX1=r.Y,A=fe#3,A=r.Z,B=fe#2,B=r.Y,C=fe#4,C=r.T,D=fe#5,D=t0,X3=fe#1,X3=r.X,Y3=fe#2,Y3=r.Y,Z3=fe#3,Z3=r.Z,T3=fe#4,T3=r.T,YpX1=fe#1,YpX1=r.X,YmX1=fe#2,YmX1=r.Y,A=fe#3,A=r.Z,B=fe#2,B=r.Y,C=fe#4,C=r.T,D=fe#5,D=t0,X3=fe#1,X3=r.X,Y3=fe#2,Y3=r.Y,Z3=fe#3,Z3=r.Z,T3=fe#4,T3=r.T,YpX1=fe#1,YpX1=r.X,YpX1=fe#1,YpX1=r.X,YmX1=fe#2,YmX1=r.Y,YmX1=fe#2,YmX1=r.Y,A=fe#3,A=r.Z,A=fe#3,A=r.Z,B=fe#2,B=r.Y,B=fe#2,B=r.Y,C=fe#4,C=r.T,C=fe#4,C=r.T,D=fe#5,D=t0,D=fe#5,D=t0,X3=fe#1,X3=r.X,X3=fe#1,X3=r.X,Y3=fe#2,Y3=r.Y,Y3=fe#2,Y3=r.Y,Z3=fe#3,Z3=r.Z,Z3=fe#3,Z3=r.Z,T3=fe#4,T3=r.T,T3=fe#4,T3=r.T,XX=fe#1,XX=r.X,XX=fe#1,XX=r.X,YY=fe#3,YY=r.Z,YY=fe#3,YY=r.Z,B=fe#4,B=r.T,B=fe#4,B=r.T,A=fe#2,A=r.Y,A=fe#2,A=r.Y,AA=fe#5,AA=t0,AA=fe#5,AA=t0,Y3=fe#2,Y3=r.Y,Y3=fe#2,Y3=r.Y,Z3=fe#3,Z3=r.Z,Z3=fe#3,Z3=r.Z,X3=fe#1,X3=r.X,X3=fe#1,X3=r.X,T3=fe#4,T3=r.T,T3=fe#4,T3=r.T,>= 31; /* 1: yes; 0: no */ return (byte)y; } @@ -86,7 +120,28 @@ public static void ge_scalarmult_base(out GroupElementP3 h, byte[] a, int offset GroupElementP2 s; GroupElementPreComp t; + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + for (int i = 0; i < 32; ++i) +After: + for (var i = 0; i < 32; ++i) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + for (int i = 0; i < 32; ++i) +After: + for (var i = 0; i < 32; ++i) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: for (int i = 0; i < 32; ++i) +After: + for (var i = 0; i < 32; ++i) +*/ + for (var i = 0; i < 32; ++i) { e[2 * i + 0] = (sbyte)((a[offset + i] >> 0) & 15); e[2 * i + 1] = (sbyte)((a[offset + i] >> 4) & 15); @@ -95,7 +150,7 @@ public static void ge_scalarmult_base(out GroupElementP3 h, byte[] a, int offset /* e[63] is between 0 and 7 */ carry = 0; - for (int i = 0; i < 63; ++i) + for (var i = 0; i < 63; ++i) { e[i] += carry; carry = (sbyte)(e[i] + 8); @@ -106,23 +161,29 @@ public static void ge_scalarmult_base(out GroupElementP3 h, byte[] a, int offset /* each e[i] is between -8 and 8 */ ge_p3_0(out h); - for (int i = 1; i < 64; i += 2) + for (var i = 1; i < 64; i += 2) { select(out t, i / 2, e[i]); - ge_madd(out r, ref h, ref t); ge_p1p1_to_p3(out h, ref r); + ge_madd(out r, ref h, ref t); + ge_p1p1_to_p3(out h, ref r); } - ge_p3_dbl(out r, ref h); ge_p1p1_to_p2(out s, ref r); - ge_p2_dbl(out r, ref s); ge_p1p1_to_p2(out s, ref r); - ge_p2_dbl(out r, ref s); ge_p1p1_to_p2(out s, ref r); - ge_p2_dbl(out r, ref s); ge_p1p1_to_p3(out h, ref r); + ge_p3_dbl(out r, ref h); + ge_p1p1_to_p2(out s, ref r); + ge_p2_dbl(out r, ref s); + ge_p1p1_to_p2(out s, ref r); + ge_p2_dbl(out r, ref s); + ge_p1p1_to_p2(out s, ref r); + ge_p2_dbl(out r, ref s); + ge_p1p1_to_p3(out h, ref r); - for (int i = 0; i < 64; i += 2) + for (var i = 0; i < 64; i += 2) { select(out t, i / 2, e[i]); - ge_madd(out r, ref h, ref t); ge_p1p1_to_p3(out h, ref r); + ge_madd(out r, ref h, ref t); + ge_p1p1_to_p3(out h, ref r); } } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/ge_sub.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/ge_sub.cs index 41ea5691..c2d2500b 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/ge_sub.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/ge_sub.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -17,73 +17,73 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - internal static partial class GroupOperations - { - /* + internal static partial class GroupOperations + { + /* r = p - q */ - public static void ge_sub(out GroupElementP1P1 r, ref GroupElementP3 p, ref GroupElementCached q) - { - FieldElement t0; - - /* qhasm: YpX1 = Y1+X1 */ - /* asm 1: fe_add(>YpX1=fe#1,YpX1=r.X,YmX1=fe#2,YmX1=r.Y,A=fe#3,A=r.Z,B=fe#2,B=r.Y,C=fe#4,C=r.T,ZZ=fe#1,ZZ=r.X,D=fe#5,D=t0,X3=fe#1,X3=r.X,Y3=fe#2,Y3=r.Y,Z3=fe#3,Z3=r.Z,T3=fe#4,T3=r.T,YpX1=fe#1,YpX1=r.X,YmX1=fe#2,YmX1=r.Y,A=fe#3,A=r.Z,B=fe#2,B=r.Y,C=fe#4,C=r.T,ZZ=fe#1,ZZ=r.X,D=fe#5,D=t0,X3=fe#1,X3=r.X,Y3=fe#2,Y3=r.Y,Z3=fe#3,Z3=r.Z,T3=fe#4,T3=r.T,> 5); + long a2 = 2097151 & (load_3(a, 5) >> 2); + long a3 = 2097151 & (load_4(a, 7) >> 7); + long a4 = 2097151 & (load_4(a, 10) >> 4); + long a5 = 2097151 & (load_3(a, 13) >> 1); + long a6 = 2097151 & (load_4(a, 15) >> 6); + long a7 = 2097151 & (load_3(a, 18) >> 3); + long a8 = 2097151 & load_3(a, 21); + long a9 = 2097151 & (load_4(a, 23) >> 5); + long a10 = 2097151 & (load_3(a, 26) >> 2); + long a11 = (load_4(a, 28) >> 7); + long b0 = 2097151 & load_3(b, 0); + long b1 = 2097151 & (load_4(b, 2) >> 5); + long b2 = 2097151 & (load_3(b, 5) >> 2); + long b3 = 2097151 & (load_4(b, 7) >> 7); + long b4 = 2097151 & (load_4(b, 10) >> 4); + long b5 = 2097151 & (load_3(b, 13) >> 1); + long b6 = 2097151 & (load_4(b, 15) >> 6); + long b7 = 2097151 & (load_3(b, 18) >> 3); + long b8 = 2097151 & load_3(b, 21); + long b9 = 2097151 & (load_4(b, 23) >> 5); + long b10 = 2097151 & (load_3(b, 26) >> 2); + long b11 = (load_4(b, 28) >> 7); + long c0 = 2097151 & load_3(c, 0); + long c1 = 2097151 & (load_4(c, 2) >> 5); + long c2 = 2097151 & (load_3(c, 5) >> 2); + long c3 = 2097151 & (load_4(c, 7) >> 7); + long c4 = 2097151 & (load_4(c, 10) >> 4); + long c5 = 2097151 & (load_3(c, 13) >> 1); + long c6 = 2097151 & (load_4(c, 15) >> 6); + long c7 = 2097151 & (load_3(c, 18) >> 3); + long c8 = 2097151 & load_3(c, 21); + long c9 = 2097151 & (load_4(c, 23) >> 5); + long c10 = 2097151 & (load_3(c, 26) >> 2); + long c11 = (load_4(c, 28) >> 7); +After: + var a0 = 2097151 & load_3(a, 0); + var a1 = 2097151 & (load_4(a, 2) >> 5); + var a2 = 2097151 & (load_3(a, 5) >> 2); + var a3 = 2097151 & (load_4(a, 7) >> 7); + var a4 = 2097151 & (load_4(a, 10) >> 4); + var a5 = 2097151 & (load_3(a, 13) >> 1); + var a6 = 2097151 & (load_4(a, 15) >> 6); + var a7 = 2097151 & (load_3(a, 18) >> 3); + var a8 = 2097151 & load_3(a, 21); + var a9 = 2097151 & (load_4(a, 23) >> 5); + var a10 = 2097151 & (load_3(a, 26) >> 2); + var a11 = (load_4(a, 28) >> 7); + var b0 = 2097151 & load_3(b, 0); + var b1 = 2097151 & (load_4(b, 2) >> 5); + var b2 = 2097151 & (load_3(b, 5) >> 2); + var b3 = 2097151 & (load_4(b, 7) >> 7); + var b4 = 2097151 & (load_4(b, 10) >> 4); + var b5 = 2097151 & (load_3(b, 13) >> 1); + var b6 = 2097151 & (load_4(b, 15) >> 6); + var b7 = 2097151 & (load_3(b, 18) >> 3); + var b8 = 2097151 & load_3(b, 21); + var b9 = 2097151 & (load_4(b, 23) >> 5); + var b10 = 2097151 & (load_3(b, 26) >> 2); + var b11 = (load_4(b, 28) >> 7); + var c0 = 2097151 & load_3(c, 0); + var c1 = 2097151 & (load_4(c, 2) >> 5); + var c2 = 2097151 & (load_3(c, 5) >> 2); + var c3 = 2097151 & (load_4(c, 7) >> 7); + var c4 = 2097151 & (load_4(c, 10) >> 4); + var c5 = 2097151 & (load_3(c, 13) >> 1); + var c6 = 2097151 & (load_4(c, 15) >> 6); + var c7 = 2097151 & (load_3(c, 18) >> 3); + var c8 = 2097151 & load_3(c, 21); + var c9 = 2097151 & (load_4(c, 23) >> 5); + var c10 = 2097151 & (load_3(c, 26) >> 2); + var c11 = (load_4(c, 28) >> 7); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + long a0 = 2097151 & load_3(a, 0); + long a1 = 2097151 & (load_4(a, 2) >> 5); + long a2 = 2097151 & (load_3(a, 5) >> 2); + long a3 = 2097151 & (load_4(a, 7) >> 7); + long a4 = 2097151 & (load_4(a, 10) >> 4); + long a5 = 2097151 & (load_3(a, 13) >> 1); + long a6 = 2097151 & (load_4(a, 15) >> 6); + long a7 = 2097151 & (load_3(a, 18) >> 3); + long a8 = 2097151 & load_3(a, 21); + long a9 = 2097151 & (load_4(a, 23) >> 5); + long a10 = 2097151 & (load_3(a, 26) >> 2); + long a11 = (load_4(a, 28) >> 7); + long b0 = 2097151 & load_3(b, 0); + long b1 = 2097151 & (load_4(b, 2) >> 5); + long b2 = 2097151 & (load_3(b, 5) >> 2); + long b3 = 2097151 & (load_4(b, 7) >> 7); + long b4 = 2097151 & (load_4(b, 10) >> 4); + long b5 = 2097151 & (load_3(b, 13) >> 1); + long b6 = 2097151 & (load_4(b, 15) >> 6); + long b7 = 2097151 & (load_3(b, 18) >> 3); + long b8 = 2097151 & load_3(b, 21); + long b9 = 2097151 & (load_4(b, 23) >> 5); + long b10 = 2097151 & (load_3(b, 26) >> 2); + long b11 = (load_4(b, 28) >> 7); + long c0 = 2097151 & load_3(c, 0); + long c1 = 2097151 & (load_4(c, 2) >> 5); + long c2 = 2097151 & (load_3(c, 5) >> 2); + long c3 = 2097151 & (load_4(c, 7) >> 7); + long c4 = 2097151 & (load_4(c, 10) >> 4); + long c5 = 2097151 & (load_3(c, 13) >> 1); + long c6 = 2097151 & (load_4(c, 15) >> 6); + long c7 = 2097151 & (load_3(c, 18) >> 3); + long c8 = 2097151 & load_3(c, 21); + long c9 = 2097151 & (load_4(c, 23) >> 5); + long c10 = 2097151 & (load_3(c, 26) >> 2); + long c11 = (load_4(c, 28) >> 7); +After: + var a0 = 2097151 & load_3(a, 0); + var a1 = 2097151 & (load_4(a, 2) >> 5); + var a2 = 2097151 & (load_3(a, 5) >> 2); + var a3 = 2097151 & (load_4(a, 7) >> 7); + var a4 = 2097151 & (load_4(a, 10) >> 4); + var a5 = 2097151 & (load_3(a, 13) >> 1); + var a6 = 2097151 & (load_4(a, 15) >> 6); + var a7 = 2097151 & (load_3(a, 18) >> 3); + var a8 = 2097151 & load_3(a, 21); + var a9 = 2097151 & (load_4(a, 23) >> 5); + var a10 = 2097151 & (load_3(a, 26) >> 2); + var a11 = (load_4(a, 28) >> 7); + var b0 = 2097151 & load_3(b, 0); + var b1 = 2097151 & (load_4(b, 2) >> 5); + var b2 = 2097151 & (load_3(b, 5) >> 2); + var b3 = 2097151 & (load_4(b, 7) >> 7); + var b4 = 2097151 & (load_4(b, 10) >> 4); + var b5 = 2097151 & (load_3(b, 13) >> 1); + var b6 = 2097151 & (load_4(b, 15) >> 6); + var b7 = 2097151 & (load_3(b, 18) >> 3); + var b8 = 2097151 & load_3(b, 21); + var b9 = 2097151 & (load_4(b, 23) >> 5); + var b10 = 2097151 & (load_3(b, 26) >> 2); + var b11 = (load_4(b, 28) >> 7); + var c0 = 2097151 & load_3(c, 0); + var c1 = 2097151 & (load_4(c, 2) >> 5); + var c2 = 2097151 & (load_3(c, 5) >> 2); + var c3 = 2097151 & (load_4(c, 7) >> 7); + var c4 = 2097151 & (load_4(c, 10) >> 4); + var c5 = 2097151 & (load_3(c, 13) >> 1); + var c6 = 2097151 & (load_4(c, 15) >> 6); + var c7 = 2097151 & (load_3(c, 18) >> 3); + var c8 = 2097151 & load_3(c, 21); + var c9 = 2097151 & (load_4(c, 23) >> 5); + var c10 = 2097151 & (load_3(c, 26) >> 2); + var c11 = (load_4(c, 28) >> 7); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: long a0 = 2097151 & load_3(a, 0); long a1 = 2097151 & (load_4(a, 2) >> 5); long a2 = 2097151 & (load_3(a, 5) >> 2); @@ -87,6 +242,82 @@ public static void sc_muladd(byte[] s, byte[] a, byte[] b, byte[] c) long c9 = 2097151 & (load_4(c, 23) >> 5); long c10 = 2097151 & (load_3(c, 26) >> 2); long c11 = (load_4(c, 28) >> 7); +After: + var a0 = 2097151 & load_3(a, 0); + var a1 = 2097151 & (load_4(a, 2) >> 5); + var a2 = 2097151 & (load_3(a, 5) >> 2); + var a3 = 2097151 & (load_4(a, 7) >> 7); + var a4 = 2097151 & (load_4(a, 10) >> 4); + var a5 = 2097151 & (load_3(a, 13) >> 1); + var a6 = 2097151 & (load_4(a, 15) >> 6); + var a7 = 2097151 & (load_3(a, 18) >> 3); + var a8 = 2097151 & load_3(a, 21); + var a9 = 2097151 & (load_4(a, 23) >> 5); + var a10 = 2097151 & (load_3(a, 26) >> 2); + var a11 = (load_4(a, 28) >> 7); + var b0 = 2097151 & load_3(b, 0); + var b1 = 2097151 & (load_4(b, 2) >> 5); + var b2 = 2097151 & (load_3(b, 5) >> 2); + var b3 = 2097151 & (load_4(b, 7) >> 7); + var b4 = 2097151 & (load_4(b, 10) >> 4); + var b5 = 2097151 & (load_3(b, 13) >> 1); + var b6 = 2097151 & (load_4(b, 15) >> 6); + var b7 = 2097151 & (load_3(b, 18) >> 3); + var b8 = 2097151 & load_3(b, 21); + var b9 = 2097151 & (load_4(b, 23) >> 5); + var b10 = 2097151 & (load_3(b, 26) >> 2); + var b11 = (load_4(b, 28) >> 7); + var c0 = 2097151 & load_3(c, 0); + var c1 = 2097151 & (load_4(c, 2) >> 5); + var c2 = 2097151 & (load_3(c, 5) >> 2); + var c3 = 2097151 & (load_4(c, 7) >> 7); + var c4 = 2097151 & (load_4(c, 10) >> 4); + var c5 = 2097151 & (load_3(c, 13) >> 1); + var c6 = 2097151 & (load_4(c, 15) >> 6); + var c7 = 2097151 & (load_3(c, 18) >> 3); + var c8 = 2097151 & load_3(c, 21); + var c9 = 2097151 & (load_4(c, 23) >> 5); + var c10 = 2097151 & (load_3(c, 26) >> 2); + var c11 = (load_4(c, 28) >> 7); +*/ + + { + var a0 = 2097151 & load_3(a, 0); + var a1 = 2097151 & (load_4(a, 2) >> 5); + var a2 = 2097151 & (load_3(a, 5) >> 2); + var a3 = 2097151 & (load_4(a, 7) >> 7); + var a4 = 2097151 & (load_4(a, 10) >> 4); + var a5 = 2097151 & (load_3(a, 13) >> 1); + var a6 = 2097151 & (load_4(a, 15) >> 6); + var a7 = 2097151 & (load_3(a, 18) >> 3); + var a8 = 2097151 & load_3(a, 21); + var a9 = 2097151 & (load_4(a, 23) >> 5); + var a10 = 2097151 & (load_3(a, 26) >> 2); + var a11 = (load_4(a, 28) >> 7); + var b0 = 2097151 & load_3(b, 0); + var b1 = 2097151 & (load_4(b, 2) >> 5); + var b2 = 2097151 & (load_3(b, 5) >> 2); + var b3 = 2097151 & (load_4(b, 7) >> 7); + var b4 = 2097151 & (load_4(b, 10) >> 4); + var b5 = 2097151 & (load_3(b, 13) >> 1); + var b6 = 2097151 & (load_4(b, 15) >> 6); + var b7 = 2097151 & (load_3(b, 18) >> 3); + var b8 = 2097151 & load_3(b, 21); + var b9 = 2097151 & (load_4(b, 23) >> 5); + var b10 = 2097151 & (load_3(b, 26) >> 2); + var b11 = (load_4(b, 28) >> 7); + var c0 = 2097151 & load_3(c, 0); + var c1 = 2097151 & (load_4(c, 2) >> 5); + var c2 = 2097151 & (load_3(c, 5) >> 2); + var c3 = 2097151 & (load_4(c, 7) >> 7); + var c4 = 2097151 & (load_4(c, 10) >> 4); + var c5 = 2097151 & (load_3(c, 13) >> 1); + var c6 = 2097151 & (load_4(c, 15) >> 6); + var c7 = 2097151 & (load_3(c, 18) >> 3); + var c8 = 2097151 & load_3(c, 21); + var c9 = 2097151 & (load_4(c, 23) >> 5); + var c10 = 2097151 & (load_3(c, 26) >> 2); + var c11 = (load_4(c, 28) >> 7); long s0; long s1; long s2; @@ -160,30 +391,76 @@ public static void sc_muladd(byte[] s, byte[] a, byte[] b, byte[] c) s22 = a11 * b11; s23 = 0; - carry0 = (s0 + (1 << 20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1 << 20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1 << 20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1 << 20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1 << 20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - carry12 = (s12 + (1 << 20)) >> 21; s13 += carry12; s12 -= carry12 << 21; - carry14 = (s14 + (1 << 20)) >> 21; s15 += carry14; s14 -= carry14 << 21; - carry16 = (s16 + (1 << 20)) >> 21; s17 += carry16; s16 -= carry16 << 21; - carry18 = (s18 + (1 << 20)) >> 21; s19 += carry18; s18 -= carry18 << 21; - carry20 = (s20 + (1 << 20)) >> 21; s21 += carry20; s20 -= carry20 << 21; - carry22 = (s22 + (1 << 20)) >> 21; s23 += carry22; s22 -= carry22 << 21; - - carry1 = (s1 + (1 << 20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1 << 20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1 << 20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1 << 20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1 << 20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1 << 20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - carry13 = (s13 + (1 << 20)) >> 21; s14 += carry13; s13 -= carry13 << 21; - carry15 = (s15 + (1 << 20)) >> 21; s16 += carry15; s15 -= carry15 << 21; - carry17 = (s17 + (1 << 20)) >> 21; s18 += carry17; s17 -= carry17 << 21; - carry19 = (s19 + (1 << 20)) >> 21; s20 += carry19; s19 -= carry19 << 21; - carry21 = (s21 + (1 << 20)) >> 21; s22 += carry21; s21 -= carry21 << 21; + carry0 = (s0 + (1 << 20)) >> 21; + s1 += carry0; + s0 -= carry0 << 21; + carry2 = (s2 + (1 << 20)) >> 21; + s3 += carry2; + s2 -= carry2 << 21; + carry4 = (s4 + (1 << 20)) >> 21; + s5 += carry4; + s4 -= carry4 << 21; + carry6 = (s6 + (1 << 20)) >> 21; + s7 += carry6; + s6 -= carry6 << 21; + carry8 = (s8 + (1 << 20)) >> 21; + s9 += carry8; + s8 -= carry8 << 21; + carry10 = (s10 + (1 << 20)) >> 21; + s11 += carry10; + s10 -= carry10 << 21; + carry12 = (s12 + (1 << 20)) >> 21; + s13 += carry12; + s12 -= carry12 << 21; + carry14 = (s14 + (1 << 20)) >> 21; + s15 += carry14; + s14 -= carry14 << 21; + carry16 = (s16 + (1 << 20)) >> 21; + s17 += carry16; + s16 -= carry16 << 21; + carry18 = (s18 + (1 << 20)) >> 21; + s19 += carry18; + s18 -= carry18 << 21; + carry20 = (s20 + (1 << 20)) >> 21; + s21 += carry20; + s20 -= carry20 << 21; + carry22 = (s22 + (1 << 20)) >> 21; + s23 += carry22; + s22 -= carry22 << 21; + + carry1 = (s1 + (1 << 20)) >> 21; + s2 += carry1; + s1 -= carry1 << 21; + carry3 = (s3 + (1 << 20)) >> 21; + s4 += carry3; + s3 -= carry3 << 21; + carry5 = (s5 + (1 << 20)) >> 21; + s6 += carry5; + s5 -= carry5 << 21; + carry7 = (s7 + (1 << 20)) >> 21; + s8 += carry7; + s7 -= carry7 << 21; + carry9 = (s9 + (1 << 20)) >> 21; + s10 += carry9; + s9 -= carry9 << 21; + carry11 = (s11 + (1 << 20)) >> 21; + s12 += carry11; + s11 -= carry11 << 21; + carry13 = (s13 + (1 << 20)) >> 21; + s14 += carry13; + s13 -= carry13 << 21; + carry15 = (s15 + (1 << 20)) >> 21; + s16 += carry15; + s15 -= carry15 << 21; + carry17 = (s17 + (1 << 20)) >> 21; + s18 += carry17; + s17 -= carry17 << 21; + carry19 = (s19 + (1 << 20)) >> 21; + s20 += carry19; + s19 -= carry19 << 21; + carry21 = (s21 + (1 << 20)) >> 21; + s22 += carry21; + s21 -= carry21 << 21; s11 += s23 * 666643; s12 += s23 * 470296; @@ -233,18 +510,40 @@ public static void sc_muladd(byte[] s, byte[] a, byte[] b, byte[] c) s11 -= s18 * 683901; s18 = 0; - carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1 << 20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1 << 20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - carry12 = (s12 + (1 << 20)) >> 21; s13 += carry12; s12 -= carry12 << 21; - carry14 = (s14 + (1 << 20)) >> 21; s15 += carry14; s14 -= carry14 << 21; - carry16 = (s16 + (1 << 20)) >> 21; s17 += carry16; s16 -= carry16 << 21; + carry6 = (s6 + (1 << 20)) >> 21; + s7 += carry6; + s6 -= carry6 << 21; + carry8 = (s8 + (1 << 20)) >> 21; + s9 += carry8; + s8 -= carry8 << 21; + carry10 = (s10 + (1 << 20)) >> 21; + s11 += carry10; + s10 -= carry10 << 21; + carry12 = (s12 + (1 << 20)) >> 21; + s13 += carry12; + s12 -= carry12 << 21; + carry14 = (s14 + (1 << 20)) >> 21; + s15 += carry14; + s14 -= carry14 << 21; + carry16 = (s16 + (1 << 20)) >> 21; + s17 += carry16; + s16 -= carry16 << 21; - carry7 = (s7 + (1 << 20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1 << 20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1 << 20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - carry13 = (s13 + (1 << 20)) >> 21; s14 += carry13; s13 -= carry13 << 21; - carry15 = (s15 + (1 << 20)) >> 21; s16 += carry15; s15 -= carry15 << 21; + carry7 = (s7 + (1 << 20)) >> 21; + s8 += carry7; + s7 -= carry7 << 21; + carry9 = (s9 + (1 << 20)) >> 21; + s10 += carry9; + s9 -= carry9 << 21; + carry11 = (s11 + (1 << 20)) >> 21; + s12 += carry11; + s11 -= carry11 << 21; + carry13 = (s13 + (1 << 20)) >> 21; + s14 += carry13; + s13 -= carry13 << 21; + carry15 = (s15 + (1 << 20)) >> 21; + s16 += carry15; + s15 -= carry15 << 21; s5 += s17 * 666643; s6 += s17 * 470296; @@ -294,19 +593,43 @@ public static void sc_muladd(byte[] s, byte[] a, byte[] b, byte[] c) s5 -= s12 * 683901; s12 = 0; - carry0 = (s0 + (1 << 20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1 << 20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1 << 20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1 << 20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1 << 20)) >> 21; s11 += carry10; s10 -= carry10 << 21; + carry0 = (s0 + (1 << 20)) >> 21; + s1 += carry0; + s0 -= carry0 << 21; + carry2 = (s2 + (1 << 20)) >> 21; + s3 += carry2; + s2 -= carry2 << 21; + carry4 = (s4 + (1 << 20)) >> 21; + s5 += carry4; + s4 -= carry4 << 21; + carry6 = (s6 + (1 << 20)) >> 21; + s7 += carry6; + s6 -= carry6 << 21; + carry8 = (s8 + (1 << 20)) >> 21; + s9 += carry8; + s8 -= carry8 << 21; + carry10 = (s10 + (1 << 20)) >> 21; + s11 += carry10; + s10 -= carry10 << 21; - carry1 = (s1 + (1 << 20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1 << 20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1 << 20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1 << 20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1 << 20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1 << 20)) >> 21; s12 += carry11; s11 -= carry11 << 21; + carry1 = (s1 + (1 << 20)) >> 21; + s2 += carry1; + s1 -= carry1 << 21; + carry3 = (s3 + (1 << 20)) >> 21; + s4 += carry3; + s3 -= carry3 << 21; + carry5 = (s5 + (1 << 20)) >> 21; + s6 += carry5; + s5 -= carry5 << 21; + carry7 = (s7 + (1 << 20)) >> 21; + s8 += carry7; + s7 -= carry7 << 21; + carry9 = (s9 + (1 << 20)) >> 21; + s10 += carry9; + s9 -= carry9 << 21; + carry11 = (s11 + (1 << 20)) >> 21; + s12 += carry11; + s11 -= carry11 << 21; s0 += s12 * 666643; s1 += s12 * 470296; @@ -316,18 +639,42 @@ public static void sc_muladd(byte[] s, byte[] a, byte[] b, byte[] c) s5 -= s12 * 683901; s12 = 0; - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; + carry0 = s0 >> 21; + s1 += carry0; + s0 -= carry0 << 21; + carry1 = s1 >> 21; + s2 += carry1; + s1 -= carry1 << 21; + carry2 = s2 >> 21; + s3 += carry2; + s2 -= carry2 << 21; + carry3 = s3 >> 21; + s4 += carry3; + s3 -= carry3 << 21; + carry4 = s4 >> 21; + s5 += carry4; + s4 -= carry4 << 21; + carry5 = s5 >> 21; + s6 += carry5; + s5 -= carry5 << 21; + carry6 = s6 >> 21; + s7 += carry6; + s6 -= carry6 << 21; + carry7 = s7 >> 21; + s8 += carry7; + s7 -= carry7 << 21; + carry8 = s8 >> 21; + s9 += carry8; + s8 -= carry8 << 21; + carry9 = s9 >> 21; + s10 += carry9; + s9 -= carry9 << 21; + carry10 = s10 >> 21; + s11 += carry10; + s10 -= carry10 << 21; + carry11 = s11 >> 21; + s12 += carry11; + s11 -= carry11 << 21; s0 += s12 * 666643; s1 += s12 * 470296; @@ -337,17 +684,39 @@ public static void sc_muladd(byte[] s, byte[] a, byte[] b, byte[] c) s5 -= s12 * 683901; s12 = 0; - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; + carry0 = s0 >> 21; + s1 += carry0; + s0 -= carry0 << 21; + carry1 = s1 >> 21; + s2 += carry1; + s1 -= carry1 << 21; + carry2 = s2 >> 21; + s3 += carry2; + s2 -= carry2 << 21; + carry3 = s3 >> 21; + s4 += carry3; + s3 -= carry3 << 21; + carry4 = s4 >> 21; + s5 += carry4; + s4 -= carry4 << 21; + carry5 = s5 >> 21; + s6 += carry5; + s5 -= carry5 << 21; + carry6 = s6 >> 21; + s7 += carry6; + s6 -= carry6 << 21; + carry7 = s7 >> 21; + s8 += carry7; + s7 -= carry7 << 21; + carry8 = s8 >> 21; + s9 += carry8; + s8 -= carry8 << 21; + carry9 = s9 >> 21; + s10 += carry9; + s9 -= carry9 << 21; + carry10 = s10 >> 21; + s11 += carry10; + s10 -= carry10 << 21; unchecked { @@ -386,4 +755,4 @@ public static void sc_muladd(byte[] s, byte[] a, byte[] b, byte[] c) } } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/sc_reduce.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/sc_reduce.cs index 0db3000d..b2c306cf 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/sc_reduce.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/sc_reduce.cs @@ -30,7 +30,8 @@ Overwrites s in place. */ public static void sc_reduce(byte[] s) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: long s0 = 2097151 & load_3(s, 0); long s1 = 2097151 & (load_4(s, 2) >> 5); long s2 = 2097151 & (load_3(s, 5) >> 2); @@ -55,6 +56,164 @@ public static void sc_reduce(byte[] s) long s21 = 2097151 & (load_3(s, 55) >> 1); long s22 = 2097151 & (load_4(s, 57) >> 6); long s23 = (load_4(s, 60) >> 3); +After: + var s0 = 2097151 & load_3(s, 0); + var s1 = 2097151 & (load_4(s, 2) >> 5); + var s2 = 2097151 & (load_3(s, 5) >> 2); + var s3 = 2097151 & (load_4(s, 7) >> 7); + var s4 = 2097151 & (load_4(s, 10) >> 4); + var s5 = 2097151 & (load_3(s, 13) >> 1); + var s6 = 2097151 & (load_4(s, 15) >> 6); + var s7 = 2097151 & (load_3(s, 18) >> 3); + var s8 = 2097151 & load_3(s, 21); + var s9 = 2097151 & (load_4(s, 23) >> 5); + var s10 = 2097151 & (load_3(s, 26) >> 2); + var s11 = 2097151 & (load_4(s, 28) >> 7); + var s12 = 2097151 & (load_4(s, 31) >> 4); + var s13 = 2097151 & (load_3(s, 34) >> 1); + var s14 = 2097151 & (load_4(s, 36) >> 6); + var s15 = 2097151 & (load_3(s, 39) >> 3); + var s16 = 2097151 & load_3(s, 42); + var s17 = 2097151 & (load_4(s, 44) >> 5); + var s18 = 2097151 & (load_3(s, 47) >> 2); + var s19 = 2097151 & (load_4(s, 49) >> 7); + var s20 = 2097151 & (load_4(s, 52) >> 4); + var s21 = 2097151 & (load_3(s, 55) >> 1); + var s22 = 2097151 & (load_4(s, 57) >> 6); + var s23 = (load_4(s, 60) >> 3); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + long s0 = 2097151 & load_3(s, 0); + long s1 = 2097151 & (load_4(s, 2) >> 5); + long s2 = 2097151 & (load_3(s, 5) >> 2); + long s3 = 2097151 & (load_4(s, 7) >> 7); + long s4 = 2097151 & (load_4(s, 10) >> 4); + long s5 = 2097151 & (load_3(s, 13) >> 1); + long s6 = 2097151 & (load_4(s, 15) >> 6); + long s7 = 2097151 & (load_3(s, 18) >> 3); + long s8 = 2097151 & load_3(s, 21); + long s9 = 2097151 & (load_4(s, 23) >> 5); + long s10 = 2097151 & (load_3(s, 26) >> 2); + long s11 = 2097151 & (load_4(s, 28) >> 7); + long s12 = 2097151 & (load_4(s, 31) >> 4); + long s13 = 2097151 & (load_3(s, 34) >> 1); + long s14 = 2097151 & (load_4(s, 36) >> 6); + long s15 = 2097151 & (load_3(s, 39) >> 3); + long s16 = 2097151 & load_3(s, 42); + long s17 = 2097151 & (load_4(s, 44) >> 5); + long s18 = 2097151 & (load_3(s, 47) >> 2); + long s19 = 2097151 & (load_4(s, 49) >> 7); + long s20 = 2097151 & (load_4(s, 52) >> 4); + long s21 = 2097151 & (load_3(s, 55) >> 1); + long s22 = 2097151 & (load_4(s, 57) >> 6); + long s23 = (load_4(s, 60) >> 3); +After: + var s0 = 2097151 & load_3(s, 0); + var s1 = 2097151 & (load_4(s, 2) >> 5); + var s2 = 2097151 & (load_3(s, 5) >> 2); + var s3 = 2097151 & (load_4(s, 7) >> 7); + var s4 = 2097151 & (load_4(s, 10) >> 4); + var s5 = 2097151 & (load_3(s, 13) >> 1); + var s6 = 2097151 & (load_4(s, 15) >> 6); + var s7 = 2097151 & (load_3(s, 18) >> 3); + var s8 = 2097151 & load_3(s, 21); + var s9 = 2097151 & (load_4(s, 23) >> 5); + var s10 = 2097151 & (load_3(s, 26) >> 2); + var s11 = 2097151 & (load_4(s, 28) >> 7); + var s12 = 2097151 & (load_4(s, 31) >> 4); + var s13 = 2097151 & (load_3(s, 34) >> 1); + var s14 = 2097151 & (load_4(s, 36) >> 6); + var s15 = 2097151 & (load_3(s, 39) >> 3); + var s16 = 2097151 & load_3(s, 42); + var s17 = 2097151 & (load_4(s, 44) >> 5); + var s18 = 2097151 & (load_3(s, 47) >> 2); + var s19 = 2097151 & (load_4(s, 49) >> 7); + var s20 = 2097151 & (load_4(s, 52) >> 4); + var s21 = 2097151 & (load_3(s, 55) >> 1); + var s22 = 2097151 & (load_4(s, 57) >> 6); + var s23 = (load_4(s, 60) >> 3); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + long s0 = 2097151 & load_3(s, 0); + long s1 = 2097151 & (load_4(s, 2) >> 5); + long s2 = 2097151 & (load_3(s, 5) >> 2); + long s3 = 2097151 & (load_4(s, 7) >> 7); + long s4 = 2097151 & (load_4(s, 10) >> 4); + long s5 = 2097151 & (load_3(s, 13) >> 1); + long s6 = 2097151 & (load_4(s, 15) >> 6); + long s7 = 2097151 & (load_3(s, 18) >> 3); + long s8 = 2097151 & load_3(s, 21); + long s9 = 2097151 & (load_4(s, 23) >> 5); + long s10 = 2097151 & (load_3(s, 26) >> 2); + long s11 = 2097151 & (load_4(s, 28) >> 7); + long s12 = 2097151 & (load_4(s, 31) >> 4); + long s13 = 2097151 & (load_3(s, 34) >> 1); + long s14 = 2097151 & (load_4(s, 36) >> 6); + long s15 = 2097151 & (load_3(s, 39) >> 3); + long s16 = 2097151 & load_3(s, 42); + long s17 = 2097151 & (load_4(s, 44) >> 5); + long s18 = 2097151 & (load_3(s, 47) >> 2); + long s19 = 2097151 & (load_4(s, 49) >> 7); + long s20 = 2097151 & (load_4(s, 52) >> 4); + long s21 = 2097151 & (load_3(s, 55) >> 1); + long s22 = 2097151 & (load_4(s, 57) >> 6); + long s23 = (load_4(s, 60) >> 3); +After: + var s0 = 2097151 & load_3(s, 0); + var s1 = 2097151 & (load_4(s, 2) >> 5); + var s2 = 2097151 & (load_3(s, 5) >> 2); + var s3 = 2097151 & (load_4(s, 7) >> 7); + var s4 = 2097151 & (load_4(s, 10) >> 4); + var s5 = 2097151 & (load_3(s, 13) >> 1); + var s6 = 2097151 & (load_4(s, 15) >> 6); + var s7 = 2097151 & (load_3(s, 18) >> 3); + var s8 = 2097151 & load_3(s, 21); + var s9 = 2097151 & (load_4(s, 23) >> 5); + var s10 = 2097151 & (load_3(s, 26) >> 2); + var s11 = 2097151 & (load_4(s, 28) >> 7); + var s12 = 2097151 & (load_4(s, 31) >> 4); + var s13 = 2097151 & (load_3(s, 34) >> 1); + var s14 = 2097151 & (load_4(s, 36) >> 6); + var s15 = 2097151 & (load_3(s, 39) >> 3); + var s16 = 2097151 & load_3(s, 42); + var s17 = 2097151 & (load_4(s, 44) >> 5); + var s18 = 2097151 & (load_3(s, 47) >> 2); + var s19 = 2097151 & (load_4(s, 49) >> 7); + var s20 = 2097151 & (load_4(s, 52) >> 4); + var s21 = 2097151 & (load_3(s, 55) >> 1); + var s22 = 2097151 & (load_4(s, 57) >> 6); + var s23 = (load_4(s, 60) >> 3); +*/ + + { + var s0 = 2097151 & load_3(s, 0); + var s1 = 2097151 & (load_4(s, 2) >> 5); + var s2 = 2097151 & (load_3(s, 5) >> 2); + var s3 = 2097151 & (load_4(s, 7) >> 7); + var s4 = 2097151 & (load_4(s, 10) >> 4); + var s5 = 2097151 & (load_3(s, 13) >> 1); + var s6 = 2097151 & (load_4(s, 15) >> 6); + var s7 = 2097151 & (load_3(s, 18) >> 3); + var s8 = 2097151 & load_3(s, 21); + var s9 = 2097151 & (load_4(s, 23) >> 5); + var s10 = 2097151 & (load_3(s, 26) >> 2); + var s11 = 2097151 & (load_4(s, 28) >> 7); + var s12 = 2097151 & (load_4(s, 31) >> 4); + var s13 = 2097151 & (load_3(s, 34) >> 1); + var s14 = 2097151 & (load_4(s, 36) >> 6); + var s15 = 2097151 & (load_3(s, 39) >> 3); + var s16 = 2097151 & load_3(s, 42); + var s17 = 2097151 & (load_4(s, 44) >> 5); + var s18 = 2097151 & (load_3(s, 47) >> 2); + var s19 = 2097151 & (load_4(s, 49) >> 7); + var s20 = 2097151 & (load_4(s, 52) >> 4); + var s21 = 2097151 & (load_3(s, 55) >> 1); + var s22 = 2097151 & (load_4(s, 57) >> 6); + var s23 = (load_4(s, 60) >> 3); long carry0; long carry1; @@ -122,18 +281,40 @@ public static void sc_reduce(byte[] s) s11 -= s18 * 683901; s18 = 0; - carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1 << 20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1 << 20)) >> 21; s11 += carry10; s10 -= carry10 << 21; - carry12 = (s12 + (1 << 20)) >> 21; s13 += carry12; s12 -= carry12 << 21; - carry14 = (s14 + (1 << 20)) >> 21; s15 += carry14; s14 -= carry14 << 21; - carry16 = (s16 + (1 << 20)) >> 21; s17 += carry16; s16 -= carry16 << 21; + carry6 = (s6 + (1 << 20)) >> 21; + s7 += carry6; + s6 -= carry6 << 21; + carry8 = (s8 + (1 << 20)) >> 21; + s9 += carry8; + s8 -= carry8 << 21; + carry10 = (s10 + (1 << 20)) >> 21; + s11 += carry10; + s10 -= carry10 << 21; + carry12 = (s12 + (1 << 20)) >> 21; + s13 += carry12; + s12 -= carry12 << 21; + carry14 = (s14 + (1 << 20)) >> 21; + s15 += carry14; + s14 -= carry14 << 21; + carry16 = (s16 + (1 << 20)) >> 21; + s17 += carry16; + s16 -= carry16 << 21; - carry7 = (s7 + (1 << 20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1 << 20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1 << 20)) >> 21; s12 += carry11; s11 -= carry11 << 21; - carry13 = (s13 + (1 << 20)) >> 21; s14 += carry13; s13 -= carry13 << 21; - carry15 = (s15 + (1 << 20)) >> 21; s16 += carry15; s15 -= carry15 << 21; + carry7 = (s7 + (1 << 20)) >> 21; + s8 += carry7; + s7 -= carry7 << 21; + carry9 = (s9 + (1 << 20)) >> 21; + s10 += carry9; + s9 -= carry9 << 21; + carry11 = (s11 + (1 << 20)) >> 21; + s12 += carry11; + s11 -= carry11 << 21; + carry13 = (s13 + (1 << 20)) >> 21; + s14 += carry13; + s13 -= carry13 << 21; + carry15 = (s15 + (1 << 20)) >> 21; + s16 += carry15; + s15 -= carry15 << 21; s5 += s17 * 666643; s6 += s17 * 470296; @@ -183,19 +364,43 @@ public static void sc_reduce(byte[] s) s5 -= s12 * 683901; s12 = 0; - carry0 = (s0 + (1 << 20)) >> 21; s1 += carry0; s0 -= carry0 << 21; - carry2 = (s2 + (1 << 20)) >> 21; s3 += carry2; s2 -= carry2 << 21; - carry4 = (s4 + (1 << 20)) >> 21; s5 += carry4; s4 -= carry4 << 21; - carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21; - carry8 = (s8 + (1 << 20)) >> 21; s9 += carry8; s8 -= carry8 << 21; - carry10 = (s10 + (1 << 20)) >> 21; s11 += carry10; s10 -= carry10 << 21; + carry0 = (s0 + (1 << 20)) >> 21; + s1 += carry0; + s0 -= carry0 << 21; + carry2 = (s2 + (1 << 20)) >> 21; + s3 += carry2; + s2 -= carry2 << 21; + carry4 = (s4 + (1 << 20)) >> 21; + s5 += carry4; + s4 -= carry4 << 21; + carry6 = (s6 + (1 << 20)) >> 21; + s7 += carry6; + s6 -= carry6 << 21; + carry8 = (s8 + (1 << 20)) >> 21; + s9 += carry8; + s8 -= carry8 << 21; + carry10 = (s10 + (1 << 20)) >> 21; + s11 += carry10; + s10 -= carry10 << 21; - carry1 = (s1 + (1 << 20)) >> 21; s2 += carry1; s1 -= carry1 << 21; - carry3 = (s3 + (1 << 20)) >> 21; s4 += carry3; s3 -= carry3 << 21; - carry5 = (s5 + (1 << 20)) >> 21; s6 += carry5; s5 -= carry5 << 21; - carry7 = (s7 + (1 << 20)) >> 21; s8 += carry7; s7 -= carry7 << 21; - carry9 = (s9 + (1 << 20)) >> 21; s10 += carry9; s9 -= carry9 << 21; - carry11 = (s11 + (1 << 20)) >> 21; s12 += carry11; s11 -= carry11 << 21; + carry1 = (s1 + (1 << 20)) >> 21; + s2 += carry1; + s1 -= carry1 << 21; + carry3 = (s3 + (1 << 20)) >> 21; + s4 += carry3; + s3 -= carry3 << 21; + carry5 = (s5 + (1 << 20)) >> 21; + s6 += carry5; + s5 -= carry5 << 21; + carry7 = (s7 + (1 << 20)) >> 21; + s8 += carry7; + s7 -= carry7 << 21; + carry9 = (s9 + (1 << 20)) >> 21; + s10 += carry9; + s9 -= carry9 << 21; + carry11 = (s11 + (1 << 20)) >> 21; + s12 += carry11; + s11 -= carry11 << 21; s0 += s12 * 666643; s1 += s12 * 470296; @@ -205,18 +410,42 @@ public static void sc_reduce(byte[] s) s5 -= s12 * 683901; s12 = 0; - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; + carry0 = s0 >> 21; + s1 += carry0; + s0 -= carry0 << 21; + carry1 = s1 >> 21; + s2 += carry1; + s1 -= carry1 << 21; + carry2 = s2 >> 21; + s3 += carry2; + s2 -= carry2 << 21; + carry3 = s3 >> 21; + s4 += carry3; + s3 -= carry3 << 21; + carry4 = s4 >> 21; + s5 += carry4; + s4 -= carry4 << 21; + carry5 = s5 >> 21; + s6 += carry5; + s5 -= carry5 << 21; + carry6 = s6 >> 21; + s7 += carry6; + s6 -= carry6 << 21; + carry7 = s7 >> 21; + s8 += carry7; + s7 -= carry7 << 21; + carry8 = s8 >> 21; + s9 += carry8; + s8 -= carry8 << 21; + carry9 = s9 >> 21; + s10 += carry9; + s9 -= carry9 << 21; + carry10 = s10 >> 21; + s11 += carry10; + s10 -= carry10 << 21; + carry11 = s11 >> 21; + s12 += carry11; + s11 -= carry11 << 21; s0 += s12 * 666643; s1 += s12 * 470296; @@ -226,17 +455,39 @@ public static void sc_reduce(byte[] s) s5 -= s12 * 683901; s12 = 0; - carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; - carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; - carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; - carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; - carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; - carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; - carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; - carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; - carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; - carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; - carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; + carry0 = s0 >> 21; + s1 += carry0; + s0 -= carry0 << 21; + carry1 = s1 >> 21; + s2 += carry1; + s1 -= carry1 << 21; + carry2 = s2 >> 21; + s3 += carry2; + s2 -= carry2 << 21; + carry3 = s3 >> 21; + s4 += carry3; + s3 -= carry3 << 21; + carry4 = s4 >> 21; + s5 += carry4; + s4 -= carry4 << 21; + carry5 = s5 >> 21; + s6 += carry5; + s5 -= carry5 << 21; + carry6 = s6 >> 21; + s7 += carry6; + s6 -= carry6 << 21; + carry7 = s7 >> 21; + s8 += carry7; + s7 -= carry7 << 21; + carry8 = s8 >> 21; + s9 += carry8; + s8 -= carry8 << 21; + carry9 = s9 >> 21; + s10 += carry9; + s9 -= carry9 << 21; + carry10 = s10 >> 21; + s11 += carry10; + s10 -= carry10 << 21; unchecked { @@ -276,4 +527,4 @@ public static void sc_reduce(byte[] s) } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/scalarmult.cs b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/scalarmult.cs index d3e41e21..82acc161 100644 --- a/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/scalarmult.cs +++ b/src/NATS.Client/v1/NaCl/Internal/Ed25519Ref10/scalarmult.cs @@ -17,152 +17,194 @@ namespace NATS.Client.NaCl.Internal.Ed25519Ref10 { - internal static class MontgomeryOperations - { - public static void scalarmult( - byte[] q, int qoffset, - byte[] n, int noffset, - byte[] p, int poffset) - { - FieldElement p0, q0; - FieldOperations.fe_frombytes2(out p0, p, poffset); - scalarmult(out q0, n, noffset, ref p0); - FieldOperations.fe_tobytes(q, qoffset, ref q0); - } - - internal static void scalarmult( - out FieldElement q, - byte[] n, int noffset, - ref FieldElement p) - { + internal static class MontgomeryOperations + { + public static void scalarmult( + byte[] q, int qoffset, + byte[] n, int noffset, + byte[] p, int poffset) + { + FieldElement p0, q0; + FieldOperations.fe_frombytes2(out p0, p, poffset); + scalarmult(out q0, n, noffset, ref p0); + FieldOperations.fe_tobytes(q, qoffset, ref q0); + } + + internal static void scalarmult( + out FieldElement q, + byte[] n, int noffset, + ref FieldElement p) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: byte[] e = new byte[32];//ToDo: remove allocation - FieldElement x1, x2, x3; - FieldElement z2, z3; - FieldElement tmp0, tmp1; - - for (int i = 0; i < 32; ++i) - e[i] = n[noffset + i]; - ScalarOperations.sc_clamp(e, 0); - x1 = p; - FieldOperations.fe_1(out x2); - FieldOperations.fe_0(out z2); - x3 = x1; - FieldOperations.fe_1(out z3); - - uint swap = 0; - for (int pos = 254; pos >= 0; --pos) - { +After: + var e = new byte[32];//ToDo: remove allocation +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + byte[] e = new byte[32];//ToDo: remove allocation +After: + var e = new byte[32];//ToDo: remove allocation +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + byte[] e = new byte[32];//ToDo: remove allocation +After: + var e = new byte[32];//ToDo: remove allocation +*/ + + { + var e = new byte[32];//ToDo: remove allocation + FieldElement x1, x2, x3; + FieldElement z2, z3; + FieldElement tmp0, tmp1; + + for (var i = 0; i < 32; ++i) + e[i] = n[noffset + i]; + ScalarOperations.sc_clamp(e, 0); + x1 = p; + FieldOperations.fe_1(out x2); + FieldOperations.fe_0(out z2); + x3 = x1; + FieldOperations.fe_1(out z3); + + uint swap = 0; + for (var pos = 254; pos >= 0; --pos) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + uint b = (uint)(e[pos / 8] >> (pos & 7)); +After: + var b = (uint)(e[pos / 8] >> (pos & 7)); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + uint b = (uint)(e[pos / 8] >> (pos & 7)); +After: + var b = (uint)(e[pos / 8] >> (pos & 7)); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: uint b = (uint)(e[pos / 8] >> (pos & 7)); - b &= 1; - swap ^= b; - FieldOperations.fe_cswap(ref x2, ref x3, swap); - FieldOperations.fe_cswap(ref z2, ref z3, swap); - swap = b; - - /* qhasm: enter ladder */ - - /* qhasm: D = X3-Z3 */ - /* asm 1: fe_sub(>D=fe#5,D=tmp0,B=fe#6,B=tmp1,A=fe#1,A=x2,C=fe#2,C=z2,DA=fe#4,DA=z3,CB=fe#2,CB=z2,BB=fe#5,BB=tmp0,AA=fe#6,AA=tmp1,t0=fe#3,t0=x3,t1=fe#2,t1=z2,X4=fe#1,X4=x2,E=fe#6,E=tmp1,t2=fe#2,t2=z2,t3=fe#4,t3=z3,X5=fe#3,X5=x3,t4=fe#5,t4=tmp0,Z5=fe#4,x1,Z5=z3,x1,Z4=fe#2,Z4=z2,> (pos & 7)); +*/ + + { + var b = (uint)(e[pos / 8] >> (pos & 7)); + b &= 1; + swap ^= b; + FieldOperations.fe_cswap(ref x2, ref x3, swap); + FieldOperations.fe_cswap(ref z2, ref z3, swap); + swap = b; + + /* qhasm: enter ladder */ + + /* qhasm: D = X3-Z3 */ + /* asm 1: fe_sub(>D=fe#5,D=tmp0,B=fe#6,B=tmp1,A=fe#1,A=x2,C=fe#2,C=z2,DA=fe#4,DA=z3,CB=fe#2,CB=z2,BB=fe#5,BB=tmp0,AA=fe#6,AA=tmp1,t0=fe#3,t0=x3,t1=fe#2,t1=z2,X4=fe#1,X4=x2,E=fe#6,E=tmp1,t2=fe#2,t2=z2,t3=fe#4,t3=z3,X5=fe#3,X5=x3,t4=fe#5,t4=tmp0,Z5=fe#4,x1,Z5=z3,x1,Z4=fe#2,Z4=z2, outputState, ref Array8 input var w13 = input.x13; var w14 = input.x14; var w15 = input.x15; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int t = 0; +After: + var t = 0; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int t = 0; +After: + var t = 0; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int t = 0; +After: + var t = 0; +*/ + + + var t = 0; while (true) { ulong t1, t2; @@ -79,11 +100,11 @@ internal static void Core(out Array8 outputState, ref Array8 input {//0 t1 = h + ((e >> 14) ^ (e << (64 - 14)) ^ (e >> 18) ^ (e << (64 - 18)) ^ (e >> 41) ^ (e << (64 - 41))) + - //Sigma1(e) + //Sigma1(e) ((e & f) ^ (~e & g)) + //Ch(e,f,g) K[t] + w0; t2 = ((a >> 28) ^ (a << (64 - 28)) ^ (a >> 34) ^ (a << (64 - 34)) ^ (a >> 39) ^ (a << (64 - 39))) + - //Sigma0(a) + //Sigma0(a) ((a & b) ^ (a & c) ^ (b & c)); //Maj(a,b,c) h = g; g = f; @@ -98,11 +119,11 @@ internal static void Core(out Array8 outputState, ref Array8 input {//1 t1 = h + ((e >> 14) ^ (e << (64 - 14)) ^ (e >> 18) ^ (e << (64 - 18)) ^ (e >> 41) ^ (e << (64 - 41))) + - //Sigma1(e) + //Sigma1(e) ((e & f) ^ (~e & g)) + //Ch(e,f,g) K[t] + w1; t2 = ((a >> 28) ^ (a << (64 - 28)) ^ (a >> 34) ^ (a << (64 - 34)) ^ (a >> 39) ^ (a << (64 - 39))) + - //Sigma0(a) + //Sigma0(a) ((a & b) ^ (a & c) ^ (b & c)); //Maj(a,b,c) h = g; g = f; @@ -117,11 +138,11 @@ internal static void Core(out Array8 outputState, ref Array8 input {//2 t1 = h + ((e >> 14) ^ (e << (64 - 14)) ^ (e >> 18) ^ (e << (64 - 18)) ^ (e >> 41) ^ (e << (64 - 41))) + - //Sigma1(e) + //Sigma1(e) ((e & f) ^ (~e & g)) + //Ch(e,f,g) K[t] + w2; t2 = ((a >> 28) ^ (a << (64 - 28)) ^ (a >> 34) ^ (a << (64 - 34)) ^ (a >> 39) ^ (a << (64 - 39))) + - //Sigma0(a) + //Sigma0(a) ((a & b) ^ (a & c) ^ (b & c)); //Maj(a,b,c) h = g; g = f; @@ -136,11 +157,11 @@ internal static void Core(out Array8 outputState, ref Array8 input {//3 t1 = h + ((e >> 14) ^ (e << (64 - 14)) ^ (e >> 18) ^ (e << (64 - 18)) ^ (e >> 41) ^ (e << (64 - 41))) + - //Sigma1(e) + //Sigma1(e) ((e & f) ^ (~e & g)) + //Ch(e,f,g) K[t] + w3; t2 = ((a >> 28) ^ (a << (64 - 28)) ^ (a >> 34) ^ (a << (64 - 34)) ^ (a >> 39) ^ (a << (64 - 39))) + - //Sigma0(a) + //Sigma0(a) ((a & b) ^ (a & c) ^ (b & c)); //Maj(a,b,c) h = g; g = f; @@ -155,11 +176,11 @@ internal static void Core(out Array8 outputState, ref Array8 input {//4 t1 = h + ((e >> 14) ^ (e << (64 - 14)) ^ (e >> 18) ^ (e << (64 - 18)) ^ (e >> 41) ^ (e << (64 - 41))) + - //Sigma1(e) + //Sigma1(e) ((e & f) ^ (~e & g)) + //Ch(e,f,g) K[t] + w4; t2 = ((a >> 28) ^ (a << (64 - 28)) ^ (a >> 34) ^ (a << (64 - 34)) ^ (a >> 39) ^ (a << (64 - 39))) + - //Sigma0(a) + //Sigma0(a) ((a & b) ^ (a & c) ^ (b & c)); //Maj(a,b,c) h = g; g = f; @@ -174,11 +195,11 @@ internal static void Core(out Array8 outputState, ref Array8 input {//5 t1 = h + ((e >> 14) ^ (e << (64 - 14)) ^ (e >> 18) ^ (e << (64 - 18)) ^ (e >> 41) ^ (e << (64 - 41))) + - //Sigma1(e) + //Sigma1(e) ((e & f) ^ (~e & g)) + //Ch(e,f,g) K[t] + w5; t2 = ((a >> 28) ^ (a << (64 - 28)) ^ (a >> 34) ^ (a << (64 - 34)) ^ (a >> 39) ^ (a << (64 - 39))) + - //Sigma0(a) + //Sigma0(a) ((a & b) ^ (a & c) ^ (b & c)); //Maj(a,b,c) h = g; g = f; @@ -193,11 +214,11 @@ internal static void Core(out Array8 outputState, ref Array8 input {//6 t1 = h + ((e >> 14) ^ (e << (64 - 14)) ^ (e >> 18) ^ (e << (64 - 18)) ^ (e >> 41) ^ (e << (64 - 41))) + - //Sigma1(e) + //Sigma1(e) ((e & f) ^ (~e & g)) + //Ch(e,f,g) K[t] + w6; t2 = ((a >> 28) ^ (a << (64 - 28)) ^ (a >> 34) ^ (a << (64 - 34)) ^ (a >> 39) ^ (a << (64 - 39))) + - //Sigma0(a) + //Sigma0(a) ((a & b) ^ (a & c) ^ (b & c)); //Maj(a,b,c) h = g; g = f; @@ -212,11 +233,11 @@ internal static void Core(out Array8 outputState, ref Array8 input {//7 t1 = h + ((e >> 14) ^ (e << (64 - 14)) ^ (e >> 18) ^ (e << (64 - 18)) ^ (e >> 41) ^ (e << (64 - 41))) + - //Sigma1(e) + //Sigma1(e) ((e & f) ^ (~e & g)) + //Ch(e,f,g) K[t] + w7; t2 = ((a >> 28) ^ (a << (64 - 28)) ^ (a >> 34) ^ (a << (64 - 34)) ^ (a >> 39) ^ (a << (64 - 39))) + - //Sigma0(a) + //Sigma0(a) ((a & b) ^ (a & c) ^ (b & c)); //Maj(a,b,c) h = g; g = f; @@ -231,11 +252,11 @@ internal static void Core(out Array8 outputState, ref Array8 input {//8 t1 = h + ((e >> 14) ^ (e << (64 - 14)) ^ (e >> 18) ^ (e << (64 - 18)) ^ (e >> 41) ^ (e << (64 - 41))) + - //Sigma1(e) + //Sigma1(e) ((e & f) ^ (~e & g)) + //Ch(e,f,g) K[t] + w8; t2 = ((a >> 28) ^ (a << (64 - 28)) ^ (a >> 34) ^ (a << (64 - 34)) ^ (a >> 39) ^ (a << (64 - 39))) + - //Sigma0(a) + //Sigma0(a) ((a & b) ^ (a & c) ^ (b & c)); //Maj(a,b,c) h = g; g = f; @@ -250,11 +271,11 @@ internal static void Core(out Array8 outputState, ref Array8 input {//9 t1 = h + ((e >> 14) ^ (e << (64 - 14)) ^ (e >> 18) ^ (e << (64 - 18)) ^ (e >> 41) ^ (e << (64 - 41))) + - //Sigma1(e) + //Sigma1(e) ((e & f) ^ (~e & g)) + //Ch(e,f,g) K[t] + w9; t2 = ((a >> 28) ^ (a << (64 - 28)) ^ (a >> 34) ^ (a << (64 - 34)) ^ (a >> 39) ^ (a << (64 - 39))) + - //Sigma0(a) + //Sigma0(a) ((a & b) ^ (a & c) ^ (b & c)); //Maj(a,b,c) h = g; g = f; @@ -269,11 +290,11 @@ internal static void Core(out Array8 outputState, ref Array8 input {//10 t1 = h + ((e >> 14) ^ (e << (64 - 14)) ^ (e >> 18) ^ (e << (64 - 18)) ^ (e >> 41) ^ (e << (64 - 41))) + - //Sigma1(e) + //Sigma1(e) ((e & f) ^ (~e & g)) + //Ch(e,f,g) K[t] + w10; t2 = ((a >> 28) ^ (a << (64 - 28)) ^ (a >> 34) ^ (a << (64 - 34)) ^ (a >> 39) ^ (a << (64 - 39))) + - //Sigma0(a) + //Sigma0(a) ((a & b) ^ (a & c) ^ (b & c)); //Maj(a,b,c) h = g; g = f; @@ -288,11 +309,11 @@ internal static void Core(out Array8 outputState, ref Array8 input {//11 t1 = h + ((e >> 14) ^ (e << (64 - 14)) ^ (e >> 18) ^ (e << (64 - 18)) ^ (e >> 41) ^ (e << (64 - 41))) + - //Sigma1(e) + //Sigma1(e) ((e & f) ^ (~e & g)) + //Ch(e,f,g) K[t] + w11; t2 = ((a >> 28) ^ (a << (64 - 28)) ^ (a >> 34) ^ (a << (64 - 34)) ^ (a >> 39) ^ (a << (64 - 39))) + - //Sigma0(a) + //Sigma0(a) ((a & b) ^ (a & c) ^ (b & c)); //Maj(a,b,c) h = g; g = f; @@ -307,11 +328,11 @@ internal static void Core(out Array8 outputState, ref Array8 input {//12 t1 = h + ((e >> 14) ^ (e << (64 - 14)) ^ (e >> 18) ^ (e << (64 - 18)) ^ (e >> 41) ^ (e << (64 - 41))) + - //Sigma1(e) + //Sigma1(e) ((e & f) ^ (~e & g)) + //Ch(e,f,g) K[t] + w12; t2 = ((a >> 28) ^ (a << (64 - 28)) ^ (a >> 34) ^ (a << (64 - 34)) ^ (a >> 39) ^ (a << (64 - 39))) + - //Sigma0(a) + //Sigma0(a) ((a & b) ^ (a & c) ^ (b & c)); //Maj(a,b,c) h = g; g = f; @@ -326,11 +347,11 @@ internal static void Core(out Array8 outputState, ref Array8 input {//13 t1 = h + ((e >> 14) ^ (e << (64 - 14)) ^ (e >> 18) ^ (e << (64 - 18)) ^ (e >> 41) ^ (e << (64 - 41))) + - //Sigma1(e) + //Sigma1(e) ((e & f) ^ (~e & g)) + //Ch(e,f,g) K[t] + w13; t2 = ((a >> 28) ^ (a << (64 - 28)) ^ (a >> 34) ^ (a << (64 - 34)) ^ (a >> 39) ^ (a << (64 - 39))) + - //Sigma0(a) + //Sigma0(a) ((a & b) ^ (a & c) ^ (b & c)); //Maj(a,b,c) h = g; g = f; @@ -345,11 +366,11 @@ internal static void Core(out Array8 outputState, ref Array8 input {//14 t1 = h + ((e >> 14) ^ (e << (64 - 14)) ^ (e >> 18) ^ (e << (64 - 18)) ^ (e >> 41) ^ (e << (64 - 41))) + - //Sigma1(e) + //Sigma1(e) ((e & f) ^ (~e & g)) + //Ch(e,f,g) K[t] + w14; t2 = ((a >> 28) ^ (a << (64 - 28)) ^ (a >> 34) ^ (a << (64 - 34)) ^ (a >> 39) ^ (a << (64 - 39))) + - //Sigma0(a) + //Sigma0(a) ((a & b) ^ (a & c) ^ (b & c)); //Maj(a,b,c) h = g; g = f; @@ -364,11 +385,11 @@ internal static void Core(out Array8 outputState, ref Array8 input {//15 t1 = h + ((e >> 14) ^ (e << (64 - 14)) ^ (e >> 18) ^ (e << (64 - 18)) ^ (e >> 41) ^ (e << (64 - 41))) + - //Sigma1(e) + //Sigma1(e) ((e & f) ^ (~e & g)) + //Ch(e,f,g) K[t] + w15; t2 = ((a >> 28) ^ (a << (64 - 28)) ^ (a >> 34) ^ (a << (64 - 34)) ^ (a >> 39) ^ (a << (64 - 39))) + - //Sigma0(a) + //Sigma0(a) ((a & b) ^ (a & c) ^ (b & c)); //Maj(a,b,c) h = g; g = f; diff --git a/src/NATS.Client/v1/NaCl/Sha512.cs b/src/NATS.Client/v1/NaCl/Sha512.cs index f097fad0..ad17bebe 100644 --- a/src/NATS.Client/v1/NaCl/Sha512.cs +++ b/src/NATS.Client/v1/NaCl/Sha512.cs @@ -62,14 +62,59 @@ public void Update(ArraySegment data) public void Update(byte[] data, int index, int length) { // Contract.Requires(data != null); - if (data == null) throw new ArgumentNullException(); + if (data == null) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int bytesInBuffer = (int)_totalBytes & (BlockSize - 1); +After: + var bytesInBuffer = (int)_totalBytes & (BlockSize - 1); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int bytesInBuffer = (int)_totalBytes & (BlockSize - 1); +After: + var bytesInBuffer = (int)_totalBytes & (BlockSize - 1); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int bytesInBuffer = (int)_totalBytes & (BlockSize - 1); +After: + var bytesInBuffer = (int)_totalBytes & (BlockSize - 1); +*/ + + throw new ArgumentNullException(); // Contract.Requires(index >=0 && length >= 0); - if (index < 0 || length < 0) throw new ArgumentOutOfRangeException(); + if (index < 0 || length < 0) + throw new ArgumentOutOfRangeException(); // Contract.Requires((index + length) <= data.Length); - if ((index + length) > data.Length) throw new ArgumentException(); + if ( +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int bytesInBuffer = (int)_totalBytes & (BlockSize - 1); +After: + var bytesInBuffer = (int)_totalBytes & (BlockSize - 1); +*/ - Array16 block; +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int bytesInBuffer = (int)_totalBytes & (BlockSize - 1); +After: + var bytesInBuffer = (int)_totalBytes & (BlockSize - 1); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int bytesInBuffer = (int)_totalBytes & (BlockSize - 1); +After: + var bytesInBuffer = (int)_totalBytes & (BlockSize - 1); +*/ +(index + length) > data.Length) + throw new ArgumentException(); + + Array16 block; + var bytesInBuffer = (int)_totalBytes & (BlockSize - 1); _totalBytes += (uint)length; if (_totalBytes >= ulong.MaxValue / 8) @@ -112,15 +157,17 @@ public void Update(byte[] data, int index, int length) public void Finalize(ArraySegment output) { // Contract.Requires(output.Array != null); - if (output.Array == null) throw new ArgumentNullException(); + if (output.Array == null) + throw new ArgumentNullException(); // Contract.Requires(output.Count == 64); - if (output.Count != 64) throw new ArgumentException(); + if (output.Count != 64) + throw new ArgumentException(); Update(_padding, 0, _padding.Length); Array16 block; ByteIntegerConverter.Array16LoadBigEndian64(out block, _buffer, 0); CryptoBytes.InternalWipe(_buffer, 0, _buffer.Length); - int bytesInBuffer = (int)_totalBytes & (BlockSize - 1); + var bytesInBuffer = (int)_totalBytes & (BlockSize - 1); if (bytesInBuffer > BlockSize - 16) { Sha512Internal.Core(out _state, ref _state, ref block); @@ -159,7 +206,8 @@ public byte[] Finalize() public static byte[] Hash(byte[] data) { // Contract.Requires(data != null); - if (data == null) throw new ArgumentNullException(); + if (data == null) + throw new ArgumentNullException(); return Hash(data, 0, data.Length); } @@ -173,11 +221,14 @@ public static byte[] Hash(byte[] data) public static byte[] Hash(byte[] data, int index, int length) { // Contract.Requires(data != null); - if (data == null) throw new ArgumentNullException(); + if (data == null) + throw new ArgumentNullException(); // Contract.Requires(index >= 0 && length >= 0); - if (index < 0 || length < 0) throw new ArgumentOutOfRangeException(); + if (index < 0 || length < 0) + throw new ArgumentOutOfRangeException(); // Contract.Requires((index + length) <= data.Length); - if ((index + length) > data.Length) throw new ArgumentException(); + if ((index + length) > data.Length) + throw new ArgumentException(); var hasher = new Sha512(); hasher.Update(data, index, length); diff --git a/src/NATS.Client/v1/ObjectStore/IObjectStore.cs b/src/NATS.Client/v1/ObjectStore/IObjectStore.cs index e9b14bf0..5385d6c4 100644 --- a/src/NATS.Client/v1/ObjectStore/IObjectStore.cs +++ b/src/NATS.Client/v1/ObjectStore/IObjectStore.cs @@ -1,4 +1,4 @@ -// Copyright 2022 The NATS Authors +// Copyright 2022 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: diff --git a/src/NATS.Client/v1/ObjectStore/IObjectStoreManagement.cs b/src/NATS.Client/v1/ObjectStore/IObjectStoreManagement.cs index 0de2970f..cf69c96e 100644 --- a/src/NATS.Client/v1/ObjectStore/IObjectStoreManagement.cs +++ b/src/NATS.Client/v1/ObjectStore/IObjectStoreManagement.cs @@ -1,4 +1,4 @@ -// Copyright 2022 The NATS Authors +// Copyright 2022 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: diff --git a/src/NATS.Client/v1/ObjectStore/IObjectStoreWatcher.cs b/src/NATS.Client/v1/ObjectStore/IObjectStoreWatcher.cs index 3913ab7f..1c240d82 100644 --- a/src/NATS.Client/v1/ObjectStore/IObjectStoreWatcher.cs +++ b/src/NATS.Client/v1/ObjectStore/IObjectStoreWatcher.cs @@ -1,4 +1,4 @@ -// Copyright 2022 The NATS Authors +// Copyright 2022 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: diff --git a/src/NATS.Client/v1/ObjectStore/ObjectInfo.cs b/src/NATS.Client/v1/ObjectStore/ObjectInfo.cs index 10a07c09..910568a5 100644 --- a/src/NATS.Client/v1/ObjectStore/ObjectInfo.cs +++ b/src/NATS.Client/v1/ObjectStore/ObjectInfo.cs @@ -37,7 +37,7 @@ public class ObjectInfo : JsonSerializable public string Description => ObjectMeta.Description; public MsgHeader Headers => ObjectMeta.Headers; public bool IsLink => ObjectMeta.ObjectMetaOptions.Link != null; - public ObjectLink Link => ObjectMeta.ObjectMetaOptions.Link; + public ObjectLink Link => ObjectMeta.ObjectMetaOptions.Link; internal ObjectInfo(ObjectInfoBuilder b) { @@ -51,12 +51,34 @@ internal ObjectInfo(ObjectInfoBuilder b) ObjectMeta = b._metaBuilder.Build(); } - public ObjectInfo(MessageInfo mi) : this(Encoding.UTF8.GetString(mi.Data), mi.Time) {} + public ObjectInfo(MessageInfo mi) : this(Encoding.UTF8.GetString(mi.Data), mi.Time) { } - public ObjectInfo(Msg m) : this(Encoding.UTF8.GetString(m.Data), m.MetaData.Timestamp) {} + public ObjectInfo(Msg m) : this(Encoding.UTF8.GetString(m.Data), m.MetaData.Timestamp) { } - internal ObjectInfo(string json, DateTime messageTime) { + internal ObjectInfo(string json, DateTime messageTime) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: JSONNode node = JSON.Parse(json); +After: + var node = JSON.Parse(json); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONNode node = JSON.Parse(json); +After: + var node = JSON.Parse(json); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONNode node = JSON.Parse(json); +After: + var node = JSON.Parse(json); +*/ + + { + var node = JSON.Parse(json); Bucket = node[ApiConstants.Bucket]; Nuid = node[ApiConstants.Nuid]; Size = JsonUtils.AsIntOrMinus1(node, ApiConstants.Size); @@ -68,9 +90,30 @@ internal ObjectInfo(string json, DateTime messageTime) { } public override JSONNode ToJsonNode() +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + { // never write MTIME (Modified) - JSONObject jso = new JSONObject(); + var jso = new JSONObject(); ObjectMeta.EmbedJson(jso); // the go code embeds the objectMeta's fields instead of as a child object. jso[ApiConstants.Bucket] = Bucket; jso[ApiConstants.Nuid] = Nuid; @@ -83,17 +126,20 @@ public override JSONNode ToJsonNode() protected bool Equals(ObjectInfo other) { - return Bucket == other.Bucket && Nuid == other.Nuid && Size == other.Size - && Modified.Equals(other.Modified) && Chunks == other.Chunks - && Digest == other.Digest && IsDeleted == other.IsDeleted + return Bucket == other.Bucket && Nuid == other.Nuid && Size == other.Size + && Modified.Equals(other.Modified) && Chunks == other.Chunks + && Digest == other.Digest && IsDeleted == other.IsDeleted && Equals(ObjectMeta, other.ObjectMeta); } public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (ReferenceEquals(null, obj)) + return false; + if (ReferenceEquals(this, obj)) + return true; + if (obj.GetType() != GetType()) + return false; return Equals((ObjectInfo)obj); } @@ -113,19 +159,23 @@ public override int GetHashCode() } } - internal static ObjectInfoBuilder Builder(string bucket, string objectName) { + internal static ObjectInfoBuilder Builder(string bucket, string objectName) + { return new ObjectInfoBuilder(bucket, objectName); } - internal static ObjectInfoBuilder Builder(string bucket, ObjectMeta meta) { + internal static ObjectInfoBuilder Builder(string bucket, ObjectMeta meta) + { return new ObjectInfoBuilder(bucket, meta); } - internal static ObjectInfoBuilder Builder(ObjectInfo info) { + internal static ObjectInfoBuilder Builder(ObjectInfo info) + { return new ObjectInfoBuilder(info); } - public sealed class ObjectInfoBuilder { + public sealed class ObjectInfoBuilder + { internal string _bucket; internal string _nuid; internal long _size; @@ -135,17 +185,20 @@ public sealed class ObjectInfoBuilder { internal bool _deleted; internal ObjectMeta.ObjectMetaBuilder _metaBuilder; - internal ObjectInfoBuilder(string bucket, string objectName) { + internal ObjectInfoBuilder(string bucket, string objectName) + { _metaBuilder = ObjectMeta.Builder(objectName); WithBucket(bucket); } - public ObjectInfoBuilder(string bucket, ObjectMeta meta) { + public ObjectInfoBuilder(string bucket, ObjectMeta meta) + { _metaBuilder = ObjectMeta.Builder(meta); WithBucket(bucket); } - public ObjectInfoBuilder(ObjectInfo info) { + public ObjectInfoBuilder(ObjectInfo info) + { _bucket = info.Bucket; _nuid = info.Nuid; _size = info.Size; @@ -156,82 +209,245 @@ public ObjectInfoBuilder(ObjectInfo info) { _metaBuilder = ObjectMeta.Builder(info.ObjectMeta); } - public ObjectInfoBuilder WithObjectName(string name) { + public ObjectInfoBuilder WithObjectName(string name) + { _metaBuilder.WithObjectName(name); return this; } - public ObjectInfoBuilder WithBucket(string bucket) { + public ObjectInfoBuilder WithBucket(string bucket) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this._bucket = Validator.ValidateBucketName(bucket, true); +After: + _bucket = Validator.ValidateBucketName(bucket, true); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: this._bucket = Validator.ValidateBucketName(bucket, true); +After: + _bucket = Validator.ValidateBucketName(bucket, true); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this._bucket = Validator.ValidateBucketName(bucket, true); +After: + _bucket = Validator.ValidateBucketName(bucket, true); +*/ + + { + _bucket = Validator.ValidateBucketName(bucket, true); return this; } - public ObjectInfoBuilder WithNuid(string nuid) { + public ObjectInfoBuilder WithNuid(string nuid) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: this._nuid = nuid; +After: + _nuid = nuid; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this._nuid = nuid; +After: + _nuid = nuid; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this._nuid = nuid; +After: + _nuid = nuid; +*/ + + { + _nuid = nuid; return this; } - public ObjectInfoBuilder WithSize(long size) { + public ObjectInfoBuilder WithSize(long size) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this._size = size; +After: + _size = size; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: this._size = size; +After: + _size = size; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this._size = size; +After: + _size = size; +*/ + + { + _size = size; return this; } - public ObjectInfoBuilder WithModified(DateTime modified) { + public ObjectInfoBuilder WithModified(DateTime modified) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this._modified = modified; +After: + _modified = modified; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: this._modified = modified; +After: + _modified = modified; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this._modified = modified; +After: + _modified = modified; +*/ + + { + _modified = modified; return this; } - public ObjectInfoBuilder WithChunks(long chunks) { + public ObjectInfoBuilder WithChunks(long chunks) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: this._chunks = chunks; +After: + _chunks = chunks; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this._chunks = chunks; +After: + _chunks = chunks; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this._chunks = chunks; +After: + _chunks = chunks; +*/ + + { + _chunks = chunks; return this; } - public ObjectInfoBuilder WithDigest(string digest) { + public ObjectInfoBuilder WithDigest(string digest) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this._digest = digest; +After: + _digest = digest; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: this._digest = digest; +After: + _digest = digest; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this._digest = digest; +After: + _digest = digest; +*/ + + { + _digest = digest; return this; } - public ObjectInfoBuilder WithDeleted(bool deleted) { + public ObjectInfoBuilder WithDeleted(bool deleted) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this._deleted = deleted; +After: + _deleted = deleted; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: this._deleted = deleted; +After: + _deleted = deleted; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this._deleted = deleted; +After: + _deleted = deleted; +*/ + + { + _deleted = deleted; return this; } - public ObjectInfoBuilder WithDescription(string description) { + public ObjectInfoBuilder WithDescription(string description) + { _metaBuilder.WithDescription(description); return this; } - public ObjectInfoBuilder WithHeaders(MsgHeader headers) { + public ObjectInfoBuilder WithHeaders(MsgHeader headers) + { _metaBuilder.WithHeaders(headers); return this; } - public ObjectInfoBuilder WithOptions(ObjectMetaOptions objectMetaOptions) { + public ObjectInfoBuilder WithOptions(ObjectMetaOptions objectMetaOptions) + { _metaBuilder.WithOptions(objectMetaOptions); return this; } - public ObjectInfoBuilder WithChunkSize(int chunkSize) { + public ObjectInfoBuilder WithChunkSize(int chunkSize) + { _metaBuilder.WithChunkSize(chunkSize); return this; } - public ObjectInfoBuilder WithLink(ObjectLink link) { + public ObjectInfoBuilder WithLink(ObjectLink link) + { _metaBuilder.WithLink(link); return this; } - public ObjectInfoBuilder WithBucketLink(string bucket) { + public ObjectInfoBuilder WithBucketLink(string bucket) + { _metaBuilder.WithLink(new ObjectLink(bucket, null)); return this; } - public ObjectInfoBuilder WithObjectLink(string bucket, string objectName) { + public ObjectInfoBuilder WithObjectLink(string bucket, string objectName) + { _metaBuilder.WithLink(new ObjectLink(bucket, objectName)); return this; } - public ObjectInfo Build() { + public ObjectInfo Build() + { return new ObjectInfo(this); } } diff --git a/src/NATS.Client/v1/ObjectStore/ObjectLink.cs b/src/NATS.Client/v1/ObjectStore/ObjectLink.cs index d2c91a25..1272ae54 100644 --- a/src/NATS.Client/v1/ObjectStore/ObjectLink.cs +++ b/src/NATS.Client/v1/ObjectStore/ObjectLink.cs @@ -45,17 +45,40 @@ internal ObjectLink(string bucket, string objectName) ObjectName = objectName; } - public static ObjectLink ForBucket(string bucket) { + public static ObjectLink ForBucket(string bucket) + { return new ObjectLink(bucket, null); } - public static ObjectLink ForObject(string bucket, string objectName) { + public static ObjectLink ForObject(string bucket, string objectName) + { return new ObjectLink(bucket, objectName); } public override JSONNode ToJsonNode() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + + { + var jso = new JSONObject(); if (Bucket != null) { jso[ApiConstants.Bucket] = Bucket; diff --git a/src/NATS.Client/v1/ObjectStore/ObjectMeta.cs b/src/NATS.Client/v1/ObjectStore/ObjectMeta.cs index fd42aa2f..d8149b7f 100644 --- a/src/NATS.Client/v1/ObjectStore/ObjectMeta.cs +++ b/src/NATS.Client/v1/ObjectStore/ObjectMeta.cs @@ -32,7 +32,28 @@ internal ObjectMeta(JSONNode node) ObjectName = node[ApiConstants.Name]; Description = node[ApiConstants.Description]; Headers = JsonUtils.AsHeaders(node, ApiConstants.Headers); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: JSONNode optNode = node[ApiConstants.Options]; +After: + var optNode = node[ApiConstants.Options]; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONNode optNode = node[ApiConstants.Options]; +After: + var optNode = node[ApiConstants.Options]; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONNode optNode = node[ApiConstants.Options]; +After: + var optNode = node[ApiConstants.Options]; +*/ + + var optNode = node[ApiConstants.Options]; if (optNode == null) { ObjectMetaOptions = new ObjectMetaOptions(); @@ -52,8 +73,29 @@ private ObjectMeta(ObjectMetaBuilder b) } public override JSONNode ToJsonNode() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + + { + var jso = new JSONObject(); EmbedJson(jso); return jso; } @@ -71,17 +113,20 @@ internal void EmbedJson(JSONObject jsonObject) protected bool Equals(ObjectMeta other) { - return ObjectName == other.ObjectName - && Description == other.Description - && Equals(Headers, other.Headers) + return ObjectName == other.ObjectName + && Description == other.Description + && Equals(Headers, other.Headers) && Equals(ObjectMetaOptions, other.ObjectMetaOptions); } public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (ReferenceEquals(null, obj)) + return false; + if (ReferenceEquals(this, obj)) + return true; + if (obj.GetType() != GetType()) + return false; return Equals((ObjectMeta)obj); } @@ -97,19 +142,23 @@ public override int GetHashCode() } } - public static ObjectMetaBuilder Builder(string objectName) { + public static ObjectMetaBuilder Builder(string objectName) + { return new ObjectMetaBuilder(objectName); } - internal static ObjectMetaBuilder Builder(ObjectMeta om) { + internal static ObjectMetaBuilder Builder(ObjectMeta om) + { return new ObjectMetaBuilder(om); } - public static ObjectMeta ForObjectName(string objectName) { + public static ObjectMeta ForObjectName(string objectName) + { return new ObjectMetaBuilder(objectName).Build(); } - public sealed class ObjectMetaBuilder { + public sealed class ObjectMetaBuilder + { internal string _objectName; internal string _description; internal MsgHeader _headers; @@ -122,24 +171,28 @@ public ObjectMetaBuilder(string objectName) WithObjectName(objectName); } - public ObjectMetaBuilder(ObjectMeta om) { + public ObjectMetaBuilder(ObjectMeta om) + { _objectName = om.ObjectName; _description = om.Description; _headers = om.Headers; _metaOptionsBuilder = ObjectMetaOptions.Builder(om.ObjectMetaOptions); } - public ObjectMetaBuilder WithObjectName(string objectName) { + public ObjectMetaBuilder WithObjectName(string objectName) + { _objectName = Validator.ValidateNotNull(objectName, "Object Name"); return this; } - public ObjectMetaBuilder WithDescription(string description) { + public ObjectMetaBuilder WithDescription(string description) + { _description = description; return this; } - public ObjectMetaBuilder WithHeaders(MsgHeader headers) { + public ObjectMetaBuilder WithHeaders(MsgHeader headers) + { if (headers == null) { _headers.Clear(); @@ -151,22 +204,26 @@ public ObjectMetaBuilder WithHeaders(MsgHeader headers) { return this; } - public ObjectMetaBuilder WithOptions(ObjectMetaOptions options) { + public ObjectMetaBuilder WithOptions(ObjectMetaOptions options) + { _metaOptionsBuilder = ObjectMetaOptions.Builder(options); return this; } - public ObjectMetaBuilder WithChunkSize(int chunkSize) { + public ObjectMetaBuilder WithChunkSize(int chunkSize) + { _metaOptionsBuilder.WithChunkSize(chunkSize); return this; } - public ObjectMetaBuilder WithLink(ObjectLink link) { + public ObjectMetaBuilder WithLink(ObjectLink link) + { _metaOptionsBuilder.WithLink(link); return this; } - public ObjectMeta Build() { + public ObjectMeta Build() + { return new ObjectMeta(this); } } diff --git a/src/NATS.Client/v1/ObjectStore/ObjectMetaOptions.cs b/src/NATS.Client/v1/ObjectStore/ObjectMetaOptions.cs index 8b3fcfcc..5baf0343 100644 --- a/src/NATS.Client/v1/ObjectStore/ObjectMetaOptions.cs +++ b/src/NATS.Client/v1/ObjectStore/ObjectMetaOptions.cs @@ -42,8 +42,29 @@ private ObjectMetaOptions(ObjectMetaOptionsBuilder b) } public override JSONNode ToJsonNode() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + + { + var jso = new JSONObject(); if (Link != null) { jso[ApiConstants.Link] = Link.ToJsonNode(); @@ -64,9 +85,12 @@ protected bool Equals(ObjectMetaOptions other) public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (ReferenceEquals(null, obj)) + return false; + if (ReferenceEquals(this, obj)) + return true; + if (obj.GetType() != GetType()) + return false; return Equals((ObjectMetaOptions)obj); } @@ -77,37 +101,44 @@ public override int GetHashCode() return ((Link != null ? Link.GetHashCode() : 0) * 397) ^ ChunkSize; } } - - internal static ObjectMetaOptionsBuilder Builder() { + + internal static ObjectMetaOptionsBuilder Builder() + { return new ObjectMetaOptionsBuilder(); } - internal static ObjectMetaOptionsBuilder Builder(ObjectMetaOptions om) { + internal static ObjectMetaOptionsBuilder Builder(ObjectMetaOptions om) + { return new ObjectMetaOptionsBuilder(om); } - internal sealed class ObjectMetaOptionsBuilder { + internal sealed class ObjectMetaOptionsBuilder + { internal ObjectLink _link; internal int _chunkSize; - internal ObjectMetaOptionsBuilder() {} + internal ObjectMetaOptionsBuilder() { } - internal ObjectMetaOptionsBuilder(ObjectMetaOptions om) { + internal ObjectMetaOptionsBuilder(ObjectMetaOptions om) + { _link = om.Link; _chunkSize = om.ChunkSize; } - internal ObjectMetaOptionsBuilder WithLink(ObjectLink link) { + internal ObjectMetaOptionsBuilder WithLink(ObjectLink link) + { _link = link; return this; } - internal ObjectMetaOptionsBuilder WithChunkSize(int chunkSize) { + internal ObjectMetaOptionsBuilder WithChunkSize(int chunkSize) + { _chunkSize = chunkSize; return this; } - internal ObjectMetaOptions Build() { + internal ObjectMetaOptions Build() + { return new ObjectMetaOptions(this); } } diff --git a/src/NATS.Client/v1/ObjectStore/ObjectStore.cs b/src/NATS.Client/v1/ObjectStore/ObjectStore.cs index 4ebc36df..4878c281 100644 --- a/src/NATS.Client/v1/ObjectStore/ObjectStore.cs +++ b/src/NATS.Client/v1/ObjectStore/ObjectStore.cs @@ -16,8 +16,8 @@ using System.IO; using NATS.Client.Internals; using NATS.Client.JetStream; -using static NATS.Client.ObjectStore.ObjectStoreUtil; using static NATS.Client.ClientExDetail; +using static NATS.Client.ObjectStore.ObjectStoreUtil; namespace NATS.Client.ObjectStore { @@ -30,16 +30,19 @@ public class ObjectStore : FeatureBase, IObjectStore internal string PubSubMetaPrefix { get; } public string BucketName { get; } - - internal string RawChunkSubject(string nuid) { + + internal string RawChunkSubject(string nuid) + { return RawChunkPrefix + nuid; } - internal string PubSubChunkSubject(string nuid) { + internal string PubSubChunkSubject(string nuid) + { return PubSubChunkPrefix + nuid; } - internal string RawMetaSubject(string name) { + internal string RawMetaSubject(string name) + { return RawMetaPrefix + EncodeForSubject(name); } @@ -48,11 +51,13 @@ internal string RawAllMetaSubject() return RawMetaPrefix + NatsConstants.GreaterThan; } - internal string PubSubMetaSubject(string name) { + internal string PubSubMetaSubject(string name) + { return PubSubMetaPrefix + EncodeForSubject(name); } - private ObjectInfo PublishMeta(ObjectInfo info) { + private ObjectInfo PublishMeta(ObjectInfo info) + { js.Publish(new Msg(PubSubMetaSubject(info.ObjectName), MetaHeaders, info.Serialize())); return ObjectInfo.Builder(info).WithModified(DateTime.UtcNow).Build(); } @@ -64,15 +69,18 @@ internal ObjectStore(IConnection connection, string bucketName, ObjectStoreOptio StreamName = ToStreamName(bucketName); RawChunkPrefix = ToChunkPrefix(bucketName); RawMetaPrefix = ToMetaPrefix(bucketName); - if (oso == null) { + if (oso == null) + { PubSubChunkPrefix = RawChunkPrefix; PubSubMetaPrefix = RawMetaPrefix; } - else if (oso.JSOptions.IsDefaultPrefix) { + else if (oso.JSOptions.IsDefaultPrefix) + { PubSubChunkPrefix = RawChunkPrefix; PubSubMetaPrefix = RawMetaPrefix; } - else { + else + { PubSubChunkPrefix = oso.JSOptions.Prefix + RawChunkPrefix; PubSubMetaPrefix = oso.JSOptions.Prefix + RawMetaPrefix; } @@ -83,10 +91,11 @@ public ObjectInfo Put(ObjectMeta meta, Stream inputStream) Validator.ValidateNotNull(meta, "ObjectMeta"); Validator.ValidateNotNull(meta.ObjectName, "ObjectMeta name"); Validator.ValidateNotNull(inputStream, "InputStream"); - if (meta.ObjectMetaOptions.Link != null) { + if (meta.ObjectMetaOptions.Link != null) + { throw OsLinkNotAllowOnPut.Instance(); - } - +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: string nuid = Nuid.NextGlobal(); string chunkSubject = PubSubChunkSubject(nuid); @@ -372,6 +381,1795 @@ public IList GetList() return list; } + public ObjectStoreWatchSubscription Watch(IObjectStoreWatcher watcher, params ObjectStoreWatchOption[] watchOptions) + { + return new ObjectStoreWatchSubscription(this, watcher, watchOptions); +After: + var nuid = Nuid.NextGlobal(); + var chunkSubject = PubSubChunkSubject(nuid); + + var chunkSize = meta.ObjectMetaOptions.ChunkSize; + if (chunkSize <= 0) { + chunkSize = DefaultChunkSize; + } + + try + { + var digester = new Digester(); + long totalSize = 0; // track total bytes read to make sure + var chunks = 0; + + // working with chunkSize number of bytes each time. + var buffer = new byte[chunkSize]; + var red = chunkSize; + while (red == chunkSize) + { + // keep reading while last chunk was full size + red = inputStream.Read(buffer, 0, chunkSize); + if (red > 0) + { + // copy if red is less than chunk size + var payload = buffer; + if (red < chunkSize) + { + payload = new byte[red]; + Array.Copy(buffer, payload, red); + } + + // digest the actual bytes + digester.AppendData(payload); + + // publish the payload + js.Publish(chunkSubject, payload); + + // track total chunks and bytes + chunks++; + totalSize += red; + } + } + + return PublishMeta(ObjectInfo.Builder(BucketName, meta) + .WithSize(totalSize) + .WithChunks(chunks) + .WithNuid(nuid) + .WithChunkSize(chunkSize) + .WithDigest(digester.GetDigestEntry()) + .Build()); + } + catch (Exception) + { + try { + jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(RawChunkSubject(nuid))); + } + catch (Exception) { /* ignore, there is already an error */ } + + throw; + } +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string nuid = Nuid.NextGlobal(); + string chunkSubject = PubSubChunkSubject(nuid); + + int chunkSize = meta.ObjectMetaOptions.ChunkSize; + if (chunkSize <= 0) { + chunkSize = DefaultChunkSize; + } + + try + { + Digester digester = new Digester(); + long totalSize = 0; // track total bytes read to make sure + int chunks = 0; + + // working with chunkSize number of bytes each time. + byte[] buffer = new byte[chunkSize]; + int red = chunkSize; + while (red == chunkSize) + { + // keep reading while last chunk was full size + red = inputStream.Read(buffer, 0, chunkSize); + if (red > 0) + { + // copy if red is less than chunk size + byte[] payload = buffer; + if (red < chunkSize) + { + payload = new byte[red]; + Array.Copy(buffer, payload, red); + } + + // digest the actual bytes + digester.AppendData(payload); + + // publish the payload + js.Publish(chunkSubject, payload); + + // track total chunks and bytes + chunks++; + totalSize += red; + } + } + + return PublishMeta(ObjectInfo.Builder(BucketName, meta) + .WithSize(totalSize) + .WithChunks(chunks) + .WithNuid(nuid) + .WithChunkSize(chunkSize) + .WithDigest(digester.GetDigestEntry()) + .Build()); + } + catch (Exception) + { + try { + jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(RawChunkSubject(nuid))); + } + catch (Exception) { /* ignore, there is already an error */ } + + throw; + } + } + + public ObjectInfo Put(string objectName, Stream inputStream) + { + return Put(ObjectMeta.ForObjectName(objectName), inputStream); + } + + public ObjectInfo Put(string objectName, byte[] input) + { + return Put(objectName, new MemoryStream(input)); + } + + public ObjectInfo Put(FileInfo fileInfo) + { + return Put(ObjectMeta.ForObjectName(fileInfo.Name), fileInfo.OpenRead()); + } + + public ObjectInfo Get(string objectName, Stream outputStream) + { + ObjectInfo oi = GetInfo(objectName, false); + if (oi == null) { + throw OsObjectNotFound.Instance(); + } + + if (oi.IsLink) { + ObjectLink link = oi.Link; + if (link.IsBucketLink) { + throw OsGetLinkToBucket.Instance(); + } + + // is the link in the same bucket + if (link.Bucket.Equals(BucketName)) { + return Get(link.ObjectName, outputStream); + } + + // different bucket + // get the store for the linked bucket, then get the linked object + return js.Conn.CreateObjectStoreContext(link.Bucket, oso).Get(link.ObjectName, outputStream); + } + + Digester digester = new Digester(); + long totalBytes = 0; + long totalChunks = 0; + + // if there is one chunk, just go get the message directly and we're done. + if (oi.Chunks == 1) { + MessageInfo mi = jsm.GetLastMessage(StreamName, RawChunkSubject(oi.Nuid)); + // track the byte count and chunks + // update the digest + // write the bytes to the output file + totalBytes = mi.Data.Length; + totalChunks = 1; + digester.AppendData(mi.Data); + outputStream.Write(mi.Data, 0, mi.Data.Length); + } + else { + IJetStreamPushSyncSubscription sub = js.PushSubscribeSync( + RawChunkSubject(oi.Nuid), + PushSubscribeOptions.Builder() + .WithStream(StreamName) + .WithOrdered(true) + .Build()); + + bool notFinished = true; + while (notFinished) { + try + { + Msg m = sub.NextMessage(1000); + // track the byte count and chunks + // update the digest + // write the bytes to the output file + totalBytes += m.Data.Length; + totalChunks++; + digester.AppendData(m.Data); + outputStream.Write(m.Data, 0, m.Data.Length); + } + catch (NATSTimeoutException) + { + notFinished = false; + } + } + sub.Unsubscribe(); + } + outputStream.Flush(); + + if (totalBytes != oi.Size) { throw OsGetSizeMismatch.Instance(); } + if (totalChunks != oi.Chunks) { throw OsGetChunksMismatch.Instance(); } + if (!digester.DigestEntriesMatch(oi.Digest)) { throw OsGetDigestMismatch.Instance(); } + + return oi; + } + + public ObjectInfo GetInfo(string objectName) + { + return GetInfo(objectName, false); + } + + public ObjectInfo GetInfo(string objectName, bool includingDeleted) + { + MessageInfo mi = _getLast(RawMetaSubject(objectName)); + if (mi == null) + { + return null; + } + ObjectInfo info = new ObjectInfo(mi); + return includingDeleted || !info.IsDeleted ? info : null; + } + + public ObjectInfo UpdateMeta(string objectName, ObjectMeta meta) + { + Validator.ValidateNotNull(objectName, "object name"); + Validator.ValidateNotNull(meta, "ObjectMeta"); + Validator.ValidateNotNull(meta.ObjectName, "ObjectMeta name"); + + ObjectInfo currentInfo = GetInfo(objectName, true); + if (currentInfo == null) { + throw OsObjectNotFound.Instance(); + } + if (currentInfo.IsDeleted) { + throw OsObjectIsDeleted.Instance(); + } + + bool nameChange = !objectName.Equals(meta.ObjectName); + if (nameChange) { + if (GetInfo(meta.ObjectName, false) != null) { + throw OsObjectAlreadyExists.Instance(); + } + } + + currentInfo = PublishMeta(ObjectInfo.Builder(currentInfo) + .WithObjectName(meta.ObjectName) // replace the name + .WithDescription(meta.Description) // replace the description + .WithHeaders(meta.Headers) // replace the headers + .Build()); + + if (nameChange) { + // delete the meta from the old name via purge stream for subject + jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(RawMetaSubject(objectName))); + } + + return currentInfo; + } + + public ObjectInfo Delete(string objectName) + { + ObjectInfo info = GetInfo(objectName, true); + if (info == null) { + throw OsObjectNotFound.Instance(); + } + + if (info.IsDeleted) { + return info; + } + + ObjectInfo deleted = PublishMeta(ObjectInfo.Builder(info) + .WithDeleted(true) + .WithSize(0) + .WithChunks(0) + .WithDigest(null) + .Build()); + + jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(RawChunkSubject(info.Nuid))); + return deleted; + } + + public ObjectInfo AddLink(string objectName, ObjectInfo toInfo) + { + Validator.ValidateNotNull(objectName, "object name"); + Validator.ValidateNotNull(toInfo, "Link-To ObjectInfo"); + Validator.ValidateNotNull(toInfo.ObjectName, "Link-To ObjectMeta"); + + if (toInfo.IsDeleted) { + throw OsObjectIsDeleted.Instance(); + } + + if (toInfo.IsLink) { + throw OsCantLinkToLink.Instance(); + } + + ObjectInfo info = GetInfo(objectName, false); + if (info != null && !info.IsLink) { + throw OsObjectAlreadyExists.Instance(); + } + + return PublishMeta(ObjectInfo.Builder(BucketName, objectName) + .WithNuid(Nuid.NextGlobal()) + .WithObjectLink(toInfo.Bucket, toInfo.ObjectName) + .Build()); + } + + public ObjectInfo AddBucketLink(string objectName, IObjectStore toStore) + { + Validator.ValidateNotNull(objectName, "object name"); + Validator.ValidateNotNull(toStore, "Link-To ObjectStore"); + + ObjectInfo info = GetInfo(objectName, false); + if (info != null && !info.IsLink) { + throw OsObjectAlreadyExists.Instance(); + } + + return PublishMeta(ObjectInfo.Builder(BucketName, objectName) + .WithNuid(Nuid.NextGlobal()) + .WithBucketLink(toStore.BucketName) + .Build()); + } + + public ObjectStoreStatus Seal() + { + StreamInfo si = jsm.GetStreamInfo(StreamName); + si = jsm.UpdateStream(StreamConfiguration.Builder(si.Config).Seal().Build()); + return new ObjectStoreStatus(si); + } + + public IList GetList() + { + IList list = new List(); + VisitSubject(RawAllMetaSubject(), DeliverPolicy.LastPerSubject, false, true, m => { + ObjectInfo oi = new ObjectInfo(m); + if (!oi.IsDeleted) { + list.Add(oi); + } + }); + return list; + } + + public ObjectStoreWatchSubscription Watch(IObjectStoreWatcher watcher, params ObjectStoreWatchOption[] watchOptions) + { + return new ObjectStoreWatchSubscription(this, watcher, watchOptions); +After: + var nuid = Nuid.NextGlobal(); + var chunkSubject = PubSubChunkSubject(nuid); + + var chunkSize = meta.ObjectMetaOptions.ChunkSize; + if (chunkSize <= 0) { + chunkSize = DefaultChunkSize; + } + + try + { + var digester = new Digester(); + long totalSize = 0; // track total bytes read to make sure + var chunks = 0; + + // working with chunkSize number of bytes each time. + var buffer = new byte[chunkSize]; + var red = chunkSize; + while (red == chunkSize) + { + // keep reading while last chunk was full size + red = inputStream.Read(buffer, 0, chunkSize); + if (red > 0) + { + // copy if red is less than chunk size + var payload = buffer; + if (red < chunkSize) + { + payload = new byte[red]; + Array.Copy(buffer, payload, red); + } + + // digest the actual bytes + digester.AppendData(payload); + + // publish the payload + js.Publish(chunkSubject, payload); + + // track total chunks and bytes + chunks++; + totalSize += red; + } + } + + return PublishMeta(ObjectInfo.Builder(BucketName, meta) + .WithSize(totalSize) + .WithChunks(chunks) + .WithNuid(nuid) + .WithChunkSize(chunkSize) + .WithDigest(digester.GetDigestEntry()) + .Build()); + } + catch (Exception) + { + try { + jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(RawChunkSubject(nuid))); + } + catch (Exception) { /* ignore, there is already an error */ } + + throw; + } +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string nuid = Nuid.NextGlobal(); + string chunkSubject = PubSubChunkSubject(nuid); + + int chunkSize = meta.ObjectMetaOptions.ChunkSize; + if (chunkSize <= 0) { + chunkSize = DefaultChunkSize; + } + + try + { + Digester digester = new Digester(); + long totalSize = 0; // track total bytes read to make sure + int chunks = 0; + + // working with chunkSize number of bytes each time. + byte[] buffer = new byte[chunkSize]; + int red = chunkSize; + while (red == chunkSize) + { + // keep reading while last chunk was full size + red = inputStream.Read(buffer, 0, chunkSize); + if (red > 0) + { + // copy if red is less than chunk size + byte[] payload = buffer; + if (red < chunkSize) + { + payload = new byte[red]; + Array.Copy(buffer, payload, red); + } + + // digest the actual bytes + digester.AppendData(payload); + + // publish the payload + js.Publish(chunkSubject, payload); + + // track total chunks and bytes + chunks++; + totalSize += red; + } + } + + return PublishMeta(ObjectInfo.Builder(BucketName, meta) + .WithSize(totalSize) + .WithChunks(chunks) + .WithNuid(nuid) + .WithChunkSize(chunkSize) + .WithDigest(digester.GetDigestEntry()) + .Build()); + } + catch (Exception) + { + try { + jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(RawChunkSubject(nuid))); + } + catch (Exception) { /* ignore, there is already an error */ } + + throw; + } + } + + public ObjectInfo Put(string objectName, Stream inputStream) + { + return Put(ObjectMeta.ForObjectName(objectName), inputStream); + } + + public ObjectInfo Put(string objectName, byte[] input) + { + return Put(objectName, new MemoryStream(input)); + } + + public ObjectInfo Put(FileInfo fileInfo) + { + return Put(ObjectMeta.ForObjectName(fileInfo.Name), fileInfo.OpenRead()); + } + + public ObjectInfo Get(string objectName, Stream outputStream) + { + ObjectInfo oi = GetInfo(objectName, false); + if (oi == null) { + throw OsObjectNotFound.Instance(); + } + + if (oi.IsLink) { + ObjectLink link = oi.Link; + if (link.IsBucketLink) { + throw OsGetLinkToBucket.Instance(); + } + + // is the link in the same bucket + if (link.Bucket.Equals(BucketName)) { + return Get(link.ObjectName, outputStream); + } + + // different bucket + // get the store for the linked bucket, then get the linked object + return js.Conn.CreateObjectStoreContext(link.Bucket, oso).Get(link.ObjectName, outputStream); + } + + Digester digester = new Digester(); + long totalBytes = 0; + long totalChunks = 0; + + // if there is one chunk, just go get the message directly and we're done. + if (oi.Chunks == 1) { + MessageInfo mi = jsm.GetLastMessage(StreamName, RawChunkSubject(oi.Nuid)); + // track the byte count and chunks + // update the digest + // write the bytes to the output file + totalBytes = mi.Data.Length; + totalChunks = 1; + digester.AppendData(mi.Data); + outputStream.Write(mi.Data, 0, mi.Data.Length); + } + else { + IJetStreamPushSyncSubscription sub = js.PushSubscribeSync( + RawChunkSubject(oi.Nuid), + PushSubscribeOptions.Builder() + .WithStream(StreamName) + .WithOrdered(true) + .Build()); + + bool notFinished = true; + while (notFinished) { + try + { + Msg m = sub.NextMessage(1000); + // track the byte count and chunks + // update the digest + // write the bytes to the output file + totalBytes += m.Data.Length; + totalChunks++; + digester.AppendData(m.Data); + outputStream.Write(m.Data, 0, m.Data.Length); + } + catch (NATSTimeoutException) + { + notFinished = false; + } + } + sub.Unsubscribe(); + } + outputStream.Flush(); + + if (totalBytes != oi.Size) { throw OsGetSizeMismatch.Instance(); } + if (totalChunks != oi.Chunks) { throw OsGetChunksMismatch.Instance(); } + if (!digester.DigestEntriesMatch(oi.Digest)) { throw OsGetDigestMismatch.Instance(); } + + return oi; + } + + public ObjectInfo GetInfo(string objectName) + { + return GetInfo(objectName, false); + } + + public ObjectInfo GetInfo(string objectName, bool includingDeleted) + { + MessageInfo mi = _getLast(RawMetaSubject(objectName)); + if (mi == null) + { + return null; + } + ObjectInfo info = new ObjectInfo(mi); + return includingDeleted || !info.IsDeleted ? info : null; + } + + public ObjectInfo UpdateMeta(string objectName, ObjectMeta meta) + { + Validator.ValidateNotNull(objectName, "object name"); + Validator.ValidateNotNull(meta, "ObjectMeta"); + Validator.ValidateNotNull(meta.ObjectName, "ObjectMeta name"); + + ObjectInfo currentInfo = GetInfo(objectName, true); + if (currentInfo == null) { + throw OsObjectNotFound.Instance(); + } + if (currentInfo.IsDeleted) { + throw OsObjectIsDeleted.Instance(); + } + + bool nameChange = !objectName.Equals(meta.ObjectName); + if (nameChange) { + if (GetInfo(meta.ObjectName, false) != null) { + throw OsObjectAlreadyExists.Instance(); + } + } + + currentInfo = PublishMeta(ObjectInfo.Builder(currentInfo) + .WithObjectName(meta.ObjectName) // replace the name + .WithDescription(meta.Description) // replace the description + .WithHeaders(meta.Headers) // replace the headers + .Build()); + + if (nameChange) { + // delete the meta from the old name via purge stream for subject + jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(RawMetaSubject(objectName))); + } + + return currentInfo; + } + + public ObjectInfo Delete(string objectName) + { + ObjectInfo info = GetInfo(objectName, true); + if (info == null) { + throw OsObjectNotFound.Instance(); + } + + if (info.IsDeleted) { + return info; + } + + ObjectInfo deleted = PublishMeta(ObjectInfo.Builder(info) + .WithDeleted(true) + .WithSize(0) + .WithChunks(0) + .WithDigest(null) + .Build()); + + jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(RawChunkSubject(info.Nuid))); + return deleted; + } + + public ObjectInfo AddLink(string objectName, ObjectInfo toInfo) + { + Validator.ValidateNotNull(objectName, "object name"); + Validator.ValidateNotNull(toInfo, "Link-To ObjectInfo"); + Validator.ValidateNotNull(toInfo.ObjectName, "Link-To ObjectMeta"); + + if (toInfo.IsDeleted) { + throw OsObjectIsDeleted.Instance(); + } + + if (toInfo.IsLink) { + throw OsCantLinkToLink.Instance(); + } + + ObjectInfo info = GetInfo(objectName, false); + if (info != null && !info.IsLink) { + throw OsObjectAlreadyExists.Instance(); + } + + return PublishMeta(ObjectInfo.Builder(BucketName, objectName) + .WithNuid(Nuid.NextGlobal()) + .WithObjectLink(toInfo.Bucket, toInfo.ObjectName) + .Build()); + } + + public ObjectInfo AddBucketLink(string objectName, IObjectStore toStore) + { + Validator.ValidateNotNull(objectName, "object name"); + Validator.ValidateNotNull(toStore, "Link-To ObjectStore"); + + ObjectInfo info = GetInfo(objectName, false); + if (info != null && !info.IsLink) { + throw OsObjectAlreadyExists.Instance(); + } + + return PublishMeta(ObjectInfo.Builder(BucketName, objectName) + .WithNuid(Nuid.NextGlobal()) + .WithBucketLink(toStore.BucketName) + .Build()); + } + + public ObjectStoreStatus Seal() + { + StreamInfo si = jsm.GetStreamInfo(StreamName); + si = jsm.UpdateStream(StreamConfiguration.Builder(si.Config).Seal().Build()); + return new ObjectStoreStatus(si); + } + + public IList GetList() + { + IList list = new List(); + VisitSubject(RawAllMetaSubject(), DeliverPolicy.LastPerSubject, false, true, m => { + ObjectInfo oi = new ObjectInfo(m); + if (!oi.IsDeleted) { + list.Add(oi); + } + }); + return list; + } + + public ObjectStoreWatchSubscription Watch(IObjectStoreWatcher watcher, params ObjectStoreWatchOption[] watchOptions) + { + return new ObjectStoreWatchSubscription(this, watcher, watchOptions); +After: + var nuid = Nuid.NextGlobal(); + var chunkSubject = PubSubChunkSubject(nuid); + + var chunkSize = meta.ObjectMetaOptions.ChunkSize; + if (chunkSize <= 0) { + chunkSize = DefaultChunkSize; + } + + try + { + var digester = new Digester(); + long totalSize = 0; // track total bytes read to make sure + var chunks = 0; + + // working with chunkSize number of bytes each time. + var buffer = new byte[chunkSize]; + var red = chunkSize; + while (red == chunkSize) + { + // keep reading while last chunk was full size + red = inputStream.Read(buffer, 0, chunkSize); + if (red > 0) + { + // copy if red is less than chunk size + var payload = buffer; + if (red < chunkSize) + { + payload = new byte[red]; + Array.Copy(buffer, payload, red); + } + + // digest the actual bytes + digester.AppendData(payload); + + // publish the payload + js.Publish(chunkSubject, payload); + + // track total chunks and bytes + chunks++; + totalSize += red; + } + } + + return PublishMeta(ObjectInfo.Builder(BucketName, meta) + .WithSize(totalSize) + .WithChunks(chunks) + .WithNuid(nuid) + .WithChunkSize(chunkSize) + .WithDigest(digester.GetDigestEntry()) + .Build()); + } + catch (Exception) + { + try { + jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(RawChunkSubject(nuid))); + } + catch (Exception) { /* ignore, there is already an error */ } + + throw; + } +*/ + + } + + var nuid = Nuid.NextGlobal(); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + public ObjectStoreStatus GetStatus() +After: + public ObjectInfo Put(string objectName, Stream inputStream) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + public ObjectStoreStatus GetStatus() +After: + public ObjectInfo Put(string objectName, Stream inputStream) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + public ObjectStoreStatus GetStatus() +After: + public ObjectInfo Put(string objectName, Stream inputStream) +*/ + + var chunkSubject = PubSubChunkSubject(nuid); + + var chunkSize = meta.ObjectMetaOptions.ChunkSize; + if (chunkSize <= 0) + { + chunkSize = DefaultChunkSize; + } + + try + { + var digester = new Digester(); + long totalSize = 0; // track total bytes read to make sure + var chunks = 0; + + // working with chunkSize number of bytes each time. + var buffer = new byte[chunkSize]; + var red = chunkSize; + while (red == chunkSize) + { + // keep reading while last chunk was full size + red = inputStream.Read(buffer, 0, chunkSize); + if (red > 0) + { + // copy if red is less than chunk size + var payload = buffer; + if (red < chunkSize) + { + payload = new byte[red]; + Array.Copy(buffer, payload, red); + } + + // digest the actual bytes + digester.AppendData(payload); + + // publish the payload + js.Publish(chunkSubject, payload); + + // track total chunks and bytes + chunks++; + totalSize += red; + } + } + + return PublishMeta(ObjectInfo.Builder(BucketName, meta) + .WithSize(totalSize) + .WithChunks(chunks) + .WithNuid(nuid) + .WithChunkSize(chunkSize) + .WithDigest(digester.GetDigestEntry()) + .Build()); + } + catch (Exception) + { + try + { + jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(RawChunkSubject(nuid))); + } + catch (Exception) { /* ignore, there is already an error */ } + + throw; + } + } + + public ObjectInfo Put(string objectName, Stream inputStream) + { + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + return new ObjectStoreStatus(jsm.GetStreamInfo(StreamName)); +After: + return Put(ObjectMeta.ForObjectName(objectName), inputStream); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + return new ObjectStoreStatus(jsm.GetStreamInfo(StreamName)); +After: + return Put(ObjectMeta.ForObjectName(objectName), inputStream); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + return new ObjectStoreStatus(jsm.GetStreamInfo(StreamName)); +After: + return Put(ObjectMeta.ForObjectName(objectName), inputStream); +*/ + return +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + } +After: + public ObjectInfo Put(string objectName, byte[] input) + { + return Put(objectName, new MemoryStream(input)); + } + + public ObjectInfo Put(FileInfo fileInfo) + { + return Put(ObjectMeta.ForObjectName(fileInfo.Name), fileInfo.OpenRead()); + } + + public ObjectInfo Get(string objectName, Stream outputStream) + { + var oi = GetInfo(objectName, false) ?? throw OsObjectNotFound.Instance(); + + if (oi.IsLink) { + var link = oi.Link; + if (link.IsBucketLink) { + throw OsGetLinkToBucket.Instance(); + } + + // is the link in the same bucket + if (link.Bucket.Equals(BucketName)) { + return Get(link.ObjectName, outputStream); + } + + // different bucket + // get the store for the linked bucket, then get the linked object + return js.Conn.CreateObjectStoreContext(link.Bucket, oso).Get(link.ObjectName, outputStream); + } + + var digester = new Digester(); + long totalBytes = 0; + long totalChunks = 0; + + // if there is one chunk, just go get the message directly and we're done. + if (oi.Chunks == 1) { + var mi = jsm.GetLastMessage(StreamName, RawChunkSubject(oi.Nuid)); + // track the byte count and chunks + // update the digest + // write the bytes to the output file + totalBytes = mi.Data.Length; + totalChunks = 1; + digester.AppendData(mi.Data); + outputStream.Write(mi.Data, 0, mi.Data.Length); + } + else { + var sub = js.PushSubscribeSync( + RawChunkSubject(oi.Nuid), + PushSubscribeOptions.Builder() + .WithStream(StreamName) + .WithOrdered(true) + .Build()); + + var notFinished = true; + while (notFinished) { + try + { + var m = sub.NextMessage(1000); + // track the byte count and chunks + // update the digest + // write the bytes to the output file + totalBytes += m.Data.Length; + totalChunks++; + digester.AppendData(m.Data); + outputStream.Write(m.Data, 0, m.Data.Length); + } + catch (NATSTimeoutException) + { + notFinished = false; + } + } + sub.Unsubscribe(); + } + outputStream.Flush(); + + if (totalBytes != oi.Size) { throw OsGetSizeMismatch.Instance(); } + if (totalChunks != oi.Chunks) { throw OsGetChunksMismatch.Instance(); } + if (!digester.DigestEntriesMatch(oi.Digest)) { throw OsGetDigestMismatch.Instance(); } + + return oi; + } + + public ObjectInfo GetInfo(string objectName) + { + return GetInfo(objectName, false); + } + + public ObjectInfo GetInfo(string objectName, bool includingDeleted) + { + var mi = _getLast(RawMetaSubject(objectName)); + if (mi == null) + { + return null; + } + var info = new ObjectInfo(mi); + return includingDeleted || !info.IsDeleted ? info : null; + } + + public ObjectInfo UpdateMeta(string objectName, ObjectMeta meta) + { + Validator.ValidateNotNull(objectName, "object name"); + Validator.ValidateNotNull(meta, "ObjectMeta"); + Validator.ValidateNotNull(meta.ObjectName, "ObjectMeta name"); + + var currentInfo = GetInfo(objectName, true) ?? throw OsObjectNotFound.Instance(); + if (currentInfo.IsDeleted) { + throw OsObjectIsDeleted.Instance(); + } + + var nameChange = !objectName.Equals(meta.ObjectName); + if (nameChange) { + if (GetInfo(meta.ObjectName, false) != null) { + throw OsObjectAlreadyExists.Instance(); + } + } + + currentInfo = PublishMeta(ObjectInfo.Builder(currentInfo) + .WithObjectName(meta.ObjectName) // replace the name + .WithDescription(meta.Description) // replace the description + .WithHeaders(meta.Headers) // replace the headers + .Build()); + + if (nameChange) { + // delete the meta from the old name via purge stream for subject + jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(RawMetaSubject(objectName))); + } + + return currentInfo; + } + + public ObjectInfo Delete(string objectName) + { + var info = GetInfo(objectName, true) ?? throw OsObjectNotFound.Instance(); + + if (info.IsDeleted) { + return info; + } + + var deleted = PublishMeta(ObjectInfo.Builder(info) + .WithDeleted(true) + .WithSize(0) + .WithChunks(0) + .WithDigest(null) + .Build()); + + jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(RawChunkSubject(info.Nuid))); + return deleted; + } + + public ObjectInfo AddLink(string objectName, ObjectInfo toInfo) + { + Validator.ValidateNotNull(objectName, "object name"); + Validator.ValidateNotNull(toInfo, "Link-To ObjectInfo"); + Validator.ValidateNotNull(toInfo.ObjectName, "Link-To ObjectMeta"); + + if (toInfo.IsDeleted) { + throw OsObjectIsDeleted.Instance(); + } + + if (toInfo.IsLink) { + throw OsCantLinkToLink.Instance(); + } + + var info = GetInfo(objectName, false); + if (info != null && !info.IsLink) { + throw OsObjectAlreadyExists.Instance(); + } + + return PublishMeta(ObjectInfo.Builder(BucketName, objectName) + .WithNuid(Nuid.NextGlobal()) + .WithObjectLink(toInfo.Bucket, toInfo.ObjectName) + .Build()); + } + + public ObjectInfo AddBucketLink(string objectName, IObjectStore toStore) + { + Validator.ValidateNotNull(objectName, "object name"); + Validator.ValidateNotNull(toStore, "Link-To ObjectStore"); + + var info = GetInfo(objectName, false); + if (info != null && !info.IsLink) { + throw OsObjectAlreadyExists.Instance(); + } + + return PublishMeta(ObjectInfo.Builder(BucketName, objectName) + .WithNuid(Nuid.NextGlobal()) + .WithBucketLink(toStore.BucketName) + .Build()); + } + + public ObjectStoreStatus Seal() + { + var si = jsm.GetStreamInfo(StreamName); + si = jsm.UpdateStream(StreamConfiguration.Builder(si.Config).Seal().Build()); + return new ObjectStoreStatus(si); + } + + public IList GetList() + { + IList list = new List(); + VisitSubject(RawAllMetaSubject(), DeliverPolicy.LastPerSubject, false, true, m => { + var oi = new ObjectInfo(m); + if (!oi.IsDeleted) { + list.Add(oi); + } + }); + return list; + } + + public ObjectStoreWatchSubscription Watch(IObjectStoreWatcher watcher, params ObjectStoreWatchOption[] watchOptions) + { + return new ObjectStoreWatchSubscription(this, watcher, watchOptions); + } + + public ObjectStoreStatus GetStatus() + { + return new ObjectStoreStatus(jsm.GetStreamInfo(StreamName)); + } + } +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + } +After: + public ObjectInfo Put(string objectName, byte[] input) + { + return Put(objectName, new MemoryStream(input)); + } + + public ObjectInfo Put(FileInfo fileInfo) + { + return Put(ObjectMeta.ForObjectName(fileInfo.Name), fileInfo.OpenRead()); + } + + public ObjectInfo Get(string objectName, Stream outputStream) + { + var oi = GetInfo(objectName, false) ?? throw OsObjectNotFound.Instance(); + + if (oi.IsLink) { + var link = oi.Link; + if (link.IsBucketLink) { + throw OsGetLinkToBucket.Instance(); + } + + // is the link in the same bucket + if (link.Bucket.Equals(BucketName)) { + return Get(link.ObjectName, outputStream); + } + + // different bucket + // get the store for the linked bucket, then get the linked object + return js.Conn.CreateObjectStoreContext(link.Bucket, oso).Get(link.ObjectName, outputStream); + } + + var digester = new Digester(); + long totalBytes = 0; + long totalChunks = 0; + + // if there is one chunk, just go get the message directly and we're done. + if (oi.Chunks == 1) { + var mi = jsm.GetLastMessage(StreamName, RawChunkSubject(oi.Nuid)); + // track the byte count and chunks + // update the digest + // write the bytes to the output file + totalBytes = mi.Data.Length; + totalChunks = 1; + digester.AppendData(mi.Data); + outputStream.Write(mi.Data, 0, mi.Data.Length); + } + else { + var sub = js.PushSubscribeSync( + RawChunkSubject(oi.Nuid), + PushSubscribeOptions.Builder() + .WithStream(StreamName) + .WithOrdered(true) + .Build()); + + var notFinished = true; + while (notFinished) { + try + { + var m = sub.NextMessage(1000); + // track the byte count and chunks + // update the digest + // write the bytes to the output file + totalBytes += m.Data.Length; + totalChunks++; + digester.AppendData(m.Data); + outputStream.Write(m.Data, 0, m.Data.Length); + } + catch (NATSTimeoutException) + { + notFinished = false; + } + } + sub.Unsubscribe(); + } + outputStream.Flush(); + + if (totalBytes != oi.Size) { throw OsGetSizeMismatch.Instance(); } + if (totalChunks != oi.Chunks) { throw OsGetChunksMismatch.Instance(); } + if (!digester.DigestEntriesMatch(oi.Digest)) { throw OsGetDigestMismatch.Instance(); } + + return oi; + } + + public ObjectInfo GetInfo(string objectName) + { + return GetInfo(objectName, false); + } + + public ObjectInfo GetInfo(string objectName, bool includingDeleted) + { + var mi = _getLast(RawMetaSubject(objectName)); + if (mi == null) + { + return null; + } + var info = new ObjectInfo(mi); + return includingDeleted || !info.IsDeleted ? info : null; + } + + public ObjectInfo UpdateMeta(string objectName, ObjectMeta meta) + { + Validator.ValidateNotNull(objectName, "object name"); + Validator.ValidateNotNull(meta, "ObjectMeta"); + Validator.ValidateNotNull(meta.ObjectName, "ObjectMeta name"); + + var currentInfo = GetInfo(objectName, true) ?? throw OsObjectNotFound.Instance(); + if (currentInfo.IsDeleted) { + throw OsObjectIsDeleted.Instance(); + } + + var nameChange = !objectName.Equals(meta.ObjectName); + if (nameChange) { + if (GetInfo(meta.ObjectName, false) != null) { + throw OsObjectAlreadyExists.Instance(); + } + } + + currentInfo = PublishMeta(ObjectInfo.Builder(currentInfo) + .WithObjectName(meta.ObjectName) // replace the name + .WithDescription(meta.Description) // replace the description + .WithHeaders(meta.Headers) // replace the headers + .Build()); + + if (nameChange) { + // delete the meta from the old name via purge stream for subject + jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(RawMetaSubject(objectName))); + } + + return currentInfo; + } + + public ObjectInfo Delete(string objectName) + { + var info = GetInfo(objectName, true) ?? throw OsObjectNotFound.Instance(); + + if (info.IsDeleted) { + return info; + } + + var deleted = PublishMeta(ObjectInfo.Builder(info) + .WithDeleted(true) + .WithSize(0) + .WithChunks(0) + .WithDigest(null) + .Build()); + + jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(RawChunkSubject(info.Nuid))); + return deleted; + } + + public ObjectInfo AddLink(string objectName, ObjectInfo toInfo) + { + Validator.ValidateNotNull(objectName, "object name"); + Validator.ValidateNotNull(toInfo, "Link-To ObjectInfo"); + Validator.ValidateNotNull(toInfo.ObjectName, "Link-To ObjectMeta"); + + if (toInfo.IsDeleted) { + throw OsObjectIsDeleted.Instance(); + } + + if (toInfo.IsLink) { + throw OsCantLinkToLink.Instance(); + } + + var info = GetInfo(objectName, false); + if (info != null && !info.IsLink) { + throw OsObjectAlreadyExists.Instance(); + } + + return PublishMeta(ObjectInfo.Builder(BucketName, objectName) + .WithNuid(Nuid.NextGlobal()) + .WithObjectLink(toInfo.Bucket, toInfo.ObjectName) + .Build()); + } + + public ObjectInfo AddBucketLink(string objectName, IObjectStore toStore) + { + Validator.ValidateNotNull(objectName, "object name"); + Validator.ValidateNotNull(toStore, "Link-To ObjectStore"); + + var info = GetInfo(objectName, false); + if (info != null && !info.IsLink) { + throw OsObjectAlreadyExists.Instance(); + } + + return PublishMeta(ObjectInfo.Builder(BucketName, objectName) + .WithNuid(Nuid.NextGlobal()) + .WithBucketLink(toStore.BucketName) + .Build()); + } + + public ObjectStoreStatus Seal() + { + var si = jsm.GetStreamInfo(StreamName); + si = jsm.UpdateStream(StreamConfiguration.Builder(si.Config).Seal().Build()); + return new ObjectStoreStatus(si); + } + + public IList GetList() + { + IList list = new List(); + VisitSubject(RawAllMetaSubject(), DeliverPolicy.LastPerSubject, false, true, m => { + var oi = new ObjectInfo(m); + if (!oi.IsDeleted) { + list.Add(oi); + } + }); + return list; + } + + public ObjectStoreWatchSubscription Watch(IObjectStoreWatcher watcher, params ObjectStoreWatchOption[] watchOptions) + { + return new ObjectStoreWatchSubscription(this, watcher, watchOptions); + } + + public ObjectStoreStatus GetStatus() + { + return new ObjectStoreStatus(jsm.GetStreamInfo(StreamName)); + } + } +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + } +After: + public ObjectInfo Put(string objectName, byte[] input) + { + return Put(objectName, new MemoryStream(input)); + } + + public ObjectInfo Put(FileInfo fileInfo) + { + return Put(ObjectMeta.ForObjectName(fileInfo.Name), fileInfo.OpenRead()); + } + + public ObjectInfo Get(string objectName, Stream outputStream) + { + var oi = GetInfo(objectName, false) ?? throw OsObjectNotFound.Instance(); + + if (oi.IsLink) { + var link = oi.Link; + if (link.IsBucketLink) { + throw OsGetLinkToBucket.Instance(); + } + + // is the link in the same bucket + if (link.Bucket.Equals(BucketName)) { + return Get(link.ObjectName, outputStream); + } + + // different bucket + // get the store for the linked bucket, then get the linked object + return js.Conn.CreateObjectStoreContext(link.Bucket, oso).Get(link.ObjectName, outputStream); + } + + var digester = new Digester(); + long totalBytes = 0; + long totalChunks = 0; + + // if there is one chunk, just go get the message directly and we're done. + if (oi.Chunks == 1) { + var mi = jsm.GetLastMessage(StreamName, RawChunkSubject(oi.Nuid)); + // track the byte count and chunks + // update the digest + // write the bytes to the output file + totalBytes = mi.Data.Length; + totalChunks = 1; + digester.AppendData(mi.Data); + outputStream.Write(mi.Data, 0, mi.Data.Length); + } + else { + var sub = js.PushSubscribeSync( + RawChunkSubject(oi.Nuid), + PushSubscribeOptions.Builder() + .WithStream(StreamName) + .WithOrdered(true) + .Build()); + + var notFinished = true; + while (notFinished) { + try + { + var m = sub.NextMessage(1000); + // track the byte count and chunks + // update the digest + // write the bytes to the output file + totalBytes += m.Data.Length; + totalChunks++; + digester.AppendData(m.Data); + outputStream.Write(m.Data, 0, m.Data.Length); + } + catch (NATSTimeoutException) + { + notFinished = false; + } + } + sub.Unsubscribe(); + } + outputStream.Flush(); + + if (totalBytes != oi.Size) { throw OsGetSizeMismatch.Instance(); } + if (totalChunks != oi.Chunks) { throw OsGetChunksMismatch.Instance(); } + if (!digester.DigestEntriesMatch(oi.Digest)) { throw OsGetDigestMismatch.Instance(); } + + return oi; + } + + public ObjectInfo GetInfo(string objectName) + { + return GetInfo(objectName, false); + } + + public ObjectInfo GetInfo(string objectName, bool includingDeleted) + { + var mi = _getLast(RawMetaSubject(objectName)); + if (mi == null) + { + return null; + } + var info = new ObjectInfo(mi); + return includingDeleted || !info.IsDeleted ? info : null; + } + + public ObjectInfo UpdateMeta(string objectName, ObjectMeta meta) + { + Validator.ValidateNotNull(objectName, "object name"); + Validator.ValidateNotNull(meta, "ObjectMeta"); + Validator.ValidateNotNull(meta.ObjectName, "ObjectMeta name"); + + var currentInfo = GetInfo(objectName, true) ?? throw OsObjectNotFound.Instance(); + if (currentInfo.IsDeleted) { + throw OsObjectIsDeleted.Instance(); + } + + var nameChange = !objectName.Equals(meta.ObjectName); + if (nameChange) { + if (GetInfo(meta.ObjectName, false) != null) { + throw OsObjectAlreadyExists.Instance(); + } + } + + currentInfo = PublishMeta(ObjectInfo.Builder(currentInfo) + .WithObjectName(meta.ObjectName) // replace the name + .WithDescription(meta.Description) // replace the description + .WithHeaders(meta.Headers) // replace the headers + .Build()); + + if (nameChange) { + // delete the meta from the old name via purge stream for subject + jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(RawMetaSubject(objectName))); + } + + return currentInfo; + } + + public ObjectInfo Delete(string objectName) + { + var info = GetInfo(objectName, true) ?? throw OsObjectNotFound.Instance(); + + if (info.IsDeleted) { + return info; + } + + var deleted = PublishMeta(ObjectInfo.Builder(info) + .WithDeleted(true) + .WithSize(0) + .WithChunks(0) + .WithDigest(null) + .Build()); + + jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(RawChunkSubject(info.Nuid))); + return deleted; + } + + public ObjectInfo AddLink(string objectName, ObjectInfo toInfo) + { + Validator.ValidateNotNull(objectName, "object name"); + Validator.ValidateNotNull(toInfo, "Link-To ObjectInfo"); + Validator.ValidateNotNull(toInfo.ObjectName, "Link-To ObjectMeta"); + + if (toInfo.IsDeleted) { + throw OsObjectIsDeleted.Instance(); + } + + if (toInfo.IsLink) { + throw OsCantLinkToLink.Instance(); + } + + var info = GetInfo(objectName, false); + if (info != null && !info.IsLink) { + throw OsObjectAlreadyExists.Instance(); + } + + return PublishMeta(ObjectInfo.Builder(BucketName, objectName) + .WithNuid(Nuid.NextGlobal()) + .WithObjectLink(toInfo.Bucket, toInfo.ObjectName) + .Build()); + } + + public ObjectInfo AddBucketLink(string objectName, IObjectStore toStore) + { + Validator.ValidateNotNull(objectName, "object name"); + Validator.ValidateNotNull(toStore, "Link-To ObjectStore"); + + var info = GetInfo(objectName, false); + if (info != null && !info.IsLink) { + throw OsObjectAlreadyExists.Instance(); + } + + return PublishMeta(ObjectInfo.Builder(BucketName, objectName) + .WithNuid(Nuid.NextGlobal()) + .WithBucketLink(toStore.BucketName) + .Build()); + } + + public ObjectStoreStatus Seal() + { + var si = jsm.GetStreamInfo(StreamName); + si = jsm.UpdateStream(StreamConfiguration.Builder(si.Config).Seal().Build()); + return new ObjectStoreStatus(si); + } + + public IList GetList() + { + IList list = new List(); + VisitSubject(RawAllMetaSubject(), DeliverPolicy.LastPerSubject, false, true, m => { + var oi = new ObjectInfo(m); + if (!oi.IsDeleted) { + list.Add(oi); + } + }); + return list; + } + + public ObjectStoreWatchSubscription Watch(IObjectStoreWatcher watcher, params ObjectStoreWatchOption[] watchOptions) + { + return new ObjectStoreWatchSubscription(this, watcher, watchOptions); + } + + public ObjectStoreStatus GetStatus() + { + return new ObjectStoreStatus(jsm.GetStreamInfo(StreamName)); + } + } +*/ +Put(ObjectMeta.ForObjectName(objectName), inputStream); + } + + public ObjectInfo Put(string objectName, byte[] input) + { + return Put(objectName, new MemoryStream(input)); + } + + public ObjectInfo Put(FileInfo fileInfo) + { + return Put(ObjectMeta.ForObjectName(fileInfo.Name), fileInfo.OpenRead()); + } + + public ObjectInfo Get(string objectName, Stream outputStream) + { + var oi = GetInfo(objectName, false) ?? throw OsObjectNotFound.Instance(); + + if (oi.IsLink) + { + var link = oi.Link; + if (link.IsBucketLink) + { + throw OsGetLinkToBucket.Instance(); + } + + // is the link in the same bucket + if (link.Bucket.Equals(BucketName)) + { + return Get(link.ObjectName, outputStream); + } + + // different bucket + // get the store for the linked bucket, then get the linked object + return js.Conn.CreateObjectStoreContext(link.Bucket, oso).Get(link.ObjectName, outputStream); + } + + var digester = new Digester(); + long totalBytes = 0; + long totalChunks = 0; + + // if there is one chunk, just go get the message directly and we're done. + if (oi.Chunks == 1) + { + var mi = jsm.GetLastMessage(StreamName, RawChunkSubject(oi.Nuid)); + // track the byte count and chunks + // update the digest + // write the bytes to the output file + totalBytes = mi.Data.Length; + totalChunks = 1; + digester.AppendData(mi.Data); + outputStream.Write(mi.Data, 0, mi.Data.Length); + } + else + { + var sub = js.PushSubscribeSync( + RawChunkSubject(oi.Nuid), + PushSubscribeOptions.Builder() + .WithStream(StreamName) + .WithOrdered(true) + .Build()); + + var notFinished = true; + while (notFinished) + { + try + { + var m = sub.NextMessage(1000); + // track the byte count and chunks + // update the digest + // write the bytes to the output file + totalBytes += m.Data.Length; + totalChunks++; + digester.AppendData(m.Data); + outputStream.Write(m.Data, 0, m.Data.Length); + } + catch (NATSTimeoutException) + { + notFinished = false; + } + } + sub.Unsubscribe(); + } + outputStream.Flush(); + + if (totalBytes != oi.Size) + { throw OsGetSizeMismatch.Instance(); } + if (totalChunks != oi.Chunks) + { throw OsGetChunksMismatch.Instance(); } + if (!digester.DigestEntriesMatch(oi.Digest)) + { throw OsGetDigestMismatch.Instance(); } + + return oi; + } + + public ObjectInfo GetInfo(string objectName) + { + return GetInfo(objectName, false); + } + + public ObjectInfo GetInfo(string objectName, bool includingDeleted) + { + var mi = _getLast(RawMetaSubject(objectName)); + if (mi == null) + { + return null; + } + var info = new ObjectInfo(mi); + return includingDeleted || !info.IsDeleted ? info : null; + } + + public ObjectInfo UpdateMeta(string objectName, ObjectMeta meta) + { + Validator.ValidateNotNull(objectName, "object name"); + Validator.ValidateNotNull(meta, "ObjectMeta"); + Validator.ValidateNotNull(meta.ObjectName, "ObjectMeta name"); + + var currentInfo = GetInfo(objectName, true) ?? throw OsObjectNotFound.Instance(); + if (currentInfo.IsDeleted) + { + throw OsObjectIsDeleted.Instance(); + } + + var nameChange = !objectName.Equals(meta.ObjectName); + if (nameChange) + { + if (GetInfo(meta.ObjectName, false) != null) + { + throw OsObjectAlreadyExists.Instance(); + } + } + + currentInfo = PublishMeta(ObjectInfo.Builder(currentInfo) + .WithObjectName(meta.ObjectName) // replace the name + .WithDescription(meta.Description) // replace the description + .WithHeaders(meta.Headers) // replace the headers + .Build()); + + if (nameChange) + { + // delete the meta from the old name via purge stream for subject + jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(RawMetaSubject(objectName))); + } + + return currentInfo; + } + + public ObjectInfo Delete(string objectName) + { + var info = GetInfo(objectName, true) ?? throw OsObjectNotFound.Instance(); + + if (info.IsDeleted) + { + return info; + } + + var deleted = PublishMeta(ObjectInfo.Builder(info) + .WithDeleted(true) + .WithSize(0) + .WithChunks(0) + .WithDigest(null) + .Build()); + + jsm.PurgeStream(StreamName, PurgeOptions.WithSubject(RawChunkSubject(info.Nuid))); + return deleted; + } + + public ObjectInfo AddLink(string objectName, ObjectInfo toInfo) + { + Validator.ValidateNotNull(objectName, "object name"); + Validator.ValidateNotNull(toInfo, "Link-To ObjectInfo"); + Validator.ValidateNotNull(toInfo.ObjectName, "Link-To ObjectMeta"); + + if (toInfo.IsDeleted) + { + throw OsObjectIsDeleted.Instance(); + } + + if (toInfo.IsLink) + { + throw OsCantLinkToLink.Instance(); + } + + var info = GetInfo(objectName, false); + if (info != null && !info.IsLink) + { + throw OsObjectAlreadyExists.Instance(); + } + + return PublishMeta(ObjectInfo.Builder(BucketName, objectName) + .WithNuid(Nuid.NextGlobal()) + .WithObjectLink(toInfo.Bucket, toInfo.ObjectName) + .Build()); + } + + public ObjectInfo AddBucketLink(string objectName, IObjectStore toStore) + { + Validator.ValidateNotNull(objectName, "object name"); + Validator.ValidateNotNull(toStore, "Link-To ObjectStore"); + + var info = GetInfo(objectName, false); + if (info != null && !info.IsLink) + { + throw OsObjectAlreadyExists.Instance(); + } + + return PublishMeta(ObjectInfo.Builder(BucketName, objectName) + .WithNuid(Nuid.NextGlobal()) + .WithBucketLink(toStore.BucketName) + .Build()); + } + + public ObjectStoreStatus Seal() + { + var si = jsm.GetStreamInfo(StreamName); + si = jsm.UpdateStream(StreamConfiguration.Builder(si.Config).Seal().Build()); + return new ObjectStoreStatus(si); + } + + public IList GetList() + { + IList list = new List(); + VisitSubject(RawAllMetaSubject(), DeliverPolicy.LastPerSubject, false, true, m => + { + var oi = new ObjectInfo(m); + if (!oi.IsDeleted) + { + list.Add(oi); + } + }); + return list; + } + public ObjectStoreWatchSubscription Watch(IObjectStoreWatcher watcher, params ObjectStoreWatchOption[] watchOptions) { return new ObjectStoreWatchSubscription(this, watcher, watchOptions); diff --git a/src/NATS.Client/v1/ObjectStore/ObjectStoreConfiguration.cs b/src/NATS.Client/v1/ObjectStore/ObjectStoreConfiguration.cs index 139c3e0a..0388c4ac 100644 --- a/src/NATS.Client/v1/ObjectStore/ObjectStoreConfiguration.cs +++ b/src/NATS.Client/v1/ObjectStore/ObjectStoreConfiguration.cs @@ -1,4 +1,4 @@ -// Copyright 2022 The NATS Authors +// Copyright 2022 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -24,7 +24,7 @@ public class ObjectStoreConfiguration internal static readonly CompressionOption JsCompressionNo = CompressionOption.None; internal StreamConfiguration BackingConfig { get; } - + /// /// The name of the bucket /// @@ -57,7 +57,7 @@ internal ObjectStoreConfiguration(StreamConfiguration sc) /// The storage type for this bucket /// public StorageType StorageType => BackingConfig.StorageType; - + /// /// The number of replicas for this bucket /// @@ -96,7 +96,7 @@ public static ObjectStoreConfigurationBuilder Builder(string name) { return new ObjectStoreConfigurationBuilder(name); } - + /// /// Creates a builder for the ObjectStoreConfiguration. /// @@ -119,7 +119,7 @@ public sealed class ObjectStoreConfigurationBuilder /// /// Default builder /// - public ObjectStoreConfigurationBuilder() : this((ObjectStoreConfiguration)null) {} + public ObjectStoreConfigurationBuilder() : this((ObjectStoreConfiguration)null) { } /// /// Builder accepting the object store bucket name. @@ -134,12 +134,15 @@ public ObjectStoreConfigurationBuilder(string name) : this((ObjectStoreConfigura /// Construct the builder by copying another configuration /// /// the other configuration - public ObjectStoreConfigurationBuilder(ObjectStoreConfiguration osc) { - if (osc == null) { + public ObjectStoreConfigurationBuilder(ObjectStoreConfiguration osc) + { + if (osc == null) + { scBuilder = new StreamConfigurationBuilder(); WithReplicas(1); } - else { + else + { scBuilder = new StreamConfigurationBuilder(osc.BackingConfig); _name = ObjectStoreUtil.ExtractBucketName(osc.BackingConfig.Name); } @@ -150,7 +153,8 @@ public ObjectStoreConfigurationBuilder(ObjectStoreConfiguration osc) { /// /// name of the store bucket /// - public ObjectStoreConfigurationBuilder WithName(string name) { + public ObjectStoreConfigurationBuilder WithName(string name) + { _name = Validator.ValidateBucketName(name, true); return this; } @@ -160,17 +164,19 @@ public ObjectStoreConfigurationBuilder WithName(string name) { /// /// the description of the store. /// - public ObjectStoreConfigurationBuilder WithDescription(string description) { + public ObjectStoreConfigurationBuilder WithDescription(string description) + { scBuilder.WithDescription(description); return this; } - + /// /// Sets the maximum number of bytes in the ObjectStoreConfiguration. /// /// the maximum number of bytes /// - public ObjectStoreConfigurationBuilder WithMaxBucketSize(long maxBucketSize) { + public ObjectStoreConfigurationBuilder WithMaxBucketSize(long maxBucketSize) + { scBuilder.WithMaxBytes(Validator.ValidateMaxBucketBytes(maxBucketSize)); return this; } @@ -180,7 +186,8 @@ public ObjectStoreConfigurationBuilder WithMaxBucketSize(long maxBucketSize) { /// /// Sets the maximum age /// - public ObjectStoreConfigurationBuilder WithTtl(Duration ttl) { + public ObjectStoreConfigurationBuilder WithTtl(Duration ttl) + { scBuilder.WithMaxAge(ttl); return this; } @@ -190,7 +197,8 @@ public ObjectStoreConfigurationBuilder WithTtl(Duration ttl) { /// /// the storage type /// - public ObjectStoreConfigurationBuilder WithStorageType(StorageType storageType) { + public ObjectStoreConfigurationBuilder WithStorageType(StorageType storageType) + { scBuilder.WithStorageType(storageType); return this; } @@ -200,7 +208,8 @@ public ObjectStoreConfigurationBuilder WithStorageType(StorageType storageType) /// /// number of replicas /// the number of replicas - public ObjectStoreConfigurationBuilder WithReplicas(int replicas) { + public ObjectStoreConfigurationBuilder WithReplicas(int replicas) + { scBuilder.WithReplicas(replicas); return this; } @@ -210,7 +219,8 @@ public ObjectStoreConfigurationBuilder WithReplicas(int replicas) { /// /// the placement /// - public ObjectStoreConfigurationBuilder WithPlacement(Placement placement) { + public ObjectStoreConfigurationBuilder WithPlacement(Placement placement) + { scBuilder.WithPlacement(placement); return this; } diff --git a/src/NATS.Client/v1/ObjectStore/ObjectStoreManagement.cs b/src/NATS.Client/v1/ObjectStore/ObjectStoreManagement.cs index 93113bf0..bff5ebaa 100644 --- a/src/NATS.Client/v1/ObjectStore/ObjectStoreManagement.cs +++ b/src/NATS.Client/v1/ObjectStore/ObjectStoreManagement.cs @@ -14,13 +14,34 @@ internal ObjectStoreManagement(IConnection connection, ObjectStoreOptions oso) { jsm = (JetStreamManagement)connection.CreateJetStreamManagementContext(oso?.JSOptions); } - + public ObjectStoreStatus Create(ObjectStoreConfiguration config) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + StreamConfiguration sc = config.BackingConfig; +After: + var sc = config.BackingConfig; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + StreamConfiguration sc = config.BackingConfig; +After: + var sc = config.BackingConfig; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: StreamConfiguration sc = config.BackingConfig; +After: + var sc = config.BackingConfig; +*/ + + { + var sc = config.BackingConfig; return new ObjectStoreStatus(jsm.AddStream(sc)); } - + public ObjectStoreStatus Update(ObjectStoreConfiguration config) { return new ObjectStoreStatus(jsm.UpdateStream(config.BackingConfig)); @@ -29,9 +50,32 @@ public ObjectStoreStatus Update(ObjectStoreConfiguration config) public IList GetBucketNames() { IList buckets = new List(); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + IList names = jsm.GetStreamNames(); +After: + var names = jsm.GetStreamNames(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: IList names = jsm.GetStreamNames(); - foreach (string name in names) { - if (name.StartsWith(ObjStreamPrefix)) { +After: + var names = jsm.GetStreamNames(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + IList names = jsm.GetStreamNames(); +After: + var names = jsm.GetStreamNames(); +*/ + + var names = jsm.GetStreamNames(); + foreach (var name in names) + { + if (name.StartsWith(ObjStreamPrefix)) + { buckets.Add(ExtractBucketName(name)); } } @@ -43,12 +87,34 @@ public ObjectStoreStatus GetStatus(string bucketName) Validator.ValidateBucketName(bucketName, true); return new ObjectStoreStatus(jsm.GetStreamInfo(ToStreamName(bucketName))); } - + public IList GetStatuses() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: IList bucketNames = GetBucketNames(); +After: + var bucketNames = GetBucketNames(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + IList bucketNames = GetBucketNames(); +After: + var bucketNames = GetBucketNames(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + IList bucketNames = GetBucketNames(); +After: + var bucketNames = GetBucketNames(); +*/ + + { + var bucketNames = GetBucketNames(); IList statuses = new List(); - foreach (string name in bucketNames) { + foreach (var name in bucketNames) + { statuses.Add(new ObjectStoreStatus(jsm.GetStreamInfo(ToStreamName(name)))); } return statuses; diff --git a/src/NATS.Client/v1/ObjectStore/ObjectStoreOptions.cs b/src/NATS.Client/v1/ObjectStore/ObjectStoreOptions.cs index 2165e51e..31ed4b34 100644 --- a/src/NATS.Client/v1/ObjectStore/ObjectStoreOptions.cs +++ b/src/NATS.Client/v1/ObjectStore/ObjectStoreOptions.cs @@ -1,4 +1,4 @@ -// Copyright 2022 The NATS Authors +// Copyright 2022 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -18,8 +18,8 @@ namespace NATS.Client.ObjectStore { public sealed class ObjectStoreOptions : FeatureOptions { - private ObjectStoreOptions(JetStreamOptions jso) : base(jso) {} - + private ObjectStoreOptions(JetStreamOptions jso) : base(jso) { } + /// /// Gets a ObjectStoreOptionsBuilder builder. /// @@ -30,7 +30,7 @@ public static ObjectStoreOptionsBuilder Builder() { return new ObjectStoreOptionsBuilder(); } - + /// /// Gets the ObjectStoreOptions builder based on an existing ObjectStoreOptions object. /// @@ -40,7 +40,7 @@ public static ObjectStoreOptionsBuilder Builder(ObjectStoreOptions oso) { return new ObjectStoreOptionsBuilder(oso); } - + /// /// Gets the ObjectStoreOptions builder based on an existing JetStreamOptions object. /// @@ -58,7 +58,7 @@ public sealed class ObjectStoreOptionsBuilder /// /// Construct a builder /// - public ObjectStoreOptionsBuilder() : this(null) {} + public ObjectStoreOptionsBuilder() : this(null) { } /// /// Construct a builder from an existing ObjectStoreOptions object @@ -68,7 +68,7 @@ public ObjectStoreOptionsBuilder(ObjectStoreOptions oso) { _jsoBuilder = JetStreamOptions.Builder(oso?.JSOptions); } - + /// /// Sets the JetStreamOptions. /// @@ -85,7 +85,8 @@ public ObjectStoreOptionsBuilder WithJetStreamOptions(JetStreamOptions jso) /// /// the duration to wait for responses. /// The ObjectStoreOptionsBuilder - public ObjectStoreOptionsBuilder WithRequestTimeout(Duration requestTimeout) { + public ObjectStoreOptionsBuilder WithRequestTimeout(Duration requestTimeout) + { _jsoBuilder.WithRequestTimeout(requestTimeout); return this; } @@ -102,7 +103,7 @@ public ObjectStoreOptionsBuilder WithJsPrefix(string prefix) _jsoBuilder.WithPrefix(prefix); return this; } - + /// /// Sets the domain for JetStream subjects. A domain can be used in conjunction with /// user permissions to restrict access to certain JetStream instances. This must @@ -110,7 +111,7 @@ public ObjectStoreOptionsBuilder WithJsPrefix(string prefix) /// /// The domain. /// The JetStreamOptionsBuilder - public ObjectStoreOptionsBuilder WithJsDomain(string domain) + public ObjectStoreOptionsBuilder WithJsDomain(string domain) { _jsoBuilder.WithDomain(domain); return this; diff --git a/src/NATS.Client/v1/ObjectStore/ObjectStoreStatus.cs b/src/NATS.Client/v1/ObjectStore/ObjectStoreStatus.cs index c6215918..150ebcb8 100644 --- a/src/NATS.Client/v1/ObjectStore/ObjectStoreStatus.cs +++ b/src/NATS.Client/v1/ObjectStore/ObjectStoreStatus.cs @@ -1,4 +1,4 @@ -// Copyright 2021 The NATS Authors +// Copyright 2021 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -29,7 +29,8 @@ public class ObjectStoreStatus /// public ObjectStoreConfiguration Config { get; } - public ObjectStoreStatus(StreamInfo si) { + public ObjectStoreStatus(StreamInfo si) + { BackingStreamInfo = si; Config = new ObjectStoreConfiguration(si.Config); } @@ -63,7 +64,7 @@ public ObjectStoreStatus(StreamInfo si) { /// The storage type for this bucket /// public StorageType StorageType => Config.StorageType; - + /// /// The number of replicas for this bucket /// diff --git a/src/NATS.Client/v1/ObjectStore/ObjectStoreUtil.cs b/src/NATS.Client/v1/ObjectStore/ObjectStoreUtil.cs index e51220c3..6c09bc1a 100644 --- a/src/NATS.Client/v1/ObjectStore/ObjectStoreUtil.cs +++ b/src/NATS.Client/v1/ObjectStore/ObjectStoreUtil.cs @@ -1,4 +1,4 @@ -// Copyright 2022 The NATS Authors +// Copyright 2022 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: diff --git a/src/NATS.Client/v1/ObjectStore/ObjectStoreWatchOption.cs b/src/NATS.Client/v1/ObjectStore/ObjectStoreWatchOption.cs index 4cd48e4a..bd8b979c 100644 --- a/src/NATS.Client/v1/ObjectStore/ObjectStoreWatchOption.cs +++ b/src/NATS.Client/v1/ObjectStore/ObjectStoreWatchOption.cs @@ -1,4 +1,4 @@ -// Copyright 2022 The NATS Authors +// Copyright 2022 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -20,13 +20,13 @@ public enum ObjectStoreWatchOption /// Default is to include deletes. /// IgnoreDelete, - + /// /// Watch starting at the first entry for all keys. /// Default is to start at the last per key. /// IncludeHistory, - + /// /// Watch starting when there are new entries for keys. /// Default is to start at the last per key. diff --git a/src/NATS.Client/v1/ObjectStore/ObjectStoreWatchSubscription.cs b/src/NATS.Client/v1/ObjectStore/ObjectStoreWatchSubscription.cs index dda138fd..943d5abf 100644 --- a/src/NATS.Client/v1/ObjectStore/ObjectStoreWatchSubscription.cs +++ b/src/NATS.Client/v1/ObjectStore/ObjectStoreWatchSubscription.cs @@ -24,32 +24,113 @@ public class ObjectStoreWatchSubscription : IDisposable public ObjectStoreWatchSubscription(ObjectStore os, IObjectStoreWatcher watcher, params ObjectStoreWatchOption[] watchOptions) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string subscribeSubject = os.RawAllMetaSubject(); + + // figure out the result options + bool headersOnly = false; + bool includeDeletes = true; + DeliverPolicy deliverPolicy = DeliverPolicy.LastPerSubject; +After: + var subscribeSubject = os.RawAllMetaSubject(); + + // figure out the result options + var headersOnly = false; + var includeDeletes = true; + var deliverPolicy = DeliverPolicy.LastPerSubject; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string subscribeSubject = os.RawAllMetaSubject(); + + // figure out the result options + bool headersOnly = false; + bool includeDeletes = true; + DeliverPolicy deliverPolicy = DeliverPolicy.LastPerSubject; +After: + var subscribeSubject = os.RawAllMetaSubject(); + + // figure out the result options + var headersOnly = false; + var includeDeletes = true; + var deliverPolicy = DeliverPolicy.LastPerSubject; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string subscribeSubject = os.RawAllMetaSubject(); // figure out the result options bool headersOnly = false; bool includeDeletes = true; DeliverPolicy deliverPolicy = DeliverPolicy.LastPerSubject; - foreach (ObjectStoreWatchOption wo in watchOptions) { - switch (wo) { - case ObjectStoreWatchOption.IgnoreDelete: includeDeletes = false; break; - case ObjectStoreWatchOption.UpdatesOnly: deliverPolicy = DeliverPolicy.New; break; - case ObjectStoreWatchOption.IncludeHistory: deliverPolicy = DeliverPolicy.All; break; +After: + var subscribeSubject = os.RawAllMetaSubject(); + + // figure out the result options + var headersOnly = false; + var includeDeletes = true; + var deliverPolicy = DeliverPolicy.LastPerSubject; +*/ + + { + var subscribeSubject = os.RawAllMetaSubject(); + + // figure out the result options + var headersOnly = false; + var includeDeletes = true; + var deliverPolicy = DeliverPolicy.LastPerSubject; + foreach (var wo in watchOptions) + { + switch (wo) + { + case ObjectStoreWatchOption.IgnoreDelete: + includeDeletes = false; + break; + case ObjectStoreWatchOption.UpdatesOnly: + deliverPolicy = DeliverPolicy.New; + break; + case ObjectStoreWatchOption.IncludeHistory: + deliverPolicy = DeliverPolicy.All; + break; } } if (deliverPolicy == DeliverPolicy.New - || os._getLast(subscribeSubject) == null) { + || os._getLast(subscribeSubject) == null) + { endOfDataSent = new InterlockedBoolean(true); watcher.EndOfData(); } else { endOfDataSent = new InterlockedBoolean(false); - } - +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: PushSubscribeOptions pso = PushSubscribeOptions.Builder() +After: + var pso = PushSubscribeOptions.Builder() +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + PushSubscribeOptions pso = PushSubscribeOptions.Builder() +After: + var pso = PushSubscribeOptions.Builder() +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + PushSubscribeOptions pso = PushSubscribeOptions.Builder() +After: + var pso = PushSubscribeOptions.Builder() +*/ + + } + + var pso = PushSubscribeOptions.Builder() .WithStream(os.StreamName) .WithOrdered(true) .WithConfiguration( @@ -62,8 +143,29 @@ public ObjectStoreWatchSubscription(ObjectStore os, .Build(); EventHandler handler = (sender, args) => - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: ObjectInfo oi = new ObjectInfo(args.Message); +After: + var oi = new ObjectInfo(args.Message); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + ObjectInfo oi = new ObjectInfo(args.Message); +After: + var oi = new ObjectInfo(args.Message); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + ObjectInfo oi = new ObjectInfo(args.Message); +After: + var oi = new ObjectInfo(args.Message); +*/ + + { + var oi = new ObjectInfo(args.Message); if (includeDeletes || !oi.IsDeleted) { watcher.Watch(oi); @@ -78,8 +180,29 @@ public ObjectStoreWatchSubscription(ObjectStore os, sub = os.js.PushSubscribeAsync(subscribeSubject, handler, false, pso); if (endOfDataSent.IsFalse()) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: ulong pending = sub.GetConsumerInformation().CalculatedPending; +After: + var pending = sub.GetConsumerInformation().CalculatedPending; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + ulong pending = sub.GetConsumerInformation().CalculatedPending; +After: + var pending = sub.GetConsumerInformation().CalculatedPending; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + ulong pending = sub.GetConsumerInformation().CalculatedPending; +After: + var pending = sub.GetConsumerInformation().CalculatedPending; +*/ + + { + var pending = sub.GetConsumerInformation().CalculatedPending; if (pending == 0) { endOfDataSent.Set(true); diff --git a/src/NATS.Client/v1/Options.cs b/src/NATS.Client/v1/Options.cs index 4a5c96e3..41e588e3 100644 --- a/src/NATS.Client/v1/Options.cs +++ b/src/NATS.Client/v1/Options.cs @@ -39,10 +39,10 @@ public sealed class Options bool tlsFirst = false; private bool clientSideLimitChecks = true; IServerProvider serverProvider = null; - int maxReconnect = Defaults.MaxReconnect; + int maxReconnect = Defaults.MaxReconnect; int reconnectWait = Defaults.ReconnectWait; - int pingInterval = Defaults.PingInterval; - int timeout = Defaults.Timeout; + int pingInterval = Defaults.PingInterval; + int timeout = Defaults.Timeout; int reconnectJitter = Defaults.ReconnectJitter; int reconnectJitterTLS = Defaults.ReconnectJitterTLS; ITCPConnection tcpConnection = null; @@ -51,37 +51,37 @@ public sealed class Options private bool Equals(Options other) { - return url == other.url + return url == other.url && Equals(servers, other.servers) - && noRandomize == other.noRandomize + && noRandomize == other.noRandomize && name == other.name && verbose == other.verbose - && pedantic == other.pedantic - && useOldRequestStyle == other.useOldRequestStyle - && secure == other.secure - && allowReconnect == other.allowReconnect - && noEcho == other.noEcho - && ignoreDiscoveredServers == other.ignoreDiscoveredServers - && tlsFirst == other.tlsFirst - && clientSideLimitChecks == other.clientSideLimitChecks - && maxReconnect == other.maxReconnect - && reconnectWait == other.reconnectWait - && pingInterval == other.pingInterval - && timeout == other.timeout - && reconnectJitter == other.reconnectJitter - && reconnectJitterTLS == other.reconnectJitterTLS + && pedantic == other.pedantic + && useOldRequestStyle == other.useOldRequestStyle + && secure == other.secure + && allowReconnect == other.allowReconnect + && noEcho == other.noEcho + && ignoreDiscoveredServers == other.ignoreDiscoveredServers + && tlsFirst == other.tlsFirst + && clientSideLimitChecks == other.clientSideLimitChecks + && maxReconnect == other.maxReconnect + && reconnectWait == other.reconnectWait + && pingInterval == other.pingInterval + && timeout == other.timeout + && reconnectJitter == other.reconnectJitter + && reconnectJitterTLS == other.reconnectJitterTLS && Equals(certificates, other.certificates) - && maxPingsOut == other.maxPingsOut - && pendingMessageLimit == other.pendingMessageLimit - && pendingBytesLimit == other.pendingBytesLimit - && subscriberDeliveryTaskCount == other.subscriberDeliveryTaskCount - && subscriptionBatchSize == other.subscriptionBatchSize - && reconnectBufSize == other.reconnectBufSize - && user == other.user - && password == other.password - && token == other.token - && nkey == other.nkey - && customInboxPrefix == other.customInboxPrefix + && maxPingsOut == other.maxPingsOut + && pendingMessageLimit == other.pendingMessageLimit + && pendingBytesLimit == other.pendingBytesLimit + && subscriberDeliveryTaskCount == other.subscriberDeliveryTaskCount + && subscriptionBatchSize == other.subscriptionBatchSize + && reconnectBufSize == other.reconnectBufSize + && user == other.user + && password == other.password + && token == other.token + && nkey == other.nkey + && customInboxPrefix == other.customInboxPrefix && CheckCertificateRevocation == other.CheckCertificateRevocation; } @@ -91,10 +91,31 @@ public override bool Equals(object obj) } public override int GetHashCode() +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int hashCode = (url != null ? url.GetHashCode() : 0); +After: + var hashCode = (url != null ? url.GetHashCode() : 0); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int hashCode = (url != null ? url.GetHashCode() : 0); +After: + var hashCode = (url != null ? url.GetHashCode() : 0); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int hashCode = (url != null ? url.GetHashCode() : 0); +After: + var hashCode = (url != null ? url.GetHashCode() : 0); +*/ + { unchecked { - int hashCode = (url != null ? url.GetHashCode() : 0); + var hashCode = (url != null ? url.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (servers != null ? servers.GetHashCode() : 0); hashCode = (hashCode * 397) ^ noRandomize.GetHashCode(); hashCode = (hashCode * 397) ^ (name != null ? name.GetHashCode() : 0); @@ -237,7 +258,7 @@ public override int GetHashCode() /// public EventHandler FlowControlProcessedEventHandler; public EventHandler FlowControlProcessedEventHandlerOrDefault => FlowControlProcessedEventHandler ?? DefaultFlowControlProcessedEventHandler(); - + /// /// Represents the optional method that is used to fetch and /// return the account signed JWT for this user. Exceptions thrown @@ -346,8 +367,10 @@ public void SetNkey(string publicNkey, EventHandler user /// A path to a file containing the private Nkey. public void SetNkey(string publicNkey, string privateKeyPath) { - if (string.IsNullOrWhiteSpace(publicNkey)) throw new ArgumentException("Invalid publicNkey", nameof(publicNkey)); - if (string.IsNullOrWhiteSpace(privateKeyPath)) throw new ArgumentException("Invalid filePath", nameof(privateKeyPath)); + if (string.IsNullOrWhiteSpace(publicNkey)) + throw new ArgumentException("Invalid publicNkey", nameof(publicNkey)); + if (string.IsNullOrWhiteSpace(privateKeyPath)) + throw new ArgumentException("Invalid filePath", nameof(privateKeyPath)); nkey = publicNkey; UserSignatureEventHandler = (obj, args) => @@ -453,13 +476,13 @@ internal Options(Options o) CheckCertificateRevocation = o.CheckCertificateRevocation; } - static readonly string[] protcolSep = new[] {"://"}; - + static readonly string[] protcolSep = new[] { "://" }; + static string ensureProperUrl(string url) { if (string.IsNullOrWhiteSpace(url)) return url; - + if (url.StartsWith("nats://", StringComparison.OrdinalIgnoreCase)) return url; @@ -469,7 +492,7 @@ static string ensureProperUrl(string url) var parts = url.Split(protcolSep, StringSplitOptions.RemoveEmptyEntries); if (parts.Length == 1) return $"nats://{url.Trim()}"; - + throw new ArgumentException("Allowed protocols are: 'nats://, tls://'."); } @@ -490,7 +513,7 @@ public string Url url = null; servers = null; } - else + else { Servers = value.Split(','); } @@ -516,7 +539,7 @@ public string[] Servers else { servers = new string[value.Length]; - for (int i = 0; i < value.Length; i++) + for (var i = 0; i < value.Length; i++) { servers[i] = ensureProperUrl(value[i]); } @@ -531,8 +554,8 @@ public string[] Servers /// public bool NoRandomize { - get { return noRandomize; } - set { noRandomize = value; } + get { return noRandomize; } + set { noRandomize = value; } } /// @@ -549,7 +572,7 @@ public string Name /// public bool Verbose { - get { return verbose; } + get { return verbose; } set { verbose = value; } } @@ -766,7 +789,28 @@ public void AddCertificate(string fileName) { if (fileName == null) throw new ArgumentNullException("fileName"); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: X509Certificate2 cert = new X509Certificate2(fileName); +After: + var cert = new X509Certificate2(fileName); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + X509Certificate2 cert = new X509Certificate2(fileName); +After: + var cert = new X509Certificate2(fileName); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + X509Certificate2 cert = new X509Certificate2(fileName); +After: + var cert = new X509Certificate2(fileName); +*/ + + var cert = new X509Certificate2(fileName); AddCertificate(cert); } @@ -871,7 +915,7 @@ public int SubscriptionBatchSize /// Whether or not to ignore discovered servers when considering for connect/reconnect /// public bool IgnoreDiscoveredServers { get => ignoreDiscoveredServers; set => ignoreDiscoveredServers = value; } - + /// /// Whether or not to to do Tls Handshake First. Valid against servers 2.10.3 and later /// @@ -883,7 +927,7 @@ public int SubscriptionBatchSize public bool ClientSideLimitChecks { get => clientSideLimitChecks; set => clientSideLimitChecks = value; } internal IServerProvider ServerProvider { get => serverProvider; set => serverProvider = value; } - + private void appendEventHandler(StringBuilder sb, string name, Delegate eh) { if (eh != null) @@ -892,7 +936,7 @@ private void appendEventHandler(StringBuilder sb, string name, Delegate eh) sb.AppendFormat("{0}=null;", name); } - + /// /// Constant used to sets the reconnect buffer size to unbounded. /// @@ -983,8 +1027,29 @@ public void SetReconnectJitter(int jitter, int tlsJitter) /// /// string value of this instance. public override string ToString() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + StringBuilder sb = new StringBuilder(); +After: + var sb = new StringBuilder(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: StringBuilder sb = new StringBuilder(); +After: + var sb = new StringBuilder(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + StringBuilder sb = new StringBuilder(); +After: + var sb = new StringBuilder(); +*/ + + { + var sb = new StringBuilder(); sb.Append("{"); sb.AppendFormat("AllowReconnect={0};", allowReconnect); @@ -1004,7 +1069,7 @@ public override string ToString() sb.AppendFormat("MaxPingsOut={0};", MaxPingsOut); sb.AppendFormat("MaxReconnect={0};", MaxReconnect); - sb.AppendFormat("Name={0};", Name != null ? Name : "null"); + sb.AppendFormat("Name={0};", Name ?? "null"); sb.AppendFormat("NoRandomize={0};", NoRandomize); sb.AppendFormat("NoEcho={0};", NoEcho); sb.AppendFormat("IgnoreDiscoveredServers={0};", ignoreDiscoveredServers); @@ -1031,10 +1096,10 @@ public override string ToString() else { sb.Append("Servers={"); - foreach (string s in servers) + foreach (var s in servers) { sb.AppendFormat("[{0}]", s); - if (s != servers[servers.Length-1]) + if (s != servers[servers.Length - 1]) sb.AppendFormat(","); } sb.Append("};"); diff --git a/src/NATS.Client/v1/Parser.cs b/src/NATS.Client/v1/Parser.cs index d5b23291..4188c5c4 100644 --- a/src/NATS.Client/v1/Parser.cs +++ b/src/NATS.Client/v1/Parser.cs @@ -13,16 +13,16 @@ using System; using System.IO; - + namespace NATS.Client { internal sealed class MsgArg { - internal string subject; - internal string reply; - internal long sid; - internal int hdr; - internal int size; + internal string subject; + internal string reply; + internal long sid; + internal int hdr; + internal int size; } internal sealed class Parser @@ -49,45 +49,45 @@ internal Parser(Connection conn) // baked into the IL code (thus faster). An enum would // be nice, but we want speed in this critical section of // message handling. - private const int OP_START = 0; - private const int OP_PLUS = 1; - private const int OP_PLUS_O = 2; - private const int OP_PLUS_OK = 3; - private const int OP_MINUS = 4; - private const int OP_MINUS_E = 5; - private const int OP_MINUS_ER = 6; - private const int OP_MINUS_ERR = 7; + private const int OP_START = 0; + private const int OP_PLUS = 1; + private const int OP_PLUS_O = 2; + private const int OP_PLUS_OK = 3; + private const int OP_MINUS = 4; + private const int OP_MINUS_E = 5; + private const int OP_MINUS_ER = 6; + private const int OP_MINUS_ERR = 7; private const int OP_MINUS_ERR_SPC = 8; - private const int MINUS_ERR_ARG = 9; - private const int OP_C = 10; - private const int OP_CO = 11; - private const int OP_CON = 12; - private const int OP_CONN = 13; - private const int OP_CONNE = 14; - private const int OP_CONNEC = 15; - private const int OP_CONNECT = 16; - private const int CONNECT_ARG = 17; - private const int OP_M = 18; - private const int OP_MS = 19; - private const int OP_MSG = 20; - private const int OP_MSG_SPC = 21; - private const int MSG_ARG = 22; - private const int MSG_PAYLOAD = 23; - private const int MSG_END = 24; - private const int OP_P = 25; - private const int OP_H = 26; - private const int OP_PI = 27; - private const int OP_PIN = 28; - private const int OP_PING = 29; - private const int OP_PO = 30; - private const int OP_PON = 31; - private const int OP_PONG = 32; - private const int OP_I = 33; - private const int OP_IN = 34; - private const int OP_INF = 35; - private const int OP_INFO = 36; - private const int OP_INFO_SPC = 37; - private const int INFO_ARG = 38; + private const int MINUS_ERR_ARG = 9; + private const int OP_C = 10; + private const int OP_CO = 11; + private const int OP_CON = 12; + private const int OP_CONN = 13; + private const int OP_CONNE = 14; + private const int OP_CONNEC = 15; + private const int OP_CONNECT = 16; + private const int CONNECT_ARG = 17; + private const int OP_M = 18; + private const int OP_MS = 19; + private const int OP_MSG = 20; + private const int OP_MSG_SPC = 21; + private const int MSG_ARG = 22; + private const int MSG_PAYLOAD = 23; + private const int MSG_END = 24; + private const int OP_P = 25; + private const int OP_H = 26; + private const int OP_PI = 27; + private const int OP_PIN = 28; + private const int OP_PING = 29; + private const int OP_PO = 30; + private const int OP_PON = 31; + private const int OP_PONG = 32; + private const int OP_I = 33; + private const int OP_IN = 34; + private const int OP_INF = 35; + private const int OP_INFO = 36; + private const int OP_INFO_SPC = 37; + private const int INFO_ARG = 38; private void parseError(byte[] buffer, int position) { @@ -105,453 +105,507 @@ internal void parse(byte[] buffer, int len) switch (state) { - case OP_START: - switch (b) - { - case 'M': - case 'm': - state = OP_M; - hdr = -1; - break; - case 'H': - case 'h': - state = OP_H; - hdr = 1; - break; - case 'C': - case 'c': - state = OP_C; - break; - case 'P': - case 'p': - state = OP_P; - break; - case '+': - state = OP_PLUS; - break; - case '-': - state = OP_MINUS; - break; - case 'i': - case 'I': - state = OP_I; - break; - default: - parseError(buffer,i); - break; - } + case OP_START: + switch (b) + { + case 'M': + case 'm': + state = OP_M; + hdr = -1; break; - case OP_H: - switch(b) - { - case 'M': - case 'm': - state = OP_M; - break; - default: - parseError(buffer, i); - break; - } + case 'H': + case 'h': + state = OP_H; + hdr = 1; break; - case OP_M: - switch (b) - { - case 'S': - case 's': - state = OP_MS; - break; - default: - parseError(buffer, i); - break; - } + case 'C': + case 'c': + state = OP_C; break; - case OP_MS: - switch (b) - { - case 'G': - case 'g': - state = OP_MSG; - break; - default: - parseError(buffer, i); - break; - } + case 'P': + case 'p': + state = OP_P; break; - case OP_MSG: - switch (b) - { - case ' ': - case '\t': - state = OP_MSG_SPC; - break; - default: - parseError(buffer, i); - break; - } + case '+': + state = OP_PLUS; break; - case OP_MSG_SPC: - switch (b) - { - case ' ': - break; - case '\t': - break; - default: - state = MSG_ARG; - i--; - break; - } + case '-': + state = OP_MINUS; break; - case MSG_ARG: - switch (b) - { - case '\r': - break; - case '\n': - if (hdr >= 0) - { - conn.processHeaderMsgArgs(argBufBase, argBufStream.Position); - } - else - { - conn.processMsgArgs(argBufBase, argBufStream.Position); - } - argBufStream.Position = 0; - if (conn.msgArgs.size > msgBufBase.Length) - { - // Add 2 to account for the \r\n - msgBufBase = new byte[conn.msgArgs.size+2]; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int msgSize = conn.msgArgs.size; +After: + var msgSize = conn.msgArgs.size; +*/ - msgBufStream?.Dispose(); - msgBufStream = new MemoryStream(msgBufBase); - } - state = MSG_PAYLOAD; - break; - default: - argBufStream.WriteByte((byte)b); - break; - } - break; - case MSG_PAYLOAD: +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: int msgSize = conn.msgArgs.size; - if (msgSize == 0) - { - conn.processMsg(msgBufBase, msgSize); - state = MSG_END; - } - else - { +After: + var msgSize = conn.msgArgs.size; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int msgSize = conn.msgArgs.size; +After: + var msgSize = conn.msgArgs.size; +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: long position = msgBufStream.Position; int writeLen = msgSize - (int)position; int avail = len - i; +After: + var position = msgBufStream.Position; + var writeLen = msgSize - (int)position; + var avail = len - i; +*/ - if (avail < writeLen) - { - writeLen = avail; - } +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + long position = msgBufStream.Position; + int writeLen = msgSize - (int)position; + int avail = len - i; +After: + var position = msgBufStream.Position; + var writeLen = msgSize - (int)position; + var avail = len - i; +*/ - msgBufStream.Write(buffer, i, writeLen); - i += (writeLen - 1); +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + long position = msgBufStream.Position; + int writeLen = msgSize - (int)position; + int avail = len - i; +After: + var position = msgBufStream.Position; + var writeLen = msgSize - (int)position; + var avail = len - i; +*/ - if ((position + writeLen) >= msgSize) - { - conn.processMsg(msgBufBase, msgSize); - msgBufStream.Position = 0; - state = MSG_END; - } - } + case 'i': + case 'I': + state = OP_I; break; - case MSG_END: - switch (b) - { - case '\n': - state = OP_START; - break; - default: - continue; - } + default: + parseError(buffer, i); break; - case OP_PLUS: - switch (b) - { - case 'O': - case 'o': - state = OP_PLUS_O; - break; - default: - parseError(buffer, i); - break; - } + } + break; + case OP_H: + switch (b) + { + case 'M': + case 'm': + state = OP_M; break; - case OP_PLUS_O: - switch (b) - { - case 'K': - case 'k': - state = OP_PLUS_OK; - break; - default: - parseError(buffer, i); - break; - } + default: + parseError(buffer, i); break; - case OP_PLUS_OK: - switch (b) - { - case '\n': - conn.processOK(); - state = OP_START; - break; - } + } + break; + case OP_M: + switch (b) + { + case 'S': + case 's': + state = OP_MS; break; - case OP_MINUS: - switch (b) - { - case 'E': - case 'e': - state = OP_MINUS_E; - break; - default: - parseError(buffer, i); - break; - } + default: + parseError(buffer, i); break; - case OP_MINUS_E: - switch (b) - { - case 'R': - case 'r': - state = OP_MINUS_ER; - break; - default: - parseError(buffer, i); - break; - } + } + break; + case OP_MS: + switch (b) + { + case 'G': + case 'g': + state = OP_MSG; break; - case OP_MINUS_ER: - switch (b) - { - case 'R': - case 'r': - state = OP_MINUS_ERR; - break; - default: - parseError(buffer, i); - break; - } + default: + parseError(buffer, i); break; - case OP_MINUS_ERR: - switch (b) - { - case ' ': - case '\t': - state = OP_MINUS_ERR_SPC; - break; - default: - parseError(buffer, i); - break; - } + } + break; + case OP_MSG: + switch (b) + { + case ' ': + case '\t': + state = OP_MSG_SPC; break; - case OP_MINUS_ERR_SPC: - switch (b) - { - case ' ': - case '\t': - state = OP_MINUS_ERR_SPC; - break; - default: - state = MINUS_ERR_ARG; - i--; - break; - } + default: + parseError(buffer, i); break; - case MINUS_ERR_ARG: - switch (b) - { - case '\r': - break; - case '\n': - conn.processErr(argBufStream); - argBufStream.Position = 0; - state = OP_START; - break; - default: - argBufStream.WriteByte((byte)b); - break; - } + } + break; + case OP_MSG_SPC: + switch (b) + { + case ' ': break; - case OP_P: - switch (b) - { - case 'I': - case 'i': - state = OP_PI; - break; - case 'O': - case 'o': - state = OP_PO; - break; - default: - parseError(buffer, i); - break; - } + case '\t': break; - case OP_PO: - switch (b) - { - case 'N': - case 'n': - state = OP_PON; - break; - default: - parseError(buffer, i); - break; - } + default: + state = MSG_ARG; + i--; break; - case OP_PON: - switch (b) - { - case 'G': - case 'g': - state = OP_PONG; - break; - default: - parseError(buffer, i); - break; - } + } + break; + case MSG_ARG: + switch (b) + { + case '\r': break; - case OP_PONG: - switch (b) + case '\n': + if (hdr >= 0) { - case '\r': - break; - case '\n': - conn.processPong(); - state = OP_START; - break; + conn.processHeaderMsgArgs(argBufBase, argBufStream.Position); } - break; - case OP_PI: - switch (b) + else { - case 'N': - case 'n': - state = OP_PIN; - break; - default: - parseError(buffer, i); - break; + conn.processMsgArgs(argBufBase, argBufStream.Position); } - break; - case OP_PIN: - switch (b) + argBufStream.Position = 0; + if (conn.msgArgs.size > msgBufBase.Length) { - case 'G': - case 'g': - state = OP_PING; - break; - default: - parseError(buffer, i); - break; + // Add 2 to account for the \r\n + msgBufBase = new byte[conn.msgArgs.size + 2]; + + msgBufStream?.Dispose(); + msgBufStream = new MemoryStream(msgBufBase); } + state = MSG_PAYLOAD; break; - case OP_PING: - switch (b) - { - case '\r': - break; - case '\n': - conn.processPing(); - state = OP_START; - break; - default: - parseError(buffer, i); - break; - } + default: + argBufStream.WriteByte((byte)b); break; - case OP_I: - switch (b) + } + break; + case MSG_PAYLOAD: + var msgSize = conn.msgArgs.size; + if (msgSize == 0) + { + conn.processMsg(msgBufBase, msgSize); + state = MSG_END; + } + else + { + var position = msgBufStream.Position; + var writeLen = msgSize - (int)position; + var avail = len - i; + + if (avail < writeLen) { - case 'N': - case 'n': - state = OP_IN; - break; - default: - parseError(buffer, i); - break; + writeLen = avail; } - break; - case OP_IN: - switch (b) + + msgBufStream.Write(buffer, i, writeLen); + i += (writeLen - 1); + + if ((position + writeLen) >= msgSize) { - case 'F': - case 'f': - state = OP_INF; - break; - default: - parseError(buffer, i); - break; + conn.processMsg(msgBufBase, msgSize); + msgBufStream.Position = 0; + state = MSG_END; } + } + break; + case MSG_END: + switch (b) + { + case '\n': + state = OP_START; break; - case OP_INF: - switch (b) - { - case 'O': - case 'o': - state = OP_INFO; - break; - default: - parseError(buffer, i); - break; - } + default: + continue; + } + break; + case OP_PLUS: + switch (b) + { + case 'O': + case 'o': + state = OP_PLUS_O; break; - case OP_INFO: - switch (b) - { - case ' ': - case '\t': - state = OP_INFO_SPC; - break; - default: - parseError(buffer, i); - break; - } + default: + parseError(buffer, i); break; - case OP_INFO_SPC: - switch (b) - { - case ' ': - case '\t': - break; - default: - argBufStream.Position = 0; - state = INFO_ARG; - i--; - break; - } + } + break; + case OP_PLUS_O: + switch (b) + { + case 'K': + case 'k': + state = OP_PLUS_OK; break; - case INFO_ARG: - switch (b) - { - case '\r': - break; - case '\n': - conn.processAsyncInfo(argBufBase, (int)argBufStream.Position); - argBufStream.Position = 0; - state = OP_START; - break; - default: - argBufStream.WriteByte((byte)b); - break; - } + default: + parseError(buffer, i); + break; + } + break; + case OP_PLUS_OK: + switch (b) + { + case '\n': + conn.processOK(); + state = OP_START; + break; + } + break; + case OP_MINUS: + switch (b) + { + case 'E': + case 'e': + state = OP_MINUS_E; + break; + default: + parseError(buffer, i); + break; + } + break; + case OP_MINUS_E: + switch (b) + { + case 'R': + case 'r': + state = OP_MINUS_ER; break; default: - throw new NATSException("Unable to parse."); + parseError(buffer, i); + break; + } + break; + case OP_MINUS_ER: + switch (b) + { + case 'R': + case 'r': + state = OP_MINUS_ERR; + break; + default: + parseError(buffer, i); + break; + } + break; + case OP_MINUS_ERR: + switch (b) + { + case ' ': + case '\t': + state = OP_MINUS_ERR_SPC; + break; + default: + parseError(buffer, i); + break; + } + break; + case OP_MINUS_ERR_SPC: + switch (b) + { + case ' ': + case '\t': + state = OP_MINUS_ERR_SPC; + break; + default: + state = MINUS_ERR_ARG; + i--; + break; + } + break; + case MINUS_ERR_ARG: + switch (b) + { + case '\r': + break; + case '\n': + conn.processErr(argBufStream); + argBufStream.Position = 0; + state = OP_START; + break; + default: + argBufStream.WriteByte((byte)b); + break; + } + break; + case OP_P: + switch (b) + { + case 'I': + case 'i': + state = OP_PI; + break; + case 'O': + case 'o': + state = OP_PO; + break; + default: + parseError(buffer, i); + break; + } + break; + case OP_PO: + switch (b) + { + case 'N': + case 'n': + state = OP_PON; + break; + default: + parseError(buffer, i); + break; + } + break; + case OP_PON: + switch (b) + { + case 'G': + case 'g': + state = OP_PONG; + break; + default: + parseError(buffer, i); + break; + } + break; + case OP_PONG: + switch (b) + { + case '\r': + break; + case '\n': + conn.processPong(); + state = OP_START; + break; + } + break; + case OP_PI: + switch (b) + { + case 'N': + case 'n': + state = OP_PIN; + break; + default: + parseError(buffer, i); + break; + } + break; + case OP_PIN: + switch (b) + { + case 'G': + case 'g': + state = OP_PING; + break; + default: + parseError(buffer, i); + break; + } + break; + case OP_PING: + switch (b) + { + case '\r': + break; + case '\n': + conn.processPing(); + state = OP_START; + break; + default: + parseError(buffer, i); + break; + } + break; + case OP_I: + switch (b) + { + case 'N': + case 'n': + state = OP_IN; + break; + default: + parseError(buffer, i); + break; + } + break; + case OP_IN: + switch (b) + { + case 'F': + case 'f': + state = OP_INF; + break; + default: + parseError(buffer, i); + break; + } + break; + case OP_INF: + switch (b) + { + case 'O': + case 'o': + state = OP_INFO; + break; + default: + parseError(buffer, i); + break; + } + break; + case OP_INFO: + switch (b) + { + case ' ': + case '\t': + state = OP_INFO_SPC; + break; + default: + parseError(buffer, i); + break; + } + break; + case OP_INFO_SPC: + switch (b) + { + case ' ': + case '\t': + break; + default: + argBufStream.Position = 0; + state = INFO_ARG; + i--; + break; + } + break; + case INFO_ARG: + switch (b) + { + case '\r': + break; + case '\n': + conn.processAsyncInfo(argBufBase, (int)argBufStream.Position); + argBufStream.Position = 0; + state = OP_START; + break; + default: + argBufStream.WriteByte((byte)b); + break; + } + break; + default: + throw new NATSException("Unable to parse."); } // switch(state) } // for - + } // parse } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/ReconnectOptions.cs b/src/NATS.Client/v1/ReconnectOptions.cs index 388c46a2..fffd257b 100644 --- a/src/NATS.Client/v1/ReconnectOptions.cs +++ b/src/NATS.Client/v1/ReconnectOptions.cs @@ -1,4 +1,4 @@ -// Copyright 2024 The NATS Authors +// Copyright 2024 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -21,12 +21,12 @@ namespace NATS.Client public sealed class ReconnectOptions { private int flushTimeout = 0; - + /// /// Milliseconds. If supplied and at least 1 millisecond, the Reconnect will /// call IConnection.Flush(timeout) before closing and reconnecting. /// - public int FlushTimeout + public int FlushTimeout { get { return flushTimeout; } set { flushTimeout = value < 1 ? 0 : flushTimeout; } diff --git a/src/NATS.Client/v1/Rx/INATSObservable.cs b/src/NATS.Client/v1/Rx/INATSObservable.cs index 313df585..11be0c35 100644 --- a/src/NATS.Client/v1/Rx/INATSObservable.cs +++ b/src/NATS.Client/v1/Rx/INATSObservable.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -21,4 +21,4 @@ namespace NATS.Client.Rx /// /// public interface INATSObservable : IObservable, IDisposable { } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Rx/NATSObservable.cs b/src/NATS.Client/v1/Rx/NATSObservable.cs index de3ba5ce..5de66184 100644 --- a/src/NATS.Client/v1/Rx/NATSObservable.cs +++ b/src/NATS.Client/v1/Rx/NATSObservable.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -55,7 +55,7 @@ protected void InvokeObservers(T data) private void DisposeSubscription(ObserverSubscription sub) { - if(!subscriptions.TryRemove(sub.Id, out _)) + if (!subscriptions.TryRemove(sub.Id, out _)) return; try @@ -79,8 +79,8 @@ public IDisposable Subscribe(IObserver observer) throw new ArgumentNullException(nameof(observer)); var sub = new ObserverSubscription(observer, DisposeSubscription); - - if(!subscriptions.TryAdd(sub.Id, sub)) + + if (!subscriptions.TryAdd(sub.Id, sub)) throw new ArgumentException("Could not subscribe observer. Ensure it has not already been subscribed.", nameof(observer)); return sub; @@ -105,7 +105,7 @@ public ObserverSubscription(IObserver observer, Action protected virtual void Dispose(bool disposing) { - if(!disposing) + if (!disposing) return; var exceptions = new List(); @@ -123,7 +123,7 @@ protected virtual void Dispose(bool disposing) } } - if(exceptions.Any()) + if (exceptions.Any()) throw new NATSRxException( "One or more exception(s) occurred while disposing the NATS Observable's' subscriptions. See inner exception (AggregateException) for more details.", new AggregateException(exceptions)); @@ -135,4 +135,4 @@ public void Dispose() GC.SuppressFinalize(this); } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Rx/NATSObservableSubscription.cs b/src/NATS.Client/v1/Rx/NATSObservableSubscription.cs index 2bd451bb..9a0c5c2c 100644 --- a/src/NATS.Client/v1/Rx/NATSObservableSubscription.cs +++ b/src/NATS.Client/v1/Rx/NATSObservableSubscription.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -37,7 +37,7 @@ private NATSObservableSubscription(IAsyncSubscription subscription) /// /// public static INATSObservable Wrap(IAsyncSubscription subscription) - => new NATSObservableSubscription(subscription); + => new NATSObservableSubscription(subscription); private void OnIncomingMessage(object _, MsgHandlerEventArgs e) => InvokeObservers(e.Message); @@ -46,11 +46,11 @@ protected override void Dispose(bool disposing) { base.Dispose(disposing); - if(!disposing) + if (!disposing) return; subscription.MessageHandler -= OnIncomingMessage; subscription.Dispose(); } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Rx/NATSRxException.cs b/src/NATS.Client/v1/Rx/NATSRxException.cs index 92200532..2e9c31e6 100644 --- a/src/NATS.Client/v1/Rx/NATSRxException.cs +++ b/src/NATS.Client/v1/Rx/NATSRxException.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -20,8 +20,8 @@ namespace NATS.Client.Rx /// public class NATSRxException : NATSException { - public NATSRxException(string message) : base(message) {} + public NATSRxException(string message) : base(message) { } - public NATSRxException(string message, Exception innerException) : base(message, innerException) {} + public NATSRxException(string message, Exception innerException) : base(message, innerException) { } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Rx/Ops/DelegatingObserver.cs b/src/NATS.Client/v1/Rx/Ops/DelegatingObserver.cs index 963f02bd..827d5008 100644 --- a/src/NATS.Client/v1/Rx/Ops/DelegatingObserver.cs +++ b/src/NATS.Client/v1/Rx/Ops/DelegatingObserver.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -40,4 +40,4 @@ public void OnError(Exception error) public void OnCompleted() => onCompleted?.Invoke(); } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Rx/Ops/MapObservable.cs b/src/NATS.Client/v1/Rx/Ops/MapObservable.cs index 5b571391..d3074b61 100644 --- a/src/NATS.Client/v1/Rx/Ops/MapObservable.cs +++ b/src/NATS.Client/v1/Rx/Ops/MapObservable.cs @@ -23,7 +23,28 @@ internal sealed class MapObservable : INATSObservable public MapObservable(INATSObservable src, Func predicate) { this.src = src ?? throw new ArgumentNullException(nameof(src)); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: this.mapper = predicate ?? throw new ArgumentNullException(nameof(predicate)); +After: + mapper = predicate ?? throw new ArgumentNullException(nameof(predicate)); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this.mapper = predicate ?? throw new ArgumentNullException(nameof(predicate)); +After: + mapper = predicate ?? throw new ArgumentNullException(nameof(predicate)); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this.mapper = predicate ?? throw new ArgumentNullException(nameof(predicate)); +After: + mapper = predicate ?? throw new ArgumentNullException(nameof(predicate)); +*/ + + mapper = predicate ?? throw new ArgumentNullException(nameof(predicate)); } public void Dispose() => src?.Dispose(); @@ -51,4 +72,4 @@ public void OnCompleted() => observer.OnCompleted(); } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Rx/Ops/OpsExtensions.cs b/src/NATS.Client/v1/Rx/Ops/OpsExtensions.cs index fac7b8ea..88547ec5 100644 --- a/src/NATS.Client/v1/Rx/Ops/OpsExtensions.cs +++ b/src/NATS.Client/v1/Rx/Ops/OpsExtensions.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -72,6 +72,6 @@ public static INATSObservable Where(this INATSObservable ob, Func /// public static INATSObservable Select(this INATSObservable ob, Func mapper) - => new MapObservable(ob, mapper); + => new MapObservable(ob, mapper); } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Rx/Ops/SafeObserver.cs b/src/NATS.Client/v1/Rx/Ops/SafeObserver.cs index 94ee3722..c7184a60 100644 --- a/src/NATS.Client/v1/Rx/Ops/SafeObserver.cs +++ b/src/NATS.Client/v1/Rx/Ops/SafeObserver.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -49,4 +49,4 @@ public void OnError(Exception error) public void OnCompleted() => onCompleted?.Invoke(); } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Rx/Ops/WhereObservable.cs b/src/NATS.Client/v1/Rx/Ops/WhereObservable.cs index 46896786..8b12e094 100644 --- a/src/NATS.Client/v1/Rx/Ops/WhereObservable.cs +++ b/src/NATS.Client/v1/Rx/Ops/WhereObservable.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -55,4 +55,4 @@ public void OnCompleted() => observer.OnCompleted(); } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Rx/RxExtensions.cs b/src/NATS.Client/v1/Rx/RxExtensions.cs index 9db49f7a..b624b7c3 100644 --- a/src/NATS.Client/v1/Rx/RxExtensions.cs +++ b/src/NATS.Client/v1/Rx/RxExtensions.cs @@ -1,4 +1,4 @@ -// Copyright 2019 The NATS Authors +// Copyright 2019 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -39,4 +39,4 @@ public static INATSObservable Observe(this IConnection cn, string subject) public static INATSObservable ToObservable(this IAsyncSubscription subscription) => NATSObservableSubscription.Wrap(subscription); } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/ServerPool.cs b/src/NATS.Client/v1/ServerPool.cs index e01c71a5..a93b59ea 100644 --- a/src/NATS.Client/v1/ServerPool.cs +++ b/src/NATS.Client/v1/ServerPool.cs @@ -99,7 +99,7 @@ public virtual void ConnectToAServer(Predicate connectToServer) // Access the srvPool via index. SrvPool can theoretically grow // if a connection is made, info processed, then disconnected. // The ServerPool index operation is threadsafe to account for this. - for (int i = 0; (s = this[i]) != null; i++) + for (var i = 0; (s = this[i]) != null; i++) { if (connectToServer(s)) { @@ -145,14 +145,35 @@ public virtual void SetCurrentServer(Srv value) public virtual Srv SelectNextServer(int maxReconnect) { lock (poolLock) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Srv s = currentServer; +After: + var s = currentServer; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: Srv s = currentServer; - +After: + var s = currentServer; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Srv s = currentServer; +After: + var s = currentServer; +*/ + + { + var s = currentServer; + // remove the current server. if (s != null) { sList.Remove(s); - if (maxReconnect == Options.ReconnectForever || + if (maxReconnect == Options.ReconnectForever || (maxReconnect > 0 && s.Reconnects < maxReconnect)) { // if we haven't surpassed max reconnects, add it @@ -184,7 +205,7 @@ public virtual string[] GetServerList(bool implicitOnly) return null; var rv = new List(); - foreach (Srv s in list) + foreach (var s in list) { if (implicitOnly && !s.IsImplicit) continue; @@ -248,12 +269,33 @@ public virtual bool AcceptDiscoveredServers(string[] discoveredUrls) PruneOutdatedServers(discoveredUrls); return Add(discoveredUrls, true); - } - + } + // removes implicit servers NOT found in the provided list. internal void PruneOutdatedServers(string[] newUrls) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: LinkedList ulist = new LinkedList(newUrls); +After: + var ulist = new LinkedList(newUrls); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + LinkedList ulist = new LinkedList(newUrls); +After: + var ulist = new LinkedList(newUrls); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + LinkedList ulist = new LinkedList(newUrls); +After: + var ulist = new LinkedList(newUrls); +*/ + + { + var ulist = new LinkedList(newUrls); lock (poolLock) { @@ -262,12 +304,33 @@ internal void PruneOutdatedServers(string[] newUrls) // if a server is implicit and cannot be found in the url // list the remove it unless we are connected to it. - foreach (Srv s in tmp) + foreach (var s in tmp) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string hp = string.Format("{0}:{1}", s.Url.Host, s.Url.Port); +After: + var hp = string.Format("{0}:{1}", s.Url.Host, s.Url.Port); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string hp = string.Format("{0}:{1}", s.Url.Host, s.Url.Port); +After: + var hp = string.Format("{0}:{1}", s.Url.Host, s.Url.Port); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string hp = string.Format("{0}:{1}", s.Url.Host, s.Url.Port); +After: + var hp = string.Format("{0}:{1}", s.Url.Host, s.Url.Port); +*/ + { // The server returns ":". We can't compare // against Uri.Authority because that API may strip out // ports. - string hp = string.Format("{0}:{1}", s.Url.Host, s.Url.Port); + var hp = string.Format("{0}:{1}", s.Url.Host, s.Url.Port); if (s.IsImplicit && !ulist.Contains(hp) && s != currentServer) { @@ -283,9 +346,30 @@ internal bool Add(string[] urls, bool isImplicit) { if (urls == null) return false; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + bool didAdd = false; +After: + var didAdd = false; +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: bool didAdd = false; - foreach (string s in urls) +After: + var didAdd = false; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + bool didAdd = false; +After: + var didAdd = false; +*/ + + + var didAdd = false; + foreach (var s in urls) { didAdd |= Add(s, isImplicit); } @@ -299,16 +383,79 @@ internal static void Shuffle(IList list) { if (list == null) return; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int n = list.Count; +After: + var n = list.Count; +*/ +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: int n = list.Count; +After: + var n = list.Count; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int n = list.Count; +After: + var n = list.Count; +*/ + + + var n = list.Count; if (n == 1) return; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Random r = new Random(); +After: + var r = new Random(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Random r = new Random(); +After: + var r = new Random(); +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: Random r = new Random(); +After: + var r = new Random(); +*/ + + + var r = new Random(); while (n > 1) { n--; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: int k = r.Next(n + 1); +After: + var k = r.Next(n + 1); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int k = r.Next(n + 1); +After: + var k = r.Next(n + 1); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int k = r.Next(n + 1); +After: + var k = r.Next(n + 1); +*/ + + var k = r.Next(n + 1); var value = list[k]; list[k] = list[n]; list[n] = value; @@ -323,7 +470,7 @@ protected virtual void Shuffle() Shuffle(servers); sList.Clear(); - foreach (Srv s in servers) + foreach (var s in servers) { sList.AddLast(s); } @@ -353,7 +500,7 @@ public virtual bool HasSecureServer() { lock (poolLock) { - foreach (Srv s in sList) + foreach (var s in sList) { if (s.Secure) return true; diff --git a/src/NATS.Client/v1/Service/Discovery.cs b/src/NATS.Client/v1/Service/Discovery.cs index 417cb4e8..f068d24b 100644 --- a/src/NATS.Client/v1/Service/Discovery.cs +++ b/src/NATS.Client/v1/Service/Discovery.cs @@ -23,7 +23,7 @@ public class Discovery private readonly int maxResults; private Func _inboxSupplier; - + /// /// Override the normal inbox with a custom inbox to support you security model /// @@ -42,7 +42,7 @@ public Func InboxSupplier /// the NATS Connection /// optional, the maximum time to wait for discovery requests to complete or any number less than 1 to use the default /// optional, the maximum number of results to wait for or any number less than 1 to use the default - public Discovery(IConnection conn, int maxTimeMillis = 0, int maxResults = 0) + public Discovery(IConnection conn, int maxTimeMillis = 0, int maxResults = 0) { this.conn = conn; this.maxTimeMillis = maxTimeMillis < 1 ? DefaultDiscoveryMaxTimeMillis : maxTimeMillis; @@ -53,7 +53,7 @@ public Discovery(IConnection conn, int maxTimeMillis = 0, int maxResults = 0) // ---------------------------------------------------------------------------------------------------- // ping // ---------------------------------------------------------------------------------------------------- - + /// /// Make a ping request to all services running on the server. /// @@ -61,7 +61,8 @@ public Discovery(IConnection conn, int maxTimeMillis = 0, int maxResults = 0) public IList Ping() { IList list = new List(); - DiscoverMany(Service.SrvPing, null, json => { + DiscoverMany(Service.SrvPing, null, json => + { list.Add(new PingResponse(json)); }); return list; @@ -75,7 +76,8 @@ public IList Ping() public IList Ping(string serviceName) { IList list = new List(); - DiscoverMany(Service.SrvPing, serviceName, json => { + DiscoverMany(Service.SrvPing, serviceName, json => + { list.Add(new PingResponse(json)); }); return list; @@ -87,9 +89,30 @@ public IList Ping(string serviceName) /// the service name /// the specific service id /// the list of - public PingResponse PingForNameAndId(string serviceName, string serviceId) - { + public PingResponse PingForNameAndId(string serviceName, string serviceId) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string json = DiscoverOne(Service.SrvPing, serviceName, serviceId); +After: + var json = DiscoverOne(Service.SrvPing, serviceName, serviceId); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string json = DiscoverOne(Service.SrvPing, serviceName, serviceId); +After: + var json = DiscoverOne(Service.SrvPing, serviceName, serviceId); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string json = DiscoverOne(Service.SrvPing, serviceName, serviceId); +After: + var json = DiscoverOne(Service.SrvPing, serviceName, serviceId); +*/ + + { + var json = DiscoverOne(Service.SrvPing, serviceName, serviceId); return json == null ? null : new PingResponse(json); } @@ -104,7 +127,8 @@ public PingResponse PingForNameAndId(string serviceName, string serviceId) public IList Info() { IList list = new List(); - DiscoverMany(Service.SrvInfo, null, json => { + DiscoverMany(Service.SrvInfo, null, json => + { list.Add(new InfoResponse(json)); }); return list; @@ -118,7 +142,8 @@ public IList Info() public IList Info(string serviceName) { IList list = new List(); - DiscoverMany(Service.SrvInfo, serviceName, json => { + DiscoverMany(Service.SrvInfo, serviceName, json => + { list.Add(new InfoResponse(json)); }); return list; @@ -130,9 +155,30 @@ public IList Info(string serviceName) /// the service name /// the specific service id /// the list of - public InfoResponse InfoForNameAndId(string serviceName, string serviceId) - { + public InfoResponse InfoForNameAndId(string serviceName, string serviceId) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string json = DiscoverOne(Service.SrvInfo, serviceName, serviceId); +After: + var json = DiscoverOne(Service.SrvInfo, serviceName, serviceId); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string json = DiscoverOne(Service.SrvInfo, serviceName, serviceId); +After: + var json = DiscoverOne(Service.SrvInfo, serviceName, serviceId); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string json = DiscoverOne(Service.SrvInfo, serviceName, serviceId); +After: + var json = DiscoverOne(Service.SrvInfo, serviceName, serviceId); +*/ + + { + var json = DiscoverOne(Service.SrvInfo, serviceName, serviceId); return json == null ? null : new InfoResponse(json); } @@ -147,7 +193,8 @@ public InfoResponse InfoForNameAndId(string serviceName, string serviceId) public IList Stats() { IList list = new List(); - DiscoverMany(Service.SrvStats, null, json => { + DiscoverMany(Service.SrvStats, null, json => + { list.Add(new StatsResponse(json)); }); return list; @@ -161,7 +208,8 @@ public IList Stats() public IList Stats(string serviceName) { IList list = new List(); - DiscoverMany(Service.SrvStats, serviceName, json => { + DiscoverMany(Service.SrvStats, serviceName, json => + { list.Add(new StatsResponse(json)); }); return list; @@ -173,44 +221,191 @@ public IList Stats(string serviceName) /// the service name /// the specific service id /// the list of - public StatsResponse StatsForNameAndId(string serviceName, string serviceId) - { + public StatsResponse StatsForNameAndId(string serviceName, string serviceId) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string json = DiscoverOne(Service.SrvStats, serviceName, serviceId); +After: + var json = DiscoverOne(Service.SrvStats, serviceName, serviceId); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: string json = DiscoverOne(Service.SrvStats, serviceName, serviceId); +After: + var json = DiscoverOne(Service.SrvStats, serviceName, serviceId); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string json = DiscoverOne(Service.SrvStats, serviceName, serviceId); +After: + var json = DiscoverOne(Service.SrvStats, serviceName, serviceId); +*/ + + { + var json = DiscoverOne(Service.SrvStats, serviceName, serviceId); return json == null ? null : new StatsResponse(json); } // ---------------------------------------------------------------------------------------------------- // workers // ---------------------------------------------------------------------------------------------------- - private string DiscoverOne(string action, string serviceName, string serviceId) - { - try { + private string DiscoverOne(string action, string serviceName, string serviceId) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: string subject = Service.ToDiscoverySubject(action, serviceName, serviceId); Msg m = conn.Request(subject, null, maxTimeMillis); +After: + var subject = Service.ToDiscoverySubject(action, serviceName, serviceId); + var m = conn.Request(subject, null, maxTimeMillis); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string subject = Service.ToDiscoverySubject(action, serviceName, serviceId); + Msg m = conn.Request(subject, null, maxTimeMillis); +After: + var subject = Service.ToDiscoverySubject(action, serviceName, serviceId); + var m = conn.Request(subject, null, maxTimeMillis); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + string subject = Service.ToDiscoverySubject(action, serviceName, serviceId); + Msg m = conn.Request(subject, null, maxTimeMillis); +After: + var subject = Service.ToDiscoverySubject(action, serviceName, serviceId); + var m = conn.Request(subject, null, maxTimeMillis); +*/ + + { + try + { + var subject = Service.ToDiscoverySubject(action, serviceName, serviceId); + var m = conn.Request(subject, null, maxTimeMillis); return Encoding.UTF8.GetString(m.Data); } - catch (NATSTimeoutException) {} + catch (NATSTimeoutException) { } return null; } - private void DiscoverMany(string action, string serviceName, Action stringConsumer) + private void DiscoverMany(string action, string serviceName, Action stringConsumer) { ISyncSubscription sub = null; - try { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string replyTo = InboxSupplier.Invoke(); +After: + var replyTo = InboxSupplier.Invoke(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string replyTo = InboxSupplier.Invoke(); +After: + var replyTo = InboxSupplier.Invoke(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string replyTo = InboxSupplier.Invoke(); +After: + var replyTo = InboxSupplier.Invoke(); +*/ + + try + { + var replyTo = InboxSupplier.Invoke(); sub = conn.SubscribeSync(replyTo); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + string subject = Service.ToDiscoverySubject(action, serviceName, null); +After: + var subject = Service.ToDiscoverySubject(action, serviceName, null); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + string subject = Service.ToDiscoverySubject(action, serviceName, null); +After: + var subject = Service.ToDiscoverySubject(action, serviceName, null); +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: string subject = Service.ToDiscoverySubject(action, serviceName, null); +After: + var subject = Service.ToDiscoverySubject(action, serviceName, null); +*/ + + + var subject = Service.ToDiscoverySubject(action, serviceName, null); conn.Publish(subject, replyTo, null); +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int resultsLeft = maxResults; + Stopwatch sw = Stopwatch.StartNew(); + int timeLeft = maxTimeMillis; +After: + var resultsLeft = maxResults; + var sw = Stopwatch.StartNew(); + var timeLeft = maxTimeMillis; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int resultsLeft = maxResults; + Stopwatch sw = Stopwatch.StartNew(); + int timeLeft = maxTimeMillis; +After: + var resultsLeft = maxResults; + var sw = Stopwatch.StartNew(); + var timeLeft = maxTimeMillis; +*/ +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: int resultsLeft = maxResults; Stopwatch sw = Stopwatch.StartNew(); int timeLeft = maxTimeMillis; - while (resultsLeft > 0 && sw.ElapsedMilliseconds < maxTimeMillis) { +After: + var resultsLeft = maxResults; + var sw = Stopwatch.StartNew(); + var timeLeft = maxTimeMillis; +*/ + + + var resultsLeft = maxResults; + var sw = Stopwatch.StartNew(); + var timeLeft = maxTimeMillis; + while (resultsLeft > 0 && sw.ElapsedMilliseconds < maxTimeMillis) +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Msg msg = sub.NextMessage(timeLeft); +After: + var msg = sub.NextMessage(timeLeft); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Msg msg = sub.NextMessage(timeLeft); +After: + var msg = sub.NextMessage(timeLeft); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Msg msg = sub.NextMessage(timeLeft); +After: + var msg = sub.NextMessage(timeLeft); +*/ + + { try { - Msg msg = sub.NextMessage(timeLeft); + var msg = sub.NextMessage(timeLeft); stringConsumer.Invoke(Encoding.UTF8.GetString(msg.Data)); resultsLeft--; // try again while we have time @@ -222,9 +417,12 @@ private void DiscoverMany(string action, string serviceName, Action stri } } } - finally { - try { sub?.Unsubscribe(); } catch (Exception) { /* ignored */ } + finally + { + try + { sub?.Unsubscribe(); } + catch (Exception) { /* ignored */ } } } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Service/Endpoint.cs b/src/NATS.Client/v1/Service/Endpoint.cs index ab20634a..08f3a22c 100644 --- a/src/NATS.Client/v1/Service/Endpoint.cs +++ b/src/NATS.Client/v1/Service/Endpoint.cs @@ -21,10 +21,10 @@ public class Endpoint : JsonSerializable /// The name of the Endpoint public string Name { get; } - + /// The subject of the Endpoint public string Subject { get; } - + /// The queue group of the Endpoint public string QueueGroup { get; } @@ -36,21 +36,21 @@ public class Endpoint : JsonSerializable /// Directly construct an Endpoint with a name, which becomes the subject /// /// the name - public Endpoint(string name) : this(name, null, null, null, true) {} + public Endpoint(string name) : this(name, null, null, null, true) { } /// /// Directly construct an Endpoint with a name, which becomes the subject, and metadata /// /// the name /// the metadata - public Endpoint(string name, IDictionary metadata) : this(name, null, null, metadata, true) {} + public Endpoint(string name, IDictionary metadata) : this(name, null, null, metadata, true) { } /// /// Directly construct an Endpoint with a name and a subject /// /// the name /// the subject - public Endpoint(string name, string subject) : this(name, subject, null, null, true) {} + public Endpoint(string name, string subject) : this(name, subject, null, null, true) { } /// /// Directly construct an Endpoint with a name, the subject, and metadata @@ -58,7 +58,7 @@ public Endpoint(string name, string subject) : this(name, subject, null, null, t /// the name /// the subject /// the metadata - public Endpoint(string name, string subject, IDictionary metadata) : this(name, subject, null, metadata, true) {} + public Endpoint(string name, string subject, IDictionary metadata) : this(name, subject, null, metadata, true) { } /// /// Directly construct an Endpoint with a name, the subject, and metadata @@ -67,26 +67,33 @@ public Endpoint(string name, string subject, IDictionary metadat /// the subject /// the queue group /// the metadata - public Endpoint(string name, string subject, string queueGroup, IDictionary metadata) : this(name, subject, queueGroup, metadata, true) {} + public Endpoint(string name, string subject, string queueGroup, IDictionary metadata) : this(name, subject, queueGroup, metadata, true) { } // internal use constructors - internal Endpoint(string name, string subject, string queueGroup, IDictionary metadata, bool validate) { - if (validate) { + internal Endpoint(string name, string subject, string queueGroup, IDictionary metadata, bool validate) + { + if (validate) + { Name = Validator.ValidateIsRestrictedTerm(name, "Endpoint Name", true); - if (subject == null) { + if (subject == null) + { Subject = Name; } - else { + else + { Subject = Validator.ValidateSubjectTerm(subject, "Endpoint Subject", false); } - if (queueGroup == null) { + if (queueGroup == null) + { QueueGroup = DefaultQueueGroup; } - else { + else + { QueueGroup = Validator.ValidateSubjectTerm(queueGroup, "Endpoint Queue Group", true); } } - else { + else + { Name = name; Subject = subject; } @@ -109,15 +116,36 @@ internal Endpoint(JSONNode node) _metadata = JsonUtils.StringStringDictionary(node, ApiConstants.Metadata, true); } - private Endpoint(EndpointBuilder b) - : this(b._name, b._subject, b._queueGroup, b._metadata, true) {} + private Endpoint(EndpointBuilder b) + : this(b._name, b._subject, b._queueGroup, b._metadata, true) { } /// /// Build a service using a fluent builder. Use Service.Builder() to get an instance or new ServiceBuilder() /// public override JSONNode ToJsonNode() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + + { + var jso = new JSONObject(); JsonUtils.AddField(jso, ApiConstants.Name, Name); JsonUtils.AddField(jso, ApiConstants.Subject, Subject); JsonUtils.AddField(jso, ApiConstants.QueueGroup, QueueGroup); @@ -130,7 +158,7 @@ public override JSONNode ToJsonNode() /// /// the instance public static EndpointBuilder Builder() => new EndpointBuilder(); - + /// /// Build an Endpoint using a fluent builder. /// @@ -156,7 +184,8 @@ public EndpointBuilder WithEndpoint(Endpoint endpoint) /// /// the endpoint name /// - public EndpointBuilder WithName(string name) { + public EndpointBuilder WithName(string name) + { _name = name; return this; } @@ -166,7 +195,8 @@ public EndpointBuilder WithName(string name) { /// /// the subject /// - public EndpointBuilder WithSubject(string subject) { + public EndpointBuilder WithSubject(string subject) + { _subject = subject; return this; } @@ -176,7 +206,8 @@ public EndpointBuilder WithSubject(string subject) { /// /// the queue group /// - public EndpointBuilder WithQueueGroup(string queueGroup) { + public EndpointBuilder WithQueueGroup(string queueGroup) + { _queueGroup = queueGroup ?? DefaultQueueGroup; return this; } @@ -203,7 +234,8 @@ public EndpointBuilder WithMetadata(IDictionary metadata) /// Build the Endpoint instance. /// /// the Endpoint instance - public Endpoint Build() { + public Endpoint Build() + { return new Endpoint(this); } } @@ -220,17 +252,41 @@ protected bool Equals(Endpoint other) public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (ReferenceEquals(null, obj)) + return false; + if (ReferenceEquals(this, obj)) + return true; + if (obj.GetType() != GetType()) + return false; return Equals((Endpoint)obj); } public override int GetHashCode() +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int hashCode = (_metadata != null ? _metadata.GetHashCode() : 0); +After: + var hashCode = (_metadata != null ? _metadata.GetHashCode() : 0); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int hashCode = (_metadata != null ? _metadata.GetHashCode() : 0); +After: + var hashCode = (_metadata != null ? _metadata.GetHashCode() : 0); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int hashCode = (_metadata != null ? _metadata.GetHashCode() : 0); +After: + var hashCode = (_metadata != null ? _metadata.GetHashCode() : 0); +*/ + { unchecked { - int hashCode = (_metadata != null ? _metadata.GetHashCode() : 0); + var hashCode = (_metadata != null ? _metadata.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (Name != null ? Name.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (Subject != null ? Subject.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (QueueGroup != null ? QueueGroup.GetHashCode() : 0); @@ -238,4 +294,4 @@ public override int GetHashCode() } } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Service/EndpointContext.cs b/src/NATS.Client/v1/Service/EndpointContext.cs index 48962aff..e3bb1f23 100644 --- a/src/NATS.Client/v1/Service/EndpointContext.cs +++ b/src/NATS.Client/v1/Service/EndpointContext.cs @@ -38,7 +38,28 @@ internal EndpointContext(IConnection conn, bool internalEndpoint, ServiceEndpoin { this.conn = conn; this.se = se; +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: this.recordStats = !internalEndpoint; +After: + recordStats = !internalEndpoint; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this.recordStats = !internalEndpoint; +After: + recordStats = !internalEndpoint; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this.recordStats = !internalEndpoint; +After: + recordStats = !internalEndpoint; +*/ + + recordStats = !internalEndpoint; qGroup = internalEndpoint ? null : se.QueueGroup; numRequests = new InterlockedLong(); @@ -53,9 +74,36 @@ internal void Start() } internal void OnMessage(object sender, MsgHandlerEventArgs args) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: ServiceMsg smsg = new ServiceMsg(args.Message); Stopwatch sw = Stopwatch.StartNew(); +After: + var smsg = new ServiceMsg(args.Message); + var sw = Stopwatch.StartNew(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + ServiceMsg smsg = new ServiceMsg(args.Message); + Stopwatch sw = Stopwatch.StartNew(); +After: + var smsg = new ServiceMsg(args.Message); + var sw = Stopwatch.StartNew(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + ServiceMsg smsg = new ServiceMsg(args.Message); + Stopwatch sw = Stopwatch.StartNew(); +After: + var smsg = new ServiceMsg(args.Message); + var sw = Stopwatch.StartNew(); +*/ + + { + var smsg = new ServiceMsg(args.Message); + var sw = Stopwatch.StartNew(); try { if (recordStats) @@ -65,9 +113,36 @@ internal void OnMessage(object sender, MsgHandlerEventArgs args) se.Handler.Invoke(this, new ServiceMsgHandlerEventArgs(smsg)); } catch (Exception e) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: Exception b = e.GetBaseException(); string message = b.GetType() + ": " + b.Message; +After: + var b = e.GetBaseException(); + var message = b.GetType() + ": " + b.Message; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Exception b = e.GetBaseException(); + string message = b.GetType() + ": " + b.Message; +After: + var b = e.GetBaseException(); + var message = b.GetType() + ": " + b.Message; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Exception b = e.GetBaseException(); + string message = b.GetType() + ": " + b.Message; +After: + var b = e.GetBaseException(); + var message = b.GetType() + ": " + b.Message; +*/ + + { + var b = e.GetBaseException(); + var message = b.GetType() + ": " + b.Message; if (recordStats) { numErrors.Increment(); @@ -88,8 +163,9 @@ internal void OnMessage(object sender, MsgHandlerEventArgs args) } } } - - internal EndpointStats GetEndpointStats() { + + internal EndpointStats GetEndpointStats() + { return new EndpointStats( se.Endpoint.Name, se.Subject, @@ -102,7 +178,8 @@ internal EndpointStats GetEndpointStats() { started); } - internal void Reset() { + internal void Reset() + { numRequests.Set(0); numErrors.Set(0); processingTime.Set(0); @@ -110,4 +187,4 @@ internal void Reset() { started = DateTime.UtcNow; } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Service/EndpointStats.cs b/src/NATS.Client/v1/Service/EndpointStats.cs index 1cae52ef..93c1bced 100644 --- a/src/NATS.Client/v1/Service/EndpointStats.cs +++ b/src/NATS.Client/v1/Service/EndpointStats.cs @@ -67,22 +67,22 @@ public class EndpointStats : JsonSerializable { /// Get the name of the Endpoint public string Name { get; } - + /// Get the subject of the Endpoint public string Subject { get; } - + /// Get the queue group for the Endpoint public string QueueGroup { get; } - + /// The number of requests received by the endpoint - public long NumRequests { get; } - + public long NumRequests { get; } + /// Number of errors that the endpoint has raised - public long NumErrors { get; } - + public long NumErrors { get; } + /// Total processing time for the endpoint - public long ProcessingTime { get; } - + public long ProcessingTime { get; } + /// Average processing time is the total processing time divided by the num requests public long AverageProcessingTime { get; } @@ -94,11 +94,12 @@ public class EndpointStats : JsonSerializable /// The json representation of the custom data. May be null public string DataAsJson => Data == null ? null : Data.ToString(); - + /// Get the time the endpoint was started (or restarted) public DateTime Started { get; } - internal EndpointStats(string name, string subject, string queueGroup, long numRequests, long numErrors, long processingTime, string lastError, JSONNode data, DateTime started) { + internal EndpointStats(string name, string subject, string queueGroup, long numRequests, long numErrors, long processingTime, string lastError, JSONNode data, DateTime started) + { Name = name; Subject = subject; QueueGroup = queueGroup; @@ -122,7 +123,7 @@ internal EndpointStats(JSONNode node) AverageProcessingTime = JsonUtils.AsLongOrZero(node, ApiConstants.AverageProcessingTime); LastError = node[ApiConstants.LastError]; Data = node[ApiConstants.Data]; - Started = JsonUtils.AsDate(node[ApiConstants.Started]); + Started = JsonUtils.AsDate(node[ApiConstants.Started]); } internal static IList ListOf(JSONNode listNode) @@ -137,10 +138,31 @@ internal static IList ListOf(JSONNode listNode) } return list; } - + public override JSONNode ToJsonNode() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + + { + var jso = new JSONObject(); JsonUtils.AddField(jso, ApiConstants.Name, Name); JsonUtils.AddField(jso, ApiConstants.Subject, Subject); JsonUtils.AddField(jso, ApiConstants.QueueGroup, QueueGroup); @@ -161,31 +183,55 @@ public override string ToString() protected bool Equals(EndpointStats other) { - return Name == other.Name - && Subject == other.Subject - && QueueGroup == other.QueueGroup - && NumRequests == other.NumRequests - && NumErrors == other.NumErrors - && ProcessingTime == other.ProcessingTime - && AverageProcessingTime == other.AverageProcessingTime - && LastError == other.LastError + return Name == other.Name + && Subject == other.Subject + && QueueGroup == other.QueueGroup + && NumRequests == other.NumRequests + && NumErrors == other.NumErrors + && ProcessingTime == other.ProcessingTime + && AverageProcessingTime == other.AverageProcessingTime + && LastError == other.LastError && DataAsJson == other.DataAsJson && Started.Equals(other.Started); } public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (ReferenceEquals(null, obj)) + return false; + if (ReferenceEquals(this, obj)) + return true; + if (obj.GetType() != GetType()) + return false; return Equals((EndpointStats)obj); } public override int GetHashCode() +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int hashCode = (Name != null ? Name.GetHashCode() : 0); +After: + var hashCode = (Name != null ? Name.GetHashCode() : 0); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int hashCode = (Name != null ? Name.GetHashCode() : 0); +After: + var hashCode = (Name != null ? Name.GetHashCode() : 0); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int hashCode = (Name != null ? Name.GetHashCode() : 0); +After: + var hashCode = (Name != null ? Name.GetHashCode() : 0); +*/ + { unchecked { - int hashCode = (Name != null ? Name.GetHashCode() : 0); + var hashCode = (Name != null ? Name.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (Subject != null ? Subject.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (QueueGroup != null ? QueueGroup.GetHashCode() : 0); hashCode = (hashCode * 397) ^ NumRequests.GetHashCode(); diff --git a/src/NATS.Client/v1/Service/Group.cs b/src/NATS.Client/v1/Service/Group.cs index f64b167d..75bb972a 100644 --- a/src/NATS.Client/v1/Service/Group.cs +++ b/src/NATS.Client/v1/Service/Group.cs @@ -21,13 +21,13 @@ namespace NATS.Client.Service public class Group { private Group _next; - + /// Get the name of the group. public string Name { get; } - + /// Get the next group after this group. May be null. public Group Next => _next; - + /// The resolved subject of a group by concatenating the group name and any groups. /// /// For example, this: @@ -60,15 +60,37 @@ public Group(string name) /// the group to append /// like a fluent builder, return the Group instance public Group AppendGroup(Group group) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Group last = this; +After: + var last = this; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: Group last = this; - while (last._next != null) { +After: + var last = this; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Group last = this; +After: + var last = this; +*/ + + { + var last = this; + while (last._next != null) + { last = last._next; } last._next = group; return this; } - + public override string ToString() { return "Group [" + Subject.Replace('.', '/') + "]"; @@ -81,9 +103,12 @@ protected bool Equals(Group other) public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (ReferenceEquals(null, obj)) + return false; + if (ReferenceEquals(this, obj)) + return true; + if (obj.GetType() != GetType()) + return false; return Equals((Group)obj); } diff --git a/src/NATS.Client/v1/Service/InfoResponse.cs b/src/NATS.Client/v1/Service/InfoResponse.cs index 947e604f..2dcfd263 100644 --- a/src/NATS.Client/v1/Service/InfoResponse.cs +++ b/src/NATS.Client/v1/Service/InfoResponse.cs @@ -28,7 +28,7 @@ public class InfoResponse : ServiceResponse /// Description for the service public string Description { get; } - + /// List of endpoints public IList Endpoints { get; } @@ -37,7 +37,8 @@ public InfoResponse(string id, string name, string version, IDictionary(); - foreach (ServiceEndpoint se in serviceEndpoints) { + foreach (var se in serviceEndpoints) + { Endpoints.Add(new Endpoint( se.Name, se.Subject, @@ -47,7 +48,7 @@ public InfoResponse(string id, string name, string version, IDictionary metadata) - : base(ResponseType, id, name, version, metadata) {} + internal PingResponse(string id, string name, string version, IDictionary metadata) + : base(ResponseType, id, name, version, metadata) { } - internal PingResponse(string json) : this(JSON.Parse(json)) {} + internal PingResponse(string json) : this(JSON.Parse(json)) { } + + internal PingResponse(JSONNode node) : base(ResponseType, node) { } - internal PingResponse(JSONNode node) : base(ResponseType, node) {} - public override JSONNode ToJsonNode() { return BaseJsonObject(); diff --git a/src/NATS.Client/v1/Service/Service.cs b/src/NATS.Client/v1/Service/Service.cs index 28d65d89..22d85b01 100644 --- a/src/NATS.Client/v1/Service/Service.cs +++ b/src/NATS.Client/v1/Service/Service.cs @@ -43,12 +43,161 @@ public class Service /// The pre-constructed ping response. /// public PingResponse PingResponse { get; } - + /// /// The pre-constructed info response. /// public InfoResponse InfoResponse { get; } + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + private readonly Object startStopLock; + private TaskCompletionSource runningIndicator; + private DateTime started; + + internal Service(ServiceBuilder b) + { + string id = new Nuid().GetNext(); + conn = b.Conn; + DrainTimeoutMillis = b.DrainTimeoutMillis; + startStopLock = new object(); + + // set up the service contexts + // ! also while we are here, we need to collect the endpoints for the SchemaResponse + serviceContexts = new Dictionary(); + foreach (ServiceEndpoint se in b.ServiceEndpoints.Values) + { + serviceContexts[se.Name] = new EndpointContext(conn, false, se); + } + + // build static responses + PingResponse = new PingResponse(id, b.Name, b.Version, b.Metadata); + InfoResponse = new InfoResponse(id, b.Name, b.Version, b.Metadata, b.Description, b.ServiceEndpoints.Values); + + discoveryContexts = new List(); + AddDiscoveryContexts(SrvPing, PingResponse); + AddDiscoveryContexts(SrvInfo, InfoResponse); + AddStatsContexts(); + } + + private void AddDiscoveryContexts(string discoveryName, EventHandler handler) { + Endpoint[] endpoints = { + InternalEndpoint(discoveryName, null, null), + InternalEndpoint(discoveryName, PingResponse.Name, null), + InternalEndpoint(discoveryName, PingResponse.Name, PingResponse.Id) + }; + + foreach (Endpoint endpoint in endpoints) { + discoveryContexts.Add( + new EndpointContext(conn, true, + new ServiceEndpoint(endpoint, handler))); + } +After: + private readonly object startStopLock; + private TaskCompletionSource runningIndicator; + private DateTime started; + + internal Service(ServiceBuilder b) + { + var id = new Nuid().GetNext(); + conn = b.Conn; + DrainTimeoutMillis = b.DrainTimeoutMillis; + startStopLock = new object(); + + // set up the service contexts + // ! also while we are here, we need to collect the endpoints for the SchemaResponse + serviceContexts = new Dictionary(); + foreach (var se in b.ServiceEndpoints.Values) + { + serviceContexts[se.Name] = new EndpointContext(conn, false, se); + } + + // build static responses + PingResponse = new PingResponse(id, b.Name, b.Version, b.Metadata); + InfoResponse = new InfoResponse(id, b.Name, b.Version, b.Metadata, b.Description, b.ServiceEndpoints.Values); + + discoveryContexts = new List(); + AddDiscoveryContexts(SrvPing, PingResponse); + AddDiscoveryContexts(SrvInfo, InfoResponse); + AddStatsContexts(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + private readonly Object startStopLock; + private TaskCompletionSource runningIndicator; + private DateTime started; + + internal Service(ServiceBuilder b) + { + string id = new Nuid().GetNext(); + conn = b.Conn; + DrainTimeoutMillis = b.DrainTimeoutMillis; + startStopLock = new object(); + + // set up the service contexts + // ! also while we are here, we need to collect the endpoints for the SchemaResponse + serviceContexts = new Dictionary(); + foreach (ServiceEndpoint se in b.ServiceEndpoints.Values) + { + serviceContexts[se.Name] = new EndpointContext(conn, false, se); + } + + // build static responses + PingResponse = new PingResponse(id, b.Name, b.Version, b.Metadata); + InfoResponse = new InfoResponse(id, b.Name, b.Version, b.Metadata, b.Description, b.ServiceEndpoints.Values); + + discoveryContexts = new List(); + AddDiscoveryContexts(SrvPing, PingResponse); + AddDiscoveryContexts(SrvInfo, InfoResponse); + AddStatsContexts(); + } + + private void AddDiscoveryContexts(string discoveryName, EventHandler handler) { + Endpoint[] endpoints = { + InternalEndpoint(discoveryName, null, null), + InternalEndpoint(discoveryName, PingResponse.Name, null), + InternalEndpoint(discoveryName, PingResponse.Name, PingResponse.Id) + }; + + foreach (Endpoint endpoint in endpoints) { + discoveryContexts.Add( + new EndpointContext(conn, true, + new ServiceEndpoint(endpoint, handler))); + } +After: + private readonly object startStopLock; + private TaskCompletionSource runningIndicator; + private DateTime started; + + internal Service(ServiceBuilder b) + { + var id = new Nuid().GetNext(); + conn = b.Conn; + DrainTimeoutMillis = b.DrainTimeoutMillis; + startStopLock = new object(); + + // set up the service contexts + // ! also while we are here, we need to collect the endpoints for the SchemaResponse + serviceContexts = new Dictionary(); + foreach (var se in b.ServiceEndpoints.Values) + { + serviceContexts[se.Name] = new EndpointContext(conn, false, se); + } + + // build static responses + PingResponse = new PingResponse(id, b.Name, b.Version, b.Metadata); + InfoResponse = new InfoResponse(id, b.Name, b.Version, b.Metadata, b.Description, b.ServiceEndpoints.Values); + + discoveryContexts = new List(); + AddDiscoveryContexts(SrvPing, PingResponse); + AddDiscoveryContexts(SrvInfo, InfoResponse); + AddStatsContexts(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: private readonly Object startStopLock; private TaskCompletionSource runningIndicator; private DateTime started; @@ -90,8 +239,67 @@ private void AddDiscoveryContexts(string discoveryName, EventHandler runningIndicator; + private DateTime started; + + internal Service(ServiceBuilder b) + { + var id = new Nuid().GetNext(); + conn = b.Conn; + DrainTimeoutMillis = b.DrainTimeoutMillis; + startStopLock = new object(); + + // set up the service contexts + // ! also while we are here, we need to collect the endpoints for the SchemaResponse + serviceContexts = new Dictionary(); + foreach (var se in b.ServiceEndpoints.Values) + { + serviceContexts[se.Name] = new EndpointContext(conn, false, se); + } + + // build static responses + PingResponse = new PingResponse(id, b.Name, b.Version, b.Metadata); + InfoResponse = new InfoResponse(id, b.Name, b.Version, b.Metadata, b.Description, b.ServiceEndpoints.Values); + + discoveryContexts = new List(); + AddDiscoveryContexts(SrvPing, PingResponse); + AddDiscoveryContexts(SrvInfo, InfoResponse); + AddStatsContexts(); +*/ + private readonly object startStopLock; + private TaskCompletionSource runningIndicator; + private DateTime started; + + internal Service(ServiceBuilder b) + { + var id = new Nuid().GetNext(); + conn = b.Conn; + DrainTimeoutMillis = b.DrainTimeoutMillis; + startStopLock = new object(); + + // set up the service contexts + // ! also while we are here, we need to collect the endpoints for the SchemaResponse + serviceContexts = new Dictionary(); + foreach (var se in b.ServiceEndpoints.Values) + { + serviceContexts[se.Name] = new EndpointContext(conn, false, se); + } + + // build static responses + PingResponse = new PingResponse(id, b.Name, b.Version, b.Metadata); + InfoResponse = new InfoResponse(id, b.Name, b.Version, b.Metadata, b.Description, b.ServiceEndpoints.Values); + + discoveryContexts = new List(); + AddDiscoveryContexts(SrvPing, PingResponse); + AddDiscoveryContexts(SrvInfo, InfoResponse); + AddStatsContexts(); } + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: private void AddDiscoveryContexts(string discoveryName, ServiceResponse sr) { byte[] responseBytes = sr.Serialize(); void Handler(object sender, ServiceMsgHandlerEventArgs args) => args.Message.Respond(conn, responseBytes); @@ -279,19 +487,1273 @@ public EndpointStats GetEndpointStats(string endpointName) return c.GetEndpointStats(); } return null; +After: + private void AddDiscoveryContexts(string discoveryName, EventHandler handler) { + Endpoint[] responseBytes = { + InternalEndpoint(discoveryName, null, null), + InternalEndpoint(discoveryName, PingResponse.Name, null), + InternalEndpoint(discoveryName, PingResponse.Name, PingResponse.Id) + }; + + foreach (var endpoint in endpoints) { + discoveryContexts.Add( + new EndpointContext(conn, true, + new ServiceEndpoint(endpoint, handler))); + } } - public override string ToString() + private void AddDiscoveryContexts(string discoveryName, ServiceResponse sr) { + var responseBytes = sr.Serialize(); + void Handler(object sender, ServiceMsgHandlerEventArgs args) => args.Message.Respond(conn, responseBytes); + AddDiscoveryContexts(discoveryName, Handler); + } + + private void AddStatsContexts() { - JSONObject o = new JSONObject(); - JsonUtils.AddField(o, ApiConstants.Id, InfoResponse.Id); - JsonUtils.AddField(o, ApiConstants.Name, InfoResponse.Name); - JsonUtils.AddField(o, ApiConstants.Version, InfoResponse.Version); - JsonUtils.AddField(o, ApiConstants.Description, InfoResponse.Description); - JSONArray ja = new JSONArray(); + void Handler(object sender, ServiceMsgHandlerEventArgs args) => args.Message.Respond(conn, GetStatsResponse().Serialize()); + AddDiscoveryContexts(SrvStats, Handler); + } + + private Endpoint InternalEndpoint(string discoveryName, string optionalServiceNameSegment, string optionalServiceIdSegment) { + var subject = ToDiscoverySubject(endpointName, optionalServiceNameSegment, optionalServiceIdSegment); + return new Endpoint(subject, subject, null, null, false); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + private void AddDiscoveryContexts(string discoveryName, ServiceResponse sr) { + byte[] responseBytes = sr.Serialize(); + void Handler(object sender, ServiceMsgHandlerEventArgs args) => args.Message.Respond(conn, responseBytes); + AddDiscoveryContexts(discoveryName, Handler); + } + + private void AddStatsContexts() + { + void Handler(object sender, ServiceMsgHandlerEventArgs args) => args.Message.Respond(conn, GetStatsResponse().Serialize()); + AddDiscoveryContexts(SrvStats, Handler); + } + + private Endpoint InternalEndpoint(string discoveryName, string optionalServiceNameSegment, string optionalServiceIdSegment) { + string subject = ToDiscoverySubject(discoveryName, optionalServiceNameSegment, optionalServiceIdSegment); + return new Endpoint(subject, subject, null, null, false); + } + + internal static string ToDiscoverySubject(string discoverySubject, string serviceName, string serviceId) + { + if (string.IsNullOrEmpty(serviceId)) + { + if (string.IsNullOrEmpty(serviceName)) + { + return DefaultServicePrefix + discoverySubject; + } + + return DefaultServicePrefix + discoverySubject + "." + serviceName; + } + + return DefaultServicePrefix + discoverySubject + "." + serviceName + "." + serviceId; + } + + /// + /// Start the service + /// + /// a task that can be held to see if another thread called stop + public Task StartService() + { + lock (startStopLock) + { + if (runningIndicator == null) + { + runningIndicator = new TaskCompletionSource(); + foreach (var ctx in serviceContexts.Values) + { + ctx.Start(); + } + foreach (var ctx in discoveryContexts) + { + ctx.Start(); + } + started = DateTime.UtcNow; + } + return runningIndicator.Task; + } + } + + /// + /// Get an instance of a ServiceBuilder. + /// + /// the instance + public static ServiceBuilder Builder() + { + return new ServiceBuilder(); + } + + /// + /// Stop the service by draining. + /// + public void Stop() + { + Stop(true, null); + } + + /// + /// Stop the service by draining. Mark the task that was received from the start method that the service had an exception. + /// + /// the error cause + public void Stop(Exception e) + { + Stop(true, e); + } + + /// + /// Stop the service, optionally draining. + /// + /// the flag indicating to drain or not + public void Stop(bool drain) + { + Stop(drain, null); + } + + /// + /// Stop the service, optionally draining and optionally with an error cause + /// + /// the flag indicating to drain or not + /// the optional error cause. If supplied, mark the task that was received from the start method that the service had an exception. + public void Stop(bool drain, Exception e) + { + lock (startStopLock) { + if (runningIndicator != null) { + if (drain) + { + List tasks = new List(); + + foreach (var c in serviceContexts.Values) { + tasks.Add(c.Sub.DrainAsync(DrainTimeoutMillis)); + } + + foreach (var c in discoveryContexts) { + tasks.Add(c.Sub.DrainAsync(DrainTimeoutMillis)); + } + + // make sure drain is done before closing dispatcher + foreach (var t in tasks) + { + try { + t.Wait(DrainTimeoutMillis); + } + catch (Exception) { + // don't care if it completes successfully or not, just that it's done. + } + } + } + + // ok we are done + if (e == null) { + runningIndicator.SetResult(true); + } + else { + runningIndicator.SetException(e); + } + runningIndicator = null; // we don't need a copy anymore + } + } + } + + public void Reset() + { + started = DateTime.UtcNow; + foreach (EndpointContext c in discoveryContexts) { + c.Reset(); + } + foreach (EndpointContext c in serviceContexts.Values) { + c.Reset(); + } + } + + /// The id of the service + public string Id => InfoResponse.Id; + + /// The name of the service + public string Name => InfoResponse.Name; + + /// The version of the service + public string Version => InfoResponse.Version; + + /// The description of the service + public string Description => InfoResponse.Description; + + /// + /// Get the up-to-date stats response which contains a list of all + /// + /// the stats response + public StatsResponse GetStatsResponse() + { + IList endpointStatsList = new List(); + foreach (EndpointContext c in serviceContexts.Values) + { + endpointStatsList.Add(c.GetEndpointStats()); + } + return new StatsResponse(PingResponse, started, endpointStatsList); + } + + /// + /// Get the up-to-date for a specific endpoint + /// + /// the endpoint name + /// the EndpointStats or null if the name is not found + public EndpointStats GetEndpointStats(string endpointName) + { + EndpointContext c; + if (serviceContexts.TryGetValue(endpointName, out c)) + { + return c.GetEndpointStats(); + } + return null; +After: + private void AddDiscoveryContexts(string discoveryName, EventHandler handler) { + Endpoint[] responseBytes = { + InternalEndpoint(discoveryName, null, null), + InternalEndpoint(discoveryName, PingResponse.Name, null), + InternalEndpoint(discoveryName, PingResponse.Name, PingResponse.Id) + }; + + foreach (var endpoint in endpoints) { + discoveryContexts.Add( + new EndpointContext(conn, true, + new ServiceEndpoint(endpoint, handler))); + } + } + + private void AddDiscoveryContexts(string discoveryName, ServiceResponse sr) { + var responseBytes = sr.Serialize(); + void Handler(object sender, ServiceMsgHandlerEventArgs args) => args.Message.Respond(conn, responseBytes); + AddDiscoveryContexts(discoveryName, Handler); + } + + private void AddStatsContexts() + { + void Handler(object sender, ServiceMsgHandlerEventArgs args) => args.Message.Respond(conn, GetStatsResponse().Serialize()); + AddDiscoveryContexts(SrvStats, Handler); + } + + private Endpoint InternalEndpoint(string discoveryName, string optionalServiceNameSegment, string optionalServiceIdSegment) { + var subject = ToDiscoverySubject(endpointName, optionalServiceNameSegment, optionalServiceIdSegment); + return new Endpoint(subject, subject, null, null, false); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + private void AddDiscoveryContexts(string discoveryName, ServiceResponse sr) { + byte[] responseBytes = sr.Serialize(); + void Handler(object sender, ServiceMsgHandlerEventArgs args) => args.Message.Respond(conn, responseBytes); + AddDiscoveryContexts(discoveryName, Handler); + } + + private void AddStatsContexts() + { + void Handler(object sender, ServiceMsgHandlerEventArgs args) => args.Message.Respond(conn, GetStatsResponse().Serialize()); + AddDiscoveryContexts(SrvStats, Handler); + } + + private Endpoint InternalEndpoint(string discoveryName, string optionalServiceNameSegment, string optionalServiceIdSegment) { + string subject = ToDiscoverySubject(discoveryName, optionalServiceNameSegment, optionalServiceIdSegment); + return new Endpoint(subject, subject, null, null, false); + } + + internal static string ToDiscoverySubject(string discoverySubject, string serviceName, string serviceId) + { + if (string.IsNullOrEmpty(serviceId)) + { + if (string.IsNullOrEmpty(serviceName)) + { + return DefaultServicePrefix + discoverySubject; + } + + return DefaultServicePrefix + discoverySubject + "." + serviceName; + } + + return DefaultServicePrefix + discoverySubject + "." + serviceName + "." + serviceId; + } + + /// + /// Start the service + /// + /// a task that can be held to see if another thread called stop + public Task StartService() + { + lock (startStopLock) + { + if (runningIndicator == null) + { + runningIndicator = new TaskCompletionSource(); + foreach (var ctx in serviceContexts.Values) + { + ctx.Start(); + } + foreach (var ctx in discoveryContexts) + { + ctx.Start(); + } + started = DateTime.UtcNow; + } + return runningIndicator.Task; + } + } + + /// + /// Get an instance of a ServiceBuilder. + /// + /// the instance + public static ServiceBuilder Builder() + { + return new ServiceBuilder(); + } + + /// + /// Stop the service by draining. + /// + public void Stop() + { + Stop(true, null); + } + + /// + /// Stop the service by draining. Mark the task that was received from the start method that the service had an exception. + /// + /// the error cause + public void Stop(Exception e) + { + Stop(true, e); + } + + /// + /// Stop the service, optionally draining. + /// + /// the flag indicating to drain or not + public void Stop(bool drain) + { + Stop(drain, null); + } + + /// + /// Stop the service, optionally draining and optionally with an error cause + /// + /// the flag indicating to drain or not + /// the optional error cause. If supplied, mark the task that was received from the start method that the service had an exception. + public void Stop(bool drain, Exception e) + { + lock (startStopLock) { + if (runningIndicator != null) { + if (drain) + { + List tasks = new List(); + + foreach (var c in serviceContexts.Values) { + tasks.Add(c.Sub.DrainAsync(DrainTimeoutMillis)); + } + + foreach (var c in discoveryContexts) { + tasks.Add(c.Sub.DrainAsync(DrainTimeoutMillis)); + } + + // make sure drain is done before closing dispatcher + foreach (var t in tasks) + { + try { + t.Wait(DrainTimeoutMillis); + } + catch (Exception) { + // don't care if it completes successfully or not, just that it's done. + } + } + } + + // ok we are done + if (e == null) { + runningIndicator.SetResult(true); + } + else { + runningIndicator.SetException(e); + } + runningIndicator = null; // we don't need a copy anymore + } + } + } + + public void Reset() + { + started = DateTime.UtcNow; + foreach (EndpointContext c in discoveryContexts) { + c.Reset(); + } + foreach (EndpointContext c in serviceContexts.Values) { + c.Reset(); + } + } + + /// The id of the service + public string Id => InfoResponse.Id; + + /// The name of the service + public string Name => InfoResponse.Name; + + /// The version of the service + public string Version => InfoResponse.Version; + + /// The description of the service + public string Description => InfoResponse.Description; + + /// + /// Get the up-to-date stats response which contains a list of all + /// + /// the stats response + public StatsResponse GetStatsResponse() + { + IList endpointStatsList = new List(); + foreach (EndpointContext c in serviceContexts.Values) + { + endpointStatsList.Add(c.GetEndpointStats()); + } + return new StatsResponse(PingResponse, started, endpointStatsList); + } + + /// + /// Get the up-to-date for a specific endpoint + /// + /// the endpoint name + /// the EndpointStats or null if the name is not found + public EndpointStats GetEndpointStats(string endpointName) + { + EndpointContext c; + if (serviceContexts.TryGetValue(endpointName, out c)) + { + return c.GetEndpointStats(); + } + return null; +After: + private void AddDiscoveryContexts(string discoveryName, EventHandler handler) { + Endpoint[] responseBytes = { + InternalEndpoint(discoveryName, null, null), + InternalEndpoint(discoveryName, PingResponse.Name, null), + InternalEndpoint(discoveryName, PingResponse.Name, PingResponse.Id) + }; + + foreach (var endpoint in endpoints) { + discoveryContexts.Add( + new EndpointContext(conn, true, + new ServiceEndpoint(endpoint, handler))); + } + } + + private void AddDiscoveryContexts(string discoveryName, ServiceResponse sr) { + var responseBytes = sr.Serialize(); + void Handler(object sender, ServiceMsgHandlerEventArgs args) => args.Message.Respond(conn, responseBytes); + AddDiscoveryContexts(discoveryName, Handler); + } + + private void AddStatsContexts() + { + void Handler(object sender, ServiceMsgHandlerEventArgs args) => args.Message.Respond(conn, GetStatsResponse().Serialize()); + AddDiscoveryContexts(SrvStats, Handler); + } + + private Endpoint InternalEndpoint(string discoveryName, string optionalServiceNameSegment, string optionalServiceIdSegment) { + var subject = ToDiscoverySubject(endpointName, optionalServiceNameSegment, optionalServiceIdSegment); + return new Endpoint(subject, subject, null, null, false); +*/ + private void AddDiscoveryContexts(string discoveryName, EventHandler handler) + { + Endpoint[] endpoints = { + InternalEndpoint(discoveryName, null, null), + InternalEndpoint(discoveryName, PingResponse.Name, null), + InternalEndpoint(discoveryName, PingResponse.Name, PingResponse.Id) + }; + + foreach (var endpoint in endpoints) + { + discoveryContexts.Add( + new EndpointContext(conn, true, + new ServiceEndpoint(endpoint, handler))); + } + } + + private void AddDiscoveryContexts(string discoveryName, ServiceResponse sr) + { + var responseBytes = sr.Serialize(); + void Handler(object sender, ServiceMsgHandlerEventArgs args) => args.Message.Respond(conn, responseBytes); + AddDiscoveryContexts(discoveryName, Handler); + } + + private void AddStatsContexts() + { + void Handler(object sender, ServiceMsgHandlerEventArgs args) => args.Message.Respond(conn, GetStatsResponse().Serialize()); + AddDiscoveryContexts(SrvStats, Handler); + } + + private Endpoint InternalEndpoint(string discoveryName, string optionalServiceNameSegment, string optionalServiceIdSegment) + { + var subject = ToDiscoverySubject(discoveryName, optionalServiceNameSegment, optionalServiceIdSegment); + return n +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Added: + internal static string ToDiscoverySubject(string discoverySubject, string serviceName, string serviceId) + { + if (string.IsNullOrEmpty(serviceId)) + { + if (string.IsNullOrEmpty(serviceName)) + { + return DefaultServicePrefix + discoverySubject; + } + + return DefaultServicePrefix + discoverySubject + "." + serviceName; + } + + return DefaultServicePrefix + discoverySubject + "." + serviceName + "." + serviceId; + } + + /// + /// Start the service + /// + /// a task that can be held to see if another thread called stop + public Task StartService() + { + lock (startStopLock) + { + if (runningIndicator == null) + { + runningIndicator = new TaskCompletionSource(); + foreach (var ctx in serviceContexts.Values) + { + ctx.Start(); + } + foreach (var ctx in discoveryContexts) + { + ctx.Start(); + } + started = DateTime.UtcNow; + } + return runningIndicator.Task; + } + } + + /// + /// Get an instance of a ServiceBuilder. + /// + /// the instance + public static ServiceBuilder Builder() + { + return new ServiceBuilder(); + } + + /// + /// Stop the service by draining. + /// + public void Stop() + { + Stop(true, null); + } + + /// + /// Stop the service by draining. Mark the task that was received from the start method that the service had an exception. + /// + /// the error cause + public void Stop(Exception e) + { + Stop(true, e); + } + + /// + /// Stop the service, optionally draining. + /// + /// the flag indicating to drain or not + public void Stop(bool drain) + { + Stop(drain, null); + } + + /// + /// Stop the service, optionally draining and optionally with an error cause + /// + /// the flag indicating to drain or not + /// the optional error cause. If supplied, mark the task that was received from the start method that the service had an exception. + public void Stop(bool drain, Exception e) + { + lock (startStopLock) { + if (runningIndicator != null) { + if (drain) + { + var tasks = new List(); + + foreach (var c in serviceContexts.Values) { + tasks.Add(c.Sub.DrainAsync(DrainTimeoutMillis)); + } + + foreach (var c in discoveryContexts) { + tasks.Add(c.Sub.DrainAsync(DrainTimeoutMillis)); + } + + // make sure drain is done before closing dispatcher + foreach (var t in tasks) + { + try { + t.Wait(DrainTimeoutMillis); + } + catch (Exception) { + // don't care if it completes successfully or not, just that it's done. + } + } + } + + // ok we are done + if (e == null) { + runningIndicator.SetResult(true); + } + else { + runningIndicator.SetException(e); + } + runningIndicator = null; // we don't need a copy anymore + } + } + } + + public void Reset() + { + started = DateTime.UtcNow; + foreach (var c in discoveryContexts) { + c.Reset(); + } + foreach (var c in serviceContexts.Values) { + c.Reset(); + } + } + + /// The id of the service + public string Id => InfoResponse.Id; + + /// The name of the service + public string Name => InfoResponse.Name; + + /// The version of the service + public string Version => InfoResponse.Version; + + /// The description of the service + public string Description => InfoResponse.Description; + + /// + /// Get the up-to-date stats response which contains a list of all + /// + /// the stats response + public StatsResponse GetStatsResponse() + { + IList endpointStatsList = new List(); + foreach (var c in serviceContexts.Values) + { + endpointStatsList.Add(c.GetEndpointStats()); + } + return new StatsResponse(PingResponse, started, endpointStatsList); + } + + /// + /// Get the up-to-date for a specific endpoint + /// + /// the endpoint name + /// the EndpointStats or null if the name is not found + public EndpointStats GetEndpointStats(string endpointName) + { + EndpointContext c; + if (serviceContexts.TryGetValue(endpointName, out c)) + { + return c.GetEndpointStats(); + } + return null; + } +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Added: + internal static string ToDiscoverySubject(string discoverySubject, string serviceName, string serviceId) + { + if (string.IsNullOrEmpty(serviceId)) + { + if (string.IsNullOrEmpty(serviceName)) + { + return DefaultServicePrefix + discoverySubject; + } + + return DefaultServicePrefix + discoverySubject + "." + serviceName; + } + + return DefaultServicePrefix + discoverySubject + "." + serviceName + "." + serviceId; + } + + /// + /// Start the service + /// + /// a task that can be held to see if another thread called stop + public Task StartService() + { + lock (startStopLock) + { + if (runningIndicator == null) + { + runningIndicator = new TaskCompletionSource(); + foreach (var ctx in serviceContexts.Values) + { + ctx.Start(); + } + foreach (var ctx in discoveryContexts) + { + ctx.Start(); + } + started = DateTime.UtcNow; + } + return runningIndicator.Task; + } + } + + /// + /// Get an instance of a ServiceBuilder. + /// + /// the instance + public static ServiceBuilder Builder() + { + return new ServiceBuilder(); + } + + /// + /// Stop the service by draining. + /// + public void Stop() + { + Stop(true, null); + } + + /// + /// Stop the service by draining. Mark the task that was received from the start method that the service had an exception. + /// + /// the error cause + public void Stop(Exception e) + { + Stop(true, e); + } + + /// + /// Stop the service, optionally draining. + /// + /// the flag indicating to drain or not + public void Stop(bool drain) + { + Stop(drain, null); + } + + /// + /// Stop the service, optionally draining and optionally with an error cause + /// + /// the flag indicating to drain or not + /// the optional error cause. If supplied, mark the task that was received from the start method that the service had an exception. + public void Stop(bool drain, Exception e) + { + lock (startStopLock) { + if (runningIndicator != null) { + if (drain) + { + var tasks = new List(); + + foreach (var c in serviceContexts.Values) { + tasks.Add(c.Sub.DrainAsync(DrainTimeoutMillis)); + } + + foreach (var c in discoveryContexts) { + tasks.Add(c.Sub.DrainAsync(DrainTimeoutMillis)); + } + + // make sure drain is done before closing dispatcher + foreach (var t in tasks) + { + try { + t.Wait(DrainTimeoutMillis); + } + catch (Exception) { + // don't care if it completes successfully or not, just that it's done. + } + } + } + + // ok we are done + if (e == null) { + runningIndicator.SetResult(true); + } + else { + runningIndicator.SetException(e); + } + runningIndicator = null; // we don't need a copy anymore + } + } + } + + public void Reset() + { + started = DateTime.UtcNow; + foreach (var c in discoveryContexts) { + c.Reset(); + } + foreach (var c in serviceContexts.Values) { + c.Reset(); + } + } + + /// The id of the service + public string Id => InfoResponse.Id; + + /// The name of the service + public string Name => InfoResponse.Name; + + /// The version of the service + public string Version => InfoResponse.Version; + + /// The description of the service + public string Description => InfoResponse.Description; + + /// + /// Get the up-to-date stats response which contains a list of all + /// + /// the stats response + public StatsResponse GetStatsResponse() + { + IList endpointStatsList = new List(); + foreach (var c in serviceContexts.Values) + { + endpointStatsList.Add(c.GetEndpointStats()); + } + return new StatsResponse(PingResponse, started, endpointStatsList); + } + + /// + /// Get the up-to-date for a specific endpoint + /// + /// the endpoint name + /// the EndpointStats or null if the name is not found + public EndpointStats GetEndpointStats(string endpointName) + { + EndpointContext c; + if (serviceContexts.TryGetValue(endpointName, out c)) + { + return c.GetEndpointStats(); + } + return null; + } +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Added: + internal static string ToDiscoverySubject(string discoverySubject, string serviceName, string serviceId) + { + if (string.IsNullOrEmpty(serviceId)) + { + if (string.IsNullOrEmpty(serviceName)) + { + return DefaultServicePrefix + discoverySubject; + } + + return DefaultServicePrefix + discoverySubject + "." + serviceName; + } + + return DefaultServicePrefix + discoverySubject + "." + serviceName + "." + serviceId; + } + + /// + /// Start the service + /// + /// a task that can be held to see if another thread called stop + public Task StartService() + { + lock (startStopLock) + { + if (runningIndicator == null) + { + runningIndicator = new TaskCompletionSource(); + foreach (var ctx in serviceContexts.Values) + { + ctx.Start(); + } + foreach (var ctx in discoveryContexts) + { + ctx.Start(); + } + started = DateTime.UtcNow; + } + return runningIndicator.Task; + } + } + + /// + /// Get an instance of a ServiceBuilder. + /// + /// the instance + public static ServiceBuilder Builder() + { + return new ServiceBuilder(); + } + + /// + /// Stop the service by draining. + /// + public void Stop() + { + Stop(true, null); + } + + /// + /// Stop the service by draining. Mark the task that was received from the start method that the service had an exception. + /// + /// the error cause + public void Stop(Exception e) + { + Stop(true, e); + } + + /// + /// Stop the service, optionally draining. + /// + /// the flag indicating to drain or not + public void Stop(bool drain) + { + Stop(drain, null); + } + + /// + /// Stop the service, optionally draining and optionally with an error cause + /// + /// the flag indicating to drain or not + /// the optional error cause. If supplied, mark the task that was received from the start method that the service had an exception. + public void Stop(bool drain, Exception e) + { + lock (startStopLock) { + if (runningIndicator != null) { + if (drain) + { + var tasks = new List(); + + foreach (var c in serviceContexts.Values) { + tasks.Add(c.Sub.DrainAsync(DrainTimeoutMillis)); + } + + foreach (var c in discoveryContexts) { + tasks.Add(c.Sub.DrainAsync(DrainTimeoutMillis)); + } + + // make sure drain is done before closing dispatcher + foreach (var t in tasks) + { + try { + t.Wait(DrainTimeoutMillis); + } + catch (Exception) { + // don't care if it completes successfully or not, just that it's done. + } + } + } + + // ok we are done + if (e == null) { + runningIndicator.SetResult(true); + } + else { + runningIndicator.SetException(e); + } + runningIndicator = null; // we don't need a copy anymore + } + } + } + + public void Reset() + { + started = DateTime.UtcNow; + foreach (var c in discoveryContexts) { + c.Reset(); + } + foreach (var c in serviceContexts.Values) { + c.Reset(); + } + } + + /// The id of the service + public string Id => InfoResponse.Id; + + /// The name of the service + public string Name => InfoResponse.Name; + + /// The version of the service + public string Version => InfoResponse.Version; + + /// The description of the service + public string Description => InfoResponse.Description; + + /// + /// Get the up-to-date stats response which contains a list of all + /// + /// the stats response + public StatsResponse GetStatsResponse() + { + IList endpointStatsList = new List(); + foreach (var c in serviceContexts.Values) + { + endpointStatsList.Add(c.GetEndpointStats()); + } + return new StatsResponse(PingResponse, started, endpointStatsList); + } + + /// + /// Get the up-to-date for a specific endpoint + /// + /// the endpoint name + /// the EndpointStats or null if the name is not found + public EndpointStats GetEndpointStats(string endpointName) + { + EndpointContext c; + if (serviceContexts.TryGetValue(endpointName, out c)) + { + return c.GetEndpointStats(); + } + return null; + } +*/ +ew Endpoint(subject, subject, null, null, false); + } + + internal static string ToDiscoverySubject(string discoverySubject, string serviceName, string serviceId) + { + if (string.IsNullOrEmpty(serviceId)) + { + if (string.IsNullOrEmpty(serviceName)) + { + return DefaultServicePrefix + discoverySubject; + } + + return DefaultServicePrefix + discoverySubject + "." + serviceName; + } + + return DefaultServicePrefix + discoverySubject + "." + serviceName + "." + serviceId; + } + + /// + /// Start the service + /// + /// a task that can be held to see if another thread called stop + public Task StartService() + { + lock (startStopLock) + { + if (runningIndicator == null) + { + runningIndicator = new TaskCompletionSource(); + foreach (var ctx in serviceContexts.Values) + { + ctx.Start(); + } + foreach (var ctx in discoveryContexts) + { + ctx.Start(); + } + started = DateTime.UtcNow; + } + return runningIndicator.Task; + } + } + + /// + /// Get an instance of a ServiceBuilder. + /// + /// the instance + public static ServiceBuilder Builder() + { + return new ServiceBuilder(); + } + + /// + /// Stop the service by draining. + /// + public void Stop() + { + Stop(true, null); + } + + /// + /// Stop the service by draining. Mark the task that was received from the start method that the service had an exception. + /// + /// the error cause + public void Stop(Exception e) + { + Stop(true, e); + } + + /// + /// Stop the service, optionally draining. + /// + /// the flag indicating to drain or not + public void Stop(bool drain) + { + Stop(drain, null); + } + + /// + /// Stop the service, optionally draining and optionally with an error cause + /// + /// the flag indicating to drain or not + /// the optional error cause. If supplied, mark the task that was received from the start method that the service had an exception. + public void Stop(bool drain, Exception e) + { + lock (startStopLock) + { + if (runningIndicator != null) + { + if (drain) + { + var tasks = new List(); + + foreach (var c in serviceContexts.Values) + { + tasks.Add(c.Sub.DrainAsync(DrainTimeoutMillis)); + } + + foreach (var c in discoveryContexts) + { + tasks.Add(c.Sub.DrainAsync(DrainTimeoutMillis)); + } + + // make sure drain is done before closing dispatcher + foreach (var t in tasks) + { + try + { + t.Wait(DrainTimeoutMillis); + } + catch (Exception) + { + // don't care if it completes successfully or not, just that it's done. + } + } + } + + // ok we are done + if (e == null) + { + runningIndicator.SetResult(true); + } + else + { + runningIndicator.SetException(e); + } + runningIndicator = null; // we don't need a copy anymore + } + } + } + + public void Reset() + { + started = DateTime.UtcNow; + foreach (var c in discoveryContexts) + { + c.Reset(); + } + foreach (var c in serviceContexts.Values) + { + c.Reset(); + } + } + + /// The id of the service + public string Id => InfoResponse.Id; + + /// The name of the service + public string Name => InfoResponse.Name; + + /// The version of the service + public string Version => InfoResponse.Version; + + /// The description of the service + public string Description => InfoResponse.Description; + + /// + /// Get the up-to-date stats response which contains a list of all + /// + /// the stats response + public StatsResponse GetStatsResponse() +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject o = new JSONObject(); +After: + var o = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONArray ja = new JSONArray(); +After: + var ja = new JSONArray(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONArray ja = new JSONArray(); +After: + var ja = new JSONArray(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONArray ja = new JSONArray(); +After: + var ja = new JSONArray(); +*/ + + { + IList endpointStatsList = new List(); + foreach (var c in serviceContexts.Values) + { + endpointStatsList.Add(c.GetEndpointStats()); + } + return new StatsResponse(PingResponse, started, endpointStatsList); + } + + /// + /// Get the up-to-date for a specific endpoint + /// + /// the endpoint name + /// the EndpointStats or null if the name is not found + public EndpointStats GetEndpointStats(string endpointName) + { + EndpointContext c; + if (serviceContexts.TryGetValue(endpointName, out c)) + { + return c.GetEndpointStats(); + } + return null; + } + + public override string ToString() + { + var o = new JSONObject(); + JsonUtils.AddField(o, ApiConstants.Id, InfoResponse.Id); + JsonUtils.AddField(o, ApiConstants.Name, InfoResponse.Name); + JsonUtils.AddField(o, ApiConstants.Version, InfoResponse.Version); + JsonUtils.AddField(o, ApiConstants.Description, InfoResponse.Description); + var ja = new JSONArray(); o[ApiConstants.Endpoints] = ja; return "\"Service\":" + o.ToString(); // ToString() is needed because of how the JSONObject was written } } - } - \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Service/ServiceBuilder.cs b/src/NATS.Client/v1/Service/ServiceBuilder.cs index 42d883cb..75b3a61b 100644 --- a/src/NATS.Client/v1/Service/ServiceBuilder.cs +++ b/src/NATS.Client/v1/Service/ServiceBuilder.cs @@ -1,4 +1,4 @@ -// Copyright 2023 The NATS Authors +// Copyright 2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -36,7 +36,7 @@ public class ServiceBuilder /// /// connection /// the ServiceBuilder - public ServiceBuilder WithConnection(IConnection conn) + public ServiceBuilder WithConnection(IConnection conn) { Conn = conn; return this; @@ -47,7 +47,7 @@ public ServiceBuilder WithConnection(IConnection conn) /// /// the name /// the ServiceBuilder - public ServiceBuilder WithName(string name) + public ServiceBuilder WithName(string name) { Name = ValidateIsRestrictedTerm(name, "Service Name", true); return this; @@ -58,7 +58,7 @@ public ServiceBuilder WithName(string name) /// /// the description /// the ServiceBuilder - public ServiceBuilder WithDescription(string description) + public ServiceBuilder WithDescription(string description) { Description = description; return this; @@ -69,7 +69,7 @@ public ServiceBuilder WithDescription(string description) /// /// the version /// the ServiceBuilder - public ServiceBuilder WithVersion(string version) + public ServiceBuilder WithVersion(string version) { Version = ValidateSemVer(version, "Service Version", true); return this; @@ -91,7 +91,8 @@ public ServiceBuilder WithMetadata(IDictionary metadata) /// /// the endpoint /// the ServiceBuilder - public ServiceBuilder AddServiceEndpoint(ServiceEndpoint serviceEndpoint) { + public ServiceBuilder AddServiceEndpoint(ServiceEndpoint serviceEndpoint) + { ServiceEndpoints[serviceEndpoint.Name] = serviceEndpoint; return this; } @@ -106,12 +107,13 @@ public ServiceBuilder WithDrainTimeoutMillis(int drainTimeoutMillis) DrainTimeoutMillis = drainTimeoutMillis; return this; } - + /// /// Build the Service instance /// /// the Service instance - public Service Build() { + public Service Build() + { Required(Conn, "Connection"); Required(Name, "Name"); Required(Version, "Version"); diff --git a/src/NATS.Client/v1/Service/ServiceEndpoint.cs b/src/NATS.Client/v1/Service/ServiceEndpoint.cs index 4e93a934..415fca93 100644 --- a/src/NATS.Client/v1/Service/ServiceEndpoint.cs +++ b/src/NATS.Client/v1/Service/ServiceEndpoint.cs @@ -42,7 +42,7 @@ public class ServiceEndpoint internal EventHandler Handler { get; } internal Func StatsDataSupplier { get; } internal Endpoint Endpoint { get; } - + /// The name of the public string Name => Endpoint.Name; @@ -54,7 +54,7 @@ public class ServiceEndpoint /// A copy of the metadata of the public IDictionary Metadata => Endpoint.Metadata == null ? null : new Dictionary(Endpoint.Metadata); - + /// The name for this ServiceEndpoint, or null if there is no group public string GroupName => Group == null ? null : Group.Name; @@ -65,8 +65,9 @@ internal ServiceEndpoint(ServiceEndpointBuilder b, Endpoint e) Handler = b.Handler; StatsDataSupplier = b.StatsDataSupplier; } - - internal ServiceEndpoint(Endpoint endpoint, EventHandler handler) { + + internal ServiceEndpoint(Endpoint endpoint, EventHandler handler) + { Group = null; Endpoint = endpoint; Handler = handler; @@ -77,14 +78,16 @@ internal ServiceEndpoint(Endpoint endpoint, EventHandler /// the instance - public static ServiceEndpointBuilder Builder() { + public static ServiceEndpointBuilder Builder() + { return new ServiceEndpointBuilder(); } - + /// /// Build a ServiceEndpoint using a fluent builder. /// - public sealed class ServiceEndpointBuilder { + public sealed class ServiceEndpointBuilder + { internal Group Group; internal EventHandler Handler; internal Func StatsDataSupplier; @@ -95,7 +98,8 @@ public sealed class ServiceEndpointBuilder { /// /// The group /// the ServiceEndpointBuilder - public ServiceEndpointBuilder WithGroup(Group group) { + public ServiceEndpointBuilder WithGroup(Group group) + { Group = group; return this; } @@ -105,7 +109,8 @@ public ServiceEndpointBuilder WithGroup(Group group) { /// /// /// the ServiceEndpointBuilder - public ServiceEndpointBuilder WithEndpoint(Endpoint endpoint) { + public ServiceEndpointBuilder WithEndpoint(Endpoint endpoint) + { EndpointBuilder.WithEndpoint(endpoint); return this; } @@ -115,7 +120,8 @@ public ServiceEndpointBuilder WithEndpoint(Endpoint endpoint) { /// /// /// the ServiceEndpointBuilder - public ServiceEndpointBuilder WithEndpointName(string name) { + public ServiceEndpointBuilder WithEndpointName(string name) + { EndpointBuilder.WithName(name); return this; } @@ -125,7 +131,8 @@ public ServiceEndpointBuilder WithEndpointName(string name) { /// /// /// the ServiceEndpointBuilder - public ServiceEndpointBuilder WithEndpointSubject(string subject) { + public ServiceEndpointBuilder WithEndpointSubject(string subject) + { EndpointBuilder.WithSubject(subject); return this; } @@ -135,7 +142,8 @@ public ServiceEndpointBuilder WithEndpointSubject(string subject) { /// /// /// the ServiceEndpointBuilder - public ServiceEndpointBuilder WithEndpointQueueGroup(string queueGroup) { + public ServiceEndpointBuilder WithEndpointQueueGroup(string queueGroup) + { EndpointBuilder.WithQueueGroup(queueGroup); return this; } @@ -145,7 +153,8 @@ public ServiceEndpointBuilder WithEndpointQueueGroup(string queueGroup) { /// /// the metadata /// the ServiceEndpointBuilder - public ServiceEndpointBuilder WithEndpointMetadata(IDictionary metadata) { + public ServiceEndpointBuilder WithEndpointMetadata(IDictionary metadata) + { EndpointBuilder.WithMetadata(metadata); return this; } @@ -155,7 +164,8 @@ public ServiceEndpointBuilder WithEndpointMetadata(IDictionary m /// /// /// the ServiceEndpointBuilder - public ServiceEndpointBuilder WithHandler(EventHandler handler) { + public ServiceEndpointBuilder WithHandler(EventHandler handler) + { Handler = handler; return this; } @@ -165,7 +175,8 @@ public ServiceEndpointBuilder WithHandler(EventHandler /// the data supplier /// the ServiceEndpointBuilder - public ServiceEndpointBuilder WithStatsDataSupplier(Func statsDataSupplier) { + public ServiceEndpointBuilder WithStatsDataSupplier(Func statsDataSupplier) + { StatsDataSupplier = statsDataSupplier; return this; } @@ -174,8 +185,30 @@ public ServiceEndpointBuilder WithStatsDataSupplier(Func statsDataSupp /// Build the ServiceEndpoint instance. /// /// the ServiceEndpoint instance - public ServiceEndpoint Build() { + public ServiceEndpoint Build() +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Endpoint endpoint = EndpointBuilder.Build(); +After: + var endpoint = EndpointBuilder.Build(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Endpoint endpoint = EndpointBuilder.Build(); +After: + var endpoint = EndpointBuilder.Build(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: Endpoint endpoint = EndpointBuilder.Build(); +After: + var endpoint = EndpointBuilder.Build(); +*/ + + { + var endpoint = EndpointBuilder.Build(); Validator.Required(Handler, "Message Handler"); return new ServiceEndpoint(this, endpoint); } @@ -188,9 +221,12 @@ protected bool Equals(ServiceEndpoint other) public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (ReferenceEquals(null, obj)) + return false; + if (ReferenceEquals(this, obj)) + return true; + if (obj.GetType() != GetType()) + return false; return Equals((ServiceEndpoint)obj); } diff --git a/src/NATS.Client/v1/Service/ServiceException.cs b/src/NATS.Client/v1/Service/ServiceException.cs index be4bcc1a..0c36d6eb 100644 --- a/src/NATS.Client/v1/Service/ServiceException.cs +++ b/src/NATS.Client/v1/Service/ServiceException.cs @@ -1,4 +1,4 @@ -// Copyright 2023 The NATS Authors +// Copyright 2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -23,7 +23,8 @@ public class ServiceException : Exception /// The exception code public int Code { get; } - internal ServiceException(string message, int code = -1) : base(message) { + internal ServiceException(string message, int code = -1) : base(message) + { Code = code; } diff --git a/src/NATS.Client/v1/Service/ServiceMsg.cs b/src/NATS.Client/v1/Service/ServiceMsg.cs index ef98724e..58cca2a9 100644 --- a/src/NATS.Client/v1/Service/ServiceMsg.cs +++ b/src/NATS.Client/v1/Service/ServiceMsg.cs @@ -1,4 +1,4 @@ -// Copyright 2023 The NATS Authors +// Copyright 2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: @@ -26,12 +26,12 @@ public class ServiceMsg /// Standard header name used to report the text of an error /// public const string NatsServiceError = "Nats-Service-Error"; - + /// /// Standard header name used to report the code of an error /// public const string NatsServiceErrorCode = "Nats-Service-Error-Code"; - + private readonly Msg msg; /// The subject that this message was sent to. @@ -48,7 +48,7 @@ public class ServiceMsg /// The data from the message. public byte[] Data => msg.Data; - + internal ServiceMsg(Msg msg) { this.msg = msg; @@ -79,7 +79,7 @@ public void Respond(IConnection conn, string response) /// /// the NATS connection /// the response payload in the form of a object - public void Respond(IConnection conn, JsonSerializable response) + public void Respond(IConnection conn, JsonSerializable response) { conn.Publish(new Msg(msg.Reply, null, null, response.Serialize())); } @@ -89,7 +89,7 @@ public void Respond(IConnection conn, JsonSerializable response) /// /// the NATS connection /// the response payload in the form of a object - public void Respond(IConnection conn, JSONNode response) + public void Respond(IConnection conn, JSONNode response) { conn.Publish(new Msg(msg.Reply, null, null, Encoding.UTF8.GetBytes(response.ToString()))); } @@ -122,7 +122,7 @@ public void Respond(IConnection conn, string response, MsgHeader headers) /// the NATS connection /// the response payload in the form of a object /// the custom headers - public void Respond(IConnection conn, JsonSerializable response, MsgHeader headers) + public void Respond(IConnection conn, JsonSerializable response, MsgHeader headers) { conn.Publish(new Msg(msg.Reply, null, headers, response.Serialize())); } @@ -133,7 +133,7 @@ public void Respond(IConnection conn, JsonSerializable response, MsgHeader heade /// the NATS connection /// the response payload in the form of a object /// the custom headers - public void Respond(IConnection conn, JSONNode response, MsgHeader headers) + public void Respond(IConnection conn, JSONNode response, MsgHeader headers) { conn.Publish(new Msg(msg.Reply, null, headers, Encoding.UTF8.GetBytes(response.ToString()))); } @@ -146,13 +146,13 @@ public void Respond(IConnection conn, JSONNode response, MsgHeader headers) /// the error message code public void RespondStandardError(IConnection conn, string errorText, int errorCode) { - conn.Publish(new Msg(msg.Reply, null, - new MsgHeader + conn.Publish(new Msg(msg.Reply, null, + new MsgHeader { [NatsServiceError] = errorText, - [NatsServiceErrorCode] = $"{errorCode}" - }, + [NatsServiceErrorCode] = $"{errorCode}" + }, null)); - } + } } } diff --git a/src/NATS.Client/v1/Service/ServiceMsgHandlerEventArgs.cs b/src/NATS.Client/v1/Service/ServiceMsgHandlerEventArgs.cs index 29a94417..867f2d62 100644 --- a/src/NATS.Client/v1/Service/ServiceMsgHandlerEventArgs.cs +++ b/src/NATS.Client/v1/Service/ServiceMsgHandlerEventArgs.cs @@ -1,4 +1,4 @@ -// Copyright 2023 The NATS Authors +// Copyright 2023 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: diff --git a/src/NATS.Client/v1/Service/ServiceResponse.cs b/src/NATS.Client/v1/Service/ServiceResponse.cs index 09615658..a3d2956a 100644 --- a/src/NATS.Client/v1/Service/ServiceResponse.cs +++ b/src/NATS.Client/v1/Service/ServiceResponse.cs @@ -15,16 +15,16 @@ public abstract class ServiceResponse : JsonSerializable /// The type of this response public string Type { get; } - + /// The unique ID of the service public string Id { get; } - + /// The name of the service public string Name { get; } - + /// The version of the service public string Version { get; } - + /// A copy of the metadata for the service, or null if there is no metadata public IDictionary Metadata => _metadata == null ? null : new Dictionary(_metadata); @@ -46,15 +46,17 @@ internal ServiceResponse(string type, string id, string name, string version, ID } internal ServiceResponse(string type, ServiceResponse template) - : this(type, template.Id, template.Name, template.Version, template._metadata) {} - + : this(type, template.Id, template.Name, template.Version, template._metadata) { } + internal ServiceResponse(string type, JSONNode node) { string inType = node[ApiConstants.Type]; - if (Validator.EmptyAsNull(inType) == null) { + if (Validator.EmptyAsNull(inType) == null) + { throw new ArgumentException("Type cannot be null or empty."); } - if (!type.Equals(inType)) { + if (!type.Equals(inType)) + { throw new ArgumentException("Invalid type for " + GetType().Name + ". Expecting: " + type + ". Received " + inType); } Type = type; @@ -63,10 +65,31 @@ internal ServiceResponse(string type, JSONNode node) Version = Validator.ValidateSemVer(node[ApiConstants.Version], "Version", true); _metadata = JsonUtils.StringStringDictionary(node, ApiConstants.Metadata); } - + protected JSONObject BaseJsonObject() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject jso = new JSONObject(); +After: + var jso = new JSONObject(); +*/ + + { + var jso = new JSONObject(); JsonUtils.AddField(jso, ApiConstants.Id, Id); JsonUtils.AddField(jso, ApiConstants.Name, Name); JsonUtils.AddField(jso, ApiConstants.Type, Type); @@ -82,9 +105,12 @@ protected bool Equals(ServiceResponse other) public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (ReferenceEquals(null, obj)) + return false; + if (ReferenceEquals(this, obj)) + return true; + if (obj.GetType() != GetType()) + return false; return Equals((ServiceResponse)obj); } @@ -105,4 +131,4 @@ public override string ToString() return JsonUtils.ToKey(GetType()) + ToJsonString(); } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/Service/StatsResponse.cs b/src/NATS.Client/v1/Service/StatsResponse.cs index 6a2c9548..9e91b1cd 100644 --- a/src/NATS.Client/v1/Service/StatsResponse.cs +++ b/src/NATS.Client/v1/Service/StatsResponse.cs @@ -63,30 +63,63 @@ public class StatsResponse : ServiceResponse /// The time the endpoint was started (or restarted) public DateTime Started { get; } - + /// Get the list of public IList EndpointStatsList { get; } - - internal StatsResponse(ServiceResponse template, DateTime started, IList endpointStatsList) - :base(ResponseType, template) + + internal StatsResponse(ServiceResponse template, DateTime started, IList endpointStatsList) + : base(ResponseType, template) { Started = started; EndpointStatsList = endpointStatsList; } - internal StatsResponse(string json) : this(JSON.Parse(json)) {} + internal StatsResponse(string json) : this(JSON.Parse(json)) { } internal StatsResponse(JSONNode node) : base(ResponseType, node) { Started = JsonUtils.AsDate(node[ApiConstants.Started]); EndpointStatsList = EndpointStats.ListOf(node[ApiConstants.Endpoints]); } - + public override JSONNode ToJsonNode() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: JSONObject jso = BaseJsonObject(); jso[ApiConstants.Started] = JsonUtils.UnsafeToString(Started); JSONArray arr = new JSONArray(); +After: + var jso = BaseJsonObject(); + jso[ApiConstants.Started] = JsonUtils.UnsafeToString(Started); + var arr = new JSONArray(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + JSONObject jso = BaseJsonObject(); + jso[ApiConstants.Started] = JsonUtils.UnsafeToString(Started); + JSONArray arr = new JSONArray(); +After: + var jso = BaseJsonObject(); + jso[ApiConstants.Started] = JsonUtils.UnsafeToString(Started); + var arr = new JSONArray(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + JSONObject jso = BaseJsonObject(); + jso[ApiConstants.Started] = JsonUtils.UnsafeToString(Started); + JSONArray arr = new JSONArray(); +After: + var jso = BaseJsonObject(); + jso[ApiConstants.Started] = JsonUtils.UnsafeToString(Started); + var arr = new JSONArray(); +*/ + + { + var jso = BaseJsonObject(); + jso[ApiConstants.Started] = JsonUtils.UnsafeToString(Started); + var arr = new JSONArray(); foreach (var ess in EndpointStatsList) { arr.Add(null, ess.ToJsonNode()); @@ -103,17 +136,41 @@ protected bool Equals(StatsResponse other) public override bool Equals(object obj) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (ReferenceEquals(null, obj)) + return false; + if (ReferenceEquals(this, obj)) + return true; + if (obj.GetType() != GetType()) + return false; return Equals((StatsResponse)obj); } public override int GetHashCode() +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + int hashCode = base.GetHashCode(); +After: + var hashCode = base.GetHashCode(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + int hashCode = base.GetHashCode(); +After: + var hashCode = base.GetHashCode(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + int hashCode = base.GetHashCode(); +After: + var hashCode = base.GetHashCode(); +*/ + { unchecked { - int hashCode = base.GetHashCode(); + var hashCode = base.GetHashCode(); hashCode = (hashCode * 397) ^ Started.GetHashCode(); hashCode = (hashCode * 397) ^ (EndpointStatsList != null ? EndpointStatsList.GetHashCode() : 0); return hashCode; diff --git a/src/NATS.Client/v1/Srv.cs b/src/NATS.Client/v1/Srv.cs index 63255c5f..58f1d414 100644 --- a/src/NATS.Client/v1/Srv.cs +++ b/src/NATS.Client/v1/Srv.cs @@ -37,7 +37,7 @@ public class Srv public const string DefaultScheme = "nats://"; public const int DefaultPort = 4222; public const int NoPortSpecified = -1; - + public Uri Url { get; private set; } public bool IsImplicit { get; } public bool Secure { get; } @@ -58,18 +58,39 @@ public Srv(string urlString) { Secure = urlString.Contains("tls://"); } - + SetUrl(urlString); - + LastAttempt = DateTime.Now; } + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: internal void SetUrl(String urlString) +After: + internal void SetUrl(string urlString) +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + internal void SetUrl(String urlString) +After: + internal void SetUrl(string urlString) +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + internal void SetUrl(String urlString) +After: + internal void SetUrl(string urlString) +*/ + internal void SetUrl(string urlString) { var uri = new Uri(urlString); - Url = uri.Port == NoPortSpecified ? new UriBuilder(uri) {Port = DefaultPort}.Uri : uri; + Url = uri.Port == NoPortSpecified ? new UriBuilder(uri) { Port = DefaultPort }.Uri : uri; } - + public Srv(string urlString, bool isUrlImplicit) : this(urlString) { IsImplicit = isUrlImplicit; diff --git a/src/NATS.Client/v1/Statistics.cs b/src/NATS.Client/v1/Statistics.cs index b25b34e8..098fa305 100644 --- a/src/NATS.Client/v1/Statistics.cs +++ b/src/NATS.Client/v1/Statistics.cs @@ -67,27 +67,111 @@ public long OutBytes /// public long Reconnects { - get { return reconnects; } + get { return reconnects; } } // deep copy constructor internal Statistics(Statistics obj) - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this.inMsgs = obj.inMsgs; + this.inBytes = obj.inBytes; + this.outBytes = obj.outBytes; + this.outMsgs = obj.outMsgs; + this.reconnects = obj.reconnects; +After: + inMsgs = obj.inMsgs; + inBytes = obj.inBytes; + outBytes = obj.outBytes; + outMsgs = obj.outMsgs; + reconnects = obj.reconnects; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: this.inMsgs = obj.inMsgs; this.inBytes = obj.inBytes; this.outBytes = obj.outBytes; this.outMsgs = obj.outMsgs; this.reconnects = obj.reconnects; +After: + inMsgs = obj.inMsgs; + inBytes = obj.inBytes; + outBytes = obj.outBytes; + outMsgs = obj.outMsgs; + reconnects = obj.reconnects; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this.inMsgs = obj.inMsgs; + this.inBytes = obj.inBytes; + this.outBytes = obj.outBytes; + this.outMsgs = obj.outMsgs; + this.reconnects = obj.reconnects; +After: + inMsgs = obj.inMsgs; + inBytes = obj.inBytes; + outBytes = obj.outBytes; + outMsgs = obj.outMsgs; + reconnects = obj.reconnects; +*/ + + { + inMsgs = obj.inMsgs; + inBytes = obj.inBytes; + outBytes = obj.outBytes; + outMsgs = obj.outMsgs; + reconnects = obj.reconnects; } internal void clear() - { +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this.inBytes = 0; + this.inMsgs = 0; + this.outBytes = 0; + this.outMsgs = 0; +After: + inBytes = 0; + inMsgs = 0; + outBytes = 0; + outMsgs = 0; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: this.inBytes = 0; this.inMsgs = 0; this.outBytes = 0; this.outMsgs = 0; +After: + inBytes = 0; + inMsgs = 0; + outBytes = 0; + outMsgs = 0; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this.inBytes = 0; + this.inMsgs = 0; + this.outBytes = 0; + this.outMsgs = 0; +After: + inBytes = 0; + inMsgs = 0; + outBytes = 0; + outMsgs = 0; +*/ + + { + inBytes = 0; + inMsgs = 0; + outBytes = 0; + outMsgs = 0; } } -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/StringUserJWTHandler.cs b/src/NATS.Client/v1/StringUserJWTHandler.cs index 064d48d0..3373b39c 100644 --- a/src/NATS.Client/v1/StringUserJWTHandler.cs +++ b/src/NATS.Client/v1/StringUserJWTHandler.cs @@ -1,4 +1,4 @@ -// Copyright 2024 The NATS Authors +// Copyright 2024 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -36,8 +36,8 @@ public class StringUserJWTHandler /// /// The text containing the "-----BEGIN NATS USER JWT-----" block /// and the text containing the "-----BEGIN USER NKEY SEED-----" block - public StringUserJWTHandler(string credentialsText) : this(credentialsText, credentialsText) {} - + public StringUserJWTHandler(string credentialsText) : this(credentialsText, credentialsText) { } + /// /// Creates a static user jwt handler. /// diff --git a/src/NATS.Client/v1/Subscription.cs b/src/NATS.Client/v1/Subscription.cs index 2ebba3e8..4fa69593 100644 --- a/src/NATS.Client/v1/Subscription.cs +++ b/src/NATS.Client/v1/Subscription.cs @@ -33,22 +33,70 @@ internal class SidGenerator public class Subscription : ISubscription, IDisposable { - internal readonly object mu = new object(); // lock + internal readonly object mu = new object(); // lock - internal long sid; // subscriber ID. - private long msgs; - internal long delivered; - private long bytes; - internal long max = -1; + internal long sid; // subscriber ID. + private long msgs; + internal long delivered; + private long bytes; + internal long max = -1; // slow consumer - internal bool sc = false; + internal bool sc = false; internal Connection conn = null; internal bool closed = false; internal bool connClosed = false; - internal Channel mch = null; + internal Channel +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this.msgs++; +After: + msgs++; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this.msgs++; +After: + msgs++; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this.msgs++; +After: + msgs++; +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + c = this.conn; + isClosed = this.closed; +After: + c = conn; + isClosed = closed; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + c = this.conn; + isClosed = this.closed; +After: + c = conn; + isClosed = closed; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + c = this.conn; + isClosed = this.closed; +After: + c = conn; + isClosed = closed; +*/ +mch = null; internal bool ownsChannel = true; // Pending stats, async subscriptions, high-speed etc. @@ -62,7 +110,70 @@ public class Subscription : ISubscription, IDisposable // Subject that represents this subscription. This can be different // than the received subject inside a Msg if this is a wildcard. - private string subject = null; + private string +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + StringBuilder sb = new StringBuilder(); +After: + var sb = new StringBuilder(); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + StringBuilder sb = new StringBuilder(); +After: + var sb = new StringBuilder(); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + StringBuilder sb = new StringBuilder(); +After: + var sb = new StringBuilder(); +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + Subject, (Queue == null ? "null" : Queue), +After: + Subject, (Queue ?? "null"), +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + Subject, (Queue == null ? "null" : Queue), +After: + Subject, (Queue ?? "null"), +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + Subject, (Queue == null ? "null" : Queue), +After: + Subject, (Queue ?? "null"), +*/ + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + this.GetType().ToString()); +After: + GetType().ToString()); +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + this.GetType().ToString()); +After: + GetType().ToString()); +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: + this.GetType().ToString()); +After: + GetType().ToString()); +*/ +subject = null; internal Func _beforeChannelAddCheck; internal Func BeforeChannelAddCheck @@ -89,12 +200,12 @@ internal Subscription(Connection conn, string subject, string queue) pendingMessagesLimit = conn.Opts.PendingMessageLimit; pendingBytesLimit = conn.Opts.PendingBytesLimit; - + sid = SidGenerator.Next(); BeforeChannelAddCheck = null; } - + internal void ReSubscribe(string deliverSubject) { conn.SendUnsub(sid, 0); @@ -127,7 +238,7 @@ internal void close(bool closeChannel) /// /// the id associated with the subscription, used by the connection when processing an incoming /// - public long Sid => sid; + public long Sid => sid; /// /// Gets the subject for this subscription. @@ -163,7 +274,7 @@ internal bool tallyMessage(long bytes) if (max > 0 && msgs > max) return true; - this.msgs++; + msgs++; this.bytes += bytes; return false; @@ -222,7 +333,7 @@ internal bool addMessage(Msg msg) { pendingMessagesMax = pendingMessages; } - + pendingBytes += msg.Data.Length; if (pendingBytes > pendingBytesMax) { @@ -264,8 +375,8 @@ internal void unsubscribe(bool throwEx) bool isClosed; lock (mu) { - c = this.conn; - isClosed = this.closed; + c = conn; + isClosed = closed; } if (c == null) @@ -407,18 +518,18 @@ public void Dispose() /// A string that represents the current . public override string ToString() { - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); sb.Append("{"); - + sb.AppendFormat("Subject={0};Queue={1};" + "QueuedMessageCount={2};IsValid={3};Type={4}", - Subject, (Queue == null ? "null" : Queue), - QueuedMessageCount, IsValid, - this.GetType().ToString()); - + Subject, (Queue ?? "null"), + QueuedMessageCount, IsValid, + GetType().ToString()); + sb.Append("}"); - + return sb.ToString(); } @@ -458,8 +569,8 @@ private void SetPendingMessageLimitInternal(long messageLimit) /// Gets or sets the maximum allowed count of pending bytes. /// /// The pending byte limit if greater than 0 or -1 for unlimited. - public long PendingByteLimit - { + public long PendingByteLimit + { get { lock (mu) @@ -514,7 +625,7 @@ public void GetPending(out long pendingBytes, out long pendingMessages) lock (mu) { checkState(); - pendingBytes = this.pendingBytes; + pendingBytes = this.pendingBytes; pendingMessages = this.pendingMessages; } } @@ -561,7 +672,7 @@ public void GetMaxPending(out long maxPendingBytes, out long maxPendingMessages) lock (mu) { checkState(); - maxPendingBytes = pendingBytesMax; + maxPendingBytes = pendingBytesMax; maxPendingMessages = pendingMessagesMax; } } @@ -637,7 +748,7 @@ public Task DrainAsync(int timeout) public void Drain() { - Drain(Defaults.DefaultDrainTimeout); + Drain(Defaults.DefaultDrainTimeout); } public void Drain(int timeout) @@ -689,7 +800,7 @@ public long Dropped #region validation - private static readonly char[] invalidSubjectChars = { '\r', '\n', '\t', ' '}; + private static readonly char[] invalidSubjectChars = { '\r', '\n', '\t', ' ' }; private static bool ContainsInvalidChars(string value) { @@ -733,4 +844,4 @@ public static bool IsValidQueueGroupName(string queueGroup) } // Subscription -} \ No newline at end of file +} diff --git a/src/NATS.Client/v1/SyncSub.cs b/src/NATS.Client/v1/SyncSub.cs index 23a9b95d..640ed7d4 100644 --- a/src/NATS.Client/v1/SyncSub.cs +++ b/src/NATS.Client/v1/SyncSub.cs @@ -18,7 +18,7 @@ namespace NATS.Client /// to and . This class should /// not be used directly. /// - public class SyncSubscription : Subscription, ISyncSubscription, ISubscription + public class SyncSubscription : Subscription, ISyncSubscription, ISubscription { internal SyncSubscription(Connection conn, string subject, string queue) : base(conn, subject, queue) @@ -90,12 +90,45 @@ protected Msg NextMessageImpl(int timeout) throw new NATSSlowConsumerException(); } + +/* Unmerged change from project 'NATS.Client(netstandard2.1)' +Before: + localConn = this.conn; + localChannel = this.mch; + localMax = this.max; +After: + localConn = conn; + localChannel = mch; + localMax = max; +*/ + +/* Unmerged change from project 'NATS.Client(net6.0)' +Before: + localConn = this.conn; + localChannel = this.mch; + localMax = this.max; +After: + localConn = conn; + localChannel = mch; + localMax = max; +*/ + +/* Unmerged change from project 'NATS.Client(net8.0)' +Before: localConn = this.conn; localChannel = this.mch; localMax = this.max; +After: + localConn = conn; + localChannel = mch; + localMax = max; +*/ + localConn = conn; + localChannel = mch; + localMax = max; } - if (localMax > 0 && this.delivered >= localMax) + if (localMax > 0 && delivered >= localMax) { throw new NATSMaxMessagesException(); } @@ -136,4 +169,4 @@ protected Msg NextMessageImpl(int timeout) return msg; } } -} \ No newline at end of file +}