diff --git a/src/MongoDB.Bson/ObjectModel/ObjectId.cs b/src/MongoDB.Bson/ObjectModel/ObjectId.cs index 6cebdff4f7e..059480be7b5 100644 --- a/src/MongoDB.Bson/ObjectModel/ObjectId.cs +++ b/src/MongoDB.Bson/ObjectModel/ObjectId.cs @@ -449,12 +449,86 @@ public void ToByteArray(byte[] destination, int offset) destination[offset + 11] = (byte)(_c); } +#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + /// + /// Converts the ObjectId to a byte buffer provided by the input span. + /// + /// The destination byte span. + /// Not enough room in destination span. + public void ToByteSpan(Span destination) + { + if (destination.Length < 12) + { + throw new ArgumentException("Not enough room in destination span.", "destination"); + } + + destination[0] = (byte)(_a >> 24); + destination[1] = (byte)(_a >> 16); + destination[2] = (byte)(_a >> 8); + destination[3] = (byte)(_a); + destination[4] = (byte)(_b >> 24); + destination[5] = (byte)(_b >> 16); + destination[6] = (byte)(_b >> 8); + destination[7] = (byte)(_b); + destination[8] = (byte)(_c >> 24); + destination[9] = (byte)(_c >> 16); + destination[10] = (byte)(_c >> 8); + destination[11] = (byte)(_c); + } + + /// + /// Fills a character span with the characters corresponding to the string representation of the value. + /// + /// The span to fill the characters in. + /// Not enough room in destination span. + public void ToCharSpan(Span destination) + { + if (destination.Length < 24) + { + throw new ArgumentException("Not enough room in destination span.", "destination"); + } + + Span span = stackalloc byte[12]; + ToByteSpan(span); + destination[0] = BsonUtils.ToHexChar(span[0] >> 4); + destination[1] = BsonUtils.ToHexChar(span[0] & 0xF); + destination[2] = BsonUtils.ToHexChar(span[1] >> 4); + destination[3] = BsonUtils.ToHexChar(span[1] & 0xF); + destination[4] = BsonUtils.ToHexChar(span[2] >> 4); + destination[5] = BsonUtils.ToHexChar(span[2] & 0xF); + destination[6] = BsonUtils.ToHexChar(span[3] >> 4); + destination[7] = BsonUtils.ToHexChar(span[3] & 0xF); + destination[8] = BsonUtils.ToHexChar(span[4] >> 4); + destination[9] = BsonUtils.ToHexChar(span[4] & 0xF); + destination[10] = BsonUtils.ToHexChar(span[5] >> 4); + destination[11] = BsonUtils.ToHexChar(span[5] & 0xF); + destination[12] = BsonUtils.ToHexChar(span[6] >> 4); + destination[13] = BsonUtils.ToHexChar(span[6] & 0xF); + destination[14] = BsonUtils.ToHexChar(span[7] >> 4); + destination[15] = BsonUtils.ToHexChar(span[7] & 0xF); + destination[16] = BsonUtils.ToHexChar(span[8] >> 4); + destination[17] = BsonUtils.ToHexChar(span[8] & 0xF); + destination[18] = BsonUtils.ToHexChar(span[9] >> 4); + destination[19] = BsonUtils.ToHexChar(span[9] & 0xF); + destination[20] = BsonUtils.ToHexChar(span[10] >> 4); + destination[21] = BsonUtils.ToHexChar(span[10] & 0xF); + destination[22] = BsonUtils.ToHexChar(span[11] >> 4); + destination[23] = BsonUtils.ToHexChar(span[11] & 0xF); + } +#endif + /// /// Returns a string representation of the value. /// /// A string representation of the value. public override string ToString() { +#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + return string.Create(24, this, static (span, input) => + { + input.ToCharSpan(span); + }); +#else var c = new char[24]; c[0] = BsonUtils.ToHexChar((_a >> 28) & 0x0f); c[1] = BsonUtils.ToHexChar((_a >> 24) & 0x0f); @@ -481,6 +555,7 @@ public override string ToString() c[22] = BsonUtils.ToHexChar((_c >> 4) & 0x0f); c[23] = BsonUtils.ToHexChar(_c & 0x0f); return new string(c); +#endif } // explicit IConvertible implementation diff --git a/tests/MongoDB.Bson.Tests/ObjectModel/ObjectIdTests.cs b/tests/MongoDB.Bson.Tests/ObjectModel/ObjectIdTests.cs index 01c36fb88cd..48c6b5ddfc2 100644 --- a/tests/MongoDB.Bson.Tests/ObjectModel/ObjectIdTests.cs +++ b/tests/MongoDB.Bson.Tests/ObjectModel/ObjectIdTests.cs @@ -87,6 +87,11 @@ public void TestByteArrayConstructor() Assert.Equal(BsonConstants.UnixEpoch.AddSeconds(0x01020304), objectId.CreationTime); Assert.Equal("0102030405060708090a0b0c", objectId.ToString()); Assert.True(bytes.SequenceEqual(objectId.ToByteArray())); +#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Span span = new byte[12]; + objectId.ToByteSpan(span); + Assert.True(span.SequenceEqual(bytes)); +#endif } [Fact] @@ -101,6 +106,11 @@ public void TestStringConstructor() Assert.Equal(BsonConstants.UnixEpoch.AddSeconds(0x01020304), objectId.CreationTime); Assert.Equal("0102030405060708090a0b0c", objectId.ToString()); Assert.True(bytes.SequenceEqual(objectId.ToByteArray())); +#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Span span = new char[24]; + objectId.ToCharSpan(span); + Assert.True(span.SequenceEqual("0102030405060708090a0b0c")); +#endif } [Fact]