1use super::{
7 buffer::{self, cmp_table_header_name, Buffer, BufferError, Res},
8 slice::{FDBBucketHeaderSlice, FDBColumnHeaderSlice, FDBFieldDataSlice, FDBTableHeaderSlice},
9 BaseHandle, Handle,
10};
11use crate::fdb::{
12 common::{Latin1Str, UnknownValueType, ValueType},
13 file::{
14 FDBBucketHeader, FDBColumnHeader, FDBFieldData, FDBFieldValue, FDBHeader, FDBRowHeader,
15 FDBRowHeaderListEntry, FDBTableDataHeader, FDBTableDefHeader, FDBTableHeader,
16 },
17};
18use assembly_core::displaydoc::Display;
19use std::{
20 borrow::Cow, convert::TryFrom, error::Error, fmt, ops::Deref, result::Result as StdResult,
21};
22
23pub type Result<'a, T> = std::result::Result<Handle<'a, T>, BufferError>;
25
26#[derive(Debug, Clone, PartialEq, Eq)]
27pub struct BaseError<P: Deref>
29where
30 P::Target: AsRef<[u8]>,
31{
32 mem: P,
33 kind: BaseErrorKind,
34}
35
36impl<P: Deref + fmt::Debug> Error for BaseError<P>
37where
38 P::Target: AsRef<[u8]>,
39{
40 fn source(&self) -> Option<&(dyn Error + 'static)> {
41 match &self.kind {
42 BaseErrorKind::Unimplemented => None,
43 BaseErrorKind::Buffer(e) => Some(e),
44 }
45 }
46}
47
48impl<P: Deref> fmt::Display for BaseError<P>
49where
50 P::Target: AsRef<[u8]>,
51{
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 self.kind.fmt(f)
54 }
55}
56
57impl<P: Deref> BaseError<P>
58where
59 P::Target: AsRef<[u8]>,
60{
61 pub fn unimplemented(mem: P) -> Self {
63 Self {
64 mem,
65 kind: BaseErrorKind::Unimplemented,
66 }
67 }
68}
69
70#[derive(Debug, Display, Clone, PartialEq, Eq)]
71pub enum BaseErrorKind {
73 Unimplemented,
75 Buffer(BufferError),
77}
78
79impl From<BufferError> for BaseErrorKind {
80 fn from(b: BufferError) -> Self {
81 Self::Buffer(b)
82 }
83}
84
85pub type BaseResult<P, T> = std::result::Result<BaseHandle<P, T>, BaseError<P>>;
87
88impl<P: Deref, T> BaseHandle<P, T>
89where
90 P::Target: AsRef<[u8]>,
91{
92 pub fn map_into<M, O, E>(self, map: M) -> BaseResult<P, O>
94 where
95 M: Fn(&[u8], T) -> std::result::Result<O, E>,
96 E: Into<BaseErrorKind>,
97 {
98 match map(self.mem.deref().as_ref(), self.raw) {
99 Ok(new_raw) => Ok(BaseHandle {
100 mem: self.mem,
101 raw: new_raw,
102 }),
103 Err(e) => Err(BaseError {
104 mem: self.mem,
105 kind: e.into(),
106 }),
107 }
108 }
109}
110
111impl<P: Deref> BaseHandle<P, ()>
112where
113 P::Target: AsRef<[u8]>,
114{
115 pub fn into_tables(self) -> BaseResult<P, FDBHeader> {
117 self.map_into(buffer::header)
118 }
119}
120
121impl<P: Deref> BaseHandle<P, FDBHeader>
122where
123 P::Target: AsRef<[u8]>,
124{
125 pub fn into_table_at(self, index: usize) -> BaseResult<P, Option<FDBTableHeader>> {
127 self.map_into(|buf, header| -> Res<Option<FDBTableHeader>> {
128 let slice = buffer::table_headers(buf, &header)?;
129 Ok(slice.get(index).copied())
130 })
131 }
132
133 pub fn into_table_by_name(self, name: &Latin1Str) -> BaseResult<P, Option<FDBTableHeader>> {
135 self.map_into(|buf, header| -> Res<Option<FDBTableHeader>> {
136 let slice = buffer::table_headers(buf, &header)?;
137 match slice.binary_search_by(|t| cmp_table_header_name(buf, name.as_bytes(), *t)) {
138 Ok(index) => Ok(Some(*slice.get(index).unwrap())),
139 Err(_) => Ok(None),
140 }
141 })
142 }
143}
144
145impl<P: Deref> BaseHandle<P, FDBTableHeader>
146where
147 P::Target: AsRef<[u8]>,
148{
149 pub fn into_definition(self) -> BaseResult<P, FDBTableDefHeader> {
151 self.map_into(buffer::table_definition)
152 }
153
154 pub fn into_data(self) -> BaseResult<P, FDBTableDataHeader> {
156 self.map_into(buffer::table_data)
157 }
158}
159
160impl<P: Deref> BaseHandle<P, FDBTableDataHeader>
161where
162 P::Target: AsRef<[u8]>,
163{
164 pub fn get_bucket_for_hash(self, id: u32) -> BaseResult<P, FDBBucketHeader> {
166 self.map_into::<_,_,BufferError>(|buf, raw| {
167 let bucket_count = raw.buckets.count as usize;
168 let buckets_addr = raw.buckets.base_offset as usize;
169 let slice: &[FDBBucketHeader] = buffer::get_slice_at(buf, buckets_addr, bucket_count)?;
170 Ok(slice[id as usize % bucket_count])
171 })
172 }
173}
174
175pub type Database<'a> = Handle<'a, ()>;
177
178impl<'a> Database<'a> {
179 pub fn new_ref(mem: &'a [u8]) -> Self {
181 Self {
182 mem: Buffer::new(mem),
183 raw: (),
184 }
185 }
186
187 pub fn tables(&self) -> Result<'a, FDBHeader> {
189 let header = buffer::header(self.mem.as_bytes(), ())?;
190 Ok(self.wrap(header))
191 }
192}
193
194impl<'a> Handle<'a, FDBHeader> {
195 pub fn table_count(&self) -> u32 {
197 self.raw.tables.count
198 }
199
200 pub fn table_header_list(&self) -> Result<'a, FDBTableHeaderSlice<'a>> {
202 let len = self.table_count() as usize * 8;
203 let buf = self
204 .mem
205 .get_len_at(self.raw.tables.base_offset as usize, len)?;
206 Ok(self.wrap(FDBTableHeaderSlice(buf)))
207 }
208}
209
210impl<'a> IntoIterator for &Handle<'a, FDBTableHeaderSlice<'a>> {
211 type Item = Handle<'a, FDBTableHeader>;
212 type IntoIter = Handle<'a, FDBTableHeaderSlice<'a>>;
213
214 fn into_iter(self) -> Self::IntoIter {
215 *self
216 }
217}
218
219impl<'a> Iterator for Handle<'a, FDBTableHeaderSlice<'a>> {
220 type Item = Handle<'a, FDBTableHeader>;
221
222 fn next(&mut self) -> Option<Self::Item> {
223 self.raw.next().map(|raw| Handle { mem: self.mem, raw })
224 }
225}
226
227impl<'a> DoubleEndedIterator for Handle<'a, FDBTableHeaderSlice<'a>> {
228 fn next_back(&mut self) -> Option<Self::Item> {
229 self.raw
230 .next_back()
231 .map(|raw| Handle { mem: self.mem, raw })
232 }
233}
234
235impl<'a> Handle<'a, FDBTableHeader> {
236 pub fn table_def_header(&self) -> Result<'a, FDBTableDefHeader> {
238 let raw = self.mem.table_def_header(self.raw.table_def_header_addr)?;
239 Ok(self.wrap(raw))
240 }
241
242 pub fn table_data_header(&self) -> Result<'a, FDBTableDataHeader> {
244 let raw = self
245 .mem
246 .table_data_header(self.raw.table_data_header_addr)?;
247 Ok(self.wrap(raw))
248 }
249}
250
251impl<'a> Handle<'a, FDBTableDefHeader> {
252 pub fn column_count(&self) -> u32 {
254 self.raw.column_count
255 }
256
257 pub fn table_name(&self) -> Result<'a, &'a Latin1Str> {
259 let raw = self.mem.string(self.raw.table_name_addr)?;
260 Ok(self.wrap(raw))
261 }
262
263 pub fn column_header_list(&self) -> Result<'a, FDBColumnHeaderSlice<'a>> {
265 let len = self.column_count() as usize * 8;
266 let buf = self
267 .mem
268 .get_len_at(self.raw.column_header_list_addr as usize, len)?;
269 Ok(self.wrap(FDBColumnHeaderSlice(buf)))
270 }
271}
272
273#[cfg(feature = "serde-derives")]
274impl<'a> serde::Serialize for Handle<'a, FDBTableDefHeader> {
275 fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
276 where
277 S: serde::Serializer,
278 {
279 use serde::ser::SerializeStruct;
280 let mut tbl = serializer.serialize_struct("Table", 2)?;
281 tbl.serialize_field("name", self.table_name().unwrap().raw().decode().as_ref())?;
282 tbl.serialize_field("columns", &self.column_header_list().unwrap())?;
283 tbl.end()
284 }
285}
286
287impl<'a> IntoIterator for &Handle<'a, FDBColumnHeaderSlice<'a>> {
288 type Item = Handle<'a, FDBColumnHeader>;
289 type IntoIter = Handle<'a, FDBColumnHeaderSlice<'a>>;
290
291 fn into_iter(self) -> Self::IntoIter {
292 *self
293 }
294}
295
296impl<'a> Iterator for Handle<'a, FDBColumnHeaderSlice<'a>> {
297 type Item = Handle<'a, FDBColumnHeader>;
298
299 fn next(&mut self) -> Option<Self::Item> {
300 self.raw.next().map(|raw| Handle { mem: self.mem, raw })
301 }
302}
303
304#[cfg(feature = "serde-derives")]
305impl<'a> serde::Serialize for Handle<'a, FDBColumnHeaderSlice<'a>> {
306 fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
307 where
308 S: serde::Serializer,
309 {
310 use serde::ser::SerializeSeq;
311 let len = self.raw().len();
312 let mut seq = serializer.serialize_seq(Some(len))?;
313 for element in self.into_iter() {
314 seq.serialize_element(&element)?;
315 }
316 seq.end()
317 }
318}
319
320impl<'a> DoubleEndedIterator for Handle<'a, FDBColumnHeaderSlice<'a>> {
321 fn next_back(&mut self) -> Option<Self::Item> {
322 self.raw
323 .next_back()
324 .map(|raw| Handle { mem: self.mem, raw })
325 }
326}
327
328impl<'a> Handle<'a, FDBColumnHeader> {
329 pub fn column_name(&self) -> Result<'a, &'a Latin1Str> {
331 let raw = self.mem.string(self.raw.column_name_addr)?;
332 Ok(self.wrap(raw))
333 }
334
335 pub fn column_data_type(&self) -> StdResult<ValueType, UnknownValueType> {
337 ValueType::try_from(self.raw.column_data_type)
338 }
339}
340
341#[cfg(feature = "serde-derives")]
342impl<'a> serde::Serialize for Handle<'a, FDBColumnHeader> {
343 fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
344 where
345 S: serde::Serializer,
346 {
347 use serde::ser::SerializeStruct;
348 let mut col = serializer.serialize_struct("Column", 2)?;
349 col.serialize_field("name", self.column_name().unwrap().raw().decode().as_ref())?;
350 col.serialize_field("data_type", &self.column_data_type().unwrap())?;
351 col.end()
352 }
353}
354
355impl<'a> Handle<'a, FDBTableDataHeader> {
356 pub fn bucket_count(&self) -> u32 {
358 self.raw.buckets.count
359 }
360
361 pub fn bucket_header_list(&self) -> Result<'a, FDBBucketHeaderSlice<'a>> {
363 let len = self.bucket_count() as usize * 4;
364 let buf = self
365 .mem
366 .get_len_at(self.raw.buckets.base_offset as usize, len)?;
367 Ok(self.wrap(FDBBucketHeaderSlice(buf)))
368 }
369}
370
371impl<'a> IntoIterator for &Handle<'a, FDBBucketHeaderSlice<'a>> {
372 type Item = Handle<'a, FDBBucketHeader>;
373 type IntoIter = Handle<'a, FDBBucketHeaderSlice<'a>>;
374
375 fn into_iter(self) -> Self::IntoIter {
376 *self
377 }
378}
379
380impl<'a> Iterator for Handle<'a, FDBBucketHeaderSlice<'a>> {
381 type Item = Handle<'a, FDBBucketHeader>;
382
383 fn next(&mut self) -> Option<Self::Item> {
384 self.raw.next().map(|raw| Handle { mem: self.mem, raw })
385 }
386
387 fn nth(&mut self, n: usize) -> Option<Self::Item> {
388 self.raw.nth(n).map(|raw| Handle { mem: self.mem, raw })
389 }
390}
391
392impl<'a> DoubleEndedIterator for Handle<'a, FDBBucketHeaderSlice<'a>> {
393 fn next_back(&mut self) -> Option<Self::Item> {
394 self.raw
395 .next_back()
396 .map(|raw| Handle { mem: self.mem, raw })
397 }
398}
399
400impl<'a> Handle<'a, FDBBucketHeader> {
401 pub fn first(&self) -> Option<Result<'a, FDBRowHeaderListEntry>> {
403 let addr = self.raw.row_header_list_head_addr;
404 if addr == 0xFFFFFFFF {
405 None
406 } else {
407 Some(self.mem.row_header_list_entry(addr).map(|e| self.wrap(e)))
408 }
409 }
410
411 pub fn row_header_iter(&self) -> Handle<'a, FDBRowHeaderRef> {
413 self.wrap(FDBRowHeaderRef(self.raw.row_header_list_head_addr))
414 }
415}
416
417#[derive(Debug, Copy, Clone)]
418#[allow(clippy::upper_case_acronyms)]
420pub struct FDBRowHeaderRef(u32);
421
422impl<'a> Iterator for Handle<'a, FDBRowHeaderRef> {
423 type Item = Result<'a, FDBRowHeader>;
424
425 fn next(&mut self) -> Option<Self::Item> {
426 let addr = self.raw.0;
427 if addr == 0xFFFFFFFF {
428 None
429 } else {
430 match self.mem.row_header_list_entry(addr) {
431 Ok(e) => {
432 self.raw.0 = e.row_header_list_next_addr;
433 match self.mem.row_header(e.row_header_addr) {
434 Ok(rh) => Some(Ok(self.wrap(rh))),
435 Err(e) => {
436 self.raw.0 = 0xFFFFFFFF;
437 Some(Err(e))
438 }
439 }
440 }
441 Err(e) => {
442 self.raw.0 = 0xFFFFFFFF;
443 Some(Err(e))
444 }
445 }
446 }
447 }
448}
449
450impl<'a> Handle<'a, FDBRowHeaderListEntry> {
451 pub fn next(&self) -> Option<Result<'a, FDBRowHeaderListEntry>> {
453 let addr = self.raw.row_header_list_next_addr;
454 if addr == 0xFFFFFFFF {
455 None
456 } else {
457 Some(self.mem.row_header_list_entry(addr).map(|e| self.wrap(e)))
458 }
459 }
460
461 pub fn row_header(&self) -> Result<'a, FDBRowHeader> {
463 let e = self.mem.row_header(self.raw.row_header_addr)?;
464 Ok(self.wrap(e))
465 }
466}
467
468impl<'a> Handle<'a, FDBRowHeader> {
469 pub fn field_count(&self) -> u32 {
471 self.raw.fields.count
472 }
473
474 pub fn field_data_list(&self) -> Result<'a, FDBFieldDataSlice<'a>> {
476 let len = self.field_count() as usize * 8;
477 let buf = self
478 .mem
479 .get_len_at(self.raw.fields.base_offset as usize, len)?;
480 Ok(self.wrap(FDBFieldDataSlice(buf)))
481 }
482}
483
484impl<'a> IntoIterator for &Handle<'a, FDBFieldDataSlice<'a>> {
485 type Item = Handle<'a, FDBFieldData>;
486 type IntoIter = Handle<'a, FDBFieldDataSlice<'a>>;
487
488 fn into_iter(self) -> Self::IntoIter {
489 *self
490 }
491}
492
493impl<'a> Iterator for Handle<'a, FDBFieldDataSlice<'a>> {
494 type Item = Handle<'a, FDBFieldData>;
495
496 fn next(&mut self) -> Option<Self::Item> {
497 self.raw.next().map(|raw| Handle { mem: self.mem, raw })
498 }
499}
500
501impl<'a> DoubleEndedIterator for Handle<'a, FDBFieldDataSlice<'a>> {
502 fn next_back(&mut self) -> Option<Self::Item> {
503 self.raw
504 .next_back()
505 .map(|raw| Handle { mem: self.mem, raw })
506 }
507}
508
509impl<'a> Handle<'a, FDBFieldData> {
510 pub fn try_get_value(&self) -> Result<'a, FDBFieldValue> {
512 Ok(self.map(|_, r| FDBFieldValue::try_from(r).unwrap()))
514 }
515}
516
517impl<'a> Handle<'a, &'a Latin1Str> {
518 pub fn to_str(&self) -> Cow<'a, str> {
520 self.raw.decode()
521 }
522}