This commit is contained in:
2026-08-23 18:18:50 -04:00
parent 68d133a27e
commit 0b62d31878
4 changed files with 84 additions and 0 deletions

69
src/disc_id.rs Normal file
View File

@@ -0,0 +1,69 @@
use std::{convert, ops::Index};
const B64TABLE: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._";
fn b64(data: &[u8]) -> String {
let binary: Vec<u8> = data
.iter()
.flat_map(|b| (0..8).rev().map(move |i| (b >> i) & 1))
.collect();
let mut chunks: Vec<Vec<u8>> = binary.chunks(6).map(|s| s.to_vec()).collect();
let last = chunks.last_mut().unwrap();
if last.len() < 6 {
for _ in last.len()..6 {
last.push(0);
}
}
let decimal: Vec<u8> = chunks
.iter()
.map(|bits| bits.iter().fold(0, |acc, &bit| (acc << 1) | bit))
.collect();
let mut converted: Vec<String> = Vec::new();
for dec in decimal {
converted.push(B64TABLE.chars().nth(dec as usize).unwrap().to_string());
}
match data.len() % 3 {
1 => {
converted.push("--".to_string());
}
2 => {
converted.push("-".to_string());
}
_ => {}
}
converted.join("")
}
pub fn compute_disc_id(first_track: u8, last_track: u8, leadout: u32, offsets: &[u32]) -> String {
let mut toc = String::new();
toc.push_str(&format!("{first_track:02X}{last_track:02X}{leadout:08X}"));
for i in 0..99 {
let offset = offsets.get(i).copied().unwrap_or(0);
toc.push_str(&format!("{:08X}", offset));
}
toc
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn known_example() {
let first_track = 1;
let last_track = 12;
let leadout = 224556;
let offsets = [
150, 9078, 13528, 34182, 53768, 70987, 96424, 118425, 136793, 159514, 179777, 198006,
];
assert_eq!(
compute_disc_id(first_track, last_track, leadout, &offsets),
"T_prJXQSrqbnH8OE.dgOKsHm5Uw-"
);
}
#[test]
fn base64() {
assert_eq!(b64("Man".as_bytes()), "TWFu".to_string());
assert_eq!(b64("M".as_bytes()), "TQ--".to_string());
assert_eq!(b64("Ma".as_bytes()), "TWE-".to_string());
}
}