use anyhow::{bail, Context, Result};
use base64::{engine::general_purpose, Engine as _};
use serde::{Deserialize, Serialize};
use std::io::{Read, Write};
pub const RECORD_DESCRIPTOR_MAGIC: &[u8; 4] = b"BRD1";
pub const RECORD_DESCRIPTOR_VERSION: u8 = 1;
pub const RECORD_DESCRIPTOR_PREFIX_LENGTH: usize = 19;
pub const RECORD_DESCRIPTOR_TEXT_LIMIT: usize = 96;
pub const RECORD_DESCRIPTOR_CREATOR_METADATA_TEXT_LIMIT: usize = 1024;
pub const RECORD_DESCRIPTOR_SIGNED_RELEASE_TEXT_LIMIT: usize = 4096;
pub const RECORD_DESCRIPTOR_CHAIN_RECEIPT_TEXT_LIMIT: usize = 8192;
pub const RECORD_DESCRIPTOR_COMPRESSION_BROTLI: u8 = 1;
pub const RECORD_DESCRIPTOR_BROTLI_QUALITY: u32 = 11;
pub const STREAM_BYTE_LENGTH_ABSENT: u64 = u64::MAX;
pub const METADATA_GRAYSCALE_NIBBLE_BASE: u8 = 120;
pub const UNUSED_METADATA_GROOVE_RGB_MIN: u8 = 112;
pub const UNUSED_METADATA_GROOVE_RGB_SPAN: u8 = 32;
pub const UNUSED_METADATA_GROOVE_ALPHA: u8 = 128;
pub const UNUSED_METADATA_GROOVE_FADE_TURNS: f64 = 0.5;
pub const SEGMENT_DESCRIPTOR_CRC32: u8 = 1;
pub const SEGMENT_STREAM_BYTE_LENGTH: u8 = 2;
pub const SEGMENT_GENERATION_VERSION: u8 = 3;
pub const SEGMENT_RECORD_PROFILE: u8 = 4;
pub const SEGMENT_TITLE: u8 = 5;
pub const SEGMENT_ARTIST: u8 = 6;
pub const SEGMENT_PAYLOAD_ENCODING: u8 = 7;
pub const SEGMENT_RELEASE_ID: u8 = 8;
pub const SEGMENT_CATALOG_NUMBER: u8 = 9;
pub const SEGMENT_LABEL: u8 = 10;
pub const SEGMENT_ARTWORK_CREDIT: u8 = 11;
pub const SEGMENT_LICENSE: u8 = 12;
pub const SEGMENT_CANONICAL_URL: u8 = 13;
pub const SEGMENT_CREATED_AT: u8 = 14;
pub const SEGMENT_ARBITRARY_METADATA: u8 = 15;
pub const SEGMENT_SIGNED_RELEASE_MANIFEST: u8 = 16;
pub const SEGMENT_SIGNATURE_ALGORITHM: u8 = 17;
pub const SEGMENT_SIGNATURE_KEY_ID: u8 = 18;
pub const SEGMENT_SIGNATURE: u8 = 19;
pub const SEGMENT_MANIFEST_SHA256: u8 = 20;
pub const SEGMENT_STEGO_SIDECAR_DESCRIPTOR: u8 = 21;
pub const SEGMENT_CHAIN_REGISTRATION_RECEIPT: u8 = 22;
pub const SEGMENT_ARBITRARY_METADATA_BROTLI: u8 = 23;
pub const SEGMENT_SIGNED_RELEASE_MANIFEST_BROTLI: u8 = 24;
pub const SEGMENT_CHAIN_REGISTRATION_RECEIPT_BROTLI: u8 = 25;
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RecordDescriptorInput {
pub record_profile: String,
pub stream_byte_length: Option<usize>,
pub generation_version: Option<String>,
pub payload_encoding: Option<String>,
pub title: Option<String>,
pub artist: Option<String>,
pub release_id: Option<String>,
pub catalog_number: Option<String>,
pub label: Option<String>,
pub artwork_credit: Option<String>,
pub license: Option<String>,
pub canonical_url: Option<String>,
pub created_at: Option<String>,
pub arbitrary_metadata: Option<String>,
pub signed_release_manifest: Option<String>,
pub signature_algorithm: Option<String>,
pub signature_key_id: Option<String>,
pub signature: Option<String>,
pub manifest_sha256: Option<String>,
pub stego_sidecar_descriptor: Option<Vec<u8>>,
pub chain_registration_receipt: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RecordDescriptor {
pub version: u8,
pub checksum_protected: bool,
pub b_value: f64,
pub record_profile: Option<String>,
pub stream_byte_length: Option<usize>,
pub generation_version: Option<String>,
pub payload_encoding: Option<String>,
pub title: Option<String>,
pub artist: Option<String>,
pub release_id: Option<String>,
pub catalog_number: Option<String>,
pub label: Option<String>,
pub artwork_credit: Option<String>,
pub license: Option<String>,
pub canonical_url: Option<String>,
pub created_at: Option<String>,
pub arbitrary_metadata: Option<String>,
pub signed_release_manifest: Option<String>,
pub signature_algorithm: Option<String>,
pub signature_key_id: Option<String>,
pub signature: Option<String>,
pub manifest_sha256: Option<String>,
pub stego_sidecar_descriptor: Option<String>,
pub chain_registration_receipt: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DescriptorPrefix {
pub version: u8,
pub payload_len: usize,
pub segment_count: usize,
pub segment_stream_len: usize,
pub b_value_bits: u64,
}
pub fn metadata_pixel_count_for_byte_length(byte_length: usize) -> usize {
byte_length.saturating_mul(2)
}
pub fn metadata_byte_capacity_for_pixel_count(pixel_count: usize) -> usize {
pixel_count / 2
}
pub fn metadata_fade_pixel_count(pixel_count: usize, turns: f64) -> usize {
if pixel_count == 0 {
return 0;
}
let pixels_per_turn = pixel_count as f64 / turns.max(0.01);
(pixels_per_turn * UNUSED_METADATA_GROOVE_FADE_TURNS)
.round()
.max(1.0) as usize
}
pub fn metadata_bytes_from_grayscale_rgba(
rgba: &[u8],
indices: &[usize],
byte_length: usize,
label: &str,
) -> Result<Vec<u8>> {
let pixel_count = metadata_pixel_count_for_byte_length(byte_length);
if indices.len() < pixel_count {
bail!("{label} spiral capacity is too small");
}
let mut bytes = Vec::with_capacity(byte_length);
for byte_number in 0..byte_length {
let mut nibbles = [0_u8; 2];
for nibble_index in 0..2 {
let pixel_index = indices[byte_number * 2 + nibble_index];
let rgba_index = pixel_index * 4;
if rgba_index + 3 >= rgba.len() {
bail!("{label} spiral pixel index is outside RGBA buffer");
}
let red = rgba[rgba_index];
let green = rgba[rgba_index + 1];
let blue = rgba[rgba_index + 2];
let alpha = rgba[rgba_index + 3];
if alpha == 0 {
bail!("{label} spiral pixel is empty");
}
if red != green || green != blue {
bail!("{label} metadata pixel is not grayscale");
}
let Some(nibble) = red.checked_sub(METADATA_GRAYSCALE_NIBBLE_BASE) else {
bail!("{label} metadata pixel is outside light grayscale encoding");
};
if nibble > 0x0f {
bail!("{label} metadata pixel is outside light grayscale encoding");
}
nibbles[nibble_index] = nibble;
}
bytes.push((nibbles[0] << 4) | nibbles[1]);
}
Ok(bytes)
}
pub fn paint_metadata_bytes_as_grayscale(
data: &mut [u8],
indices: &[usize],
bytes: &[u8],
) -> usize {
let byte_count = bytes
.len()
.min(metadata_byte_capacity_for_pixel_count(indices.len()));
for (byte_number, &byte) in bytes.iter().take(byte_count).enumerate() {
let high = METADATA_GRAYSCALE_NIBBLE_BASE + ((byte >> 4) & 0x0f);
let low = METADATA_GRAYSCALE_NIBBLE_BASE + (byte & 0x0f);
for (nibble_index, value) in [high, low].iter().enumerate() {
let pixel_index = indices[byte_number * 2 + nibble_index];
let rgba_index = pixel_index * 4;
if rgba_index + 3 >= data.len() {
continue;
}
data[rgba_index] = *value;
data[rgba_index + 1] = *value;
data[rgba_index + 2] = *value;
data[rgba_index + 3] = 255;
}
}
metadata_pixel_count_for_byte_length(byte_count)
}
pub fn paint_unused_metadata_groove(
data: &mut [u8],
indices: &[usize],
start_pixel: usize,
salt: usize,
fade_pixels: usize,
) {
for (pixel_number, &pixel_index) in indices.iter().enumerate().skip(start_pixel) {
let rgba_index = pixel_index * 4;
if rgba_index + 3 >= data.len() {
continue;
}
let dither = metadata_dither(pixel_index, pixel_number, salt);
let gray = UNUSED_METADATA_GROOVE_RGB_MIN
+ (dither.rotate_left(1) % (UNUSED_METADATA_GROOVE_RGB_SPAN + 1));
let alpha = unused_metadata_alpha(pixel_number, start_pixel, fade_pixels);
data[rgba_index] = gray;
data[rgba_index + 1] = gray;
data[rgba_index + 2] = gray;
data[rgba_index + 3] = alpha;
}
}
pub fn encode_record_descriptor_stream(
b_value: f64,
descriptor: &RecordDescriptorInput,
byte_capacity: usize,
) -> Result<Vec<u8>> {
if !(b_value.is_finite() && b_value > 0.0) {
bail!("A positive finite b_value is required.");
}
let (body, segment_count) = encode_segmented_body(descriptor)?;
let payload_len = RECORD_DESCRIPTOR_PREFIX_LENGTH + body.len();
if payload_len > byte_capacity {
bail!("record descriptor exceeds combined lead-in and lead-out capacity");
}
if payload_len > u16::MAX as usize {
bail!("record descriptor payload is too large");
}
if body.len() > u16::MAX as usize {
bail!("record descriptor segment stream exceeds length limit");
}
let mut full = Vec::with_capacity(payload_len);
full.extend_from_slice(RECORD_DESCRIPTOR_MAGIC);
full.push(RECORD_DESCRIPTOR_VERSION);
full.extend_from_slice(&(payload_len as u16).to_be_bytes());
full.extend_from_slice(&segment_count.to_be_bytes());
full.extend_from_slice(&(body.len() as u16).to_be_bytes());
full.extend_from_slice(&b_value.to_bits().to_be_bytes());
full.extend_from_slice(&body);
let crc32 = compute_descriptor_crc32(&full);
full[RECORD_DESCRIPTOR_PREFIX_LENGTH + 3..RECORD_DESCRIPTOR_PREFIX_LENGTH + 7]
.copy_from_slice(&crc32.to_be_bytes());
Ok(full)
}
pub fn decode_record_descriptor_bytes(bytes: &[u8]) -> Result<RecordDescriptor> {
let prefix = decode_descriptor_prefix(bytes)?;
if prefix.version != RECORD_DESCRIPTOR_VERSION {
bail!("record descriptor version mismatch");
}
if prefix.payload_len != RECORD_DESCRIPTOR_PREFIX_LENGTH + prefix.segment_stream_len {
bail!("record descriptor segment stream length mismatch");
}
let body = &bytes[RECORD_DESCRIPTOR_PREFIX_LENGTH..prefix.payload_len];
let mut offset = 0usize;
let mut crc32_range = None;
let mut crc32 = None;
let mut stream_byte_length = None;
let mut generation_version = None;
let mut payload_encoding = None;
let mut record_profile = None;
let mut title = None;
let mut artist = None;
let mut release_id = None;
let mut catalog_number = None;
let mut label = None;
let mut artwork_credit = None;
let mut license = None;
let mut canonical_url = None;
let mut created_at = None;
let mut arbitrary_metadata = None;
let mut signed_release_manifest = None;
let mut signature_algorithm = None;
let mut signature_key_id = None;
let mut signature = None;
let mut manifest_sha256 = None;
let mut stego_sidecar_descriptor = None;
let mut chain_registration_receipt = None;
for _ in 0..prefix.segment_count {
if offset + 3 > body.len() {
bail!("record descriptor segment is truncated");
}
let kind = body[offset];
let len = u16::from_be_bytes(
body[offset + 1..offset + 3]
.try_into()
.expect("slice length"),
) as usize;
let payload_start = offset + 3;
let payload_end = payload_start + len;
if payload_end > body.len() {
bail!("record descriptor segment payload is truncated");
}
let payload = &body[payload_start..payload_end];
match kind {
SEGMENT_DESCRIPTOR_CRC32 => {
if crc32.is_some() {
bail!("duplicate record descriptor CRC32 segment");
}
if payload.len() != 4 {
bail!("record descriptor CRC32 segment has invalid length");
}
crc32 = Some(u32::from_be_bytes(
payload.try_into().expect("slice length"),
));
let absolute_start = RECORD_DESCRIPTOR_PREFIX_LENGTH + payload_start;
crc32_range = Some(absolute_start..absolute_start + payload.len());
}
SEGMENT_STREAM_BYTE_LENGTH => {
if payload.len() != 8 {
bail!("record descriptor stream byte length segment has invalid length");
}
let raw_len = u64::from_be_bytes(payload.try_into().expect("slice length"));
stream_byte_length = if raw_len == STREAM_BYTE_LENGTH_ABSENT {
None
} else {
Some(
usize::try_from(raw_len)
.context("record descriptor stream byte length exceeds usize")?,
)
};
}
SEGMENT_GENERATION_VERSION => {
generation_version = decode_optional_text(payload, "generation version")?;
}
SEGMENT_PAYLOAD_ENCODING => {
payload_encoding = decode_optional_text(payload, "payload encoding")?;
}
SEGMENT_RECORD_PROFILE => {
record_profile = decode_optional_text(payload, "record profile")?;
}
SEGMENT_TITLE => {
title = decode_optional_text(payload, "title")?;
}
SEGMENT_ARTIST => {
artist = decode_optional_text(payload, "artist")?;
}
SEGMENT_RELEASE_ID => {
release_id = decode_optional_text(payload, "release ID")?;
}
SEGMENT_CATALOG_NUMBER => {
catalog_number = decode_optional_text(payload, "catalog number")?;
}
SEGMENT_LABEL => {
label = decode_optional_text(payload, "label")?;
}
SEGMENT_ARTWORK_CREDIT => {
artwork_credit = decode_optional_text(payload, "artwork credit")?;
}
SEGMENT_LICENSE => {
license = decode_optional_text(payload, "license")?;
}
SEGMENT_CANONICAL_URL => {
canonical_url = decode_optional_text(payload, "canonical URL")?;
}
SEGMENT_CREATED_AT => {
created_at = decode_optional_text(payload, "created-at timestamp")?;
}
SEGMENT_ARBITRARY_METADATA => {
arbitrary_metadata = decode_optional_text(payload, "arbitrary metadata")?;
}
SEGMENT_ARBITRARY_METADATA_BROTLI => {
arbitrary_metadata =
decode_optional_compressed_text(payload, "arbitrary metadata")?;
}
SEGMENT_SIGNED_RELEASE_MANIFEST => {
signed_release_manifest = decode_optional_text(payload, "signed release manifest")?;
}
SEGMENT_SIGNED_RELEASE_MANIFEST_BROTLI => {
signed_release_manifest =
decode_optional_compressed_text(payload, "signed release manifest")?;
}
SEGMENT_SIGNATURE_ALGORITHM => {
signature_algorithm = decode_optional_text(payload, "signature algorithm")?;
}
SEGMENT_SIGNATURE_KEY_ID => {
signature_key_id = decode_optional_text(payload, "signature key ID")?;
}
SEGMENT_SIGNATURE => {
signature = decode_optional_text(payload, "release signature")?;
}
SEGMENT_MANIFEST_SHA256 => {
manifest_sha256 = decode_optional_text(payload, "manifest SHA-256")?;
}
SEGMENT_STEGO_SIDECAR_DESCRIPTOR => {
stego_sidecar_descriptor = Some(general_purpose::STANDARD.encode(payload));
}
SEGMENT_CHAIN_REGISTRATION_RECEIPT => {
chain_registration_receipt =
decode_optional_text(payload, "chain registration receipt")?;
}
SEGMENT_CHAIN_REGISTRATION_RECEIPT_BROTLI => {
chain_registration_receipt =
decode_optional_compressed_text(payload, "chain registration receipt")?;
}
_ => {}
}
offset = payload_end;
}
if offset != body.len() {
bail!("record descriptor segment stream has trailing bytes");
}
let expected = crc32.context("record descriptor CRC32 segment is missing")?;
let range = crc32_range.context("record descriptor CRC32 segment is missing")?;
let mut canonical = bytes[..prefix.payload_len].to_vec();
canonical[range].fill(0);
let actual = compute_descriptor_crc32(&canonical);
if actual != expected {
bail!("record descriptor CRC32 mismatch");
}
let b_value = f64::from_bits(prefix.b_value_bits);
if !(b_value.is_finite() && b_value > 0.0) {
bail!("decoded invalid b_value");
}
Ok(RecordDescriptor {
version: prefix.version,
checksum_protected: true,
b_value,
record_profile,
stream_byte_length,
generation_version,
payload_encoding,
title,
artist,
release_id,
catalog_number,
label,
artwork_credit,
license,
canonical_url,
created_at,
arbitrary_metadata,
signed_release_manifest,
signature_algorithm,
signature_key_id,
signature,
manifest_sha256,
stego_sidecar_descriptor,
chain_registration_receipt,
})
}
pub fn decode_descriptor_prefix(bytes: &[u8]) -> Result<DescriptorPrefix> {
if bytes.len() < RECORD_DESCRIPTOR_PREFIX_LENGTH {
bail!("record descriptor payload too short");
}
if &bytes[..4] != RECORD_DESCRIPTOR_MAGIC {
bail!("record descriptor magic mismatch");
}
let version = bytes[4];
let payload_len = u16::from_be_bytes(bytes[5..7].try_into().expect("slice length")) as usize;
let segment_count = u16::from_be_bytes(bytes[7..9].try_into().expect("slice length")) as usize;
let segment_stream_len =
u16::from_be_bytes(bytes[9..11].try_into().expect("slice length")) as usize;
let b_value_bits = u64::from_be_bytes(bytes[11..19].try_into().expect("slice length"));
if payload_len < RECORD_DESCRIPTOR_PREFIX_LENGTH || payload_len > bytes.len() {
bail!("record descriptor payload length is invalid");
}
Ok(DescriptorPrefix {
version,
payload_len,
segment_count,
segment_stream_len,
b_value_bits,
})
}
pub fn compute_descriptor_crc32(bytes: &[u8]) -> u32 {
record_core::crc32_ieee(bytes)
}
fn encode_segmented_body(descriptor: &RecordDescriptorInput) -> Result<(Vec<u8>, u16)> {
let profile_bytes = sanitize_text(Some(&descriptor.record_profile));
let generation_bytes = sanitize_text(descriptor.generation_version.as_deref());
let payload_encoding_bytes =
sanitize_text(descriptor.payload_encoding.as_deref().or(Some("rgb")));
let title_bytes = sanitize_text(descriptor.title.as_deref());
let artist_bytes = sanitize_text(descriptor.artist.as_deref());
let release_id_bytes = sanitize_creator_metadata_text(descriptor.release_id.as_deref());
let catalog_number_bytes = sanitize_creator_metadata_text(descriptor.catalog_number.as_deref());
let label_bytes = sanitize_creator_metadata_text(descriptor.label.as_deref());
let artwork_credit_bytes = sanitize_creator_metadata_text(descriptor.artwork_credit.as_deref());
let license_bytes = sanitize_creator_metadata_text(descriptor.license.as_deref());
let canonical_url_bytes = sanitize_creator_metadata_text(descriptor.canonical_url.as_deref());
let created_at_bytes = sanitize_creator_metadata_text(descriptor.created_at.as_deref());
let arbitrary_metadata_bytes =
sanitize_creator_metadata_text(descriptor.arbitrary_metadata.as_deref());
let signed_release_manifest_bytes = exact_signed_release_text(
descriptor.signed_release_manifest.as_deref(),
"signed release manifest",
)?;
let signature_algorithm_bytes = exact_signed_release_text(
descriptor.signature_algorithm.as_deref(),
"signature algorithm",
)?;
let signature_key_id_bytes =
exact_signed_release_text(descriptor.signature_key_id.as_deref(), "signature key ID")?;
let signature_bytes =
exact_signed_release_text(descriptor.signature.as_deref(), "release signature")?;
let manifest_sha256_bytes =
exact_signed_release_text(descriptor.manifest_sha256.as_deref(), "manifest SHA-256")?;
let sidecar_bytes = descriptor
.stego_sidecar_descriptor
.clone()
.unwrap_or_default();
let chain_registration_receipt_bytes = exact_chain_receipt_text(
descriptor.chain_registration_receipt.as_deref(),
"chain registration receipt",
)?;
let raw_len = match descriptor.stream_byte_length {
Some(length) => u64::try_from(length).context("stream byte length exceeds u64")?,
None => STREAM_BYTE_LENGTH_ABSENT,
};
let mut out = Vec::new();
let mut segment_count = 0u16;
push_segment(&mut out, SEGMENT_DESCRIPTOR_CRC32, &0u32.to_be_bytes())?;
segment_count += 1;
push_segment(&mut out, SEGMENT_STREAM_BYTE_LENGTH, &raw_len.to_be_bytes())?;
segment_count += 1;
push_segment(&mut out, SEGMENT_RECORD_PROFILE, &profile_bytes)?;
segment_count += 1;
push_segment(&mut out, SEGMENT_PAYLOAD_ENCODING, &payload_encoding_bytes)?;
segment_count += 1;
let segments = vec![
(SEGMENT_GENERATION_VERSION, generation_bytes),
(SEGMENT_TITLE, title_bytes),
(SEGMENT_ARTIST, artist_bytes),
(SEGMENT_RELEASE_ID, release_id_bytes),
(SEGMENT_CATALOG_NUMBER, catalog_number_bytes),
(SEGMENT_LABEL, label_bytes),
(SEGMENT_ARTWORK_CREDIT, artwork_credit_bytes),
(SEGMENT_LICENSE, license_bytes),
(SEGMENT_CANONICAL_URL, canonical_url_bytes),
(SEGMENT_CREATED_AT, created_at_bytes),
compressed_segment(
SEGMENT_ARBITRARY_METADATA,
SEGMENT_ARBITRARY_METADATA_BROTLI,
arbitrary_metadata_bytes,
)?,
compressed_segment(
SEGMENT_SIGNED_RELEASE_MANIFEST,
SEGMENT_SIGNED_RELEASE_MANIFEST_BROTLI,
signed_release_manifest_bytes,
)?,
(SEGMENT_SIGNATURE_ALGORITHM, signature_algorithm_bytes),
(SEGMENT_SIGNATURE_KEY_ID, signature_key_id_bytes),
(SEGMENT_SIGNATURE, signature_bytes),
(SEGMENT_MANIFEST_SHA256, manifest_sha256_bytes),
(SEGMENT_STEGO_SIDECAR_DESCRIPTOR, sidecar_bytes),
compressed_segment(
SEGMENT_CHAIN_REGISTRATION_RECEIPT,
SEGMENT_CHAIN_REGISTRATION_RECEIPT_BROTLI,
chain_registration_receipt_bytes,
)?,
];
for (kind, payload) in segments {
if !payload.is_empty() {
push_segment(&mut out, kind, &payload)?;
segment_count += 1;
}
}
Ok((out, segment_count))
}
fn push_segment(out: &mut Vec<u8>, kind: u8, payload: &[u8]) -> Result<()> {
if payload.len() > u16::MAX as usize {
bail!("record descriptor segment {kind} exceeds length limit");
}
out.push(kind);
out.extend_from_slice(&(payload.len() as u16).to_be_bytes());
out.extend_from_slice(payload);
Ok(())
}
fn compressed_segment(
raw_kind: u8,
compressed_kind: u8,
payload: Vec<u8>,
) -> Result<(u8, Vec<u8>)> {
if payload.is_empty() {
return Ok((raw_kind, payload));
}
let compressed = brotli_compress_payload(&payload)?;
let framed = compressed_payload_frame(payload.len(), &compressed)?;
if framed.len() < payload.len() {
Ok((compressed_kind, framed))
} else {
Ok((raw_kind, payload))
}
}
fn compressed_payload_frame(raw_len: usize, compressed: &[u8]) -> Result<Vec<u8>> {
let raw_len =
u32::try_from(raw_len).context("compressed record descriptor payload too large")?;
let mut out = Vec::with_capacity(5 + compressed.len());
out.push(RECORD_DESCRIPTOR_COMPRESSION_BROTLI);
out.extend_from_slice(&raw_len.to_be_bytes());
out.extend_from_slice(compressed);
Ok(out)
}
fn brotli_compress_payload(payload: &[u8]) -> Result<Vec<u8>> {
let mut out = Vec::new();
{
let mut writer =
brotli::CompressorWriter::new(&mut out, 4096, RECORD_DESCRIPTOR_BROTLI_QUALITY, 22);
writer
.write_all(payload)
.context("failed to Brotli-compress record descriptor segment")?;
}
Ok(out)
}
fn brotli_decompress_payload(payload: &[u8], raw_len: usize) -> Result<Vec<u8>> {
let mut reader = brotli::Decompressor::new(payload, 4096);
let mut out = Vec::with_capacity(raw_len);
reader
.read_to_end(&mut out)
.context("failed to Brotli-decompress record descriptor segment")?;
if out.len() != raw_len {
bail!(
"decompressed record descriptor segment length {} does not match declared length {}",
out.len(),
raw_len
);
}
Ok(out)
}
fn sanitize_text_with_limit(value: Option<&str>, limit: usize) -> Vec<u8> {
let Some(value) = value else {
return Vec::new();
};
value
.trim()
.chars()
.filter(|ch| !ch.is_control())
.collect::<String>()
.into_bytes()
.into_iter()
.take(limit)
.collect()
}
fn sanitize_text(value: Option<&str>) -> Vec<u8> {
sanitize_text_with_limit(value, RECORD_DESCRIPTOR_TEXT_LIMIT)
}
fn sanitize_creator_metadata_text(value: Option<&str>) -> Vec<u8> {
sanitize_text_with_limit(value, RECORD_DESCRIPTOR_CREATOR_METADATA_TEXT_LIMIT)
}
fn exact_signed_release_text(value: Option<&str>, label: &str) -> Result<Vec<u8>> {
let Some(value) = value else {
return Ok(Vec::new());
};
let bytes = value.as_bytes();
if bytes.len() > RECORD_DESCRIPTOR_SIGNED_RELEASE_TEXT_LIMIT {
bail!("{label} exceeds record descriptor signed release length limit");
}
if value.chars().any(char::is_control) {
bail!("{label} must not contain raw control characters");
}
Ok(bytes.to_vec())
}
fn exact_chain_receipt_text(value: Option<&str>, label: &str) -> Result<Vec<u8>> {
let Some(value) = value else {
return Ok(Vec::new());
};
if value.len() > RECORD_DESCRIPTOR_CHAIN_RECEIPT_TEXT_LIMIT {
bail!("{label} exceeds length limit");
}
Ok(value.as_bytes().to_vec())
}
fn decode_optional_text(payload: &[u8], label: &str) -> Result<Option<String>> {
if payload.is_empty() {
return Ok(None);
}
Ok(Some(String::from_utf8(payload.to_vec()).with_context(
|| format!("record descriptor {label} is not valid UTF-8"),
)?))
}
fn decode_optional_compressed_text(payload: &[u8], label: &str) -> Result<Option<String>> {
if payload.is_empty() {
return Ok(None);
}
if payload.len() < 5 {
bail!("record descriptor compressed {label} segment is truncated");
}
if payload[0] != RECORD_DESCRIPTOR_COMPRESSION_BROTLI {
bail!("record descriptor compressed {label} uses unsupported compression codec");
}
let raw_len = u32::from_be_bytes(payload[1..5].try_into().expect("slice length")) as usize;
let decompressed = brotli_decompress_payload(&payload[5..], raw_len)?;
decode_optional_text(&decompressed, label)
}
fn unused_metadata_alpha(pixel_number: usize, start_pixel: usize, fade_pixels: usize) -> u8 {
let offset = pixel_number.saturating_sub(start_pixel);
if fade_pixels == 0 || offset >= fade_pixels {
return UNUSED_METADATA_GROOVE_ALPHA;
}
let t = ((offset + 1) as f64 / fade_pixels as f64).clamp(0.0, 1.0);
let eased = t * t * (3.0 - (2.0 * t));
let alpha = 255.0 - ((255.0 - f64::from(UNUSED_METADATA_GROOVE_ALPHA)) * eased);
alpha
.round()
.clamp(f64::from(UNUSED_METADATA_GROOVE_ALPHA), 255.0) as u8
}
fn metadata_dither(pixel_index: usize, sequence_index: usize, salt: usize) -> u8 {
let mut value = pixel_index as u64;
value ^= (sequence_index as u64).wrapping_mul(0x9e37_79b9_7f4a_7c15);
value ^= (salt as u64).wrapping_mul(0xbf58_476d_1ce4_e5b9);
value ^= value >> 30;
value = value.wrapping_mul(0xbf58_476d_1ce4_e5b9);
value ^= value >> 27;
value = value.wrapping_mul(0x94d0_49bb_1331_11eb);
value ^= value >> 31;
(value & 0xff) as u8
}
#[cfg(test)]
mod tests {
use super::*;
fn segment_kinds(bytes: &[u8]) -> Vec<u8> {
let prefix = decode_descriptor_prefix(bytes).unwrap();
let body = &bytes[RECORD_DESCRIPTOR_PREFIX_LENGTH..prefix.payload_len];
let mut offset = 0usize;
let mut kinds = Vec::new();
for _ in 0..prefix.segment_count {
let kind = body[offset];
let len = u16::from_be_bytes(body[offset + 1..offset + 3].try_into().unwrap()) as usize;
kinds.push(kind);
offset += 3 + len;
}
kinds
}
#[test]
fn descriptor_round_trips_required_and_optional_segments() {
let input = RecordDescriptorInput {
record_profile: "single45".to_string(),
stream_byte_length: Some(12345),
generation_version: Some("build-1".to_string()),
payload_encoding: Some("rgb".to_string()),
title: Some("Westside".to_string()),
artist: Some("Lori Asha".to_string()),
release_id: Some("rel-1".to_string()),
canonical_url: Some("https://bitneedle.com/r/rel-1".to_string()),
signed_release_manifest: Some(r#"{"v":1}"#.to_string()),
signature_algorithm: Some("ed25519".to_string()),
signature_key_id: Some("key-1".to_string()),
signature: Some("sig".to_string()),
manifest_sha256: Some("hash".to_string()),
chain_registration_receipt: Some(
r#"{"v":1,"type":"bitneedle.chainReceipts","releaseHash":"sha256:test","receipts":[]}"#
.to_string(),
),
..RecordDescriptorInput::default()
};
let bytes = encode_record_descriptor_stream(0.25, &input, 4096).unwrap();
let decoded = decode_record_descriptor_bytes(&bytes).unwrap();
assert_eq!(&bytes[..4], b"BRD1");
assert_eq!(decoded.version, RECORD_DESCRIPTOR_VERSION);
assert!(decoded.checksum_protected);
assert_eq!(decoded.b_value, 0.25);
assert_eq!(decoded.record_profile.as_deref(), Some("single45"));
assert_eq!(decoded.stream_byte_length, Some(12345));
assert_eq!(decoded.generation_version.as_deref(), Some("build-1"));
assert_eq!(decoded.payload_encoding.as_deref(), Some("rgb"));
assert_eq!(decoded.title.as_deref(), Some("Westside"));
assert_eq!(decoded.artist.as_deref(), Some("Lori Asha"));
assert_eq!(decoded.release_id.as_deref(), Some("rel-1"));
assert_eq!(
decoded.canonical_url.as_deref(),
Some("https://bitneedle.com/r/rel-1")
);
assert_eq!(
decoded.signed_release_manifest.as_deref(),
Some(r#"{"v":1}"#)
);
assert_eq!(decoded.signature_algorithm.as_deref(), Some("ed25519"));
assert_eq!(decoded.signature_key_id.as_deref(), Some("key-1"));
assert_eq!(decoded.signature.as_deref(), Some("sig"));
assert_eq!(decoded.manifest_sha256.as_deref(), Some("hash"));
assert_eq!(
decoded.chain_registration_receipt.as_deref(),
Some(
r#"{"v":1,"type":"bitneedle.chainReceipts","releaseHash":"sha256:test","receipts":[]}"#
)
);
}
#[test]
fn descriptor_rejects_crc32_corruption() {
let input = RecordDescriptorInput {
record_profile: "lp".to_string(),
stream_byte_length: Some(10),
payload_encoding: Some("rgb".to_string()),
..RecordDescriptorInput::default()
};
let mut bytes = encode_record_descriptor_stream(0.5, &input, 4096).unwrap();
let last = bytes.len() - 1;
bytes[last] ^= 0x01;
let err = decode_record_descriptor_bytes(&bytes)
.unwrap_err()
.to_string();
assert!(err.contains("CRC32 mismatch"));
}
#[test]
fn descriptor_compresses_large_optional_text_segments() {
let arbitrary_metadata = format!(
r#"{{"credits":["{}"],"notes":"{}"}}"#,
"Lori Asha; Wavey.ai; Bitneedle; ".repeat(10),
"record revolution rights ".repeat(10)
);
let signed_release_manifest = format!(
r#"{{"v":1,"type":"bitneedle.release","releaseId":"rel-1","revolutions":[{}]}}"#,
(0..60)
.map(|index| format!(r#"{{"i":{index},"sha256":"{}"}}"#, "a".repeat(43)))
.collect::<Vec<_>>()
.join(",")
);
let chain_registration_receipt = format!(
r#"{{"v":1,"type":"bitneedle.chainReceipts","releaseHash":"sha256:{}","receipts":[{}]}}"#,
"b".repeat(43),
(0..20)
.map(|index| {
format!(
r#"{{"chain":"base","chainId":84532,"network":"base-sepolia","transactionHash":"0x{}","blockNumber":{}}}"#,
"c".repeat(64),
1000 + index
)
})
.collect::<Vec<_>>()
.join(",")
);
let input = RecordDescriptorInput {
record_profile: "lp".to_string(),
stream_byte_length: Some(10),
payload_encoding: Some("rgb".to_string()),
arbitrary_metadata: Some(arbitrary_metadata.clone()),
signed_release_manifest: Some(signed_release_manifest.clone()),
chain_registration_receipt: Some(chain_registration_receipt.clone()),
..RecordDescriptorInput::default()
};
let bytes = encode_record_descriptor_stream(0.5, &input, 8192).unwrap();
let kinds = segment_kinds(&bytes);
let decoded = decode_record_descriptor_bytes(&bytes).unwrap();
assert!(kinds.contains(&SEGMENT_ARBITRARY_METADATA_BROTLI));
assert!(kinds.contains(&SEGMENT_SIGNED_RELEASE_MANIFEST_BROTLI));
assert!(kinds.contains(&SEGMENT_CHAIN_REGISTRATION_RECEIPT_BROTLI));
assert_eq!(
decoded.arbitrary_metadata.as_deref(),
Some(arbitrary_metadata.as_str())
);
assert_eq!(
decoded.signed_release_manifest.as_deref(),
Some(signed_release_manifest.as_str())
);
assert_eq!(
decoded.chain_registration_receipt.as_deref(),
Some(chain_registration_receipt.as_str())
);
}
#[test]
fn descriptor_rejects_b_value_corruption() {
let input = RecordDescriptorInput {
record_profile: "lp".to_string(),
stream_byte_length: Some(10),
payload_encoding: Some("rgb".to_string()),
..RecordDescriptorInput::default()
};
let mut bytes = encode_record_descriptor_stream(0.5, &input, 4096).unwrap();
bytes[18] ^= 0x01;
let err = decode_record_descriptor_bytes(&bytes)
.unwrap_err()
.to_string();
assert!(err.contains("CRC32 mismatch"));
}
#[test]
fn grayscale_metadata_round_trips() {
let source = b"BRD1";
let indices = vec![0, 1, 2, 3, 4, 5, 6, 7];
let mut rgba = vec![0u8; 8 * 4];
let pixels = paint_metadata_bytes_as_grayscale(&mut rgba, &indices, source);
assert_eq!(pixels, 8);
let decoded =
metadata_bytes_from_grayscale_rgba(&rgba, &indices, source.len(), "test").unwrap();
assert_eq!(decoded, source);
}
#[test]
fn rejects_wrong_magic() {
let input = RecordDescriptorInput {
record_profile: "single45".to_string(),
stream_byte_length: Some(10),
payload_encoding: Some("rgb".to_string()),
..RecordDescriptorInput::default()
};
let mut bytes = encode_record_descriptor_stream(0.25, &input, 4096).unwrap();
bytes[..4].copy_from_slice(b"BTB2");
let err = decode_record_descriptor_bytes(&bytes)
.unwrap_err()
.to_string();
assert!(err.contains("magic mismatch"));
}
}