lazy_db/
lazy_container.rs1use crate::*;
2use std::path::{Path, PathBuf};
3use std::fs;
4
5#[macro_export]
7macro_rules! write_container {
8 (($container:expr) $($item:ident)?$(($obj:expr))? = $func:ident($value:expr)) => {(|| {
9 let container = &$container;
10 $(LazyData::$func(container.data_writer(stringify!($item))?, $value)?;)?
11 $(LazyData::$func(container.data_writer($obj)?, $value)?;)?
12 Result::<(), LDBError>::Ok(())
13 })()};
14
15 (($container:expr) /$($($con:ident)?$(($can:expr))?)/ *::$($item:ident)?$(($obj:expr))? = $func:ident($value:expr)) => {(|| {
16 let mut container = &mut $container;
17 $({
18 let con = $(stringify!($con))?$($can)?;
19 container = match container.read_container(con) {
20 Ok(x) => x,
21 Err(LDBError::DirNotFound(_)) => container.new_container(con)?,
22 Err(e) => return Err(e),
23 }
24 };)*
25
26 $(LazyData::$func(container.data_writer(stringify!($item))?, $value)?;)?
27 $(LazyData::$func(container.data_writer($obj)?, $value)?;)?
28 Result::<(), LDBError>::Ok(())
29 })()}
30}
31
32#[macro_export]
34macro_rules! search_container {
35 (($container:expr) /$($($con:ident)?$(($can:expr))?)/ *) => {(|| {
36 let container = &$container;
37 $(
38 $(let container = container.read_container(stringify!($con))?;)?
39 $(let container = container.read_container($can)?;)?
40 )*
41 let result: Result<LazyContainer, LDBError> = Ok(container);
42 result
43 })()};
44
45 (($container:expr) /$($($con:ident)?$(($can:expr))?)/ *::$($item:ident)?$(($obj:expr))?) => {(|| {
46 let container = search_container!(($container) /$($($con)?$(($can))?)/ *)?;
47 $(let result: Result<LazyData, LDBError> = container.read_data(stringify!($item));)?
48 $(let result: Result<LazyData, LDBError> = container.read_data($obj);)?
49 result
50 })()};
51
52 (($container:expr) $($item:ident)?$(($obj:expr))?) => {(|| {
53 let container = &$container;
54 $(let result: Result<LazyData, LDBError> = container.read_data(stringify!($item));)?
55 $(let result: Result<LazyData, LDBError> = container.read_data($obj);)?
56 result
57 })()};
58}
59
60pub struct LazyContainer {
62 path: PathBuf,
63}
64
65impl LazyContainer {
66 pub fn init(path: impl AsRef<Path>) -> Result<Self, std::io::Error> {
68 let path = path.as_ref();
69
70 if !path.is_dir() { fs::create_dir_all(path)? };
72
73 Ok(Self {
75 path: path.to_path_buf(),
76 })
77 }
78
79 pub fn load(path: impl AsRef<Path>) -> Result<Self, LDBError> {
83 let path = path.as_ref().to_path_buf();
84
85 if !path.is_dir() { return Err(LDBError::DirNotFound(path)) };
87
88 Ok(Self {
90 path,
91 })
92 }
93
94 pub fn data_writer(&self, key: impl AsRef<Path>) -> Result<FileWrapper, LDBError> {
98 let path = self.path.join(key);
99 if path.is_file() { let _ = fs::remove_file(&path); }; let file = unwrap_result!((fs::File::create(path)) err => LDBError::IOError(err));
101 Ok(FileWrapper::new_writer(file))
102 }
103
104 pub fn new_container(&self, key: impl AsRef<Path>) -> Result<LazyContainer, LDBError> {
108 let path = self.path.join(&key);
109 if path.is_dir() { unwrap_result!((fs::remove_dir_all(&path)) err => LDBError::IOError(err)) }; Ok(unwrap_result!((LazyContainer::init(path)) err => LDBError::IOError(err)))
111 }
112
113 pub fn child_container(&self, key: impl AsRef<Path>) -> Result<LazyContainer, LDBError> {
118 let path = self.path.join(&key);
119 if path.is_dir() { return self.read_container(key) }; Ok(unwrap_result!((LazyContainer::init(path)) err => LDBError::IOError(err)))
121 }
122
123 pub fn read_data(&self, key: impl AsRef<Path>) -> Result<LazyData, LDBError> {
125 let path = self.path.join(key);
126 if !path.is_file() { return Err(LDBError::FileNotFound(path)) };
127 LazyData::load(path)
128 }
129
130 pub fn read_container(&self, key: impl AsRef<Path>) -> Result<LazyContainer, LDBError> {
132 let path = self.path.join(key);
133 if !path.is_dir() { return Err(LDBError::DirNotFound(path)) };
134 LazyContainer::load(path)
135 }
136
137 pub fn remove(&self, key: impl AsRef<Path>) -> Result<(), std::io::Error> {
139 let path = self.path.join(key);
140 if path.is_dir() {
141 fs::remove_dir_all(path)
142 } else {
143 fs::remove_file(path)
144 }
145 }
146
147 pub fn wipe(&self) -> Result<(), std::io::Error> {
149 fs::remove_dir_all(&self.path)?;
150 fs::create_dir_all(&self.path)
151 }
152
153 #[inline]
155 pub fn path(&self) -> &Path {
156 &self.path
157 }
158}