use super::positive_integer::PositiveInteger;
use alloc::{
string::{String, ToString},
vec::Vec,
};
use core::ops::Deref;
use musicxml_internal::{DatatypeDeserializer, DatatypeSerializer};
#[derive(Debug, PartialEq, Eq)]
pub struct TimeOnly(pub Vec<u8>);
impl Deref for TimeOnly {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DatatypeSerializer for TimeOnly {
fn serialize(element: &Self) -> String {
element.0.iter().map(ToString::to_string).collect::<Vec<_>>().join(",")
}
}
impl DatatypeDeserializer for TimeOnly {
fn deserialize(value: &str) -> Result<Self, String> {
let mut errs = false;
let mut res: Vec<u8> = Vec::new();
value.split(',').for_each(|item| {
if let Ok(token) = PositiveInteger::deserialize(item) {
match *token {
#[allow(clippy::cast_possible_truncation)]
1..=255 => res.push(*token as u8),
_ => errs = true,
}
} else {
errs = true;
}
});
if errs {
Err(format!("Value {value} is invalid for the <time-only> data type"))
} else {
Ok(TimeOnly(res))
}
}
}
#[cfg(test)]
mod time_only_tests {
use super::*;
#[test]
fn serialize_valid1() {
let test = TimeOnly(vec![1, 2, 4]);
let result = TimeOnly::serialize(&test);
assert_eq!(result, "1,2,4");
}
#[test]
fn deserialize_valid1() {
let result = TimeOnly::deserialize("1,2,3");
assert!(result.is_ok());
assert_eq!(result.unwrap(), TimeOnly(vec![1, 2, 3]));
}
#[test]
fn deserialize_valid2() {
let result = TimeOnly::deserialize("3");
assert!(result.is_ok());
assert_eq!(result.unwrap(), TimeOnly(vec![3]));
}
#[test]
fn deserialize_invalid1() {
let result = TimeOnly::deserialize(",1,2,");
assert!(result.is_err());
}
#[test]
fn deserialize_invalid2() {
let result = TimeOnly::deserialize("0,3234");
assert!(result.is_err());
}
#[test]
fn deserialize_invalid3() {
let result = TimeOnly::deserialize("0,1");
assert!(result.is_err());
}
#[test]
fn deserialize_invalid4() {
let result = TimeOnly::deserialize("2, 4 ");
assert!(result.is_err());
}
}