1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
use assembly_core::reader::{FileError};
use super::core::{Field, ValueType};
use super::file::FDBFieldData;
use super::reader::{DatabaseBufReader, DatabaseReader};

use std::io::{Seek, BufRead};

#[derive(Debug)]
pub enum BuildError {
    File(FileError),
    UnknownType(u32),
}

pub type BuildResult<T> = Result<T, BuildError>;

impl<T,R> DatabaseBuilder<T> for R
where
    R: DatabaseBufReader<T> + DatabaseReader<T>,
    T: Seek + BufRead {}

pub trait DatabaseBuilder<T>
where T: Seek + BufRead,
Self: DatabaseBufReader<T> + DatabaseReader<T> {
    fn try_load_field(&mut self, data: &FDBFieldData) -> BuildResult<Field> {
        let bytes = data.value;
        match ValueType::from(data.data_type) {
            ValueType::Nothing => Ok(Field::Nothing),
            ValueType::Integer => Ok(bytes)
                .map(i32::from_le_bytes)
                .map(Field::Integer),
            ValueType::Float => Ok(bytes)
                .map(u32::from_le_bytes)
                .map(f32::from_bits)
                .map(Field::Float),
            ValueType::Text => Ok(bytes)
                .map(u32::from_le_bytes)
                .and_then(|addr| self.get_string(addr).map_err(BuildError::File))
                .map(Field::Text),
            ValueType::Boolean => Ok(bytes)
                .map(|v| v != [0; 4])
                .map(Field::Boolean),
            ValueType::BigInt => Ok(bytes)
                .map(u32::from_le_bytes)
                .and_then(|addr| self.get_i64(addr).map_err(BuildError::File))
                .map(Field::BigInt),
            ValueType::VarChar => Ok(bytes)
                .map(u32::from_le_bytes)
                .and_then(|addr| self.get_string(addr).map_err(BuildError::File))
                .map(Field::VarChar),
            ValueType::Unknown(k) =>
                Err(BuildError::UnknownType(k))
        }
    }
}