reifydb_core/value/encoded/
duration.rs1use std::ptr;
5
6use reifydb_type::{Duration, Type};
7
8use crate::value::encoded::{EncodedValues, EncodedValuesLayout};
9
10impl EncodedValuesLayout {
11 pub fn set_duration(&self, row: &mut EncodedValues, index: usize, value: Duration) {
12 let field = &self.fields[index];
13 debug_assert!(row.len() >= self.total_static_size());
14 debug_assert_eq!(field.r#type, Type::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(row.make_mut().as_mut_ptr().add(field.offset) as *mut i32, months);
23 ptr::write_unaligned(row.make_mut().as_mut_ptr().add(field.offset + 4) as *mut i32, days);
25 ptr::write_unaligned(row.make_mut().as_mut_ptr().add(field.offset + 8) as *mut i64, nanos);
27 }
28 }
29
30 pub fn get_duration(&self, row: &EncodedValues, index: usize) -> Duration {
31 let field = &self.fields[index];
32 debug_assert!(row.len() >= self.total_static_size());
33 debug_assert_eq!(field.r#type, Type::Duration);
34 unsafe {
35 let months = (row.as_ptr().add(field.offset) as *const i32).read_unaligned();
37 let days = (row.as_ptr().add(field.offset + 4) as *const i32).read_unaligned();
39 let nanos = (row.as_ptr().add(field.offset + 8) as *const i64).read_unaligned();
41 Duration::new(months, days, nanos)
42 }
43 }
44
45 pub fn try_get_duration(&self, row: &EncodedValues, index: usize) -> Option<Duration> {
46 if row.is_defined(index) && self.fields[index].r#type == Type::Duration {
47 Some(self.get_duration(row, index))
48 } else {
49 None
50 }
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use reifydb_type::{Duration, Type};
57
58 use crate::value::encoded::EncodedValuesLayout;
59
60 #[test]
61 fn test_set_get_duration() {
62 let layout = EncodedValuesLayout::new(&[Type::Duration]);
63 let mut row = layout.allocate();
64
65 let value = Duration::from_seconds(-7200);
66 layout.set_duration(&mut row, 0, value.clone());
67 assert_eq!(layout.get_duration(&row, 0), value);
68 }
69
70 #[test]
71 fn test_try_get_duration() {
72 let layout = EncodedValuesLayout::new(&[Type::Duration]);
73 let mut row = layout.allocate();
74
75 assert_eq!(layout.try_get_duration(&row, 0), None);
76
77 let test_duration = Duration::from_days(30);
78 layout.set_duration(&mut row, 0, test_duration.clone());
79 assert_eq!(layout.try_get_duration(&row, 0), Some(test_duration));
80 }
81
82 #[test]
83 fn test_zero() {
84 let layout = EncodedValuesLayout::new(&[Type::Duration]);
85 let mut row = layout.allocate();
86
87 let zero = Duration::default(); layout.set_duration(&mut row, 0, zero.clone());
89 assert_eq!(layout.get_duration(&row, 0), zero);
90 }
91
92 #[test]
93 fn test_various_durations() {
94 let layout = EncodedValuesLayout::new(&[Type::Duration]);
95
96 let test_durations = [
97 Duration::from_seconds(0), Duration::from_seconds(60), Duration::from_seconds(3600), Duration::from_seconds(86400), Duration::from_days(7), Duration::from_days(30), Duration::from_weeks(52), ];
105
106 for duration in test_durations {
107 let mut row = layout.allocate();
108 layout.set_duration(&mut row, 0, duration.clone());
109 assert_eq!(layout.get_duration(&row, 0), duration);
110 }
111 }
112
113 #[test]
114 fn test_negative_durations() {
115 let layout = EncodedValuesLayout::new(&[Type::Duration]);
116
117 let negative_durations = [
118 Duration::from_seconds(-60), Duration::from_seconds(-3600), Duration::from_seconds(-86400), Duration::from_days(-7), Duration::from_weeks(-4), ];
124
125 for duration in negative_durations {
126 let mut row = layout.allocate();
127 layout.set_duration(&mut row, 0, duration.clone());
128 assert_eq!(layout.get_duration(&row, 0), duration);
129 }
130 }
131
132 #[test]
133 fn test_complex_parts() {
134 let layout = EncodedValuesLayout::new(&[Type::Duration]);
135 let mut row = layout.allocate();
136
137 let complex_duration = Duration::new(
139 6, 15, 123456789, );
143 layout.set_duration(&mut row, 0, complex_duration.clone());
144 assert_eq!(layout.get_duration(&row, 0), complex_duration);
145 }
146
147 #[test]
148 fn test_mixed_with_other_types() {
149 let layout = EncodedValuesLayout::new(&[Type::Duration, Type::Boolean, Type::Duration, Type::Int8]);
150 let mut row = layout.allocate();
151
152 let duration1 = Duration::from_hours(24);
153 let duration2 = Duration::from_minutes(-30);
154
155 layout.set_duration(&mut row, 0, duration1.clone());
156 layout.set_bool(&mut row, 1, true);
157 layout.set_duration(&mut row, 2, duration2.clone());
158 layout.set_i64(&mut row, 3, 987654321);
159
160 assert_eq!(layout.get_duration(&row, 0), duration1);
161 assert_eq!(layout.get_bool(&row, 1), true);
162 assert_eq!(layout.get_duration(&row, 2), duration2);
163 assert_eq!(layout.get_i64(&row, 3), 987654321);
164 }
165
166 #[test]
167 fn test_undefined_handling() {
168 let layout = EncodedValuesLayout::new(&[Type::Duration, Type::Duration]);
169 let mut row = layout.allocate();
170
171 let duration = Duration::from_days(100);
172 layout.set_duration(&mut row, 0, duration.clone());
173
174 assert_eq!(layout.try_get_duration(&row, 0), Some(duration));
175 assert_eq!(layout.try_get_duration(&row, 1), None);
176
177 layout.set_undefined(&mut row, 0);
178 assert_eq!(layout.try_get_duration(&row, 0), None);
179 }
180
181 #[test]
182 fn test_large_values() {
183 let layout = EncodedValuesLayout::new(&[Type::Duration]);
184 let mut row = layout.allocate();
185
186 let large_duration = Duration::new(
188 120, 3650, 123456789012345, );
192 layout.set_duration(&mut row, 0, large_duration.clone());
193 assert_eq!(layout.get_duration(&row, 0), large_duration);
194 }
195
196 #[test]
197 fn test_precision_preservation() {
198 let layout = EncodedValuesLayout::new(&[Type::Duration]);
199 let mut row = layout.allocate();
200
201 let precise_duration = Duration::new(
203 -5, 20, 999999999, );
207 layout.set_duration(&mut row, 0, precise_duration.clone());
208
209 let retrieved = layout.get_duration(&row, 0);
210 assert_eq!(retrieved, precise_duration);
211
212 let orig_months = precise_duration.get_months();
213 let orig_days = precise_duration.get_days();
214 let orig_nanos = precise_duration.get_nanos();
215 let ret_months = retrieved.get_months();
216 let ret_days = retrieved.get_days();
217 let ret_nanos = retrieved.get_nanos();
218 assert_eq!(orig_months, ret_months);
219 assert_eq!(orig_days, ret_days);
220 assert_eq!(orig_nanos, ret_nanos);
221 }
222
223 #[test]
224 fn test_common_durations() {
225 let layout = EncodedValuesLayout::new(&[Type::Duration]);
226
227 let common_durations = [
229 Duration::from_seconds(1), Duration::from_seconds(30), Duration::from_minutes(5), Duration::from_minutes(15), Duration::from_hours(1), Duration::from_hours(8), Duration::from_days(1), Duration::from_weeks(1), Duration::from_weeks(2), ];
239
240 for duration in common_durations {
241 let mut row = layout.allocate();
242 layout.set_duration(&mut row, 0, duration.clone());
243 assert_eq!(layout.get_duration(&row, 0), duration);
244 }
245 }
246
247 #[test]
248 fn test_boundary_values() {
249 let layout = EncodedValuesLayout::new(&[Type::Duration]);
250
251 let boundary_durations = [
253 Duration::new(i32::MAX, 0, 0), Duration::new(i32::MIN, 0, 0), Duration::new(0, i32::MAX, 0), Duration::new(0, i32::MIN, 0), Duration::new(0, 0, i64::MAX), Duration::new(0, 0, i64::MIN), ];
260
261 for duration in boundary_durations {
262 let mut row = layout.allocate();
263 layout.set_duration(&mut row, 0, duration.clone());
264 assert_eq!(layout.get_duration(&row, 0), duration);
265 }
266 }
267
268 #[test]
269 fn test_try_get_duration_wrong_type() {
270 let layout = EncodedValuesLayout::new(&[Type::Boolean]);
271 let mut row = layout.allocate();
272
273 layout.set_bool(&mut row, 0, true);
274
275 assert_eq!(layout.try_get_duration(&row, 0), None);
276 }
277}