use crate::*;
ext! {
name: Iref,
versions: [0, 1],
flags: {}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Reference {
pub reference_type: FourCC,
pub from_item_id: u32,
pub to_item_ids: Vec<u32>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Iref {
pub references: Vec<Reference>,
}
impl AtomExt for Iref {
type Ext = IrefExt;
const KIND_EXT: FourCC = FourCC::new(b"iref");
fn decode_body_ext<B: Buf>(buf: &mut B, ext: IrefExt) -> Result<Self> {
let mut bytes_remaining = buf.remaining();
let mut references = vec![];
while bytes_remaining > 0 {
if ext.version == IrefVersion::V0 {
let box_len = u32::decode(buf)?;
bytes_remaining -= box_len as usize;
let reference_type = FourCC::decode(buf)?;
let from_item_id: u32 = u16::decode(buf)?.into();
let reference_count: u16 = u16::decode(buf)?;
let mut to_item_ids: Vec<u32> = vec![];
for _ in 0..reference_count {
let to_item_id: u32 = u16::decode(buf)?.into();
to_item_ids.push(to_item_id);
}
let reference = Reference {
reference_type,
from_item_id,
to_item_ids,
};
references.push(reference);
} else {
let box_len = u32::decode(buf)?;
bytes_remaining -= box_len as usize;
let reference_type = FourCC::decode(buf)?;
let from_item_id: u32 = u32::decode(buf)?;
let reference_count: u16 = u16::decode(buf)?;
let mut to_item_ids: Vec<u32> = vec![];
for _ in 0..reference_count {
let to_item_id: u32 = u32::decode(buf)?;
to_item_ids.push(to_item_id);
}
let reference = Reference {
reference_type,
from_item_id,
to_item_ids,
};
references.push(reference);
}
}
Ok(Iref { references })
}
fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<IrefExt> {
let mut version = IrefVersion::V0;
'reference: for reference in &self.references {
if reference.from_item_id > (u16::MAX as u32) {
version = IrefVersion::V1;
break 'reference;
}
for id in &reference.to_item_ids {
if *id > (u16::MAX as u32) {
version = IrefVersion::V1;
break 'reference;
}
}
}
if version == IrefVersion::V0 {
for reference in &self.references {
let size = (4 + 4 + 2 + 2 + 2 * reference.to_item_ids.len()) as u32;
size.encode(buf)?;
reference.reference_type.encode(buf)?;
(reference.from_item_id as u16).encode(buf)?;
(reference.to_item_ids.len() as u16).encode(buf)?;
for id in &reference.to_item_ids {
(*id as u16).encode(buf)?;
}
}
} else {
for reference in &self.references {
let size = (4 + 4 + 4 + 2 + 4 * reference.to_item_ids.len()) as u32;
size.encode(buf)?;
reference.reference_type.encode(buf)?;
reference.from_item_id.encode(buf)?;
(reference.to_item_ids.len() as u16).encode(buf)?;
for id in &reference.to_item_ids {
id.encode(buf)?;
}
}
}
Ok(IrefExt { version })
}
}