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

12
Cargo.lock generated
View File

@@ -299,6 +299,17 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "sha1"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "sha2"
version = "0.11.0"
@@ -340,6 +351,7 @@ dependencies = [
"clap",
"hex",
"lofty",
"sha1",
"sha2",
]

View File

@@ -10,4 +10,5 @@ authors = ["Owen Feldman"]
clap = { version = "4.6.6", features = ["derive"] }
hex = "0.4.3"
lofty = "0.25.1"
sha1 = "0.11.0"
sha2 = "0.11.0"

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());
}
}

View File

@@ -1,3 +1,5 @@
mod disc_id;
use clap::{
Parser, Subcommand,
builder::styling::{AnsiColor, Effects, Styles},