minarrow/structs/column.rs
1// Copyright 2025 Peter Garfield Bower
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! # **Column Module** - *Lazy Column Reference*
16//!
17//! Provides the `Column` type for referencing columns by name without requiring
18//! explicit Field construction. Used for ergonomic column selection APIs.
19//!
20//! # Example
21//! ```rust
22//! use minarrow::{column, Column};
23//!
24//! // Create column references
25//! let col_a = column("employee_id");
26//! let col_b = Column::new("salary");
27//! ```
28
29/// Lazy reference to a column by name
30///
31/// `Column` wraps a string column name and defers resolution until selection time.
32/// This separates user intent ("I want column A") from runtime data (Field with dtype, metadata).
33#[derive(Clone, Debug, PartialEq, Eq, Hash)]
34pub struct Column {
35 name: String,
36}
37
38impl Column {
39 /// Create a new column reference
40 ///
41 /// # Example
42 /// ```rust
43 /// use minarrow::Column;
44 ///
45 /// let col = Column::new("employee_id");
46 /// assert_eq!(col.name(), "employee_id");
47 /// ```
48 pub fn new(name: impl Into<String>) -> Self {
49 Column { name: name.into() }
50 }
51
52 /// Get the column name
53 #[inline]
54 pub fn name(&self) -> &str {
55 &self.name
56 }
57
58 /// Consume and return the column name as a String
59 #[inline]
60 pub fn into_name(self) -> String {
61 self.name
62 }
63}
64
65/// User-facing constructor for column references
66///
67/// # Example
68/// ```rust
69/// use minarrow::column;
70///
71/// let col = column("employee_id");
72/// assert_eq!(col.name(), "employee_id");
73/// ```
74pub fn column(name: impl Into<String>) -> Column {
75 Column::new(name)
76}
77
78impl From<&str> for Column {
79 fn from(name: &str) -> Self {
80 Column::new(name)
81 }
82}
83
84impl From<String> for Column {
85 fn from(name: String) -> Self {
86 Column::new(name)
87 }
88}
89
90impl AsRef<str> for Column {
91 fn as_ref(&self) -> &str {
92 &self.name
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn test_column_creation() {
102 let col_a = column("employee_id");
103 assert_eq!(col_a.name(), "employee_id");
104 }
105
106 #[test]
107 fn test_column_new() {
108 let col = Column::new("salary");
109 assert_eq!(col.name(), "salary");
110 }
111
112 #[test]
113 fn test_column_from_str() {
114 let col_a: Column = "salary".into();
115 assert_eq!(col_a.name(), "salary");
116 }
117
118 #[test]
119 fn test_column_from_string() {
120 let name = String::from("department");
121 let col_a: Column = name.into();
122 assert_eq!(col_a.name(), "department");
123 }
124
125 #[test]
126 fn test_column_into_name() {
127 let col = column("age");
128 let name = col.into_name();
129 assert_eq!(name, "age");
130 }
131
132 #[test]
133 fn test_column_equality() {
134 let col_a = column("id");
135 let col_b = column("id");
136 let col_c = column("name");
137
138 assert_eq!(col_a, col_b);
139 assert_ne!(col_a, col_c);
140 }
141
142 #[test]
143 fn test_column_as_ref() {
144 let col = column("test");
145 let s: &str = col.as_ref();
146 assert_eq!(s, "test");
147 }
148}