Skip to main content

versatile_data/
lib.rs

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