// 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; using System.Buffers; using System.Diagnostics.Contracts; using System.IO; using System.Runtime.InteropServices; namespace CommunityToolkit.HighPerformance.Streams; /// /// A factory class to produce instances. /// internal static partial class MemoryStream { /// /// Creates a new from the input of instance. /// /// The input instance. /// Indicates whether or not can be written to. /// A wrapping the underlying data for . /// Thrown when has an invalid data store. [Pure] public static Stream Create(ReadOnlyMemory memory, bool isReadOnly) { if (memory.IsEmpty) { // Return an empty stream if the memory was empty return new MemoryStream(ArrayOwner.Empty, isReadOnly); } if (MemoryMarshal.TryGetArray(memory, out ArraySegment segment)) { ArrayOwner arraySpanSource = new(segment.Array!, segment.Offset, segment.Count); return new MemoryStream(arraySpanSource, isReadOnly); } if (MemoryMarshal.TryGetMemoryManager(memory, out MemoryManager? memoryManager, out int start, out int length)) { MemoryManagerOwner memoryManagerSpanSource = new(memoryManager!, start, length); return new MemoryStream(memoryManagerSpanSource, isReadOnly); } return ThrowNotSupportedExceptionForInvalidMemory(); } /// /// Creates a new from the input of instance. /// /// The input instance. /// A wrapping the underlying data for . /// Thrown when has an invalid data store. [Pure] public static Stream Create(IMemoryOwner memoryOwner) { Memory memory = memoryOwner.Memory; if (memory.IsEmpty) { // Return an empty stream if the memory was empty return new IMemoryOwnerStream(ArrayOwner.Empty, memoryOwner); } if (MemoryMarshal.TryGetArray(memory, out ArraySegment segment)) { ArrayOwner arraySpanSource = new(segment.Array!, segment.Offset, segment.Count); return new IMemoryOwnerStream(arraySpanSource, memoryOwner); } if (MemoryMarshal.TryGetMemoryManager>(memory, out MemoryManager? memoryManager, out int start, out int length)) { MemoryManagerOwner memoryManagerSpanSource = new(memoryManager, start, length); return new IMemoryOwnerStream(memoryManagerSpanSource, memoryOwner); } return ThrowNotSupportedExceptionForInvalidMemory(); } /// /// Throws a when a given /// or instance has an unsupported backing store. /// /// Nothing, this method always throws. private static Stream ThrowNotSupportedExceptionForInvalidMemory() { throw new ArgumentException("The input instance doesn't have a valid underlying data store."); } }