using System; using System.IO; namespace NetVips; /// /// An target connected to a writable . /// internal class TargetStream : TargetCustom { /// /// Write to this stream. /// private readonly Stream _stream; /// /// The start position within the stream. /// private readonly long _startPosition; /// internal TargetStream(Stream stream) { var readable = stream.CanRead; var seekable = stream.CanSeek; _stream = stream; _startPosition = seekable ? _stream.Position : 0; OnWrite += Write; if (readable) { OnRead += Read; } if (seekable) { OnSeek += Seek; } OnEnd += End; } /// /// Create a which will output to a . /// /// Write to this stream. /// A new . /// If is not writable. internal static TargetStream NewFromStream(Stream stream) { if (!stream.CanWrite) { throw new ArgumentException("The stream should be writable.", nameof(stream)); } return new TargetStream(stream); } /// /// Attach a write handler. /// /// An array of bytes. /// The number of bytes to be written to the current stream. /// The total number of bytes written to the stream. private long Write(byte[] buffer, int length) { try { _stream.Write(buffer, 0, length); } catch { return -1; } return length; } /// /// Attach a read handler. /// /// An array of bytes. /// The maximum number of bytes to be read. /// The total number of bytes read into the buffer. public int Read(byte[] buffer, int length) { return _stream.Read(buffer, 0, length); } /// /// Attach a seek handler. /// /// A byte offset relative to the /// parameter. /// A value of type indicating the /// reference point used to obtain the new position. /// The new position within the current stream. public long Seek(long offset, SeekOrigin origin) { try { return origin switch { SeekOrigin.Begin => _stream.Seek(_startPosition + offset, SeekOrigin.Begin) - _startPosition, SeekOrigin.Current => _stream.Seek(offset, SeekOrigin.Current) - _startPosition, SeekOrigin.End => _stream.Seek(offset, SeekOrigin.End) - _startPosition, _ => -1 }; } catch { return -1; } } /// /// Attach a end handler. /// /// 0 on success, -1 on error. public int End() { try { _stream.Flush(); } catch { return -1; } return 0; } }