assembly_fdb/io/
write.rs

1//! # Low-level [`std::io`] writer
2
3use std::{hint::unreachable_unchecked, io};
4
5use assembly_fdb_core::file::{
6    ArrayHeader, FDBBucketHeader, FDBColumnHeader, FDBFieldData, FDBRowHeader,
7    FDBRowHeaderListEntry, FDBTableDataHeader, FDBTableDefHeader, FDBTableHeader,
8};
9use latin1str::Latin1Str;
10
11#[allow(clippy::upper_case_acronyms)]
12/// A trait to write assembly data to file
13pub trait WriteLE {
14    /// Write `self` as little-endian bytes to `IO`
15    fn write_le<IO: io::Write>(&self, out: &mut IO) -> io::Result<()>;
16}
17
18impl WriteLE for Latin1Str {
19    fn write_le<IO: io::Write>(&self, out: &mut IO) -> io::Result<()> {
20        out.write_all(self.as_bytes())?;
21        match self.len() % 4 {
22            0 => out.write_all(&[0, 0, 0, 0])?,
23            1 => out.write_all(&[0, 0, 0])?,
24            2 => out.write_all(&[0, 0])?,
25            3 => out.write_all(&[0])?,
26            _ => unsafe { unreachable_unchecked() },
27        }
28        Ok(())
29    }
30}
31
32impl WriteLE for ArrayHeader {
33    fn write_le<IO: io::Write>(&self, out: &mut IO) -> io::Result<()> {
34        out.write_all(&self.count.to_le_bytes())?;
35        out.write_all(&self.base_offset.to_le_bytes())?;
36        Ok(())
37    }
38}
39
40impl WriteLE for FDBTableHeader {
41    fn write_le<IO: io::Write>(&self, out: &mut IO) -> io::Result<()> {
42        out.write_all(&self.table_def_header_addr.to_le_bytes())?;
43        out.write_all(&self.table_data_header_addr.to_le_bytes())?;
44        Ok(())
45    }
46}
47
48impl WriteLE for FDBTableDefHeader {
49    fn write_le<IO: io::Write>(&self, out: &mut IO) -> io::Result<()> {
50        out.write_all(&self.column_count.to_le_bytes())?;
51        out.write_all(&self.table_name_addr.to_le_bytes())?;
52        out.write_all(&self.column_header_list_addr.to_le_bytes())?;
53        Ok(())
54    }
55}
56
57impl WriteLE for FDBColumnHeader {
58    fn write_le<IO: io::Write>(&self, out: &mut IO) -> io::Result<()> {
59        out.write_all(&self.column_data_type.to_le_bytes())?;
60        out.write_all(&self.column_name_addr.to_le_bytes())?;
61        Ok(())
62    }
63}
64
65impl WriteLE for FDBTableDataHeader {
66    fn write_le<IO: io::Write>(&self, out: &mut IO) -> io::Result<()> {
67        self.buckets.write_le(out)
68    }
69}
70
71impl WriteLE for FDBBucketHeader {
72    fn write_le<IO: io::Write>(&self, out: &mut IO) -> io::Result<()> {
73        out.write_all(&self.row_header_list_head_addr.to_le_bytes())
74    }
75}
76
77impl WriteLE for FDBRowHeaderListEntry {
78    fn write_le<IO: io::Write>(&self, out: &mut IO) -> io::Result<()> {
79        out.write_all(&self.row_header_addr.to_le_bytes())?;
80        out.write_all(&self.row_header_list_next_addr.to_le_bytes())?;
81        Ok(())
82    }
83}
84
85impl WriteLE for FDBRowHeader {
86    fn write_le<IO: io::Write>(&self, out: &mut IO) -> io::Result<()> {
87        self.fields.write_le(out)
88    }
89}
90
91impl WriteLE for FDBFieldData {
92    fn write_le<IO: io::Write>(&self, out: &mut IO) -> io::Result<()> {
93        out.write_all(&u32::to_le_bytes(self.data_type))?;
94        out.write_all(&self.value)?;
95        Ok(())
96    }
97}