// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Collections.Generic; using System.Text; namespace System.Buffers { internal abstract class ReadOnlySequenceFactory { public static ReadOnlySequenceFactory ArrayFactory { get; } = new ArrayTestSequenceFactory(); public static ReadOnlySequenceFactory MemoryFactory { get; } = new MemoryTestSequenceFactory(); public static ReadOnlySequenceFactory OwnedMemoryFactory { get; } = new OwnedMemoryTestSequenceFactory(); public static ReadOnlySequenceFactory SingleSegmentFactory { get; } = new SingleSegmentTestSequenceFactory(); public static ReadOnlySequenceFactory SegmentPerByteFactory { get; } = new BytePerSegmentTestSequenceFactory(); public abstract ReadOnlySequence CreateOfSize(int size); public abstract ReadOnlySequence CreateWithContent(byte[] data); public ReadOnlySequence CreateWithContent(string data) { return CreateWithContent(Encoding.ASCII.GetBytes(data)); } internal class ArrayTestSequenceFactory : ReadOnlySequenceFactory { public override ReadOnlySequence CreateOfSize(int size) { return new ReadOnlySequence(new byte[size + 20], 10, size); } public override ReadOnlySequence CreateWithContent(byte[] data) { var startSegment = new byte[data.Length + 20]; Array.Copy(data, 0, startSegment, 10, data.Length); return new ReadOnlySequence(startSegment, 10, data.Length); } } internal class MemoryTestSequenceFactory : ReadOnlySequenceFactory { public override ReadOnlySequence CreateOfSize(int size) { return CreateWithContent(new byte[size]); } public override ReadOnlySequence CreateWithContent(byte[] data) { var startSegment = new byte[data.Length + 20]; Array.Copy(data, 0, startSegment, 10, data.Length); return new ReadOnlySequence(new Memory(startSegment, 10, data.Length)); } } internal class OwnedMemoryTestSequenceFactory : ReadOnlySequenceFactory { public override ReadOnlySequence CreateOfSize(int size) { return CreateWithContent(new byte[size]); } public override ReadOnlySequence CreateWithContent(byte[] data) { var startSegment = new byte[data.Length + 20]; Array.Copy(data, 0, startSegment, 10, data.Length); return new ReadOnlySequence(new CustomMemoryForTest(startSegment, 10, data.Length).Memory); } } internal class SingleSegmentTestSequenceFactory : ReadOnlySequenceFactory { public override ReadOnlySequence CreateOfSize(int size) { return CreateWithContent(new byte[size]); } public override ReadOnlySequence CreateWithContent(byte[] data) { return CreateSegments(data); } } internal class BytePerSegmentTestSequenceFactory : ReadOnlySequenceFactory { public override ReadOnlySequence CreateOfSize(int size) { return CreateWithContent(new byte[size]); } public override ReadOnlySequence CreateWithContent(byte[] data) { var segments = new List(); segments.Add(Array.Empty()); foreach (var b in data) { segments.Add(new[] { b }); segments.Add(Array.Empty()); } return CreateSegments(segments.ToArray()); } } public static ReadOnlySequence 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(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(first, 0, last, last.Memory.Length); } } }