Skip to main content

hff_core/write/
table_desc.rs

1use super::{ChunkArray, ChunkDesc, DataArray, DataSource, TableArray};
2use crate::{Chunk, Identifier, Table};
3
4/// Description of a table.
5#[derive(Debug)]
6pub struct TableDesc<'a> {
7    /// The table identifier.
8    identifier: Identifier,
9    /// The metadata for the table.
10    metadata: Option<DataSource<'a>>,
11    /// The chunks attached to the table.
12    chunks: Vec<ChunkDesc<'a>>,
13    /// The child tables.
14    children: Vec<TableDesc<'a>>,
15}
16
17impl<'a> TableDesc<'a> {
18    /// Create a new table description.
19    pub fn new(
20        identifier: Identifier,
21        metadata: Option<DataSource<'a>>,
22        chunks: Vec<ChunkDesc<'a>>,
23        children: Vec<TableDesc<'a>>,
24    ) -> Self {
25        Self {
26            identifier,
27            metadata,
28            chunks,
29            children,
30        }
31    }
32
33    /// Flatten the description into separate portions of tables,
34    /// chunks and the data blob.
35    pub fn flatten(
36        self,
37        has_sibling: bool,
38        tables: &mut TableArray,
39        chunks: &mut ChunkArray,
40        data: &mut DataArray<'a>,
41    ) {
42        // First, record if the table had metadata and push that to the
43        // data array if so.
44        let had_metadata = if let Some(metadata) = self.metadata {
45            data.push(metadata);
46            true
47        } else {
48            false
49        };
50
51        // Record the start of the chunks and how many there are.
52        let chunk_start = chunks.len();
53        let chunk_count = self.chunks.len();
54
55        // Second, push the chunks for this table into the chunk and data arrays.
56        for chunk in self.chunks {
57            // Push without offset/length, we don't know them at this time.
58            chunks.push(Chunk::new(chunk.identifier(), 0, 0));
59            data.push(chunk.data_source());
60        }
61
62        // Record how many tables there are so we can fix up the sibling
63        // after pushing children.
64        let table_index = tables.len();
65
66        // Push the table.
67        tables.push(
68            had_metadata,
69            Table::create()
70                .identifier(self.identifier)
71                .chunk_index(if chunk_count > 0 {
72                    chunk_start as u32
73                } else {
74                    0
75                })
76                .chunk_count(chunk_count as u32)
77                .child_count(self.children.len() as u32)
78                .end(),
79        );
80
81        // Now, flatten each child in turn.
82        let child_count = self.children.len();
83        for (index, child) in self.children.into_iter().enumerate() {
84            child.flatten(index < child_count - 1, tables, chunks, data);
85        }
86
87        // Adjust the sibling index by the number of children added if required.
88        if has_sibling {
89            // Compute the sibling.
90            let sibling = (tables.len() - table_index) as u32;
91
92            // Get the table we pushed.
93            let table = &mut tables[table_index];
94            *table.1.sibling_mut() = sibling;
95        }
96    }
97}