clickhouse_native_client/column/
ipv4.rs1use super::{
2 Column,
3 ColumnRef,
4};
5use crate::{
6 types::Type,
7 Error,
8 Result,
9};
10use bytes::BytesMut;
11use std::sync::Arc;
12
13pub struct ColumnIpv4 {
20 type_: Type,
21 data: Arc<super::ColumnUInt32>, }
24
25impl ColumnIpv4 {
26 pub fn new(type_: Type) -> Self {
28 Self { type_, data: Arc::new(super::ColumnUInt32::new()) }
29 }
30
31 pub fn with_data(mut self, data: Vec<u32>) -> Self {
33 self.data =
34 Arc::new(super::ColumnUInt32::from_vec(Type::uint32(), data));
35 self
36 }
37
38 pub fn append_from_string(&mut self, s: &str) -> Result<()> {
46 let parts: Vec<&str> = s.split('.').collect();
47 if parts.len() != 4 {
48 return Err(Error::Protocol(format!(
49 "Invalid IPv4 format: {}",
50 s
51 )));
52 }
53
54 let mut ip: u32 = 0;
55 for (i, part) in parts.iter().enumerate() {
56 let octet = part.parse::<u8>().map_err(|e| {
57 Error::Protocol(format!("Invalid IPv4 octet: {}", e))
58 })?;
59 ip |= (octet as u32) << (24 - i * 8);
61 }
62
63 self.append(ip);
64 Ok(())
65 }
66
67 pub fn append(&mut self, value: u32) {
69 Arc::get_mut(&mut self.data)
70 .expect("Cannot append to shared column")
71 .append(value);
72 }
73
74 pub fn at(&self, index: usize) -> u32 {
76 self.data.at(index)
77 }
78
79 pub fn as_string(&self, index: usize) -> String {
81 let ip = self.data.at(index);
82 format!(
83 "{}.{}.{}.{}",
84 (ip >> 24) & 0xFF,
85 (ip >> 16) & 0xFF,
86 (ip >> 8) & 0xFF,
87 ip & 0xFF
88 )
89 }
90
91 pub fn len(&self) -> usize {
93 self.data.len()
94 }
95
96 pub fn is_empty(&self) -> bool {
98 self.data.is_empty()
99 }
100
101 pub fn data(&self) -> &super::ColumnUInt32 {
103 &self.data
104 }
105}
106
107impl Column for ColumnIpv4 {
108 fn column_type(&self) -> &Type {
109 &self.type_
110 }
111
112 fn size(&self) -> usize {
113 self.data.size()
114 }
115
116 fn clear(&mut self) {
117 Arc::get_mut(&mut self.data)
118 .expect("Cannot clear shared column")
119 .clear();
120 }
121
122 fn reserve(&mut self, new_cap: usize) {
123 Arc::get_mut(&mut self.data)
124 .expect("Cannot reserve on shared column")
125 .reserve(new_cap);
126 }
127
128 fn append_column(&mut self, other: ColumnRef) -> Result<()> {
129 let other =
130 other.as_any().downcast_ref::<ColumnIpv4>().ok_or_else(|| {
131 Error::TypeMismatch {
132 expected: self.type_.name(),
133 actual: other.column_type().name(),
134 }
135 })?;
136
137 Arc::get_mut(&mut self.data)
139 .expect("Cannot append to shared column")
140 .append_column(other.data.clone() as ColumnRef)?;
141 Ok(())
142 }
143
144 fn load_from_buffer(
145 &mut self,
146 buffer: &mut &[u8],
147 rows: usize,
148 ) -> Result<()> {
149 Arc::get_mut(&mut self.data)
151 .expect("Cannot load into shared column")
152 .load_from_buffer(buffer, rows)
153 }
154
155 fn save_to_buffer(&self, buffer: &mut BytesMut) -> Result<()> {
156 self.data.save_to_buffer(buffer)
158 }
159
160 fn clone_empty(&self) -> ColumnRef {
161 Arc::new(ColumnIpv4::new(self.type_.clone()))
162 }
163
164 fn slice(&self, begin: usize, len: usize) -> Result<ColumnRef> {
165 let sliced_data = self.data.slice(begin, len)?;
167
168 Ok(Arc::new(ColumnIpv4 {
169 type_: self.type_.clone(),
170 data: sliced_data
171 .as_any()
172 .downcast_ref::<super::ColumnUInt32>()
173 .map(|col| {
174 Arc::new(super::ColumnUInt32::from_vec(
176 Type::uint32(),
177 col.data().to_vec(),
178 ))
179 })
180 .expect("Slice should return ColumnUInt32"),
181 }))
182 }
183
184 fn as_any(&self) -> &dyn std::any::Any {
185 self
186 }
187
188 fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
189 self
190 }
191}
192
193#[cfg(test)]
194#[cfg_attr(coverage_nightly, coverage(off))]
195mod tests {
196 use super::*;
197
198 #[test]
199 fn test_ipv4_from_string() {
200 let mut col = ColumnIpv4::new(Type::ipv4());
201 col.append_from_string("192.168.1.1").unwrap();
202 col.append_from_string("10.0.0.1").unwrap();
203 col.append_from_string("0.0.0.0").unwrap();
204
205 assert_eq!(col.len(), 3);
206 assert_eq!(col.as_string(0), "192.168.1.1");
207 assert_eq!(col.as_string(1), "10.0.0.1");
208 assert_eq!(col.as_string(2), "0.0.0.0");
209 }
210
211 #[test]
212 fn test_ipv4_from_u32() {
213 let mut col = ColumnIpv4::new(Type::ipv4());
214 col.append(0xC0A80101); col.append(0x0A000001); col.append(0); assert_eq!(col.len(), 3);
219 assert_eq!(col.at(0), 0xC0A80101);
220 assert_eq!(col.at(1), 0x0A000001);
221 assert_eq!(col.at(2), 0);
222 }
223
224 #[test]
225 fn test_ipv4_edge_cases() {
226 let mut col = ColumnIpv4::new(Type::ipv4());
227 col.append_from_string("255.255.255.255").unwrap();
228 col.append_from_string("127.0.0.1").unwrap();
229
230 assert_eq!(col.as_string(0), "255.255.255.255");
231 assert_eq!(col.as_string(1), "127.0.0.1");
232 }
233}