assembly_fdb/core/
loader.rs1use super::*;
11use crate::io::read::{DatabaseBufReader, DatabaseBuilder, DatabaseReader};
12use assembly_core::reader::{FileError, FileResult};
13use assembly_fdb_core::file::{
14 FDBBucketHeader, FDBColumnHeader, FDBRowHeader, FDBTableDataHeader, FDBTableDefHeader,
15 FDBTableHeader,
16};
17use std::convert::TryFrom;
18use std::fs;
19use std::io::{BufRead, BufReader, Seek};
20
21pub trait LoaderConfig {
23 fn load_table_data(&self, def: &TableDef) -> bool;
25}
26
27pub struct LoaderConfigImpl<P>
29where
30 P: Fn(&TableDef) -> bool,
31{
32 pub table_data_policy: P,
34}
35
36impl<P> LoaderConfig for LoaderConfigImpl<P>
37where
38 P: Fn(&TableDef) -> bool,
39{
40 fn load_table_data(&self, def: &TableDef) -> bool {
41 (self.table_data_policy)(def)
42 }
43}
44
45pub struct SchemaLoader<'a, T, C> {
47 inner: &'a mut T,
48 config: C,
49}
50
51impl TryFrom<&str> for Schema {
52 type Error = FileError;
53
54 fn try_from(filename: &str) -> FileResult<Schema> {
55 let file = fs::File::open(filename)?;
56 Schema::try_from(file)
57 }
58}
59
60impl TryFrom<fs::File> for Schema {
61 type Error = FileError;
62
63 fn try_from(file: fs::File) -> FileResult<Schema> {
64 let mut reader = BufReader::new(file);
65 let config = LoaderConfigImpl {
66 table_data_policy: |_| true,
67 };
68 let mut loader = SchemaLoader::open(&mut reader, config);
69 loader.try_load_schema()
70 }
71}
72
73impl<'a, T, C> SchemaLoader<'a, T, C>
74where
75 T: BufRead + Seek,
76 C: LoaderConfig,
77{
78 pub fn open(inner: &'a mut T, config: C) -> Self {
80 Self { inner, config }
81 }
82
83 pub fn try_load_row(&mut self, header: FDBRowHeader) -> FileResult<Row> {
85 let a = &mut self.inner;
86 let field_list = a.get_field_data_list(header)?;
87 let mut fields: Vec<Field> = Vec::with_capacity(field_list.len());
88 for field in field_list {
89 match self.inner.try_load_field(&field) {
90 Ok(value) => fields.push(value),
91 Err(e) => println!("{:?}", e),
92 }
93 }
94 Ok(Row::from(fields))
95 }
96
97 pub fn try_load_bucket(&mut self, header: FDBBucketHeader) -> FileResult<Bucket> {
99 let row_header_addr_it = self
100 .inner
101 .get_row_header_addr_iterator(header.row_header_list_head_addr);
102 let row_header_addr_list = row_header_addr_it.collect::<Result<Vec<_>, _>>()?;
103 let mut rows: Vec<Row> = Vec::with_capacity(row_header_addr_list.len());
104 for row_header_addr in row_header_addr_list {
105 let row_header = self.inner.get_row_header(row_header_addr)?;
106 let row = self.try_load_row(row_header)?;
107 rows.push(row);
108 }
109 Ok(Bucket(rows))
110 }
111
112 pub fn try_load_column(&mut self, header: FDBColumnHeader) -> FileResult<Column> {
114 let col_type = ValueType::try_from(header.column_data_type).unwrap();
116 let col_name = self.inner.get_string(header.column_name_addr)?;
117 Ok(Column::from((col_name.as_ref(), col_type)))
118 }
119
120 pub fn try_load_table_def(&mut self, header: FDBTableDefHeader) -> FileResult<TableDef> {
122 let name = self.inner.get_string(header.table_name_addr)?;
123 let column_header_list: Vec<FDBColumnHeader> =
124 self.inner.get_column_header_list(&header)?;
125
126 let columns: Vec<Column> = column_header_list
127 .iter()
128 .map(|column_header| self.try_load_column(*column_header))
129 .collect::<Result<Vec<_>, _>>()?;
130
131 Ok(TableDef { columns, name })
132 }
133
134 pub fn try_load_table_data(&mut self, header: FDBTableDataHeader) -> FileResult<TableData> {
136 let bucket_header_list: Vec<FDBBucketHeader> =
137 self.inner.get_bucket_header_list(&header)?;
138
139 let buckets: Vec<Bucket> = bucket_header_list
140 .iter()
141 .map(|bucket_header| self.try_load_bucket(*bucket_header))
142 .collect::<Result<Vec<_>, _>>()?;
143
144 Ok(TableData { buckets })
145 }
146
147 pub fn try_load_table(&mut self, header: FDBTableHeader) -> FileResult<Table> {
149 let def_header = self
150 .inner
151 .get_table_def_header(header.table_def_header_addr)?;
152 let definition = self.try_load_table_def(def_header)?;
153 if self.config.load_table_data(&definition) {
154 let data_header = self
155 .inner
156 .get_table_data_header(header.table_data_header_addr)?;
157 let data = self.try_load_table_data(data_header)?;
158 Ok(Table::from(definition, data))
159 } else {
160 Ok(Table::new(definition))
161 }
162 }
163
164 pub fn try_load_schema(&mut self) -> FileResult<Schema> {
166 let header = self.inner.get_header()?;
167 let table_header_list: Vec<FDBTableHeader> = self.inner.get_table_header_list(header)?;
168 let tables: Vec<Table> = table_header_list
169 .iter()
170 .map(|table_header| self.try_load_table(*table_header))
171 .collect::<Result<Vec<_>, _>>()?;
172 Ok(Schema::from(tables))
173 }
174}