pub mod rar13;
pub mod rar15;
pub mod rar20;
pub mod rar30;
pub mod rar50;
pub const MAX_PASSWORD_CHARS: usize = 127;
pub fn clamp_password(password: &[u8]) -> &[u8] {
match std::str::from_utf8(password) {
Ok(text) => match text.char_indices().nth(MAX_PASSWORD_CHARS) {
Some((byte_offset, _)) => &password[..byte_offset],
None => password,
},
Err(_) => &password[..password.len().min(MAX_PASSWORD_CHARS)],
}
}
#[cfg(test)]
mod tests {
use super::{clamp_password, MAX_PASSWORD_CHARS};
#[test]
fn clamp_password_keeps_127_characters() {
let short = b"hunter2";
assert_eq!(clamp_password(short), short);
let exact = "A".repeat(MAX_PASSWORD_CHARS);
assert_eq!(clamp_password(exact.as_bytes()), exact.as_bytes());
let long = "A".repeat(130) + "ZZZ";
assert_eq!(clamp_password(long.as_bytes()), exact.as_bytes());
}
#[test]
fn clamp_password_counts_characters_not_bytes() {
let emoji = "\u{1F600}".repeat(140);
let clamped = clamp_password(emoji.as_bytes());
let text = std::str::from_utf8(clamped).unwrap();
assert_eq!(text.chars().count(), MAX_PASSWORD_CHARS);
assert_eq!(clamped.len(), MAX_PASSWORD_CHARS * 4);
}
#[test]
fn clamp_password_falls_back_to_bytes_when_not_utf8() {
let latin1 = vec![0xe9u8; 200];
assert_eq!(clamp_password(&latin1).len(), MAX_PASSWORD_CHARS);
}
}