diff options
Diffstat (limited to 'csharp')
22 files changed, 292 insertions, 15 deletions
diff --git a/csharp/Google.Protobuf.Tools.nuspec b/csharp/Google.Protobuf.Tools.nuspec index 8a0d61e1..901d5ce9 100644 --- a/csharp/Google.Protobuf.Tools.nuspec +++ b/csharp/Google.Protobuf.Tools.nuspec @@ -33,5 +33,7 @@ <file src="..\src\google\protobuf\timestamp.proto" target="tools\google\protobuf" /> <file src="..\src\google\protobuf\type.proto" target="tools\google\protobuf" /> <file src="..\src\google\protobuf\wrappers.proto" target="tools\google\protobuf" /> + <file src="Google.Protobuf.Tools.targets" target="buildCrossTargeting" /> + <file src="Google.Protobuf.Tools.targets" target="build" /> </files> </package> diff --git a/csharp/Google.Protobuf.Tools.targets b/csharp/Google.Protobuf.Tools.targets new file mode 100644 index 00000000..682e11b0 --- /dev/null +++ b/csharp/Google.Protobuf.Tools.targets @@ -0,0 +1,11 @@ +<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <protoc_tools>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)/../tools/'))</protoc_tools>
+ <protoc_linux64>$([System.IO.Path]::GetFullPath('$(protoc_tools)/linux_x64/protoc'))</protoc_linux64>
+ <protoc_linux86>$([System.IO.Path]::GetFullPath('$(protoc_tools)/linux_x86/protoc'))</protoc_linux86>
+ <protoc_macosx64>$([System.IO.Path]::GetFullPath('$(protoc_tools)/macosx_x64/protoc'))</protoc_macosx64>
+ <protoc_macosx86>$([System.IO.Path]::GetFullPath('$(protoc_tools)/macosx_x86/protoc'))</protoc_macosx86>
+ <protoc_windows64>$([System.IO.Path]::GetFullPath('$(protoc_tools)/windows_x64/protoc.exe'))</protoc_windows64>
+ <protoc_windows86>$([System.IO.Path]::GetFullPath('$(protoc_tools)/windows_x86/protoc.exe'))</protoc_windows86>
+ </PropertyGroup>
+</Project>
diff --git a/csharp/build_packages.bat b/csharp/build_packages.bat index d7205659..8157bbab 100644 --- a/csharp/build_packages.bat +++ b/csharp/build_packages.bat @@ -1,7 +1,7 @@ @rem Builds Google.Protobuf NuGet packages dotnet restore src/Google.Protobuf.sln -dotnet pack -c Release src/Google.Protobuf.sln || goto :error +dotnet pack -c Release src/Google.Protobuf.sln /p:SourceLinkCreate=true || goto :error goto :EOF diff --git a/csharp/global.json b/csharp/global.json index 5ab775b9..080dcb94 100644 --- a/csharp/global.json +++ b/csharp/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "2.0.3" + "version": "2.1.3" } } diff --git a/csharp/src/Google.Protobuf.Conformance/Conformance.cs b/csharp/src/Google.Protobuf.Conformance/Conformance.cs index f6118ea2..6ca52c32 100644 --- a/csharp/src/Google.Protobuf.Conformance/Conformance.cs +++ b/csharp/src/Google.Protobuf.Conformance/Conformance.cs @@ -24,21 +24,24 @@ namespace Conformance { static ConformanceReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( - "ChFjb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2UiowEKEkNvbmZvcm1h", + "ChFjb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2Ui1QEKEkNvbmZvcm1h", "bmNlUmVxdWVzdBIaChBwcm90b2J1Zl9wYXlsb2FkGAEgASgMSAASFgoManNv", "bl9wYXlsb2FkGAIgASgJSAASOAoXcmVxdWVzdGVkX291dHB1dF9mb3JtYXQY", "AyABKA4yFy5jb25mb3JtYW5jZS5XaXJlRm9ybWF0EhQKDG1lc3NhZ2VfdHlw", - "ZRgEIAEoCUIJCgdwYXlsb2FkIrEBChNDb25mb3JtYW5jZVJlc3BvbnNlEhUK", - "C3BhcnNlX2Vycm9yGAEgASgJSAASGQoPc2VyaWFsaXplX2Vycm9yGAYgASgJ", - "SAASFwoNcnVudGltZV9lcnJvchgCIAEoCUgAEhoKEHByb3RvYnVmX3BheWxv", - "YWQYAyABKAxIABIWCgxqc29uX3BheWxvYWQYBCABKAlIABIRCgdza2lwcGVk", - "GAUgASgJSABCCAoGcmVzdWx0KjUKCldpcmVGb3JtYXQSDwoLVU5TUEVDSUZJ", - "RUQQABIMCghQUk9UT0JVRhABEggKBEpTT04QAkIhCh9jb20uZ29vZ2xlLnBy", - "b3RvYnVmLmNvbmZvcm1hbmNlYgZwcm90bzM=")); + "ZRgEIAEoCRIwCg10ZXN0X2NhdGVnb3J5GAUgASgOMhkuY29uZm9ybWFuY2Uu", + "VGVzdENhdGVnb3J5QgkKB3BheWxvYWQisQEKE0NvbmZvcm1hbmNlUmVzcG9u", + "c2USFQoLcGFyc2VfZXJyb3IYASABKAlIABIZCg9zZXJpYWxpemVfZXJyb3IY", + "BiABKAlIABIXCg1ydW50aW1lX2Vycm9yGAIgASgJSAASGgoQcHJvdG9idWZf", + "cGF5bG9hZBgDIAEoDEgAEhYKDGpzb25fcGF5bG9hZBgEIAEoCUgAEhEKB3Nr", + "aXBwZWQYBSABKAlIAEIICgZyZXN1bHQqNQoKV2lyZUZvcm1hdBIPCgtVTlNQ", + "RUNJRklFRBAAEgwKCFBST1RPQlVGEAESCAoESlNPThACKlQKDFRlc3RDYXRl", + "Z29yeRIPCgtCSU5BUllfVEVTVBAAEg0KCUpTT05fVEVTVBABEiQKIEpTT05f", + "SUdOT1JFX1VOS05PV05fUEFSU0lOR19URVNUEAJCIQofY29tLmdvb2dsZS5w", + "cm90b2J1Zi5jb25mb3JtYW5jZWIGcHJvdG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, - new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Conformance.WireFormat), }, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceRequest), global::Conformance.ConformanceRequest.Parser, new[]{ "ProtobufPayload", "JsonPayload", "RequestedOutputFormat", "MessageType" }, new[]{ "Payload" }, null, null), + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Conformance.WireFormat), typeof(global::Conformance.TestCategory), }, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceRequest), global::Conformance.ConformanceRequest.Parser, new[]{ "ProtobufPayload", "JsonPayload", "RequestedOutputFormat", "MessageType", "TestCategory" }, new[]{ "Payload" }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceResponse), global::Conformance.ConformanceResponse.Parser, new[]{ "ParseError", "SerializeError", "RuntimeError", "ProtobufPayload", "JsonPayload", "Skipped" }, new[]{ "Result" }, null, null) })); } @@ -52,6 +55,25 @@ namespace Conformance { [pbr::OriginalName("JSON")] Json = 2, } + public enum TestCategory { + /// <summary> + /// Test binary wire format. + /// </summary> + [pbr::OriginalName("BINARY_TEST")] BinaryTest = 0, + /// <summary> + /// Test json wire format. + /// </summary> + [pbr::OriginalName("JSON_TEST")] JsonTest = 1, + /// <summary> + /// Similar to JSON_TEST. However, during parsing json, testee should ignore + /// unknown fields. This feature is optional. Each implementation can descide + /// whether to support it. See + /// https://developers.google.com/protocol-buffers/docs/proto3#json_options + /// for more detail. + /// </summary> + [pbr::OriginalName("JSON_IGNORE_UNKNOWN_PARSING_TEST")] JsonIgnoreUnknownParsingTest = 2, + } + #endregion #region Messages @@ -89,6 +111,7 @@ namespace Conformance { public ConformanceRequest(ConformanceRequest other) : this() { requestedOutputFormat_ = other.requestedOutputFormat_; messageType_ = other.messageType_; + testCategory_ = other.testCategory_; switch (other.PayloadCase) { case PayloadOneofCase.ProtobufPayload: ProtobufPayload = other.ProtobufPayload; @@ -158,6 +181,22 @@ namespace Conformance { } } + /// <summary>Field number for the "test_category" field.</summary> + public const int TestCategoryFieldNumber = 5; + private global::Conformance.TestCategory testCategory_ = 0; + /// <summary> + /// Each test is given a specific test category. Some category may need spedific + /// support in testee programs. Refer to the defintion of TestCategory for + /// more information. + /// </summary> + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Conformance.TestCategory TestCategory { + get { return testCategory_; } + set { + testCategory_ = value; + } + } + private object payload_; /// <summary>Enum of possible cases for the "payload" oneof.</summary> public enum PayloadOneofCase { @@ -194,6 +233,7 @@ namespace Conformance { if (JsonPayload != other.JsonPayload) return false; if (RequestedOutputFormat != other.RequestedOutputFormat) return false; if (MessageType != other.MessageType) return false; + if (TestCategory != other.TestCategory) return false; if (PayloadCase != other.PayloadCase) return false; return Equals(_unknownFields, other._unknownFields); } @@ -205,6 +245,7 @@ namespace Conformance { if (payloadCase_ == PayloadOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode(); if (RequestedOutputFormat != 0) hash ^= RequestedOutputFormat.GetHashCode(); if (MessageType.Length != 0) hash ^= MessageType.GetHashCode(); + if (TestCategory != 0) hash ^= TestCategory.GetHashCode(); hash ^= (int) payloadCase_; if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); @@ -235,6 +276,10 @@ namespace Conformance { output.WriteRawTag(34); output.WriteString(MessageType); } + if (TestCategory != 0) { + output.WriteRawTag(40); + output.WriteEnum((int) TestCategory); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -255,6 +300,9 @@ namespace Conformance { if (MessageType.Length != 0) { size += 1 + pb::CodedOutputStream.ComputeStringSize(MessageType); } + if (TestCategory != 0) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) TestCategory); + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -272,6 +320,9 @@ namespace Conformance { if (other.MessageType.Length != 0) { MessageType = other.MessageType; } + if (other.TestCategory != 0) { + TestCategory = other.TestCategory; + } switch (other.PayloadCase) { case PayloadOneofCase.ProtobufPayload: ProtobufPayload = other.ProtobufPayload; @@ -308,6 +359,10 @@ namespace Conformance { MessageType = input.ReadString(); break; } + case 40: { + testCategory_ = (global::Conformance.TestCategory) input.ReadEnum(); + break; + } } } } diff --git a/csharp/src/Google.Protobuf.Conformance/Program.cs b/csharp/src/Google.Protobuf.Conformance/Program.cs index 96dc354e..1eac00be 100644 --- a/csharp/src/Google.Protobuf.Conformance/Program.cs +++ b/csharp/src/Google.Protobuf.Conformance/Program.cs @@ -87,6 +87,9 @@ namespace Google.Protobuf.Conformance switch (request.PayloadCase) { case ConformanceRequest.PayloadOneofCase.JsonPayload: + if (request.TestCategory == global::Conformance.TestCategory.JsonIgnoreUnknownParsingTest) { + return new ConformanceResponse { Skipped = "CSharp doesn't support skipping unknown fields in json parsing." }; + } var parser = new JsonParser(new JsonParser.Settings(20, typeRegistry)); message = parser.Parse<ProtobufTestMessages.Proto3.TestAllTypesProto3>(request.JsonPayload); break; diff --git a/csharp/src/Google.Protobuf.Test/ByteStringTest.cs b/csharp/src/Google.Protobuf.Test/ByteStringTest.cs index afdd491f..afdd491f 100755..100644 --- a/csharp/src/Google.Protobuf.Test/ByteStringTest.cs +++ b/csharp/src/Google.Protobuf.Test/ByteStringTest.cs diff --git a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs index 8795fa65..8795fa65 100755..100644 --- a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs +++ b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs diff --git a/csharp/src/Google.Protobuf.Test/Compatibility/StreamExtensionsTest.cs b/csharp/src/Google.Protobuf.Test/Compatibility/StreamExtensionsTest.cs index 48c0725f..48c0725f 100755..100644 --- a/csharp/src/Google.Protobuf.Test/Compatibility/StreamExtensionsTest.cs +++ b/csharp/src/Google.Protobuf.Test/Compatibility/StreamExtensionsTest.cs diff --git a/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs b/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs index abbe3c95..abbe3c95 100755..100644 --- a/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs +++ b/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs diff --git a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs index 77641163..77641163 100755..100644 --- a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs +++ b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs index 9ecd24c6..b8c07ef5 100644 --- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs +++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs @@ -111,5 +111,106 @@ namespace Google.Protobuf.WellKnownTypes var duration = new Timestamp { Seconds = 1, Nanos = -1 }; Assert.AreEqual("{ \"@warning\": \"Invalid Timestamp\", \"seconds\": \"1\", \"nanos\": -1 }", duration.ToString()); } + + [Test] + public void Comparability() + { + Timestamp + a = null, + b = new Timestamp { Seconds = 1, Nanos = 1 }, + c = new Timestamp { Seconds = 1, Nanos = 10 }, + d = new Timestamp { Seconds = 10, Nanos = 1 }, + e = new Timestamp { Seconds = 10, Nanos = 10 }; + + Assert.IsTrue(b.CompareTo(a) > 0); // null is always first (according to default behavior of Array.Sort) + Assert.IsTrue(b.CompareTo(b) == 0); + Assert.IsTrue(b.CompareTo(b.Clone()) == 0); + Assert.IsTrue(b.CompareTo(c) < 0); + Assert.IsTrue(b.CompareTo(d) < 0); + Assert.IsTrue(b.CompareTo(e) < 0); + + Assert.IsTrue(c.CompareTo(a) > 0); + Assert.IsTrue(c.CompareTo(b) > 0); + Assert.IsTrue(c.CompareTo(c) == 0); + Assert.IsTrue(c.CompareTo(c.Clone()) == 0); + Assert.IsTrue(c.CompareTo(d) < 0); + Assert.IsTrue(c.CompareTo(e) < 0); + + Assert.IsTrue(d.CompareTo(a) > 0); + Assert.IsTrue(d.CompareTo(b) > 0); + Assert.IsTrue(d.CompareTo(c) > 0); + Assert.IsTrue(d.CompareTo(d) == 0); + Assert.IsTrue(d.CompareTo(d.Clone()) == 0); + Assert.IsTrue(d.CompareTo(e) < 0); + + Assert.IsTrue(e.CompareTo(a) > 0); + Assert.IsTrue(e.CompareTo(b) > 0); + Assert.IsTrue(e.CompareTo(c) > 0); + Assert.IsTrue(e.CompareTo(d) > 0); + Assert.IsTrue(e.CompareTo(e) == 0); + Assert.IsTrue(e.CompareTo(e.Clone()) == 0); + } + + + [Test] + public void ComparabilityOperators() + { + Timestamp + a = null, + b = new Timestamp { Seconds = 1, Nanos = 1 }, + c = new Timestamp { Seconds = 1, Nanos = 10 }, + d = new Timestamp { Seconds = 10, Nanos = 1 }, + e = new Timestamp { Seconds = 10, Nanos = 10 }; + +#pragma warning disable CS1718 // Comparison made to same variable + Assert.IsTrue(b > a); + Assert.IsTrue(b == b); + Assert.IsTrue(b == b.Clone()); + Assert.IsTrue(b < c); + Assert.IsTrue(b < d); + Assert.IsTrue(b < e); + + Assert.IsTrue(c > a); + Assert.IsTrue(c > b); + Assert.IsTrue(c == c); + Assert.IsTrue(c == c.Clone()); + Assert.IsTrue(c < d); + Assert.IsTrue(c < e); + + Assert.IsTrue(d > a); + Assert.IsTrue(d > b); + Assert.IsTrue(d > c); + Assert.IsTrue(d == d); + Assert.IsTrue(d == d.Clone()); + Assert.IsTrue(d < e); + + Assert.IsTrue(e > a); + Assert.IsTrue(e > b); + Assert.IsTrue(e > c); + Assert.IsTrue(e > d); + Assert.IsTrue(e == e); + Assert.IsTrue(e == e.Clone()); + + Assert.IsTrue(b >= a); + Assert.IsTrue(b <= c); + Assert.IsTrue(b <= d); + Assert.IsTrue(b <= e); + + Assert.IsTrue(c >= a); + Assert.IsTrue(c >= b); + Assert.IsTrue(c <= d); + Assert.IsTrue(c <= e); + + Assert.IsTrue(d >= a); + Assert.IsTrue(d >= b); + Assert.IsTrue(d >= c); + Assert.IsTrue(d <= e); + + Assert.IsTrue(e >= a); + Assert.IsTrue(e >= b); + Assert.IsTrue(e >= c); + Assert.IsTrue(e >= d); +#pragma warning restore CS1718 // Comparison made to same variable + } } } diff --git a/csharp/src/Google.Protobuf/ByteString.cs b/csharp/src/Google.Protobuf/ByteString.cs index 4abdb718..4abdb718 100755..100644 --- a/csharp/src/Google.Protobuf/ByteString.cs +++ b/csharp/src/Google.Protobuf/ByteString.cs diff --git a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs index c18b63e2..c18b63e2 100755..100644 --- a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs +++ b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs diff --git a/csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs b/csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs index 95a02c72..95a02c72 100755..100644 --- a/csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs +++ b/csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs diff --git a/csharp/src/Google.Protobuf/Compatibility/StreamExtensions.cs b/csharp/src/Google.Protobuf/Compatibility/StreamExtensions.cs index bf4bf220..bf4bf220 100755..100644 --- a/csharp/src/Google.Protobuf/Compatibility/StreamExtensions.cs +++ b/csharp/src/Google.Protobuf/Compatibility/StreamExtensions.cs diff --git a/csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs b/csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs index 2f237138..2f237138 100755..100644 --- a/csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs +++ b/csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj index 11bc03d1..a056b435 100644 --- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj +++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj @@ -17,8 +17,6 @@ <PackageLicenseUrl>https://github.com/google/protobuf/blob/master/LICENSE</PackageLicenseUrl> <RepositoryType>git</RepositoryType> <RepositoryUrl>https://github.com/google/protobuf.git</RepositoryUrl> - <IncludeSymbols>true</IncludeSymbols> - <IncludeSource>true</IncludeSource> </PropertyGroup> <!-- @@ -30,4 +28,8 @@ <TargetFrameworks>netstandard1.0</TargetFrameworks> </PropertyGroup> + <ItemGroup> + <PackageReference Include="SourceLink.Create.CommandLine" Version="2.7.6" PrivateAssets="All" /> + </ItemGroup> + </Project> diff --git a/csharp/src/Google.Protobuf/JsonFormatter.cs b/csharp/src/Google.Protobuf/JsonFormatter.cs index 4ae10d8b..4ae10d8b 100755..100644 --- a/csharp/src/Google.Protobuf/JsonFormatter.cs +++ b/csharp/src/Google.Protobuf/JsonFormatter.cs diff --git a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs index 86942acc..86942acc 100755..100644 --- a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs index 4b0670f6..4b0670f6 100755..100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs index aa403473..a9251974 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs @@ -36,7 +36,7 @@ using System.Text; namespace Google.Protobuf.WellKnownTypes { - public partial class Timestamp : ICustomDiagnosticMessage + public partial class Timestamp : ICustomDiagnosticMessage, IComparable<Timestamp> { private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); // Constants determined programmatically, but then hard-coded so they can be constant expressions. @@ -223,6 +223,109 @@ namespace Google.Protobuf.WellKnownTypes } /// <summary> + /// Given another timestamp, returns 0 if the timestamps are equivalent, -1 if this timestamp precedes the other, and 1 otherwise + /// </summary> + /// <remarks> + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// </remarks> + /// <param name="other">Timestamp to compare</param> + /// <returns>an integer indicating whether this timestamp precedes or follows the other</returns> + public int CompareTo(Timestamp other) + { + return other == null ? 1 + : Seconds < other.Seconds ? -1 + : Seconds > other.Seconds ? 1 + : Nanos < other.Nanos ? -1 + : Nanos > other.Nanos ? 1 + : 0; + } + + /// <summary> + /// Compares two timestamps and returns whether the first is less than (chronologically precedes) the second + /// </summary> + /// <remarks> + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// </remarks> + /// <param name="a"></param> + /// <param name="b"></param> + /// <returns>true if a precedes b</returns> + public static bool operator <(Timestamp a, Timestamp b) + { + return a.CompareTo(b) < 0; + } + + /// <summary> + /// Compares two timestamps and returns whether the first is greater than (chronologically follows) the second + /// </summary> + /// <remarks> + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// </remarks> + /// <param name="a"></param> + /// <param name="b"></param> + /// <returns>true if a follows b</returns> + public static bool operator >(Timestamp a, Timestamp b) + { + return a.CompareTo(b) > 0; + } + + /// <summary> + /// Compares two timestamps and returns whether the first is less than (chronologically precedes) the second + /// </summary> + /// <remarks> + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// </remarks> + /// <param name="a"></param> + /// <param name="b"></param> + /// <returns>true if a precedes b</returns> + public static bool operator <=(Timestamp a, Timestamp b) + { + return a.CompareTo(b) <= 0; + } + + /// <summary> + /// Compares two timestamps and returns whether the first is greater than (chronologically follows) the second + /// </summary> + /// <remarks> + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// </remarks> + /// <param name="a"></param> + /// <param name="b"></param> + /// <returns>true if a follows b</returns> + public static bool operator >=(Timestamp a, Timestamp b) + { + return a.CompareTo(b) >= 0; + } + + + /// <summary> + /// Returns whether two timestamps are equivalent + /// </summary> + /// <remarks> + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// </remarks> + /// <param name="a"></param> + /// <param name="b"></param> + /// <returns>true if the two timestamps refer to the same nanosecond</returns> + public static bool operator ==(Timestamp a, Timestamp b) + { + return ReferenceEquals(a, b) || (a is null ? (b is null ? true : false) : a.Equals(b)); + } + + /// <summary> + /// Returns whether two timestamps differ + /// </summary> + /// <remarks> + /// Make sure the timestamps are normalized. Comparing non-normalized timestamps is not specified and may give unexpected results. + /// </remarks> + /// <param name="a"></param> + /// <param name="b"></param> + /// <returns>true if the two timestamps differ</returns> + public static bool operator !=(Timestamp a, Timestamp b) + { + return !(a == b); + } + + /// <summary> /// Returns a string representation of this <see cref="Timestamp"/> for diagnostic purposes. /// </summary> /// <remarks> |