using System.Text;
namespace XFESystem.Documents;
public sealed class DocumentService(IDocumentStorage storage, int maximumBytes = 4 * 1024 * 1024)
{
private static readonly UTF8Encoding Utf8 = new(false, true);
private readonly IDocumentStorage _storage = storage ?? throw new ArgumentNullException(nameof(storage));
private readonly int _maximumBytes = maximumBytes > 0 ? maximumBytes : throw new ArgumentOutOfRangeException(nameof(maximumBytes));
public async ValueTask<DocumentSession> OpenAsync(DocumentLocation location, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(location);
var source = await _storage.ReadAsync(location, _maximumBytes, cancellationToken).ConfigureAwait(false);
if (source.Content.Length > _maximumBytes) throw new IOException("The document exceeds the size limit.");
var bytes = source.Content.Span;
if (bytes.StartsWith(new byte[] { 0xEF, 0xBB, 0xBF })) bytes = bytes[3..];
var text = Utf8.GetString(bytes);
if (text.Contains('\0')) throw new IOException("Binary files cannot be opened as text.");
return new DocumentSession(location, source, text);
}
public ValueTask SaveAsync(DocumentSession session, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(session);
return session.SaveAsync(_storage, _maximumBytes, cancellationToken);
}
}
using System.Text;
namespace XFESystem.Documents;
public sealed class DocumentService(IDocumentStorage storage, int maximumBytes = 4 * 1024 * 1024)
{
private static readonly UTF8Encoding Utf8 = new(false, true);
private readonly IDocumentStorage _storage = storage ?? throw new ArgumentNullException(nameof(storage));
private readonly int _maximumBytes = maximumBytes > 0 ? maximumBytes : throw new ArgumentOutOfRangeException(nameof(maximumBytes));
public async ValueTask<DocumentSession> OpenAsync(DocumentLocation location, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(location);
var source = await _storage.ReadAsync(location, _maximumBytes, cancellationToken).ConfigureAwait(false);
if (source.Content.Length > _maximumBytes) throw new IOException("The document exceeds the size limit.");
var bytes = source.Content.Span;
if (bytes.StartsWith(new byte[] { 0xEF, 0xBB, 0xBF })) bytes = bytes[3..];
var text = Utf8.GetString(bytes);
if (text.Contains('\0')) throw new IOException("Binary files cannot be opened as text.");
return new DocumentSession(location, source, text);
}
public ValueTask SaveAsync(DocumentSession session, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(session);
return session.SaveAsync(_storage, _maximumBytes, cancellationToken);
}
}