Skip to main content

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