chore: initial sanitized public snapshot
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
use super::{BTreeSet, Digest, RequestGroup};
|
||||
|
||||
/// Applies a `select-file` option value to BitTorrent file selection state.
|
||||
pub(in crate::dispatcher) fn apply_bt_select_file_option(
|
||||
group: &mut RequestGroup,
|
||||
select_file: &str,
|
||||
) -> Result<(), String> {
|
||||
let Some(mut bt_state) = group.bt().cloned() else {
|
||||
return Ok(());
|
||||
};
|
||||
if bt_state.files.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let selected_indexes = parse_bt_select_file_indexes(select_file, bt_state.files.len())?;
|
||||
for (index, file) in bt_state.files.iter_mut().enumerate() {
|
||||
file.selected = selected_indexes.contains(&(index + 1));
|
||||
}
|
||||
group.set_bt(bt_state);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Parses aria2-style `select-file` syntax into a set of selected file indexes.
|
||||
pub(in crate::dispatcher) fn parse_bt_select_file_indexes(
|
||||
select_file: &str,
|
||||
file_count: usize,
|
||||
) -> Result<BTreeSet<usize>, String> {
|
||||
let mut selected = BTreeSet::new();
|
||||
let trimmed = select_file.trim();
|
||||
if trimmed.is_empty() {
|
||||
return Err("empty value".to_owned());
|
||||
}
|
||||
for token in trimmed
|
||||
.split(',')
|
||||
.map(str::trim)
|
||||
.filter(|token| !token.is_empty())
|
||||
{
|
||||
if let Some((start_raw, end_raw)) = token.split_once('-') {
|
||||
let start = start_raw
|
||||
.trim()
|
||||
.parse::<usize>()
|
||||
.map_err(|_| format!("invalid start index `{start_raw}`"))?;
|
||||
let end = end_raw
|
||||
.trim()
|
||||
.parse::<usize>()
|
||||
.map_err(|_| format!("invalid end index `{end_raw}`"))?;
|
||||
if start == 0 || end == 0 {
|
||||
return Err("indexes are 1-based".to_owned());
|
||||
}
|
||||
let (lo, hi) = if start <= end {
|
||||
(start, end)
|
||||
} else {
|
||||
(end, start)
|
||||
};
|
||||
if hi > file_count {
|
||||
return Err(format!("index {hi} out of range 1..={file_count}"));
|
||||
}
|
||||
for index in lo..=hi {
|
||||
selected.insert(index);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
let index = token
|
||||
.parse::<usize>()
|
||||
.map_err(|_| format!("invalid index `{token}`"))?;
|
||||
if index == 0 {
|
||||
return Err("indexes are 1-based".to_owned());
|
||||
}
|
||||
if index > file_count {
|
||||
return Err(format!("index {index} out of range 1..={file_count}"));
|
||||
}
|
||||
selected.insert(index);
|
||||
}
|
||||
Ok(selected)
|
||||
}
|
||||
Reference in New Issue
Block a user