use super::invalid;
use crate::{Time, ValidationError};
const MAX_TAGS: usize = 64;
const MAX_CHAPTERS: usize = 4096;
const MAX_TAG_KEY_BYTES: usize = 128;
const MAX_TEXT_BYTES: usize = 4096;
const MAX_CHAPTER_END_SECONDS: f64 = 86400.0;
#[derive(Clone, Debug)]
pub struct AudioChapter {
pub start: Time,
pub end: Time,
pub title: String,
}
#[derive(Clone, Debug, Default)]
pub struct AudioMetadata {
pub tags: std::collections::BTreeMap<String, String>,
pub chapters: Vec<AudioChapter>,
}
impl AudioMetadata {
pub fn validate(&self) -> Result<(), ValidationError> {
if self.tags.len() > MAX_TAGS
|| self.chapters.len() > MAX_CHAPTERS
|| self.tags.iter().any(|(key, value)| {
key.is_empty()
|| key.len() > MAX_TAG_KEY_BYTES
|| value.len() > MAX_TEXT_BYTES
|| key.contains('\0')
|| value.contains('\0')
})
|| self.chapters.iter().any(|chapter| {
chapter.start < Time::ZERO
|| chapter.end <= chapter.start
|| chapter.end.as_seconds() > MAX_CHAPTER_END_SECONDS
|| chapter.title.len() > MAX_TEXT_BYTES
|| chapter.title.contains('\0')
})
|| self
.chapters
.windows(2)
.any(|pair| pair[0].end > pair[1].start)
{
return Err(invalid(
"metadata",
"Invalid bounded container tags or ordered chapters",
));
}
Ok(())
}
pub fn is_empty(&self) -> bool {
self.tags.is_empty() && self.chapters.is_empty()
}
}