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