rgwml 2.0.0

Typed, local-first tabular data library with columnar in-memory storage.
Documentation
use std::collections::BTreeSet;

use crate::error::{Error, Result};

use super::Field;

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Schema {
    fields: Vec<Field>,
}

impl Schema {
    pub fn new(fields: Vec<Field>) -> Result<Self> {
        let mut seen = BTreeSet::new();
        for field in &fields {
            if !seen.insert(field.name.to_string()) {
                return Err(Error::Schema(format!(
                    "duplicate field name: {}",
                    field.name
                )));
            }
        }

        Ok(Self { fields })
    }

    pub fn fields(&self) -> &[Field] {
        &self.fields
    }

    pub fn field(&self, index: usize) -> Option<&Field> {
        self.fields.get(index)
    }

    pub fn index_of(&self, name: &str) -> Option<usize> {
        self.fields
            .iter()
            .position(|field| field.name.as_ref() == name)
    }

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

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

#[cfg(test)]
mod tests {
    use std::sync::Arc;

    use super::Schema;
    use crate::table::{DataType, Field};

    #[test]
    fn rejects_duplicate_field_names() {
        let fields = vec![
            Field::new(Arc::<str>::from("id"), DataType::I64),
            Field::new(Arc::<str>::from("id"), DataType::Utf8),
        ];

        let error = Schema::new(fields).expect_err("duplicate field names should fail");
        assert!(error.to_string().contains("duplicate field name"));
    }
}