1use std::ptr;
5
6use reifydb_value::{
7 reifydb_assertions,
8 value::{time::Time, value_type::ValueType},
9};
10
11use crate::encoded::{row::EncodedRow, shape::RowShape};
12
13impl RowShape {
14 pub fn set_time(&self, row: &mut EncodedRow, index: usize, value: Time) {
15 let field = &self.fields()[index];
16 reifydb_assertions! {
17 assert!(
18 row.len() >= self.total_static_size(),
19 "row/shape size mismatch: row.len()={} < total_static_size()={}",
20 row.len(),
21 self.total_static_size()
22 );
23 assert_eq!(*field.constraint.get_type().inner_type(), ValueType::Time);
24 }
25 row.set_valid(index, true);
26 unsafe {
27 ptr::write_unaligned(
28 row.make_mut().as_mut_ptr().add(field.offset as usize) as *mut u64,
29 value.to_nanos_since_midnight(),
30 )
31 }
32 }
33
34 pub fn get_time(&self, row: &EncodedRow, index: usize) -> Time {
35 let field = &self.fields()[index];
36 reifydb_assertions! {
37 assert!(
38 row.len() >= self.total_static_size(),
39 "row/shape size mismatch: row.len()={} < total_static_size()={}",
40 row.len(),
41 self.total_static_size()
42 );
43 assert_eq!(*field.constraint.get_type().inner_type(), ValueType::Time);
44 }
45 unsafe {
46 Time::from_nanos_since_midnight(
47 (row.as_ptr().add(field.offset as usize) as *const u64).read_unaligned(),
48 )
49 .unwrap()
50 }
51 }
52
53 pub fn try_get_time(&self, row: &EncodedRow, index: usize) -> Option<Time> {
54 if row.is_defined(index) && self.fields()[index].constraint.get_type() == ValueType::Time {
55 Some(self.get_time(row, index))
56 } else {
57 None
58 }
59 }
60}
61
62#[cfg(test)]
63pub mod tests {
64 use reifydb_value::value::{time::Time, value_type::ValueType};
65
66 use crate::encoded::shape::RowShape;
67
68 #[test]
69 fn test_set_get_time() {
70 let shape = RowShape::testing(&[ValueType::Time]);
71 let mut row = shape.allocate();
72
73 let value = Time::new(20, 50, 0, 0).unwrap();
74 shape.set_time(&mut row, 0, value.clone());
75 assert_eq!(shape.get_time(&row, 0), value);
76 }
77
78 #[test]
79 fn test_try_get_time() {
80 let shape = RowShape::testing(&[ValueType::Time]);
81 let mut row = shape.allocate();
82
83 assert_eq!(shape.try_get_time(&row, 0), None);
84
85 let test_time = Time::from_hms(14, 30, 45).unwrap();
86 shape.set_time(&mut row, 0, test_time.clone());
87 assert_eq!(shape.try_get_time(&row, 0), Some(test_time));
88 }
89
90 #[test]
91 fn test_time_midnight() {
92 let shape = RowShape::testing(&[ValueType::Time]);
93 let mut row = shape.allocate();
94
95 let midnight = Time::default(); shape.set_time(&mut row, 0, midnight.clone());
97 assert_eq!(shape.get_time(&row, 0), midnight);
98 }
99
100 #[test]
101 fn test_time_with_nanoseconds() {
102 let shape = RowShape::testing(&[ValueType::Time]);
103 let mut row = shape.allocate();
104
105 let precise_time = Time::new(15, 30, 45, 123456789).unwrap();
107 shape.set_time(&mut row, 0, precise_time.clone());
108 assert_eq!(shape.get_time(&row, 0), precise_time);
109 }
110
111 #[test]
112 fn test_time_various_times() {
113 let shape = RowShape::testing(&[ValueType::Time]);
114
115 let test_times = [
116 Time::new(0, 0, 0, 0).unwrap(), Time::new(12, 0, 0, 0).unwrap(), Time::new(23, 59, 59, 999999999).unwrap(), Time::new(6, 30, 15, 500000000).unwrap(), Time::new(18, 45, 30, 750000000).unwrap(), ];
122
123 for time in test_times {
124 let mut row = shape.allocate();
125 shape.set_time(&mut row, 0, time.clone());
126 assert_eq!(shape.get_time(&row, 0), time);
127 }
128 }
129
130 #[test]
131 fn test_time_boundary_cases() {
132 let shape = RowShape::testing(&[ValueType::Time]);
133
134 let boundary_times = [
135 Time::new(0, 0, 0, 0).unwrap(), Time::new(0, 0, 0, 1).unwrap(), Time::new(23, 59, 59, 999999998).unwrap(), Time::new(23, 59, 59, 999999999).unwrap(), ];
141
142 for time in boundary_times {
143 let mut row = shape.allocate();
144 shape.set_time(&mut row, 0, time.clone());
145 assert_eq!(shape.get_time(&row, 0), time);
146 }
147 }
148
149 #[test]
150 fn test_time_mixed_with_other_types() {
151 let shape = RowShape::testing(&[ValueType::Time, ValueType::Boolean, ValueType::Time, ValueType::Int4]);
152 let mut row = shape.allocate();
153
154 let time1 = Time::new(9, 15, 30, 0).unwrap();
155 let time2 = Time::new(21, 45, 0, 250000000).unwrap();
156
157 shape.set_time(&mut row, 0, time1.clone());
158 shape.set_bool(&mut row, 1, false);
159 shape.set_time(&mut row, 2, time2.clone());
160 shape.set_i32(&mut row, 3, -999);
161
162 assert_eq!(shape.get_time(&row, 0), time1);
163 assert_eq!(shape.get_bool(&row, 1), false);
164 assert_eq!(shape.get_time(&row, 2), time2);
165 assert_eq!(shape.get_i32(&row, 3), -999);
166 }
167
168 #[test]
169 fn test_time_undefined_handling() {
170 let shape = RowShape::testing(&[ValueType::Time, ValueType::Time]);
171 let mut row = shape.allocate();
172
173 let time = Time::new(16, 20, 45, 333000000).unwrap();
174 shape.set_time(&mut row, 0, time.clone());
175
176 assert_eq!(shape.try_get_time(&row, 0), Some(time));
177 assert_eq!(shape.try_get_time(&row, 1), None);
178
179 shape.set_none(&mut row, 0);
180 assert_eq!(shape.try_get_time(&row, 0), None);
181 }
182
183 #[test]
184 fn test_time_precision_preservation() {
185 let shape = RowShape::testing(&[ValueType::Time]);
186 let mut row = shape.allocate();
187
188 let high_precision = Time::new(12, 34, 56, 987654321).unwrap();
190 shape.set_time(&mut row, 0, high_precision.clone());
191
192 let retrieved = shape.get_time(&row, 0);
193 assert_eq!(retrieved, high_precision);
194 assert_eq!(retrieved.to_nanos_since_midnight(), high_precision.to_nanos_since_midnight());
195 }
196
197 #[test]
198 fn test_time_microsecond_precision() {
199 let shape = RowShape::testing(&[ValueType::Time]);
200 let mut row = shape.allocate();
201
202 let microsecond_precision = Time::new(14, 25, 30, 123456000).unwrap();
204 shape.set_time(&mut row, 0, microsecond_precision.clone());
205 assert_eq!(shape.get_time(&row, 0), microsecond_precision);
206 }
207
208 #[test]
209 fn test_time_millisecond_precision() {
210 let shape = RowShape::testing(&[ValueType::Time]);
211 let mut row = shape.allocate();
212
213 let millisecond_precision = Time::new(8, 15, 42, 123000000).unwrap();
215 shape.set_time(&mut row, 0, millisecond_precision.clone());
216 assert_eq!(shape.get_time(&row, 0), millisecond_precision);
217 }
218
219 #[test]
220 fn test_time_common_times() {
221 let shape = RowShape::testing(&[ValueType::Time]);
222
223 let common_times = [
225 Time::new(9, 0, 0, 0).unwrap(), Time::new(12, 0, 0, 0).unwrap(), Time::new(17, 0, 0, 0).unwrap(), Time::new(0, 0, 1, 0).unwrap(), Time::new(23, 59, 0, 0).unwrap(), ];
231
232 for time in common_times {
233 let mut row = shape.allocate();
234 shape.set_time(&mut row, 0, time.clone());
235 assert_eq!(shape.get_time(&row, 0), time);
236 }
237 }
238
239 #[test]
240 fn test_try_get_time_wrong_type() {
241 let shape = RowShape::testing(&[ValueType::Boolean]);
242 let mut row = shape.allocate();
243
244 shape.set_bool(&mut row, 0, true);
245
246 assert_eq!(shape.try_get_time(&row, 0), None);
247 }
248}