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;
}
}