// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Buffers;
using System.Collections.Generic;
namespace EpicGames.Core
{
///
/// Static utility methods
///
public static class ReadOnlySequence
{
///
/// Create a sequence from a list of segments
///
///
/// Sequence for the list of segments
public static ReadOnlySequence Create(IReadOnlyList> segments) => ReadOnlySequenceBuilder.Create(segments);
}
///
/// Utility class to combine buffers into a
///
/// Element type
public class ReadOnlySequenceBuilder
{
class Segment : ReadOnlySequenceSegment
{
public Segment(long runningIndex, ReadOnlyMemory memory)
{
RunningIndex = runningIndex;
Memory = memory;
}
public void SetNext(Segment next)
{
Next = next;
}
}
readonly List> _segments = [];
///
/// Current length of the sequence
///
public long Length { get; private set; }
///
/// Create a sequence from a list of segments
///
///
/// Sequence for the list of segments
internal static ReadOnlySequence Create(IReadOnlyList> segments)
{
if (segments.Count == 0)
{
return ReadOnlySequence.Empty;
}
Segment first = new Segment(0, segments[0]);
Segment last = first;
for (int idx = 1; idx < segments.Count; idx++)
{
Segment next = new Segment(last.RunningIndex + last.Memory.Length, segments[idx]);
last.SetNext(next);
last = next;
}
return new ReadOnlySequence(first, 0, last, last.Memory.Length);
}
///
/// Append a block of memory to the end of the sequence
///
/// Memory to append
public void Append(ReadOnlyMemory memory)
{
if (memory.Length > 0)
{
_segments.Add(memory);
Length += memory.Length;
}
}
///
/// Append another sequence to the end of this one
///
/// Sequence to append
public void Append(ReadOnlySequence sequence)
{
foreach (ReadOnlyMemory segment in sequence)
{
Append(segment);
}
}
///
/// Construct a sequence from the added blocks
///
/// Sequence for the added memory blocks
public ReadOnlySequence Construct() => Create(_segments);
}
///
/// Extension methods for
///
public static class ReadOnlySequenceExtensions
{
///
/// Gets the data from a sequence as a contiguous block of memory
///
/// Sequence to return
/// Data for the blob
public static ReadOnlyMemory AsSingleSegment(this ReadOnlySequence sequence)
{
if (sequence.IsSingleSegment)
{
return sequence.First;
}
else
{
return sequence.ToArray();
}
}
}
}