// 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.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.
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.
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.");
}
}