feat: update transformers to use ByteDocument type
Refactor the transformers in the downloader classes to use ByteDocument instead of byte arrays. This change improves type safety and clarity in handling document content during downloads, ensuring that the transformations are more consistent and maintainable.
This commit is contained in:
@@ -42,6 +42,9 @@ namespace Beam.Temporary.Cli {
|
||||
|
||||
public interface IAlternativeTransformStage {
|
||||
IContextStage WithTransformer(AsyncTransformer<RawType, OutType> transformer);
|
||||
IContextStage WithTransformer(Func<RawType, OutType> transformer) {
|
||||
return WithTransformer(rt => Task.FromResult(transformer(rt)));
|
||||
}
|
||||
}
|
||||
|
||||
public interface IContextStage {
|
||||
@@ -192,8 +195,8 @@ namespace Beam.Temporary.Cli {
|
||||
_parallelism,
|
||||
context.DownloadLogger),
|
||||
// ──────────────── fragmented binary ────────────────
|
||||
(true, AsyncTransformer<byte[], OutType> asyncBinaryTransformer,
|
||||
AsyncDownloadFailurePredicate<byte[]>[] responseFailurePredicates)
|
||||
(true, AsyncTransformer<ByteDocument, OutType> asyncBinaryTransformer,
|
||||
AsyncDownloadFailurePredicate<ByteDocument>[] responseFailurePredicates)
|
||||
=> new UnitFragmentDownloaderBinary<OutType>(
|
||||
context.Client,
|
||||
asyncBinaryTransformer,
|
||||
@@ -208,8 +211,8 @@ namespace Beam.Temporary.Cli {
|
||||
asyncHtmlTransformer,
|
||||
documentFailurePredicates),
|
||||
// ──────────────── single binary ────────────────
|
||||
(false, AsyncTransformer<byte[], OutType> asyncBinaryTransformer,
|
||||
AsyncDownloadFailurePredicate<byte[]>[] responseFailurePredicates)
|
||||
(false, AsyncTransformer<ByteDocument, OutType> asyncBinaryTransformer,
|
||||
AsyncDownloadFailurePredicate<ByteDocument>[] responseFailurePredicates)
|
||||
=> new UnitDownloaderBinary<OutType>(
|
||||
context.Client,
|
||||
asyncBinaryTransformer,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Text;
|
||||
|
||||
namespace Beam {
|
||||
internal class ByteDocument(string filename, byte[] content, Encoding? encoding = null) : Document(filename, encoding) {
|
||||
public class ByteDocument(string filename, byte[] content, Encoding? encoding = null) : Document(filename, encoding) {
|
||||
public byte[] Content { get; set; } = content;
|
||||
|
||||
public override byte[] ToBytes() {
|
||||
|
||||
@@ -16,7 +16,13 @@ namespace Beam {
|
||||
Context = context;
|
||||
Logger = logger;
|
||||
LinksEnumerator = Context.Links.GetEnumerator();
|
||||
|
||||
try {
|
||||
LinksEnumerator.Reset();
|
||||
} catch (NotSupportedException) {
|
||||
Logger?.LogWarning("Enumerator of type {} does not support resets. This may cause buggy behavior", LinksEnumerator.GetType());
|
||||
}
|
||||
|
||||
if (!LinksEnumerator.MoveNext())
|
||||
throw new ArgumentOutOfRangeException(S.M.LinksCannotBeEmpty);
|
||||
Current = default(OutType);
|
||||
@@ -29,14 +35,20 @@ namespace Beam {
|
||||
}
|
||||
|
||||
public async ValueTask<bool> MoveNextAsync() {
|
||||
if (!LinksEnumerator.Current.HasValue)
|
||||
return false;
|
||||
|
||||
//Logger?.LogInformation("MoveNextAsync()");
|
||||
var unit = GetUnitDownloader(); // safe to instantiate per request.
|
||||
var idealLinkCount = unit.LinksPerDownload;
|
||||
List<Ordered<string>> links = [];
|
||||
|
||||
//Logger?.LogInformation("MoveNextAsync() \n\t -> Links.Current = {} ", LinksEnumerator.Current.Link.AbsoluteUri);
|
||||
links.Add(new Ordered<string>(LinksEnumerator.Current.Link.ToString(), LastOrder++));
|
||||
|
||||
while (LinksEnumerator.MoveNext() && LinksEnumerator.Current != SourceLink.InvalidLink && links.Count < idealLinkCount)
|
||||
links.Add(new Ordered<string>(LinksEnumerator.Current.Link.ToString(), LastOrder++));
|
||||
//Logger?.LogInformation("MoveNextAsync() \n\t -> links.Count = {} ", links.Count);
|
||||
if (links.Count == 0) {
|
||||
Logger?.LogInformation("Out of links!");
|
||||
return false;
|
||||
|
||||
@@ -14,10 +14,16 @@ namespace Beam {
|
||||
public static SourceLink InvalidLink { get; } = new("invalid://link");
|
||||
|
||||
public static bool operator ==(SourceLink lhs, SourceLink rhs) {
|
||||
if (lhs.HasValue && rhs.HasValue)
|
||||
return lhs.Link == rhs.Link;
|
||||
else
|
||||
return lhs.Link_ == rhs.Link_;
|
||||
}
|
||||
public static bool operator !=(SourceLink lhs, SourceLink rhs) {
|
||||
if (lhs.HasValue && rhs.HasValue)
|
||||
return lhs.Link != rhs.Link;
|
||||
else
|
||||
return lhs.Link_ != rhs.Link_;
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj) {
|
||||
|
||||
@@ -10,12 +10,12 @@ namespace Beam {
|
||||
/// </summary>
|
||||
public class UnitDownloaderBinary<T>(
|
||||
HttpClient client,
|
||||
AsyncTransformer<byte[], T> transformer,
|
||||
AsyncDownloadFailurePredicate<byte[]>?[]? failurePredicates = null)
|
||||
AsyncTransformer<ByteDocument, T> transformer,
|
||||
AsyncDownloadFailurePredicate<ByteDocument>?[]? failurePredicates = null)
|
||||
: IUnitDownloader<T> {
|
||||
public HttpClient Client { get; } = client;
|
||||
public virtual AsyncTransformer<byte[], T> Transformer { get; } = transformer;
|
||||
public virtual AsyncDownloadFailurePredicate<byte[]>?[]? FailurePredicates { get; } = failurePredicates;
|
||||
public virtual AsyncTransformer<ByteDocument, T> Transformer { get; } = transformer;
|
||||
public virtual AsyncDownloadFailurePredicate<ByteDocument>?[]? FailurePredicates { get; } = failurePredicates;
|
||||
|
||||
public int LinksPerDownload { get; } = 1;
|
||||
|
||||
@@ -26,7 +26,8 @@ namespace Beam {
|
||||
var failed = false;
|
||||
await Parallel.ForEachAsync(FailurePredicates, async (pred, ct) => {
|
||||
if (failed || pred is null) return;
|
||||
if (await pred(await response.Content.ReadAsByteArrayAsync(ct))) failed = true;
|
||||
if (await pred(new ByteDocument(response.RequestMessage?.RequestUri?.AbsolutePath ?? "", await response.Content.ReadAsByteArrayAsync(ct))))
|
||||
failed = true;
|
||||
});
|
||||
return failed;
|
||||
}
|
||||
@@ -40,7 +41,7 @@ namespace Beam {
|
||||
if (await IsFailure(response)) return (false, default);
|
||||
|
||||
var bytes = await response.Content.ReadAsByteArrayAsync(ct);
|
||||
return (true, await Transformer(bytes));
|
||||
return (true, await Transformer(new ByteDocument(link, bytes)));
|
||||
} catch {
|
||||
return (false, default);
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@ namespace Beam {
|
||||
public class UnitFragmentDownloaderBinary<T>
|
||||
: IUnitDownloader<Fragment<Ordered<T>>> {
|
||||
public UnitFragmentDownloaderBinary(HttpClient client,
|
||||
AsyncTransformer<byte[], T> transformer,
|
||||
AsyncDownloadFailurePredicate<byte[]>?[]? failurePredicate = null,
|
||||
AsyncTransformer<ByteDocument, T> transformer,
|
||||
AsyncDownloadFailurePredicate<ByteDocument>?[]? failurePredicate = null,
|
||||
int fragmentSize = 4,
|
||||
ILogger? logger = null,
|
||||
IUnitDownloader<T>? internalDownloader = null) {
|
||||
@@ -27,8 +27,8 @@ namespace Beam {
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
public AsyncTransformer<byte[], T> Transformer { get; }
|
||||
public AsyncDownloadFailurePredicate<byte[]>?[]? FailurePredicate { get; }
|
||||
public AsyncTransformer<ByteDocument, T> Transformer { get; }
|
||||
public AsyncDownloadFailurePredicate<ByteDocument>?[]? FailurePredicate { get; }
|
||||
public int LinksPerDownload { get; set; }
|
||||
public ILogger? Logger { get; set; }
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<Title>Beam</Title>
|
||||
<Authors>aeqw89</Authors>
|
||||
<Company>qwsdcvghyu</Company>
|
||||
<Version>1.2.4</Version>
|
||||
<Version>1.2.10</Version>
|
||||
<Description>A library for downloading internet resources</Description>
|
||||
<PackageProjectUrl>https://github.com/qwsdcvghyu89/Beam</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/qwsdcvghyu89/Beam</RepositoryUrl>
|
||||
|
||||
Reference in New Issue
Block a user