chore: initial sanitized public snapshot
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
#![doc(hidden)]
|
||||
#![expect(
|
||||
clippy::needless_pass_by_value,
|
||||
clippy::redundant_pub_crate,
|
||||
reason = "this private runtime-planning module shares parent-only planning structs and helpers across the split CLI runtime"
|
||||
)]
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use aria2_rust_pro_compat::{ConfigParseError, ConfigProfile};
|
||||
use aria2_rust_pro_core::RuntimeConfig;
|
||||
use aria2_rust_pro_protocol::{Downloader, HttpSessionModel, Protocol};
|
||||
|
||||
use super::{
|
||||
CliError, CliTransferSource, ConfigLoadReport, DispatcherRegistrationKind,
|
||||
InProcessRpcDispatcher, StartupProfile, TransferInputEntry, TransferSelection,
|
||||
classify_transfer, derive_http_session, derive_runtime_config, expand_transfer_entries,
|
||||
load_config_report, merged_profile, parse_protocol, register_resolved_entry_with_dispatcher,
|
||||
resolve_transfer_entry_with_downloader,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(super) struct RuntimeInputContext {
|
||||
pub(super) config_report: Option<ConfigLoadReport>,
|
||||
pub(super) effective_profile: Option<ConfigProfile>,
|
||||
pub(super) recognized_schemes: Vec<String>,
|
||||
pub(super) transfer_kinds: Vec<TransferSelection>,
|
||||
pub(super) derived_runtime: RuntimeConfig,
|
||||
pub(super) http_session: HttpSessionModel,
|
||||
pub(super) resolved_entries: Vec<ResolvedRuntimeEntry>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(super) struct ResolvedRuntimeEntry {
|
||||
pub(super) entry: TransferInputEntry,
|
||||
pub(super) entry_profile: Option<ConfigProfile>,
|
||||
pub(super) runtime: RuntimeConfig,
|
||||
pub(super) http_session: HttpSessionModel,
|
||||
pub(super) uri: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(super) struct RegisteredRuntimeEntry {
|
||||
pub(super) resolved: ResolvedRuntimeEntry,
|
||||
pub(super) gid: String,
|
||||
pub(super) registration_kind: DispatcherRegistrationKind,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct DerivedEntryContext {
|
||||
runtime: RuntimeConfig,
|
||||
http_session: HttpSessionModel,
|
||||
}
|
||||
|
||||
pub(super) fn build_runtime_input_context<D: Downloader + Sync>(
|
||||
config_path: Option<PathBuf>,
|
||||
uris: Vec<String>,
|
||||
startup: &StartupProfile,
|
||||
cli_profile: Option<&ConfigProfile>,
|
||||
cli_transfer_sources: Option<&[CliTransferSource]>,
|
||||
downloader: &D,
|
||||
) -> Result<RuntimeInputContext, CliError> {
|
||||
let config_report = config_path
|
||||
.as_ref()
|
||||
.map(|path| load_config_report(path, true))
|
||||
.transpose()?;
|
||||
let file_profile = config_report.as_ref().map(|report| &report.profile);
|
||||
let effective_profile = merged_profile(file_profile, cli_profile);
|
||||
let profile = effective_profile.as_ref();
|
||||
let input_entries = expand_transfer_entries(&uris, profile, cli_transfer_sources)?;
|
||||
let first_entry_profile = input_entries.first().and_then(|entry| {
|
||||
let implied = merged_profile(entry.implied_profile.as_ref(), profile);
|
||||
merged_profile(implied.as_ref(), entry.profile.as_ref())
|
||||
});
|
||||
let report_profile = first_entry_profile.as_ref().or(profile);
|
||||
let derived_runtime = derive_runtime_config(report_profile, startup);
|
||||
let http_session = derive_http_session(report_profile, startup);
|
||||
|
||||
let recognized_schemes = input_entries
|
||||
.iter()
|
||||
.filter_map(|entry| entry.uris.first())
|
||||
.filter_map(|uri| parse_protocol(uri).map(Protocol::as_str))
|
||||
.map(str::to_owned)
|
||||
.collect::<Vec<_>>();
|
||||
let transfer_kinds = input_entries
|
||||
.iter()
|
||||
.filter_map(|entry| entry.uris.first())
|
||||
.map(String::as_str)
|
||||
.map(classify_transfer)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let resolved_entries = resolve_runtime_entries(&input_entries, startup, profile, downloader)?;
|
||||
|
||||
Ok(RuntimeInputContext {
|
||||
config_report,
|
||||
effective_profile,
|
||||
recognized_schemes,
|
||||
transfer_kinds,
|
||||
derived_runtime,
|
||||
http_session,
|
||||
resolved_entries,
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn register_runtime_entries<D: Downloader + Sync>(
|
||||
dispatcher: &mut InProcessRpcDispatcher,
|
||||
downloader: &D,
|
||||
entries: Vec<ResolvedRuntimeEntry>,
|
||||
base_profile: Option<&ConfigProfile>,
|
||||
) -> Result<Vec<RegisteredRuntimeEntry>, CliError> {
|
||||
let mut registered_entries = Vec::with_capacity(entries.len());
|
||||
for resolved in entries {
|
||||
let (gid, registration_kind) = register_resolved_entry_with_dispatcher(
|
||||
dispatcher,
|
||||
downloader,
|
||||
&resolved.entry,
|
||||
&resolved.uri,
|
||||
resolved.entry_profile.as_ref().or(base_profile),
|
||||
&resolved.http_session,
|
||||
&resolved.runtime,
|
||||
)?;
|
||||
registered_entries.push(RegisteredRuntimeEntry {
|
||||
resolved,
|
||||
gid,
|
||||
registration_kind,
|
||||
});
|
||||
}
|
||||
Ok(registered_entries)
|
||||
}
|
||||
|
||||
fn resolve_runtime_entries<D: Downloader + Sync>(
|
||||
input_entries: &[TransferInputEntry],
|
||||
startup: &StartupProfile,
|
||||
profile: Option<&ConfigProfile>,
|
||||
downloader: &D,
|
||||
) -> Result<Vec<ResolvedRuntimeEntry>, CliError> {
|
||||
let mut resolved_entries = Vec::new();
|
||||
let mut derived_context_cache = Vec::new();
|
||||
for entry in input_entries {
|
||||
let direct_passthrough = entry
|
||||
.uris
|
||||
.first()
|
||||
.is_some_and(|uri| classify_transfer(uri) != TransferSelection::Metalink);
|
||||
let pre_resolve_profile = merged_profile(
|
||||
merged_profile(entry.implied_profile.as_ref(), profile).as_ref(),
|
||||
entry.profile.as_ref(),
|
||||
);
|
||||
let pre_resolve_context = derived_entry_context(
|
||||
&mut derived_context_cache,
|
||||
pre_resolve_profile.as_ref(),
|
||||
startup,
|
||||
);
|
||||
let expanded_entries = resolve_transfer_entry_with_downloader(
|
||||
entry,
|
||||
downloader,
|
||||
&pre_resolve_context.http_session,
|
||||
&pre_resolve_context.runtime,
|
||||
)?;
|
||||
|
||||
if direct_passthrough && expanded_entries.len() == 1 {
|
||||
let resolved_uri = entry.uris.first().cloned().ok_or_else(|| {
|
||||
CliError::Config(ConfigParseError::InvalidDirective(
|
||||
"input-file entry missing URI".to_owned(),
|
||||
))
|
||||
})?;
|
||||
let expanded_entry = expanded_entries
|
||||
.into_iter()
|
||||
.next()
|
||||
.expect("direct entry fast path should preserve one resolved entry");
|
||||
resolved_entries.push(ResolvedRuntimeEntry {
|
||||
entry: expanded_entry,
|
||||
entry_profile: pre_resolve_profile,
|
||||
runtime: pre_resolve_context.runtime,
|
||||
http_session: pre_resolve_context.http_session,
|
||||
uri: resolved_uri,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
for expanded_entry in expanded_entries {
|
||||
let entry_profile = merged_profile(
|
||||
merged_profile(expanded_entry.implied_profile.as_ref(), profile).as_ref(),
|
||||
expanded_entry.profile.as_ref(),
|
||||
);
|
||||
let entry_context =
|
||||
derived_entry_context(&mut derived_context_cache, entry_profile.as_ref(), startup);
|
||||
let resolved_uri = expanded_entry.uris.first().cloned().ok_or_else(|| {
|
||||
CliError::Config(ConfigParseError::InvalidDirective(
|
||||
"input-file entry missing URI".to_owned(),
|
||||
))
|
||||
})?;
|
||||
resolved_entries.push(ResolvedRuntimeEntry {
|
||||
entry: expanded_entry,
|
||||
entry_profile,
|
||||
runtime: entry_context.runtime,
|
||||
http_session: entry_context.http_session,
|
||||
uri: resolved_uri,
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok(resolved_entries)
|
||||
}
|
||||
|
||||
fn derived_entry_context(
|
||||
cache: &mut Vec<(Option<ConfigProfile>, DerivedEntryContext)>,
|
||||
profile: Option<&ConfigProfile>,
|
||||
startup: &StartupProfile,
|
||||
) -> DerivedEntryContext {
|
||||
if let Some((_, cached)) = cache
|
||||
.iter()
|
||||
.find(|(cached_profile, _)| cached_profile.as_ref() == profile)
|
||||
{
|
||||
return cached.clone();
|
||||
}
|
||||
|
||||
let derived = DerivedEntryContext {
|
||||
runtime: derive_runtime_config(profile, startup),
|
||||
http_session: derive_http_session(profile, startup),
|
||||
};
|
||||
cache.push((profile.cloned(), derived.clone()));
|
||||
derived
|
||||
}
|
||||
Reference in New Issue
Block a user