1use std::ptr;
5
6use reifydb_value::value::{duration::Duration, value_type::ValueType};
7
8use crate::encoded::{row::EncodedRow, shape::RowShape};
9
10impl RowShape {
11 pub fn set_duration(&self, row: &mut EncodedRow, index: usize, value: Duration) {
12 let field = &self.fields()[index];
13 debug_assert!(row.len() >= self.total_static_size());
14 debug_assert_eq!(*field.constraint.get_type().inner_type(), ValueType::Duration);
15 row.set_valid(index, true);
16
17 let months = value.get_months();
18 let days = value.get_days();
19 let nanos = value.get_nanos();
20 unsafe {
21 ptr::write_unaligned(
22 row.make_mut().as_mut_ptr().add(field.offset as usize) as *mut i32,
23 months,
24 );
25
26 ptr::write_unaligned(
27 row.make_mut().as_mut_ptr().add(field.offset as usize + 4) as *mut i32,
28 days,
29 );
30
31 ptr::write_unaligned(
32 row.make_mut().as_mut_ptr().add(field.offset as usize + 8) as *mut i64,
33 nanos,
34 );
35 }
36 }
37
38 pub fn get_duration(&self, row: &EncodedRow, index: usize) -> Duration {
39 let field = &self.fields()[index];
40 debug_assert!(row.len() >= self.total_static_size());
41 debug_assert_eq!(*field.constraint.get_type().inner_type(), ValueType::Duration);
42 unsafe {
43 let months = (row.as_ptr().add(field.offset as usize) as *const i32).read_unaligned();
44
45 let days = (row.as_ptr().add(field.offset as usize + 4) as *const i32).read_unaligned();
46
47 let nanos = (row.as_ptr().add(field.offset as usize + 8) as *const i64).read_unaligned();
48 Duration::new(months, days, nanos).expect("stored duration must be valid")
49 }
50 }
51
52 pub fn try_get_duration(&self, row: &EncodedRow, index: usize) -> Option<Duration> {
53 if row.is_defined(index) && self.fields()[index].constraint.get_type() == ValueType::Duration {
54 Some(self.get_duration(row, index))
55 } else {
56 None
57 }
58 }
59}
60
61#[cfg(test)]
62pub mod tests {
63 use reifydb_value::value::{duration::Duration, value_type::ValueType};
64
65 use crate::encoded::shape::RowShape;
66
67 #[test]
68 fn test_set_get_duration() {
69 let shape = RowShape::testing(&[ValueType::Duration]);
70 let mut row = shape.allocate();
71
72 let value = Duration::from_seconds(-7200).unwrap();
73 shape.set_duration(&mut row, 0, value.clone());
74 assert_eq!(shape.get_duration(&row, 0), value);
75 }
76
77 #[test]
78 fn test_try_get_duration() {
79 let shape = RowShape::testing(&[ValueType::Duration]);
80 let mut row = shape.allocate();
81
82 assert_eq!(shape.try_get_duration(&row, 0), None);
83
84 let test_duration = Duration::from_days(30).unwrap();
85 shape.set_duration(&mut row, 0, test_duration.clone());
86 assert_eq!(shape.try_get_duration(&row, 0), Some(test_duration));
87 }
88
89 #[test]
90 fn test_zero() {
91 let shape = RowShape::testing(&[ValueType::Duration]);
92 let mut row = shape.allocate();
93
94 let zero = Duration::default(); shape.set_duration(&mut row, 0, zero.clone());
96 assert_eq!(shape.get_duration(&row, 0), zero);
97 }
98
99 #[test]
100 fn test_various_durations() {
101 let shape = RowShape::testing(&[ValueType::Duration]);
102
103 let test_durations = [
104 Duration::from_seconds(0).unwrap(), Duration::from_seconds(60).unwrap(), Duration::from_seconds(3600).unwrap(), Duration::from_seconds(86400).unwrap(), Duration::from_days(7).unwrap(), Duration::from_days(30).unwrap(), Duration::from_weeks(52).unwrap(), ];
112
113 for duration in test_durations {
114 let mut row = shape.allocate();
115 shape.set_duration(&mut row, 0, duration.clone());
116 assert_eq!(shape.get_duration(&row, 0), duration);
117 }
118 }
119
120 #[test]
121 fn test_negative_durations() {
122 let shape = RowShape::testing(&[ValueType::Duration]);
123
124 let negative_durations = [
125 Duration::from_seconds(-60).unwrap(), Duration::from_seconds(-3600).unwrap(), Duration::from_seconds(-86400).unwrap(), Duration::from_days(-7).unwrap(), Duration::from_weeks(-4).unwrap(), ];
131
132 for duration in negative_durations {
133 let mut row = shape.allocate();
134 shape.set_duration(&mut row, 0, duration.clone());
135 assert_eq!(shape.get_duration(&row, 0), duration);
136 }
137 }
138
139 #[test]
140 fn test_complex_parts() {
141 let shape = RowShape::testing(&[ValueType::Duration]);
142 let mut row = shape.allocate();
143
144 let complex_duration = Duration::new(
146 6, 15, 123456789, )
150 .unwrap();
151 shape.set_duration(&mut row, 0, complex_duration.clone());
152 assert_eq!(shape.get_duration(&row, 0), complex_duration);
153 }
154
155 #[test]
156 fn test_mixed_with_other_types() {
157 let shape = RowShape::testing(&[
158 ValueType::Duration,
159 ValueType::Boolean,
160 ValueType::Duration,
161 ValueType::Int8,
162 ]);
163 let mut row = shape.allocate();
164
165 let duration1 = Duration::from_hours(24).unwrap();
166 let duration2 = Duration::from_minutes(-30).unwrap();
167
168 shape.set_duration(&mut row, 0, duration1.clone());
169 shape.set_bool(&mut row, 1, true);
170 shape.set_duration(&mut row, 2, duration2.clone());
171 shape.set_i64(&mut row, 3, 987654321);
172
173 assert_eq!(shape.get_duration(&row, 0), duration1);
174 assert_eq!(shape.get_bool(&row, 1), true);
175 assert_eq!(shape.get_duration(&row, 2), duration2);
176 assert_eq!(shape.get_i64(&row, 3), 987654321);
177 }
178
179 #[test]
180 fn test_undefined_handling() {
181 let shape = RowShape::testing(&[ValueType::Duration, ValueType::Duration]);
182 let mut row = shape.allocate();
183
184 let duration = Duration::from_days(100).unwrap();
185 shape.set_duration(&mut row, 0, duration.clone());
186
187 assert_eq!(shape.try_get_duration(&row, 0), Some(duration));
188 assert_eq!(shape.try_get_duration(&row, 1), None);
189
190 shape.set_none(&mut row, 0);
191 assert_eq!(shape.try_get_duration(&row, 0), None);
192 }
193
194 #[test]
195 fn test_large_values() {
196 let shape = RowShape::testing(&[ValueType::Duration]);
197 let mut row = shape.allocate();
198
199 let large_duration = Duration::new(
201 120, 3650, 123456789012345, )
205 .unwrap();
206 shape.set_duration(&mut row, 0, large_duration.clone());
207 assert_eq!(shape.get_duration(&row, 0), large_duration);
208 }
209
210 #[test]
211 fn test_precision_preservation() {
212 let shape = RowShape::testing(&[ValueType::Duration]);
213 let mut row = shape.allocate();
214
215 let precise_duration = Duration::new(
217 5, 20, 999999999, )
221 .unwrap();
222 shape.set_duration(&mut row, 0, precise_duration.clone());
223
224 let retrieved = shape.get_duration(&row, 0);
225 assert_eq!(retrieved, precise_duration);
226
227 let orig_months = precise_duration.get_months();
228 let orig_days = precise_duration.get_days();
229 let orig_nanos = precise_duration.get_nanos();
230 let ret_months = retrieved.get_months();
231 let ret_days = retrieved.get_days();
232 let ret_nanos = retrieved.get_nanos();
233 assert_eq!(orig_months, ret_months);
234 assert_eq!(orig_days, ret_days);
235 assert_eq!(orig_nanos, ret_nanos);
236 }
237
238 #[test]
239 fn test_common_durations() {
240 let shape = RowShape::testing(&[ValueType::Duration]);
241
242 let common_durations = [
244 Duration::from_seconds(1).unwrap(), Duration::from_seconds(30).unwrap(), Duration::from_minutes(5).unwrap(), Duration::from_minutes(15).unwrap(), Duration::from_hours(1).unwrap(), Duration::from_hours(8).unwrap(), Duration::from_days(1).unwrap(), Duration::from_weeks(1).unwrap(), Duration::from_weeks(2).unwrap(), ];
254
255 for duration in common_durations {
256 let mut row = shape.allocate();
257 shape.set_duration(&mut row, 0, duration.clone());
258 assert_eq!(shape.get_duration(&row, 0), duration);
259 }
260 }
261
262 #[test]
263 fn test_boundary_values() {
264 let shape = RowShape::testing(&[ValueType::Duration]);
265
266 let boundary_durations = [
268 Duration::new(i32::MAX, 0, 0).unwrap(), Duration::new(i32::MIN, 0, 0).unwrap(), Duration::new(0, i32::MAX, 0).unwrap(), Duration::new(0, i32::MIN, 0).unwrap(), Duration::new(0, 0, i64::MAX).unwrap(), Duration::new(0, 0, i64::MIN).unwrap(), ];
275
276 for duration in boundary_durations {
277 let mut row = shape.allocate();
278 shape.set_duration(&mut row, 0, duration.clone());
279 assert_eq!(shape.get_duration(&row, 0), duration);
280 }
281 }
282
283 #[test]
284 fn test_try_get_duration_wrong_type() {
285 let shape = RowShape::testing(&[ValueType::Boolean]);
286 let mut row = shape.allocate();
287
288 shape.set_bool(&mut row, 0, true);
289
290 assert_eq!(shape.try_get_duration(&row, 0), None);
291 }
292}