Skip to main content

rakata_formats/tpc/
writer.rs

1//! TPC binary writer.
2
3use std::io::{Cursor, Write};
4
5use super::{expected_payload_size, write_header, Tpc, TpcBinaryError};
6
7/// Writes TPC data to a writer.
8///
9/// # Errors
10///
11/// Everything except the I/O failure is raised while sizing the payload,
12/// before any byte is written: [`TpcBinaryError::InvalidHeader`] for a zero
13/// dimension or a zero mipmap count, [`TpcBinaryError::UnsupportedPixelType`]
14/// for a pixel-format code with no known layout,
15/// [`TpcBinaryError::ValueOverflow`] when `data_size` will not fit `usize`,
16/// and [`TpcBinaryError::InvalidData`] when the payload length disagrees with
17/// the size the header implies. [`TpcBinaryError::Io`] comes from the writer
18/// and can leave a partial file.
19#[cfg_attr(
20    feature = "tracing",
21    tracing::instrument(
22        level = "debug",
23        skip(writer, tpc),
24        fields(pixel_type = tpc.header.pixel_type, mipmap_count = tpc.header.mipmap_count)
25    )
26)]
27pub fn write_tpc<W: Write>(writer: &mut W, tpc: &Tpc) -> Result<(), TpcBinaryError> {
28    let expected_payload_size = expected_payload_size(&tpc.header)?;
29    if expected_payload_size != tpc.payload.len() {
30        return Err(TpcBinaryError::InvalidData(format!(
31            "payload length mismatch: expected {expected_payload_size}, got {}",
32            tpc.payload.len()
33        )));
34    }
35
36    write_header(writer, &tpc.header)?;
37    writer.write_all(&tpc.payload)?;
38    writer.write_all(&tpc.txi_footer)?;
39    crate::trace_debug!(
40        payload_len = tpc.payload.len(),
41        txi_footer_len = tpc.txi_footer.len(),
42        "wrote tpc to writer"
43    );
44    Ok(())
45}
46
47/// Serializes TPC data to a byte vector.
48///
49/// # Errors
50///
51/// Every non-I/O failure [`write_tpc`] describes. The `Vec` target has no I/O
52/// to fail at.
53#[cfg_attr(
54    feature = "tracing",
55    tracing::instrument(
56        level = "debug",
57        skip(tpc),
58        fields(pixel_type = tpc.header.pixel_type, mipmap_count = tpc.header.mipmap_count)
59    )
60)]
61pub fn write_tpc_to_vec(tpc: &Tpc) -> Result<Vec<u8>, TpcBinaryError> {
62    let mut cursor = Cursor::new(Vec::new());
63    write_tpc(&mut cursor, tpc)?;
64    let bytes = cursor.into_inner();
65    crate::trace_debug!(bytes_len = bytes.len(), "serialized tpc to vec");
66    Ok(bytes)
67}