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"));
}
}