parent
c2925d5b93
commit
638a0813b4
3 changed files with 312 additions and 44 deletions
@ -0,0 +1,86 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2015 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 NUnit.Framework; |
||||
using System; |
||||
using Google.Protobuf.Buffers; |
||||
using System.Buffers; |
||||
|
||||
namespace Google.Protobuf |
||||
{ |
||||
public static class MessageParsingHelpers |
||||
{ |
||||
public static void AssertReadingMessage<T>(MessageParser<T> parser, byte[] bytes, Action<T> assert) where T : IMessage<T> |
||||
{ |
||||
var parsedStream = parser.ParseFrom(bytes); |
||||
|
||||
// Load content as single segment |
||||
var parsedBuffer = parser.ParseFrom(new ReadOnlySequence<byte>(bytes)); |
||||
assert(parsedBuffer); |
||||
|
||||
// Load content as multiple segments |
||||
parsedBuffer = parser.ParseFrom(ReadOnlySequenceFactory.CreateWithContent(bytes)); |
||||
assert(parsedBuffer); |
||||
|
||||
assert(parsedStream); |
||||
} |
||||
|
||||
public static void AssertReadingMessageThrows<TMessage, TException>(MessageParser<TMessage> parser, byte[] bytes) |
||||
where TMessage : IMessage<TMessage> |
||||
where TException : Exception |
||||
{ |
||||
Assert.Throws<TException>(() => parser.ParseFrom(bytes)); |
||||
|
||||
Assert.Throws<TException>(() => parser.ParseFrom(new ReadOnlySequence<byte>(bytes))); |
||||
} |
||||
|
||||
public static void AssertRoundtrip<T>(MessageParser<T> parser, T message, Action<T> additionalAssert = null) where T : IMessage<T> |
||||
{ |
||||
var bytes = message.ToByteArray(); |
||||
|
||||
// Load content as single segment |
||||
var parsedBuffer = parser.ParseFrom(new ReadOnlySequence<byte>(bytes)); |
||||
Assert.AreEqual(message, parsedBuffer); |
||||
additionalAssert?.Invoke(parsedBuffer); |
||||
|
||||
// Load content as multiple segments |
||||
parsedBuffer = parser.ParseFrom(ReadOnlySequenceFactory.CreateWithContent(bytes)); |
||||
Assert.AreEqual(message, parsedBuffer); |
||||
additionalAssert?.Invoke(parsedBuffer); |
||||
|
||||
var parsedStream = parser.ParseFrom(bytes); |
||||
|
||||
Assert.AreEqual(message, parsedStream); |
||||
additionalAssert?.Invoke(parsedStream); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,128 @@ |
||||
#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.Buffers; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Text; |
||||
using System.Threading.Tasks; |
||||
|
||||
namespace Google.Protobuf.Buffers |
||||
{ |
||||
internal static class ReadOnlySequenceFactory |
||||
{ |
||||
public static ReadOnlySequence<byte> CreateWithContent(byte[] data, int segmentSize = 1) |
||||
{ |
||||
var segments = new List<byte[]>(); |
||||
|
||||
segments.Add(new byte[0]); |
||||
var currentIndex = 0; |
||||
while (currentIndex < data.Length) |
||||
{ |
||||
var segment = new List<byte>(); |
||||
for (; currentIndex < Math.Min(currentIndex + segmentSize, data.Length); currentIndex++) |
||||
{ |
||||
segment.Add(data[currentIndex]); |
||||
} |
||||
segments.Add(segment.ToArray()); |
||||
segments.Add(new byte[0]); |
||||
} |
||||
|
||||
return CreateSegments(segments.ToArray()); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Originally from corefx, and has been contributed to Protobuf |
||||
/// https://github.com/dotnet/corefx/blob/e99ec129cfd594d53f4390bf97d1d736cff6f860/src/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceFactory.byte.cs |
||||
/// </summary> |
||||
private static ReadOnlySequence<byte> CreateSegments(params byte[][] inputs) |
||||
{ |
||||
if (inputs == null || inputs.Length == 0) |
||||
{ |
||||
throw new InvalidOperationException(); |
||||
} |
||||
|
||||
int i = 0; |
||||
|
||||
BufferSegment last = null; |
||||
BufferSegment first = null; |
||||
|
||||
do |
||||
{ |
||||
byte[] s = inputs[i]; |
||||
int length = s.Length; |
||||
int dataOffset = length; |
||||
var chars = new byte[length * 2]; |
||||
|
||||
for (int j = 0; j < length; j++) |
||||
{ |
||||
chars[dataOffset + j] = s[j]; |
||||
} |
||||
|
||||
// Create a segment that has offset relative to the OwnedMemory and OwnedMemory itself has offset relative to array |
||||
var memory = new Memory<byte>(chars).Slice(length, length); |
||||
|
||||
if (first == null) |
||||
{ |
||||
first = new BufferSegment(memory); |
||||
last = first; |
||||
} |
||||
else |
||||
{ |
||||
last = last.Append(memory); |
||||
} |
||||
i++; |
||||
} while (i < inputs.Length); |
||||
|
||||
return new ReadOnlySequence<byte>(first, 0, last, last.Memory.Length); |
||||
} |
||||
|
||||
private class BufferSegment : ReadOnlySequenceSegment<byte> |
||||
{ |
||||
public BufferSegment(Memory<byte> memory) |
||||
{ |
||||
Memory = memory; |
||||
} |
||||
|
||||
public BufferSegment Append(Memory<byte> memory) |
||||
{ |
||||
var segment = new BufferSegment(memory) |
||||
{ |
||||
RunningIndex = RunningIndex + Memory.Length |
||||
}; |
||||
Next = segment; |
||||
return segment; |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue