versatile_data/
lib.rs

1pub mod search;
2
3mod field;
4mod operation;
5mod option;
6mod row_fragment;
7mod serial;
8mod sort;
9
10pub use field::{Field, FieldName, Fields};
11use idx_binary::AvltrieeSearch;
12pub use idx_binary::{self, AvltrieeIter, FileMmap, IdxBinary, IdxFile};
13pub use operation::*;
14pub use option::DataOption;
15pub use row_fragment::RowFragment;
16pub use search::{Condition, Search};
17pub use sort::{CustomOrderKey, CustomSort, Order, OrderKey};
18pub use uuid::Uuid;
19
20use std::{
21    collections::BTreeSet,
22    fs,
23    num::NonZeroU32,
24    path::{Path, PathBuf},
25    time::{SystemTime, UNIX_EPOCH},
26};
27
28use serial::SerialNumber;
29
30pub type RowSet = BTreeSet<NonZeroU32>;
31
32pub fn uuid_string(uuid: u128) -> String {
33    Uuid::from_u128(uuid).to_string()
34}
35
36pub struct Data {
37    fields_dir: PathBuf,
38    option: DataOption,
39    serial: SerialNumber,
40    uuid: Option<IdxFile<u128>>,
41    activity: Option<IdxFile<u8>>,
42    term_begin: Option<IdxFile<u64>>,
43    term_end: Option<IdxFile<u64>>,
44    last_updated: Option<IdxFile<u64>>,
45    fields: Fields,
46}
47
48impl Data {
49    /// Opens the file and creates the Data.
50    pub fn new<P: AsRef<Path>>(dir: P, option: DataOption) -> Self {
51        let dir = dir.as_ref();
52        if !dir.exists() {
53            fs::create_dir_all(dir).unwrap();
54        }
55
56        let mut fields = Fields::default();
57
58        let mut fields_dir = dir.to_path_buf();
59        fields_dir.push("fields");
60        if fields_dir.exists() {
61            for d in fields_dir.read_dir().unwrap().into_iter() {
62                let d = d.unwrap();
63                if d.file_type().unwrap().is_dir() {
64                    if let Some(name) = d.file_name().to_str() {
65                        let field = Field::new(d.path(), option.allocation_lot);
66                        fields.insert(FieldName::new(name.into()), field);
67                    }
68                }
69            }
70        }
71
72        let serial = SerialNumber::new(
73            {
74                let mut path = dir.to_path_buf();
75                path.push("serial");
76                path
77            },
78            option.allocation_lot,
79        );
80        let uuid = option.uuid.then(|| {
81            IdxFile::new(
82                {
83                    let mut path = dir.to_path_buf();
84                    path.push("uuid.i");
85                    path
86                },
87                option.allocation_lot,
88            )
89        });
90        let activity = option.activity.then(|| {
91            IdxFile::new(
92                {
93                    let mut path = dir.to_path_buf();
94                    path.push("activity.i");
95                    path
96                },
97                option.allocation_lot,
98            )
99        });
100        let term_begin = option.term.then(|| {
101            IdxFile::new(
102                {
103                    let mut path = dir.to_path_buf();
104                    path.push("term_begin.i");
105                    path
106                },
107                option.allocation_lot,
108            )
109        });
110        let term_end = option.term.then(|| {
111            IdxFile::new(
112                {
113                    let mut path = dir.to_path_buf();
114                    path.push("term_end.i");
115                    path
116                },
117                option.allocation_lot,
118            )
119        });
120        let last_updated = option.last_updated.then(|| {
121            IdxFile::new(
122                {
123                    let mut path = dir.to_path_buf();
124                    path.push("last_updated.i");
125                    path
126                },
127                option.allocation_lot,
128            )
129        });
130
131        Self {
132            fields_dir,
133            option,
134            serial,
135            uuid,
136            activity,
137            term_begin,
138            term_end,
139            last_updated,
140            fields,
141        }
142    }
143
144    /// Returns a serial number.The serial number is incremented each time data is added.
145    pub fn serial(&self, row: NonZeroU32) -> &u32 {
146        unsafe { self.serial.value_unchecked(row) }
147    }
148
149    /// Returns a UUID.UUID is a unique ID that is automatically generated when data is registered..
150    pub fn uuid(&self, row: NonZeroU32) -> Option<&u128> {
151        self.uuid.as_ref().and_then(|uuid| uuid.value(row))
152    }
153
154    /// Returns the UUID as a string.
155    pub fn uuid_string(&self, row: NonZeroU32) -> Option<String> {
156        self.uuid.as_ref().and_then(|uuid| {
157            uuid.value(row)
158                .map(|v| uuid::Uuid::from_u128(*v).to_string())
159        })
160    }
161
162    /// Returns the activity value. activity is used to indicate whether data is valid or invalid.
163    pub fn activity(&self, row: NonZeroU32) -> Option<Activity> {
164        self.activity.as_ref().and_then(|a| {
165            a.value(row).map(|v| {
166                if *v != 0 {
167                    Activity::Active
168                } else {
169                    Activity::Inactive
170                }
171            })
172        })
173    }
174
175    /// Returns the start date and time of the data's validity period.
176    pub fn term_begin(&self, row: NonZeroU32) -> Option<&u64> {
177        self.term_begin.as_ref().and_then(|f| f.value(row))
178    }
179
180    /// Returns the end date and time of the data's validity period.
181    pub fn term_end(&self, row: NonZeroU32) -> Option<&u64> {
182        self.term_end.as_ref().and_then(|f| f.value(row))
183    }
184
185    /// Returns the date and time when the data was last updated.
186    pub fn last_updated(&self, row: NonZeroU32) -> Option<&u64> {
187        self.last_updated.as_ref().and_then(|f| f.value(row))
188    }
189
190    /// Returns all rows.
191    pub fn all(&self) -> RowSet {
192        self.serial.iter().collect()
193    }
194
195    fn now() -> u64 {
196        SystemTime::now()
197            .duration_since(UNIX_EPOCH)
198            .unwrap()
199            .as_secs()
200    }
201}