| #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; | 
 |  | 
 | namespace Google.Protobuf | 
 | { | 
 |     internal static class ReadOnlySequenceFactory | 
 |     { | 
 |         /// <summary> | 
 |         /// Create a sequence from the specified data. The data will be divided up into segments in the sequence. | 
 |         /// </summary> | 
 |         public static ReadOnlySequence<byte> CreateWithContent(byte[] data, int segmentSize = 1, bool addEmptySegmentDelimiters = true) | 
 |         { | 
 |             var segments = new List<byte[]>(); | 
 |  | 
 |             if (addEmptySegmentDelimiters) | 
 |             { | 
 |                 segments.Add(Array.Empty<byte>()); | 
 |             } | 
 |  | 
 |             var currentIndex = 0; | 
 |             while (currentIndex < data.Length) | 
 |             { | 
 |                 var segment = new List<byte>(); | 
 |                 while (segment.Count < segmentSize && currentIndex < data.Length) | 
 |                 { | 
 |                     segment.Add(data[currentIndex++]); | 
 |                 } | 
 |                 segments.Add(segment.ToArray()); | 
 |  | 
 |                 if (addEmptySegmentDelimiters) | 
 |                 { | 
 |                     segments.Add(Array.Empty<byte>()); | 
 |                 } | 
 |             } | 
 |  | 
 |             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; | 
 |             } | 
 |         } | 
 |     } | 
 | } |