rsynko_manager/downloads.rs
1use crate::ManagerSorts;
2use alux_ext::ext;
3use ambassador::delegatable_trait;
4use std::path::PathBuf;
5
6/// Provides the carrier representing a downloads collection.
7///
8/// The specification does not require that carrier to be a mutable record, a vector, or even an
9/// in-memory value. Each interpreter chooses its representation.
10pub trait DownloadsAlg: ManagerSorts {
11 /// Defines an empty downloads collection.
12 fn empty_downloads(&self) -> Self::Downloads;
13}
14
15/// Provides the carrier and constructor for one source request.
16#[delegatable_trait]
17pub trait SourceRequestAlg: ManagerSorts {
18 /// Defines one source request with explicit download options.
19 fn source(
20 &self,
21 input: impl Into<String>,
22 output: Self::Output,
23 options: Self::Options,
24 ) -> Self::Source;
25}
26
27/// Provides the carrier and constructors for initial media options.
28#[delegatable_trait]
29pub trait MediaOptionsAlg: ManagerSorts {
30 /// Defines a progressive request containing both audio and video.
31 fn progressive(&self) -> Self::Options;
32
33 /// Defines an audio-only request.
34 fn audio(&self) -> Self::Options;
35
36 /// Defines a video-only request.
37 fn video(&self) -> Self::Options;
38}
39
40/// Specifies which submitted lines a source retrieves rather than a transfer walks.
41///
42/// A line names a path unless some source recognizes it as its own. Recognizing is what a source
43/// interpreter adds, and nothing here knows what any of them look like: this application transfers
44/// paths, and every other reading of a line is something a source claimed.
45#[delegatable_trait]
46pub trait SourceRecognitionAlg {
47 /// States whether some source retrieves what the line names.
48 fn recognizes_source(&self, line: &str) -> bool;
49}
50
51/// Specifies what one submitted line names.
52///
53/// What a line names decides what transferring it means. A line naming two ends names a transfer
54/// between them, a line no source recognizes names one path to transfer, and a line a source
55/// recognizes names something that source retrieves. A path is not a media item with alternative
56/// formats, and never acquires one by being submitted.
57#[delegatable_trait]
58pub trait SubmissionAlg: ManagerSorts {
59 /// Defines the request one submitted line names.
60 fn submitted(&self, line: &str) -> Self::Source;
61}
62
63/// Provides the carrier and constructors for output choices.
64#[delegatable_trait]
65pub trait OutputChoiceAlg: ManagerSorts {
66 /// Defines output naming derived from extracted media meaning.
67 fn suggested_output(&self) -> Self::Output;
68
69 /// Defines an exact output path.
70 fn exact_output(&self, path: impl Into<PathBuf>) -> Self::Output;
71}
72
73/// Describes downloads collections that can accumulate source requests.
74pub trait DownloadCollectionAlg: ManagerSorts {
75 /// Appends source requests in declaration order.
76 #[must_use]
77 fn add_sources(self, sources: impl IntoIterator<Item = Self::Source>) -> Self;
78}
79
80/// Derives downloads-collection construction by composing associated carriers.
81#[ext(name = DownloadsExt)]
82pub impl<This> This
83where
84 This: DownloadsAlg + SourceRequestAlg,
85 This::Downloads: DownloadCollectionAlg<Source = This::Source>,
86{
87 /// Defines a downloads collection containing `sources` in declaration order.
88 fn downloads(&self, sources: impl IntoIterator<Item = This::Source>) -> This::Downloads {
89 self.empty_downloads().add_sources(sources)
90 }
91}
92
93/// Derives progressive downloads with media-derived output names.
94#[ext(name = ProgressiveDownloadsExt)]
95pub impl<This> This
96where
97 This: DownloadsAlg + SourceRequestAlg + MediaOptionsAlg + OutputChoiceAlg,
98 This::Downloads: DownloadCollectionAlg<Source = This::Source>,
99{
100 /// Defines a downloads collection from source names using progressive media and suggested
101 /// output naming.
102 fn progressive_downloads(
103 &self,
104 sources: impl IntoIterator<Item = impl Into<String>>,
105 ) -> This::Downloads {
106 self.downloads(
107 sources
108 .into_iter()
109 .map(|source| self.source(source, self.suggested_output(), self.progressive())),
110 )
111 }
112}