Skip to main content

rakata_formats/lip/
writer.rs

1//! LIP binary writer.
2
3use std::io::{Cursor, Write};
4
5use crate::binary::{write_f32, write_u32, write_u8};
6
7use super::{Lip, LipBinaryError, LIP_MAGIC, LIP_VERSION_V10};
8
9/// Writes a LIP file to a writer.
10///
11/// # Errors
12///
13/// [`LipBinaryError::ValueOverflow`] when the keyframe count exceeds `u32`,
14/// and [`LipBinaryError::Io`] when the writer fails. A partial file may
15/// already have been written in the second case.
16#[cfg_attr(
17    feature = "tracing",
18    tracing::instrument(level = "debug", skip(writer, lip))
19)]
20pub fn write_lip<W: Write>(writer: &mut W, lip: &Lip) -> Result<(), LipBinaryError> {
21    let entry_count = u32::try_from(lip.keyframes.len())
22        .map_err(|_| LipBinaryError::ValueOverflow("entry_count"))?;
23
24    writer.write_all(&LIP_MAGIC)?;
25    writer.write_all(&LIP_VERSION_V10)?;
26    write_f32(writer, lip.length)?;
27    write_u32(writer, entry_count)?;
28
29    for keyframe in &lip.keyframes {
30        write_f32(writer, keyframe.time)?;
31        write_u8(writer, keyframe.shape.raw_id())?;
32    }
33
34    Ok(())
35}
36
37/// Serializes a LIP file into bytes.
38///
39/// # Errors
40///
41/// [`LipBinaryError::ValueOverflow`] when the keyframe count exceeds `u32`.
42/// The `Vec` target has no I/O to fail at.
43#[cfg_attr(feature = "tracing", tracing::instrument(level = "debug", skip(lip)))]
44pub fn write_lip_to_vec(lip: &Lip) -> Result<Vec<u8>, LipBinaryError> {
45    let mut cursor = Cursor::new(Vec::new());
46    write_lip(&mut cursor, lip)?;
47    Ok(cursor.into_inner())
48}