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 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 pub fn serial(&self, row: NonZeroU32) -> Option<&u32> {
151 self.serial.value(row)
152 }
153
154 pub fn uuid(&self, row: NonZeroU32) -> Option<&u128> {
156 self.uuid.as_ref().and_then(|uuid| uuid.value(row))
157 }
158
159 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 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 pub fn term_begin(&self, row: NonZeroU32) -> Option<&u64> {
182 self.term_begin.as_ref().and_then(|f| f.value(row))
183 }
184
185 pub fn term_end(&self, row: NonZeroU32) -> Option<&u64> {
187 self.term_end.as_ref().and_then(|f| f.value(row))
188 }
189
190 pub fn last_updated(&self, row: NonZeroU32) -> Option<&u64> {
192 self.last_updated.as_ref().and_then(|f| f.value(row))
193 }
194
195 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}