Content Reader/Writer, StreamCopyCommandHandler
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
namespace FileTime.Core.ContentAccess;
|
||||
|
||||
public class ContentAccessStream : Stream
|
||||
{
|
||||
private readonly IContentReader? _contentReader;
|
||||
private readonly IContentWriter? _contentWriter;
|
||||
public override bool CanRead => _contentReader != null;
|
||||
|
||||
public override bool CanSeek => _contentReader != null;
|
||||
|
||||
public override bool CanWrite => _contentWriter != null;
|
||||
|
||||
public override long Length => throw new NotImplementedException();
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get => throw new NotImplementedException();
|
||||
set => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ContentAccessStream(IContentReader contentReader)
|
||||
{
|
||||
_contentReader = contentReader;
|
||||
}
|
||||
|
||||
public ContentAccessStream(IContentWriter contentWriter)
|
||||
{
|
||||
_contentWriter = contentWriter;
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
if (_contentWriter == null) throw new NotSupportedException();
|
||||
Task.Run(async () => await _contentWriter.FlushAsync()).Wait();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (_contentReader == null) throw new IOException("This stream is not readable");
|
||||
var dataTask = Task.Run(async () => await _contentReader.ReadBytesAsync(count, offset));
|
||||
dataTask.Wait();
|
||||
var data = dataTask.Result;
|
||||
|
||||
if (data.Length > count) throw new Exception("More bytes has been read than requested");
|
||||
Array.Copy(data, buffer, data.Length);
|
||||
return data.Length;
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
if (_contentReader == null) throw new NotSupportedException();
|
||||
|
||||
var newPosition = origin switch
|
||||
{
|
||||
SeekOrigin.Begin => offset,
|
||||
SeekOrigin.Current => _contentReader.Position ?? 0 + offset,
|
||||
_ => throw new NotSupportedException()
|
||||
};
|
||||
_contentReader.SetPosition(newPosition);
|
||||
return newPosition;
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (_contentWriter == null) throw new NotSupportedException();
|
||||
var data = buffer;
|
||||
if (buffer.Length != count)
|
||||
{
|
||||
data = new byte[count];
|
||||
Array.Copy(buffer, data, count);
|
||||
}
|
||||
|
||||
Task.Run(async () => await _contentWriter.WriteBytesAsync(data, offset)).Wait();
|
||||
}
|
||||
}
|
||||
@@ -4,4 +4,8 @@ public interface IContentAccessorFactory
|
||||
{
|
||||
IItemCreator<TContentProvider> GetItemCreator<TContentProvider>() where TContentProvider : IContentProvider;
|
||||
IItemCreator GetItemCreator(IContentProvider provider);
|
||||
IContentReaderFactory<TContentProvider> GetContentReaderFactory<TContentProvider>() where TContentProvider : IContentProvider;
|
||||
IContentReaderFactory GetContentReaderFactory(IContentProvider provider);
|
||||
IContentWriterFactory<TContentProvider> GetContentWriterFactory<TContentProvider>() where TContentProvider : IContentProvider;
|
||||
IContentWriterFactory GetContentWriterFactory(IContentProvider provider);
|
||||
}
|
||||
@@ -7,6 +7,8 @@ namespace FileTime.Core.ContentAccess;
|
||||
|
||||
public interface IContentProvider : IContainer, IOnContainerEnter
|
||||
{
|
||||
bool SupportsContentStreams { get; }
|
||||
|
||||
Task<IItem> GetItemByFullNameAsync(
|
||||
FullName fullName,
|
||||
PointInTime pointInTime,
|
||||
@@ -25,4 +27,5 @@ public interface IContentProvider : IContainer, IOnContainerEnter
|
||||
|
||||
Task<byte[]?> GetContentAsync(IElement element, int? maxLength = null, CancellationToken cancellationToken = default);
|
||||
bool CanHandlePath(NativePath path);
|
||||
bool CanHandlePath(FullName path);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace FileTime.Core.ContentAccess;
|
||||
|
||||
public interface IContentProviderRegistry
|
||||
{
|
||||
IEnumerable<IContentProvider> ContentProviders { get; }
|
||||
void AddContentProvider(IContentProvider contentProvider);
|
||||
void RemoveContentProvider(IContentProvider contentProvider);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace FileTime.Core.ContentAccess;
|
||||
|
||||
public interface IContentReader : IDisposable
|
||||
{
|
||||
int PreferredBufferSize { get; }
|
||||
long? Position { get; }
|
||||
|
||||
Task<byte[]> ReadBytesAsync(int bufferSize, int? offset = null);
|
||||
void SetPosition(long position);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using FileTime.Core.Models;
|
||||
|
||||
namespace FileTime.Core.ContentAccess;
|
||||
|
||||
public interface IContentReaderFactory
|
||||
{
|
||||
Task<IContentReader> CreateContentReaderAsync(IElement element);
|
||||
}
|
||||
|
||||
public interface IContentReaderFactory<in TContentProvider> : IContentReaderFactory where TContentProvider : IContentProvider
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace FileTime.Core.ContentAccess;
|
||||
|
||||
public interface IContentWriter : IDisposable
|
||||
{
|
||||
int PreferredBufferSize { get; }
|
||||
|
||||
Task WriteBytesAsync(byte[] data, int? index = null);
|
||||
Task FlushAsync();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using FileTime.Core.Models;
|
||||
|
||||
namespace FileTime.Core.ContentAccess;
|
||||
|
||||
public interface IContentWriterFactory
|
||||
{
|
||||
Task<IContentWriter> CreateContentWriterAsync(IElement element);
|
||||
}
|
||||
|
||||
public interface IContentWriterFactory<in TContentProvider> : IContentWriterFactory where TContentProvider : IContentProvider
|
||||
{
|
||||
}
|
||||
Reference in New Issue
Block a user