use assembly_core::displaydoc::Display;
use thiserror::Error;
use super::{DatabaseBufReader, DatabaseReader};
use crate::fdb::{
common::{UnknownValueType, ValueType},
core::Field,
file::FDBFieldData,
};
use std::{
convert::TryFrom,
io::{self, BufRead, Seek},
};
#[derive(Debug, Display, Error)]
pub enum BuilderError {
Io(#[from] io::Error),
UnknownValueType(#[from] UnknownValueType),
}
pub type Result<T> = std::result::Result<T, BuilderError>;
impl<T: ?Sized> DatabaseBuilder for T where T: DatabaseBufReader + DatabaseReader + Seek + BufRead {}
pub trait DatabaseBuilder
where
Self: Seek + BufRead + DatabaseBufReader + DatabaseReader,
{
fn try_load_field(&mut self, data: &FDBFieldData) -> Result<Field> {
let bytes = data.value;
match ValueType::try_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(Field::Text)
.map_err(Into::into),
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(Field::BigInt)
.map_err(Into::into),
ValueType::VarChar => Ok(bytes)
.map(u32::from_le_bytes)
.and_then(|addr| self.get_string(addr))
.map(Field::VarChar)
.map_err(Into::into),
}
}
}