using System; using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; namespace Avalonia.Gif.Extensions { [DebuggerStepThrough] internal static class StreamExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ushort SpanToShort(Span b) => (ushort)(b[0] | (b[1] << 8)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Skip(this Stream stream, long count) { stream.Position += count; } /// /// Read a Gif block from stream while advancing the position. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int ReadBlock(this Stream stream, byte[] tempBuf) { stream.Read(tempBuf, 0, 1); var blockLength = (int)tempBuf[0]; if (blockLength > 0) stream.Read(tempBuf, 0, blockLength); // Guard against infinite loop. if (stream.Position >= stream.Length) throw new InvalidGifStreamException("Reach the end of the filestream without trailer block."); return blockLength; } /// /// Skips GIF blocks until it encounters an empty block. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void SkipBlocks(this Stream stream, byte[] tempBuf) { int blockLength; do { stream.Read(tempBuf, 0, 1); blockLength = tempBuf[0]; stream.Position += blockLength; // Guard against infinite loop. if (stream.Position >= stream.Length) throw new InvalidGifStreamException("Reach the end of the filestream without trailer block."); } while (blockLength > 0); } /// /// Read a from stream by providing a temporary buffer. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ushort ReadUShortS(this Stream stream, byte[] tempBuf) { stream.Read(tempBuf, 0, 2); return SpanToShort(tempBuf); } /// /// Read a from stream by providing a temporary buffer. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte ReadByteS(this Stream stream, byte[] tempBuf) { stream.Read(tempBuf, 0, 1); var finalVal = tempBuf[0]; return finalVal; } } }