Skip to main content

nexcore_dataframe/
schema.rs

1//! Schema: column name → DataType mapping.
2
3use crate::DataType;
4
5/// Describes the structure of a DataFrame: ordered list of (name, type) pairs.
6#[derive(Debug, Clone, PartialEq)]
7pub struct Schema {
8    fields: Vec<(String, DataType)>,
9}
10
11impl Schema {
12    /// Create a new schema from field definitions.
13    #[must_use]
14    pub fn new(fields: Vec<(String, DataType)>) -> Self {
15        Self { fields }
16    }
17
18    /// Number of columns.
19    #[must_use]
20    pub fn len(&self) -> usize {
21        self.fields.len()
22    }
23
24    /// Whether the schema has no fields.
25    #[must_use]
26    pub fn is_empty(&self) -> bool {
27        self.fields.is_empty()
28    }
29
30    /// Get field names.
31    pub fn names(&self) -> impl Iterator<Item = &str> {
32        self.fields.iter().map(|(name, _)| name.as_str())
33    }
34
35    /// Get the data type for a named column.
36    #[must_use]
37    pub fn dtype(&self, name: &str) -> Option<DataType> {
38        self.fields
39            .iter()
40            .find(|(n, _)| n == name)
41            .map(|(_, dt)| *dt)
42    }
43
44    /// Get all fields as slice.
45    #[must_use]
46    pub fn fields(&self) -> &[(String, DataType)] {
47        &self.fields
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn schema_basics() {
57        let s = Schema::new(vec![
58            ("a".into(), DataType::Int64),
59            ("b".into(), DataType::Utf8),
60        ]);
61        assert_eq!(s.len(), 2);
62        assert!(!s.is_empty());
63        assert_eq!(s.dtype("a"), Some(DataType::Int64));
64        assert_eq!(s.dtype("b"), Some(DataType::Utf8));
65        assert_eq!(s.dtype("c"), None);
66    }
67}