mirror of
https://github.com/chylex/.NET-Community-Toolkit.git
synced 2024-11-24 07:42:45 +01:00
92 lines
3.9 KiB
C#
92 lines
3.9 KiB
C#
// 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;
|
|
|
|
/// <summary>
|
|
/// A factory class to produce <see cref="MemoryStream{TSource}"/> instances.
|
|
/// </summary>
|
|
internal static partial class MemoryStream
|
|
{
|
|
/// <summary>
|
|
/// Creates a new <see cref="Stream"/> from the input <see cref="ReadOnlyMemory{T}"/> of <see cref="byte"/> instance.
|
|
/// </summary>
|
|
/// <param name="memory">The input <see cref="ReadOnlyMemory{T}"/> instance.</param>
|
|
/// <param name="isReadOnly">Indicates whether or not <paramref name="memory"/> can be written to.</param>
|
|
/// <returns>A <see cref="Stream"/> wrapping the underlying data for <paramref name="memory"/>.</returns>
|
|
/// <exception cref="ArgumentException">Thrown when <paramref name="memory"/> has an invalid data store.</exception>
|
|
public static Stream Create(ReadOnlyMemory<byte> memory, bool isReadOnly)
|
|
{
|
|
if (memory.IsEmpty)
|
|
{
|
|
// Return an empty stream if the memory was empty
|
|
return new MemoryStream<ArrayOwner>(ArrayOwner.Empty, isReadOnly);
|
|
}
|
|
|
|
if (MemoryMarshal.TryGetArray(memory, out ArraySegment<byte> segment))
|
|
{
|
|
ArrayOwner arraySpanSource = new(segment.Array!, segment.Offset, segment.Count);
|
|
|
|
return new MemoryStream<ArrayOwner>(arraySpanSource, isReadOnly);
|
|
}
|
|
|
|
if (MemoryMarshal.TryGetMemoryManager(memory, out MemoryManager<byte>? memoryManager, out int start, out int length))
|
|
{
|
|
MemoryManagerOwner memoryManagerSpanSource = new(memoryManager!, start, length);
|
|
|
|
return new MemoryStream<MemoryManagerOwner>(memoryManagerSpanSource, isReadOnly);
|
|
}
|
|
|
|
return ThrowNotSupportedExceptionForInvalidMemory();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new <see cref="Stream"/> from the input <see cref="IMemoryOwner{T}"/> of <see cref="byte"/> instance.
|
|
/// </summary>
|
|
/// <param name="memoryOwner">The input <see cref="IMemoryOwner{T}"/> instance.</param>
|
|
/// <returns>A <see cref="Stream"/> wrapping the underlying data for <paramref name="memoryOwner"/>.</returns>
|
|
/// <exception cref="ArgumentException">Thrown when <paramref name="memoryOwner"/> has an invalid data store.</exception>
|
|
public static Stream Create(IMemoryOwner<byte> memoryOwner)
|
|
{
|
|
Memory<byte> memory = memoryOwner.Memory;
|
|
|
|
if (memory.IsEmpty)
|
|
{
|
|
// Return an empty stream if the memory was empty
|
|
return new IMemoryOwnerStream<ArrayOwner>(ArrayOwner.Empty, memoryOwner);
|
|
}
|
|
|
|
if (MemoryMarshal.TryGetArray(memory, out ArraySegment<byte> segment))
|
|
{
|
|
ArrayOwner arraySpanSource = new(segment.Array!, segment.Offset, segment.Count);
|
|
|
|
return new IMemoryOwnerStream<ArrayOwner>(arraySpanSource, memoryOwner);
|
|
}
|
|
|
|
if (MemoryMarshal.TryGetMemoryManager<byte, MemoryManager<byte>>(memory, out MemoryManager<byte>? memoryManager, out int start, out int length))
|
|
{
|
|
MemoryManagerOwner memoryManagerSpanSource = new(memoryManager, start, length);
|
|
|
|
return new IMemoryOwnerStream<MemoryManagerOwner>(memoryManagerSpanSource, memoryOwner);
|
|
}
|
|
|
|
return ThrowNotSupportedExceptionForInvalidMemory();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Throws a <see cref="ArgumentException"/> when a given <see cref="Memory{T}"/>
|
|
/// or <see cref="IMemoryOwner{T}"/> instance has an unsupported backing store.
|
|
/// </summary>
|
|
/// <returns>Nothing, this method always throws.</returns>
|
|
private static Stream ThrowNotSupportedExceptionForInvalidMemory()
|
|
{
|
|
throw new ArgumentException("The input instance doesn't have a valid underlying data store.");
|
|
}
|
|
}
|