use super::ion::IonValue;
use super::symbols::KfxSymbol;
#[derive(Debug, Clone)]
pub enum FragmentData {
Ion(IonValue),
Raw(Vec<u8>),
}
#[derive(Debug, Clone)]
pub struct KfxFragment {
pub ftype: u64,
pub fid: String,
pub data: FragmentData,
}
impl KfxFragment {
pub fn new(ftype: impl Into<u64>, fid: impl Into<String>, value: IonValue) -> Self {
Self {
ftype: ftype.into(),
fid: fid.into(),
data: FragmentData::Ion(value),
}
}
pub fn raw(ftype: impl Into<u64>, fid: impl Into<String>, bytes: Vec<u8>) -> Self {
Self {
ftype: ftype.into(),
fid: fid.into(),
data: FragmentData::Raw(bytes),
}
}
pub fn singleton(ftype: impl Into<u64>, value: IonValue) -> Self {
let ftype_val = ftype.into();
Self {
ftype: ftype_val,
fid: format!("${ftype_val}"),
data: FragmentData::Ion(value),
}
}
pub fn is_singleton(&self) -> bool {
self.fid == format!("${}", self.ftype)
}
pub fn is_raw(&self) -> bool {
matches!(self.data, FragmentData::Raw(_))
}
pub fn as_ion(&self) -> Option<&IonValue> {
match &self.data {
FragmentData::Ion(v) => Some(v),
FragmentData::Raw(_) => None,
}
}
pub fn as_raw(&self) -> Option<&[u8]> {
match &self.data {
FragmentData::Ion(_) => None,
FragmentData::Raw(bytes) => Some(bytes),
}
}
}
impl From<KfxSymbol> for u64 {
fn from(sym: KfxSymbol) -> u64 {
sym as u64
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_fragment_new() {
let frag = KfxFragment::new(260u64, "section-1", IonValue::Null);
assert_eq!(frag.ftype, 260);
assert_eq!(frag.fid, "section-1");
assert!(!frag.is_singleton());
assert!(!frag.is_raw());
}
#[test]
fn test_fragment_singleton() {
let frag = KfxFragment::singleton(KfxSymbol::Metadata, IonValue::Null);
assert!(frag.is_singleton());
assert_eq!(frag.fid, "$258");
}
#[test]
fn test_fragment_raw() {
let data = vec![0xFF, 0xD8, 0xFF, 0xE0]; let frag = KfxFragment::raw(KfxSymbol::Bcrawmedia, "image-1", data.clone());
assert!(frag.is_raw());
assert_eq!(frag.as_raw(), Some(data.as_slice()));
assert!(frag.as_ion().is_none());
}
#[test]
fn test_kfx_symbol_conversion() {
let frag = KfxFragment::new(KfxSymbol::Section, "sec-1", IonValue::Null);
assert_eq!(frag.ftype, 260);
}
}