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
55
56
57
58
59
60
61
use std::{fs, num::NonZeroU32, ops::Deref, sync::Arc};

use hashbrown::HashMap;
use idx_binary::IdxBinary;

use crate::Data;

pub type Field = IdxBinary;

#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct FieldName(Arc<String>);

impl<T: Into<String>> From<T> for FieldName {
    fn from(value: T) -> Self {
        Self(Arc::new(value.into()))
    }
}

impl Deref for FieldName {
    type Target = Arc<String>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

pub type Fields = HashMap<FieldName, Field>;

impl Data {
    /// Returns the value of the field with the specified name in the specified row as a slice.
    pub fn field_bytes(&self, row: NonZeroU32, name: &FieldName) -> &[u8] {
        self.fields
            .get(name)
            .and_then(|v| v.bytes(row))
            .unwrap_or(b"")
    }

    /// Returns the value of the field with the specified name in the specified row as a number.
    pub fn field_num(&self, row: NonZeroU32, name: &FieldName) -> f64 {
        self.fields
            .get(name)
            .and_then(|v| v.bytes(row))
            .and_then(|v| unsafe { std::str::from_utf8_unchecked(v) }.parse().ok())
            .unwrap_or(0.0)
    }

    pub(crate) fn create_field(&mut self, name: &FieldName) {
        if !self.fields.contains_key(name) {
            let mut fields_dir = self.fields_dir.clone();
            fields_dir.push(name.as_ref().to_string());
            fs::create_dir_all(&fields_dir).unwrap();
            let field = Field::new(fields_dir, self.option.allocation_lot);

            self.fields.insert(name.clone(), field);
        }
    }

    pub fn fields(&self) -> &Fields {
        &self.fields
    }
}