Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions src/models/data_size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,10 @@ impl FromStr for DataSize {
"Cannot parse data size '{value}'. The input should be a number followed by a letter (B, K, M, G or T) for bytes, kilobytes, etc. Example: 1G for one gigabyte."
);

if value.is_empty() {
let Some((suffix_start, suffix)) = value.char_indices().next_back() else {
return Err(error);
}

let suffix: char = value.bytes().last().unwrap() as char;
let size = &value[..value.len() - 1];
};
let size = &value[..suffix_start];
let power = match suffix {
'B' => 0,
'K' => 1,
Expand All @@ -49,11 +47,11 @@ impl FromStr for DataSize {
_ => return Err(error),
};

size.parse()
.map(|size: usize| Self {
bytes: size * 1024_usize.pow(power),
})
.map_err(|_| error)
let multiplier = 1024_usize.checked_pow(power).ok_or_else(|| error.clone())?;
let size = size.parse::<usize>().map_err(|_| error.clone())?;
let bytes = size.checked_mul(multiplier).ok_or(error)?;

Ok(Self { bytes })
}
}

Expand Down Expand Up @@ -139,4 +137,19 @@ mod tests {
1024_usize.pow(4)
)
}

#[test]
fn test_rejects_multibyte_suffix() {
let result = DataSize::from_str("10€");

assert!(result.is_err())
}

#[test]
fn test_rejects_overflowing_size() {
let value = format!("{}T", usize::MAX);
let result = DataSize::from_str(&value);

assert!(result.is_err())
}
}
Loading