structsy_tools/
lib.rs

1use structsy::internal::Description;
2use structsy::record::Record;
3use structsy::{RawAccess, RawRead, Snapshot, Structsy, StructsyError};
4
5/// Enum of all possible data types in structsy, use 'serde_integration' to allow
6/// to serialize them with serde
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8pub enum Data {
9    Definition(Description),
10    Record(Record),
11}
12
13/// Produce and iterator that allow to iterate all the data in a structsy database
14/// for then write some data on an external target.
15///
16pub fn export(structsy: &Structsy) -> Result<impl Iterator<Item = Data>, StructsyError> {
17    let definitions = structsy.list_defined()?.map(|def| Data::Definition(def));
18    let st = structsy.clone();
19    let data_iter = structsy
20        .list_defined()?
21        .map(move |def| {
22            RawRead::raw_scan(&st, &def.get_name())
23                .ok()
24                .map(|it| it.map(|(_, record)| Data::Record(record)))
25        })
26        .flatten()
27        .flatten();
28    Ok(definitions.chain(data_iter))
29}
30
31/// Produce and iterator that allow to iterate all the data in a structsy database
32/// for then write some data on an external target.
33///
34pub fn export_from_snapshot(snapshot: Snapshot) -> Result<impl Iterator<Item = Data>, StructsyError> {
35    let definitions = snapshot.list_defined()?.map(|def| Data::Definition(def));
36    let snap = snapshot.clone();
37    let data_iter = snapshot
38        .list_defined()?
39        .map(move |def| {
40            RawRead::raw_scan(&snap, &def.get_name())
41                .ok()
42                .map(|it| it.map(|(_, record)| Data::Record(record)))
43        })
44        .flatten()
45        .flatten();
46    Ok(definitions.chain(data_iter))
47}
48///Import all the data provided by the iterator to a structsy database.
49///
50pub fn import(structsy: &Structsy, iter: impl Iterator<Item = Data>) -> Result<(), StructsyError> {
51    for values in iter {
52        match values {
53            Data::Definition(def) => {
54                structsy.raw_define(def)?;
55            }
56            Data::Record(rec) => {
57                let mut raw_tx = structsy.raw_begin()?;
58                raw_tx.raw_insert(&rec)?;
59                raw_tx.prepare()?.commit()?;
60            }
61        }
62    }
63    Ok(())
64}
65
66#[cfg(test)]
67mod tests {
68    use structsy_derive::{queries, Persistent};
69
70    use super::{export, import};
71    use structsy::{Structsy, StructsyTx};
72    #[derive(Persistent)]
73    struct Simple {
74        #[index(mode = "cluster")]
75        name: String,
76        size: u32,
77    }
78
79    #[queries(Simple)]
80    trait SimpleQueries {
81        fn by_name(self, name: &str) -> Self;
82    }
83
84    #[test]
85    fn simple_export_import() {
86        let db = Structsy::memory().unwrap();
87        db.define::<Simple>().unwrap();
88        let mut tx = db.begin().unwrap();
89        tx.insert(&Simple {
90            name: "first".to_owned(),
91            size: 10,
92        })
93        .unwrap();
94        tx.commit().unwrap();
95
96        let loaded = Structsy::memory().unwrap();
97        let data = export(&db).unwrap();
98        import(&loaded, data).unwrap();
99
100        assert_eq!(loaded.query::<Simple>().by_name("first").into_iter().count(), 1);
101    }
102}