Skip to content

Commit

Permalink
Mirror Java's UnsafeByteOperations type
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesNK committed Jul 5, 2020
1 parent 5a0fc33 commit 5821555
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 14 deletions.
3 changes: 2 additions & 1 deletion Makefile.am
Expand Up @@ -261,7 +261,8 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf/WellKnownTypes/WrappersPartial.cs \
csharp/src/Google.Protobuf/WireFormat.cs \
csharp/src/Google.Protobuf/UnknownField.cs \
csharp/src/Google.Protobuf/UnknownFieldSet.cs
csharp/src/Google.Protobuf/UnknownFieldSet.cs \
csharp/src/Google.Protobuf/UnsafeByteOperations.cs

java_EXTRA_DIST= \
java/README.md \
Expand Down
8 changes: 6 additions & 2 deletions csharp/src/Google.Protobuf.Test/ByteStringTest.cs
Expand Up @@ -178,16 +178,20 @@ public void GetEnumerator()
}

[Test]
public void UnsafeFromBytes()
public void UnsafeWrap()
{
byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6 };
ByteString bs = ByteString.UnsafeFromBytes(data.AsMemory(2, 3));
ByteString bs = UnsafeByteOperations.UnsafeWrap(data.AsMemory(2, 3));
ReadOnlySpan<byte> s = bs.Span;

Assert.AreEqual(3, s.Length);
Assert.AreEqual(2, s[0]);
Assert.AreEqual(3, s[1]);
Assert.AreEqual(4, s[2]);

// Check that the value is not a copy
data[2] = byte.MaxValue;
Assert.AreEqual(byte.MaxValue, s[0]);
}

[Test]
Expand Down
19 changes: 8 additions & 11 deletions csharp/src/Google.Protobuf/ByteString.cs
Expand Up @@ -69,6 +69,14 @@ internal static ByteString AttachBytes(byte[] bytes)
return new ByteString(bytes);
}

/// <summary>
/// Internal use only. Ensure that the provided array is not mutated and belongs to this instance.
/// </summary>
internal static ByteString AttachBytes(ReadOnlyMemory<byte> bytes)
{
return new ByteString(bytes);
}

#if GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY
/// <summary>
/// Constructs a new ByteString from the given byte array. The array is
Expand Down Expand Up @@ -169,17 +177,6 @@ public string ToBase64()
#endif
}

#if GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY
/// <summary>
/// Constructs a new <see cref="ByteString" /> from the given bytes. The bytes are not copied,
/// and must not be modified while the <see cref="ByteString" /> is in use.
/// </summary>
public static ByteString UnsafeFromBytes(ReadOnlyMemory<byte> bytes)
{
return new ByteString(bytes);
}
#endif

/// <summary>
/// Constructs a <see cref="ByteString" /> from the Base64 Encoded String.
/// </summary>
Expand Down
83 changes: 83 additions & 0 deletions csharp/src/Google.Protobuf/UnsafeByteOperations.cs
@@ -0,0 +1,83 @@
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

using System;
using System.Security;

namespace Google.Protobuf
{
#if GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY
/// <summary>
/// Provides a number of unsafe byte operations to be used by advanced applications with high performance
/// requirements. These methods are referred to as "unsafe" due to the fact that they potentially expose
/// the backing buffer of a <see cref="ByteString"/> to the application.
/// </summary>
/// <remarks>
/// <para>
/// The methods in this class should only be called if it is guaranteed that the buffer backing the
/// <see cref="ByteString"/> will never change! Mutation of a <see cref="ByteString"/> can lead to unexpected
/// and undesirable consequences in your application, and will likely be difficult to debug. Proceed with caution!
/// </para>
/// <para>
/// This can have a number of significant side affects that have spooky-action-at-a-distance-like behavior. In
/// particular, if the bytes value changes out from under a Protocol Buffer:
/// </para>
/// <list type="bullet">
/// <item>
/// <description>serialization may throw</description>
/// </item>
/// <item>
/// <description>serialization may succeed but the wrong bytes may be written out</description>
/// </item>
/// <item>
/// <description>messages are no longer threadsafe</description>
/// </item>
/// <item>
/// <description>hashCode may be incorrect</description>
/// </item>
/// </list>
/// </remarks>
[SecuritySafeCritical]
public static class UnsafeByteOperations
{
/// <summary>
/// Constructs a new <see cref="ByteString" /> from the given bytes. The bytes are not copied,
/// and must not be modified while the <see cref="ByteString" /> is in use.
/// This API is experimental and subject to change.
/// </summary>
public static ByteString UnsafeWrap(ReadOnlyMemory<byte> bytes)
{
return ByteString.AttachBytes(bytes);
}
}
#endif
}

0 comments on commit 5821555

Please sign in to comment.