assembly_data/fdb/core/
mod.rs

1//! # The data structures for representing the file/database.
2//!
3//! An FDB file is layed out as a hash map. The top level is a list
4//! of tables, lexically ordered by their name (all uppercase names
5//! before all lowercase ones).
6//!
7//! Each table consists of an array of Buckets, where each bucket
8//! Corresponds to one hash value of the primary column.
9//!
10//! Each bucket consists of a list of rows. These rows may be sorted
11//! in ascending order of primary keys, but that is not fully verified.
12//!
13//! Each row contains a vector of fields, with a data type and respective
14//! data.
15//!
16//! Each Table has a list of columns with the names and default data
17//! Types corresponding to the layout of each row.
18
19pub mod iter;
20
21use std::collections::BTreeMap;
22use std::fmt;
23
24use super::{
25    common::{Context, Value, ValueType},
26    mem::Field as MemField,
27};
28
29/// The `Value` context for `core::Field`
30#[derive(Debug, PartialEq, Eq)]
31pub struct OwnedContext;
32
33impl Context for OwnedContext {
34    type String = String;
35    type I64 = i64;
36    type XML = String;
37}
38
39/// An owned field value
40pub type Field = Value<OwnedContext>;
41
42impl From<MemField<'_>> for Field {
43    fn from(src: MemField<'_>) -> Self {
44        match src {
45            MemField::Nothing => Field::Nothing,
46            MemField::Integer(v) => Field::Integer(v),
47            MemField::Float(v) => Field::Float(v),
48            MemField::Text(v) => Field::Text(v.decode().into_owned()),
49            MemField::Boolean(v) => Field::Boolean(v),
50            MemField::BigInt(v) => Field::BigInt(v),
51            MemField::VarChar(v) => Field::VarChar(v.decode().into_owned()),
52        }
53    }
54}
55
56impl PartialEq<MemField<'_>> for Field {
57    fn eq(&self, other: &MemField<'_>) -> bool {
58        match other {
59            Value::Nothing => matches!(self, Self::Nothing),
60            Value::Integer(x) => matches!(self, Self::Integer(y) if x == y),
61            Value::Float(x) => matches!(self, Self::Float(y) if x == y),
62            Value::Text(x) => matches!(self, Self::Text(y) if x.decode().as_ref() == y),
63            Value::Boolean(x) => matches!(self, Self::Boolean(y) if x == y),
64            Value::BigInt(x) => matches!(self, Self::BigInt(y) if x == y),
65            Value::VarChar(x) => matches!(self, Self::VarChar(y) if x.decode().as_ref() == y),
66        }
67    }
68}
69
70impl fmt::Display for Field {
71    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72        match self {
73            Field::Nothing => write!(f, "NULL"),
74            Field::Integer(i) => write!(f, "{}", i),
75            Field::Float(v) => write!(f, "{}", v),
76            Field::Text(t) => write!(f, "{:?}", t),
77            Field::Boolean(b) => write!(f, "{}", b),
78            Field::BigInt(i) => write!(f, "{}", i),
79            Field::VarChar(v) => write!(f, "{:?}", v),
80        }
81    }
82}
83
84/// A sequence of fields
85#[derive(Debug, Default)]
86pub struct Row(Vec<Field>);
87
88impl From<Vec<Field>> for Row {
89    fn from(fields: Vec<Field>) -> Self {
90        Row(fields)
91    }
92}
93
94impl Row {
95    /// Create a new, empty row
96    pub fn new() -> Row {
97        Row(Vec::new())
98    }
99
100    /// Return the fields of this row
101    pub fn into_fields(self) -> Vec<Field> {
102        self.0
103    }
104
105    /// Get a reference to the fields vector
106    pub fn fields(&self) -> &Vec<Field> {
107        &self.0
108    }
109
110    /// Get a mutable reference to the fields vector
111    pub fn fields_mut(&mut self) -> &mut Vec<Field> {
112        &mut self.0
113    }
114}
115
116/// A container of rows with the same hash value
117#[derive(Debug, Default)]
118pub struct Bucket(pub Vec<Row>);
119
120impl Bucket {
121    /// Create a new empty bucket
122    pub fn new() -> Bucket {
123        Bucket(Vec::new())
124    }
125
126    /// Get the rows of the bucket
127    pub fn rows(self) -> Vec<Row> {
128        self.0
129    }
130
131    /// Get a reference to the rows from a reference to a bucket
132    pub fn rows_ref(&self) -> &Vec<Row> {
133        &self.0
134    }
135
136    /// Get a mutable reference to the rows from a reference to a bucket
137    pub fn rows_mut(&mut self) -> &mut Vec<Row> {
138        &mut self.0
139    }
140}
141
142/// Name and default type for one field in each row
143#[derive(Debug)]
144pub struct Column {
145    /// The name of the column
146    pub name: String,
147    /// The type of the column
148    pub field_type: ValueType,
149}
150
151impl From<(&str, ValueType)> for Column {
152    fn from(data: (&str, ValueType)) -> Self {
153        Column {
154            name: String::from(data.0),
155            field_type: data.1,
156        }
157    }
158}
159
160/// A list of columns with types and a name
161#[derive(Debug)]
162pub struct TableDef {
163    /// The columns of the table in the same order as in the rows
164    pub columns: Vec<Column>,
165    /// The name of the table
166    pub name: String,
167}
168
169/// An array of buckets, and a collection of rows
170#[derive(Debug, Default)]
171pub struct TableData {
172    /// The buckets in this table
173    pub buckets: Vec<Bucket>,
174}
175
176impl TableData {
177    /// Creates a new instance
178    pub fn new() -> Self {
179        TableData {
180            buckets: Vec::new(),
181        }
182    }
183}
184
185/// A list of buckets and thus collection of rows with a name
186#[derive(Debug)]
187pub struct Table {
188    definition: TableDef,
189    data: TableData,
190}
191
192impl Table {
193    /// Creates a new table from a definition and data struct
194    pub fn from(definition: TableDef, data: TableData) -> Self {
195        Table { definition, data }
196    }
197
198    /// Creates a new table without data
199    pub fn new(definition: TableDef) -> Self {
200        let data = TableData::new();
201        Table { definition, data }
202    }
203
204    /// Extract the buckets vector
205    pub fn into_buckets(self) -> Vec<Bucket> {
206        self.data.buckets
207    }
208
209    /// Returns a reference to the slice of buckets
210    pub fn buckets(&self) -> &[Bucket] {
211        &self.data.buckets
212    }
213
214    /// Returns a mutable reference to the vector of buckets
215    pub fn buckets_mut(&mut self) -> &mut Vec<Bucket> {
216        &mut self.data.buckets
217    }
218
219    /// Extract the columns vector
220    pub fn into_columns(self) -> Vec<Column> {
221        self.definition.columns
222    }
223
224    /// Returns a reference to the slice of columns
225    pub fn columns(&self) -> &[Column] {
226        &self.definition.columns
227    }
228
229    /// Returns a mutable reference to the vector of columns
230    pub fn columns_mut(&mut self) -> &mut Vec<Column> {
231        &mut self.definition.columns
232    }
233
234    /// Returns the name of the table
235    pub fn name(&self) -> &str {
236        self.definition.name.as_ref()
237    }
238}
239
240/// # An ordered map of tables
241///
242/// A schema is an ordered map of tables. It represents a full
243/// relational database and is the root struct type in this module.
244#[derive(Debug, Default)]
245pub struct Schema {
246    /// The tables in this schema
247    pub tables: BTreeMap<String, Table>,
248}
249
250impl Schema {
251    /// Create a new empty schema
252    pub fn new() -> Schema {
253        Schema {
254            tables: BTreeMap::new(),
255        }
256    }
257
258    /// Get a reference to the table of that name it it exists
259    pub fn table(&self, name: &str) -> Option<&Table> {
260        self.tables.get(name)
261    }
262
263    /// Get a mutable reference to the table of that name it it exists
264    pub fn table_mut(&mut self, name: &str) -> Option<&mut Table> {
265        self.tables.get_mut(name)
266    }
267
268    /// Returns the number of tables
269    pub fn table_count(&self) -> usize {
270        self.tables.len()
271    }
272}
273
274impl From<Vec<Table>> for Schema {
275    fn from(tables: Vec<Table>) -> Self {
276        let mut tree = BTreeMap::new();
277        for table in tables {
278            tree.insert(table.name().to_string(), table);
279        }
280        Schema { tables: tree }
281    }
282}