use serde::Deserialize;
use serde_json::Value;
use crate::integer::IntegerSchema;
#[derive(Debug, Clone, Deserialize)]
#[serde(tag = "@type", rename_all = "lowercase")]
pub enum RawLengthEncoding {
Fixed,
ExplicitLength(IntegerSchema),
EndPattern { sentinel: Value },
Capacity { padding: Value },
TillEnd,
}
#[derive(Debug, Clone)]
pub enum LengthEncoding<T> {
Fixed(usize),
LengthEncoded(IntegerSchema),
EndPattern { sentinel: T },
Capacity { padding: T, capacity: usize },
TillEnd,
}
impl Default for RawLengthEncoding {
fn default() -> Self {
RawLengthEncoding::TillEnd
}
}
impl<T> LengthEncoding<T> {
pub fn fixed(fixed: usize) -> Self {
Self::Fixed(fixed)
}
pub fn length_encoded(schema: IntegerSchema) -> Self {
Self::LengthEncoded(schema)
}
pub fn end_pattern(pattern: T) -> Self {
Self::EndPattern { sentinel: pattern }
}
pub fn capacity(padding: T, capacity: usize) -> Self {
Self::Capacity { padding, capacity }
}
pub fn map<R, F>(self, f: F) -> LengthEncoding<R>
where
F: FnOnce(T) -> R,
{
match self {
Self::Fixed(fixed) => LengthEncoding::Fixed(fixed),
Self::LengthEncoded(schema) => LengthEncoding::LengthEncoded(schema),
Self::EndPattern { sentinel: pattern } => LengthEncoding::EndPattern {
sentinel: f(pattern),
},
Self::Capacity { padding, capacity } => LengthEncoding::Capacity {
padding: f(padding),
capacity,
},
Self::TillEnd => LengthEncoding::TillEnd,
}
}
pub fn try_map<R, E, F>(self, f: F) -> Result<LengthEncoding<R>, E>
where
F: FnOnce(T) -> Result<R, E>,
{
let new = match self {
Self::Fixed(fixed) => LengthEncoding::Fixed(fixed),
Self::LengthEncoded(schema) => LengthEncoding::LengthEncoded(schema),
Self::EndPattern { sentinel: pattern } => LengthEncoding::EndPattern {
sentinel: f(pattern)?,
},
Self::Capacity { padding, capacity } => LengthEncoding::Capacity {
padding: f(padding)?,
capacity,
},
Self::TillEnd => LengthEncoding::TillEnd,
};
Ok(new)
}
}