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