1use std::marker::PhantomData;
2
3use lazy_db::*;
4use soulog::*;
5
6pub fn write<T>(list: &[T], f: impl Fn(FileWrapper, &T) -> Result<(), LDBError>, container: &LazyContainer, mut logger: impl Logger) {
7 if_err!((logger) [ListIO, err => ("While clearing container: {err:?}")] retry container.wipe());
8
9 for (i, x) in list.iter().enumerate() {
10 let data_writer =
11 if_err!((logger) [ListIO, err => ("While writing element of list: {:?}", err)] retry container.data_writer(i.to_string()));
12 if_err!((logger) [ListIO, err => ("While writing element of list: {:?}", err)] {f(data_writer, x)} crash {
13 log!((logger.error) ListIO("{err:#?}") as Fatal);
14 logger.crash()
15 })
16 }
17
18 if_err!((logger) [ListIO, err => ("{:?}", err)] retry {
19 let data_writer = if_err!((logger) [ListIO, err => ("While writing list length: {:?}", err)] retry container.data_writer("length"));
20 LazyData::new_u16(data_writer, list.len() as u16)
21 })
22}
23
24pub fn push(f: impl Fn(FileWrapper) -> Result<(), LDBError>, container: &LazyContainer, mut logger: impl Logger) {
25 let length = load_length(container, logger.hollow());
26
27 let data_writer = if_err!((logger) [ListIO, err => ("While pushing to list: {:?}", err)] retry container.data_writer(length.to_string()));
28 if_err!((logger) [ListIO, err => ("While pushing to list: {:?}", err)] {f(data_writer)} crash {
29 log!((logger.error) ListIO("{err:#?}") as Fatal);
30 logger.crash()
31 });
32
33 if_err!((logger) [ListIO, err => ("{:?}", err)] retry {
34 let data_writer = if_err!((logger) [ListIO, err => ("While writing list length: {:?}", err)] retry container.data_writer("length"));
35 LazyData::new_u16(data_writer, length + 1)
36 })
37}
38
39pub fn pop<T>(f: impl Fn(LazyData) -> Result<T, LDBError>, container: &LazyContainer, mut logger: impl Logger) -> Option<T> {
40 let length = load_length(container, logger.hollow());
41
42 if length == 0 {
43 return None;
44 }
45
46 let idx = (length - 1).to_string();
47 let item = if_err!((logger) [ListIO, err => ("While reading list element: {:?}", err)] retry container.read_data(&idx));
48 let item = if_err!((logger) [ListIO, err => ("While reading list element: {:?}", err)] {f(item)} crash {
49 log!((logger.error) ListIO("{err:#?}") as Fatal);
50 logger.crash()
51 });
52
53 if_err!((logger) {container.remove(idx)} else(err) {
54 log!((logger.vital) ListIO("While removing item: {err:?}; ignoring error...") as Inconvenience)
55 });
56
57 if_err!((logger) [ListIO, err => ("{:?}", err)] retry {
58 let data_writer = if_err!((logger) [ListIO, err => ("While writing list length: {:?}", err)] retry container.data_writer("length"));
59 LazyData::new_u16(data_writer, length - 1)
60 });
61
62 Some(item)
63}
64
65pub fn read<T>(f: impl Fn(LazyData) -> Result<T, LDBError>, container: &LazyContainer, mut logger: impl Logger) -> Box<[T]> {
66 let length = load_length(container, logger.hollow());
67
68 let mut list = Vec::<T>::with_capacity(length as usize);
69
70 for i in 0..length {
71 let item = if_err!((logger) [ListIO, err => ("While reading list element: {:?}", err)] retry container.read_data(i.to_string()));
72 let item = if_err!((logger) [ListIO, err => ("While reading list element: {:?}", err)] {f(item)} crash {
73 log!((logger.error) ListIO("{err:#?}") as Fatal);
74 logger.crash()
75 });
76 list.push(item)
77 }
78
79 list.into_boxed_slice()
80}
81
82pub fn load_length(container: &LazyContainer, mut logger: impl Logger) -> u16 {
83 let length = if_err!((logger) [ListIO, err => ("While reading list length: {:?}", err)] retry container.read_data("length"));
84 if_err!((logger) [ListIO, err => ("While reading list length: {:?}", err)] {length.collect_u16()} crash {
85 log!((logger.error) ListIO("{err:#?}") as Fatal);
86 logger.crash()
87 })
88}
89
90pub struct List<T, L: Logger, F: Fn(LazyData) -> Result<T, LDBError>> {
91 _phantom_marker: PhantomData<T>,
92 read_f: F,
93 container: LazyContainer,
94 logger: L,
95 length: u16,
96 idx: u16,
97}
98
99impl<T, L: Logger, F: Fn(LazyData) -> Result<T, LDBError>> List<T, L, F> {
100 pub fn init(container: LazyContainer, read_f: F, mut logger: L) -> Self {
101 if_err!((logger) [List, err => ("While inititalising list: {err:?}")] retry write_container!((container) length = new_u16(0)));
102 Self {
103 _phantom_marker: PhantomData,
104 container,
105 read_f,
106 logger: logger.hollow(),
107 length: 0,
108 idx: 0,
109 }
110 }
111
112 pub fn load(container: LazyContainer, read_f: F, mut logger: L) -> Self {
113 let length = if_err!((logger) [List, err => ("While loading list: {err:?}")] retry
114 if_err!((logger) [List, err => ("While loading list: {err:?}")] retry
115 search_container!((container) length)
116 ).collect_u16()
117 );
118
119 Self {
120 _phantom_marker: PhantomData,
121 container,
122 read_f,
123 length,
124 logger: logger.hollow(),
125 idx: 0,
126 }
127 }
128}
129
130impl<T, L:Logger, F: Fn(LazyData) -> Result<T, LDBError>> Iterator for List<T, L, F> {
131 type Item = T;
132
133 fn next(&mut self) -> Option<T> {
134 if self.idx >= self.length { return None };
135 let mut logger = self.logger.hollow();
136 let f: &F = &self.read_f;
137
138 let item = if_err!((logger) [ListIO, err => ("While reading list element: {:?}", err)] retry self.container.read_data(self.idx.to_string()));
139 Some(if_err!((logger) [ListIO, err => ("While reading list element: {:?}", err)] {f(item)} crash {
140 log!((logger.error) ListIO("{err:#?}") as Fatal);
141 logger.crash()
142 }))
143 }
144}