using System; namespace CSNetwork { public class Octets : IDisposable { private byte[] _buffer; private int _size; private int _capacity; public int Size => _size; public int Capacity => _capacity; public int Length => _size; public Octets(int capacity = 0) { _capacity = capacity; _buffer = new byte[capacity]; _size = 0; } public void Clear() { _size = 0; // reset logical length } public Octets(byte[] data) { if (data == null) { throw new ArgumentNullException(nameof(data), "Input byte array cannot be null."); } _capacity = data.Length; _buffer = new byte[_capacity]; Buffer.BlockCopy(data, 0, _buffer, 0, data.Length); _size = data.Length; } public Octets(byte[] data, int capacity) { _capacity = capacity; _buffer = new byte[_capacity]; Buffer.BlockCopy(data, 0, _buffer, 0, capacity); _size = capacity; } /// /// Creates an Octets instance by copying a slice from a source buffer. /// /// The buffer to copy from. /// The starting position in the source buffer. /// The number of bytes to copy. public Octets(byte[] sourceBuffer, int offset, int length) { if (sourceBuffer == null) throw new ArgumentNullException(nameof(sourceBuffer)); if (offset < 0 || length < 0 || offset + length > sourceBuffer.Length) throw new ArgumentOutOfRangeException("Invalid offset or length for source buffer."); _capacity = length; _buffer = new byte[_capacity]; Buffer.BlockCopy(sourceBuffer, offset, _buffer, 0, length); _size = length; } public void Reserve(int newCapacity) { if (newCapacity <= _capacity) return; Array.Resize(ref _buffer, newCapacity); _capacity = newCapacity; } /// /// Sets the logical size of the data within the buffer. /// Throws ArgumentOutOfRangeException if newSize is negative or exceeds capacity. /// /// The new logical size. public void SetSize(int newSize) { if (newSize < 0 || newSize > _capacity) { throw new ArgumentOutOfRangeException(nameof(newSize), $"newSize must be between 0 and capacity ({_capacity})."); } _size = newSize; } public void Replace(byte[] data) { Reserve(data.Length); Buffer.BlockCopy(data, 0, _buffer, 0, data.Length); _size = data.Length; } public void Insert(int pos, byte[] data) { if (data.Length == 0) return; int newSize = _size + data.Length; Reserve(newSize); // Shift existing data Array.Copy(_buffer, pos, _buffer, pos + data.Length, _size - pos); // Insert new data Buffer.BlockCopy(data, 0, _buffer, pos, data.Length); _size = newSize; } public void Erase(int pos, int length) { if (length == 0) return; // Shift remaining data Array.Copy(_buffer, pos + length, _buffer, pos, _size - (pos + length)); _size -= length; } public byte[] ToArray() => _buffer[.._size]; public byte[] ByteArray => ToArray(); public byte[] RawBuffer => _buffer; public void Dispose() => _buffer = null; public override string ToString() { return BitConverter.ToString(_buffer, 0, _size).Replace("-", " "); } internal void Resize(int newSize) { Reserve(newSize); SetSize(newSize); } } }