using System; using System.Security.Cryptography; namespace ScreenConnect; public struct CursorBuffer { public static readonly CursorBuffer Empty = From(Extensions.EmptyArraySegment()); public required ArraySegment FullSegment; public int CurrentOffset; public byte[] BackingArray => FullSegment.Array; public int CompletedCount => CurrentOffset - FullSegment.Offset; public int RemainingCount => FullSegment.Count - CompletedCount; public static CursorBuffer From(byte[] array) { return new CursorBuffer { FullSegment = array.ToArraySegment(), CurrentOffset = 0 }; } public static CursorBuffer From(byte[] array, int offset, int count) { return new CursorBuffer { FullSegment = new ArraySegment(array, offset, count), CurrentOffset = offset }; } public static CursorBuffer From(ArraySegment segment) { segment.Array.AssertArgumentNonNull("segment.Array"); return new CursorBuffer { FullSegment = segment, CurrentOffset = segment.Offset }; } public ArraySegment GetCompletedSegment() { return new ArraySegment(BackingArray, FullSegment.Offset, CompletedCount); } public ArraySegment GetRemainingSegment() { return new ArraySegment(BackingArray, CurrentOffset, RemainingCount); } public static void ResetToBeginning(ref CursorBuffer buffer) { buffer.RemainingCount.AssertEquals(0); buffer.CurrentOffset = buffer.FullSegment.Offset; } public static void ResetToEnd(ref CursorBuffer buffer) { buffer.CompletedCount.AssertEquals(0); buffer.CurrentOffset = buffer.FullSegment.Offset + buffer.FullSegment.Count; } public static void Advance(ref CursorBuffer buffer, int count) { buffer.CurrentOffset += count; } public static bool TryAdvance(ref CursorBuffer buffer, int count) { if (buffer.RemainingCount < count) { return false; } Advance(ref buffer, count); return true; } public static bool TryReadOne(ref CursorBuffer source, out byte value) { if (source.RemainingCount <= 0) { value = 0; return false; } value = source.BackingArray[source.CurrentOffset++]; return true; } public static byte ReadOne(ref CursorBuffer source) { return source.BackingArray[source.CurrentOffset++]; } public static bool ReadOneIfEquals(ref CursorBuffer source, byte value) { if (source.BackingArray[source.CurrentOffset] == value) { source.CurrentOffset++; return true; } return false; } public static void WriteOne(ref CursorBuffer destination, byte value) { destination.BackingArray[destination.CurrentOffset++] = value; } public static int Copy(ref CursorBuffer sourceToAdvance, ref CursorBuffer destinationToAdvance) { int num = Math.Min(sourceToAdvance.RemainingCount, destinationToAdvance.RemainingCount); Buffer.BlockCopy(sourceToAdvance.BackingArray, sourceToAdvance.CurrentOffset, destinationToAdvance.BackingArray, destinationToAdvance.CurrentOffset, num); Advance(ref sourceToAdvance, num); Advance(ref destinationToAdvance, num); return num; } private static int GetTransformCount(int nonBlockBasedCount, int blockSize) { return nonBlockBasedCount - nonBlockBasedCount % blockSize; } public static int Transform(ref CursorBuffer sourceToAdvance, ref CursorBuffer destinationToAdvance, ICryptoTransform transform) { int transformCount = GetTransformCount(Math.Min(sourceToAdvance.RemainingCount, destinationToAdvance.RemainingCount), transform.InputBlockSize); if (transformCount > 0) { transform.TransformBlock(sourceToAdvance.BackingArray, sourceToAdvance.CurrentOffset, transformCount, destinationToAdvance.BackingArray, destinationToAdvance.CurrentOffset); Advance(ref sourceToAdvance, transformCount); Advance(ref destinationToAdvance, transformCount); } return transformCount; } }