b64
This commit is contained in:
12
Cargo.lock
generated
12
Cargo.lock
generated
@@ -299,6 +299,17 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"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]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
@@ -340,6 +351,7 @@ dependencies = [
|
|||||||
"clap",
|
"clap",
|
||||||
"hex",
|
"hex",
|
||||||
"lofty",
|
"lofty",
|
||||||
|
"sha1",
|
||||||
"sha2",
|
"sha2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -10,4 +10,5 @@ authors = ["Owen Feldman"]
|
|||||||
clap = { version = "4.6.6", features = ["derive"] }
|
clap = { version = "4.6.6", features = ["derive"] }
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
lofty = "0.25.1"
|
lofty = "0.25.1"
|
||||||
|
sha1 = "0.11.0"
|
||||||
sha2 = "0.11.0"
|
sha2 = "0.11.0"
|
||||||
|
|||||||
69
src/disc_id.rs
Normal file
69
src/disc_id.rs
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
mod disc_id;
|
||||||
|
|
||||||
use clap::{
|
use clap::{
|
||||||
Parser, Subcommand,
|
Parser, Subcommand,
|
||||||
builder::styling::{AnsiColor, Effects, Styles},
|
builder::styling::{AnsiColor, Effects, Styles},
|
||||||
|
|||||||
Reference in New Issue
Block a user