1use std::ptr;
5
6use reifydb_type::value::{duration::Duration, r#type::Type};
7
8use crate::encoded::{encoded::EncodedValues, schema::Schema};
9
10impl Schema {
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.constraint.get_type().inner_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(
23 row.make_mut().as_mut_ptr().add(field.offset as usize) as *mut i32,
24 months,
25 );
26 ptr::write_unaligned(
28 row.make_mut().as_mut_ptr().add(field.offset as usize + 4) as *mut i32,
29 days,
30 );
31 ptr::write_unaligned(
33 row.make_mut().as_mut_ptr().add(field.offset as usize + 8) as *mut i64,
34 nanos,
35 );
36 }
37 }
38
39 pub fn get_duration(&self, row: &EncodedValues, index: usize) -> Duration {
40 let field = &self.fields()[index];
41 debug_assert!(row.len() >= self.total_static_size());
42 debug_assert_eq!(*field.constraint.get_type().inner_type(), Type::Duration);
43 unsafe {
44 let months = (row.as_ptr().add(field.offset as usize) as *const i32).read_unaligned();
46 let days = (row.as_ptr().add(field.offset as usize + 4) as *const i32).read_unaligned();
48 let nanos = (row.as_ptr().add(field.offset as usize + 8) as *const i64).read_unaligned();
50 Duration::new(months, days, nanos)
51 }
52 }
53
54 pub fn try_get_duration(&self, row: &EncodedValues, index: usize) -> Option<Duration> {
55 if row.is_defined(index) && self.fields()[index].constraint.get_type() == Type::Duration {
56 Some(self.get_duration(row, index))
57 } else {
58 None
59 }
60 }
61}
62
63#[cfg(test)]
64pub mod tests {
65 use reifydb_type::value::{duration::Duration, r#type::Type};
66
67 use crate::encoded::schema::Schema;
68
69 #[test]
70 fn test_set_get_duration() {
71 let schema = Schema::testing(&[Type::Duration]);
72 let mut row = schema.allocate();
73
74 let value = Duration::from_seconds(-7200);
75 schema.set_duration(&mut row, 0, value.clone());
76 assert_eq!(schema.get_duration(&row, 0), value);
77 }
78
79 #[test]
80 fn test_try_get_duration() {
81 let schema = Schema::testing(&[Type::Duration]);
82 let mut row = schema.allocate();
83
84 assert_eq!(schema.try_get_duration(&row, 0), None);
85
86 let test_duration = Duration::from_days(30);
87 schema.set_duration(&mut row, 0, test_duration.clone());
88 assert_eq!(schema.try_get_duration(&row, 0), Some(test_duration));
89 }
90
91 #[test]
92 fn test_zero() {
93 let schema = Schema::testing(&[Type::Duration]);
94 let mut row = schema.allocate();
95
96 let zero = Duration::default(); schema.set_duration(&mut row, 0, zero.clone());
98 assert_eq!(schema.get_duration(&row, 0), zero);
99 }
100
101 #[test]
102 fn test_various_durations() {
103 let schema = Schema::testing(&[Type::Duration]);
104
105 let test_durations = [
106 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), ];
114
115 for duration in test_durations {
116 let mut row = schema.allocate();
117 schema.set_duration(&mut row, 0, duration.clone());
118 assert_eq!(schema.get_duration(&row, 0), duration);
119 }
120 }
121
122 #[test]
123 fn test_negative_durations() {
124 let schema = Schema::testing(&[Type::Duration]);
125
126 let negative_durations = [
127 Duration::from_seconds(-60), Duration::from_seconds(-3600), Duration::from_seconds(-86400), Duration::from_days(-7), Duration::from_weeks(-4), ];
133
134 for duration in negative_durations {
135 let mut row = schema.allocate();
136 schema.set_duration(&mut row, 0, duration.clone());
137 assert_eq!(schema.get_duration(&row, 0), duration);
138 }
139 }
140
141 #[test]
142 fn test_complex_parts() {
143 let schema = Schema::testing(&[Type::Duration]);
144 let mut row = schema.allocate();
145
146 let complex_duration = Duration::new(
148 6, 15, 123456789, );
152 schema.set_duration(&mut row, 0, complex_duration.clone());
153 assert_eq!(schema.get_duration(&row, 0), complex_duration);
154 }
155
156 #[test]
157 fn test_mixed_with_other_types() {
158 let schema = Schema::testing(&[Type::Duration, Type::Boolean, Type::Duration, Type::Int8]);
159 let mut row = schema.allocate();
160
161 let duration1 = Duration::from_hours(24);
162 let duration2 = Duration::from_minutes(-30);
163
164 schema.set_duration(&mut row, 0, duration1.clone());
165 schema.set_bool(&mut row, 1, true);
166 schema.set_duration(&mut row, 2, duration2.clone());
167 schema.set_i64(&mut row, 3, 987654321);
168
169 assert_eq!(schema.get_duration(&row, 0), duration1);
170 assert_eq!(schema.get_bool(&row, 1), true);
171 assert_eq!(schema.get_duration(&row, 2), duration2);
172 assert_eq!(schema.get_i64(&row, 3), 987654321);
173 }
174
175 #[test]
176 fn test_undefined_handling() {
177 let schema = Schema::testing(&[Type::Duration, Type::Duration]);
178 let mut row = schema.allocate();
179
180 let duration = Duration::from_days(100);
181 schema.set_duration(&mut row, 0, duration.clone());
182
183 assert_eq!(schema.try_get_duration(&row, 0), Some(duration));
184 assert_eq!(schema.try_get_duration(&row, 1), None);
185
186 schema.set_none(&mut row, 0);
187 assert_eq!(schema.try_get_duration(&row, 0), None);
188 }
189
190 #[test]
191 fn test_large_values() {
192 let schema = Schema::testing(&[Type::Duration]);
193 let mut row = schema.allocate();
194
195 let large_duration = Duration::new(
197 120, 3650, 123456789012345, );
201 schema.set_duration(&mut row, 0, large_duration.clone());
202 assert_eq!(schema.get_duration(&row, 0), large_duration);
203 }
204
205 #[test]
206 fn test_precision_preservation() {
207 let schema = Schema::testing(&[Type::Duration]);
208 let mut row = schema.allocate();
209
210 let precise_duration = Duration::new(
212 -5, 20, 999999999, );
216 schema.set_duration(&mut row, 0, precise_duration.clone());
217
218 let retrieved = schema.get_duration(&row, 0);
219 assert_eq!(retrieved, precise_duration);
220
221 let orig_months = precise_duration.get_months();
222 let orig_days = precise_duration.get_days();
223 let orig_nanos = precise_duration.get_nanos();
224 let ret_months = retrieved.get_months();
225 let ret_days = retrieved.get_days();
226 let ret_nanos = retrieved.get_nanos();
227 assert_eq!(orig_months, ret_months);
228 assert_eq!(orig_days, ret_days);
229 assert_eq!(orig_nanos, ret_nanos);
230 }
231
232 #[test]
233 fn test_common_durations() {
234 let schema = Schema::testing(&[Type::Duration]);
235
236 let common_durations = [
238 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), ];
248
249 for duration in common_durations {
250 let mut row = schema.allocate();
251 schema.set_duration(&mut row, 0, duration.clone());
252 assert_eq!(schema.get_duration(&row, 0), duration);
253 }
254 }
255
256 #[test]
257 fn test_boundary_values() {
258 let schema = Schema::testing(&[Type::Duration]);
259
260 let boundary_durations = [
262 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), ];
269
270 for duration in boundary_durations {
271 let mut row = schema.allocate();
272 schema.set_duration(&mut row, 0, duration.clone());
273 assert_eq!(schema.get_duration(&row, 0), duration);
274 }
275 }
276
277 #[test]
278 fn test_try_get_duration_wrong_type() {
279 let schema = Schema::testing(&[Type::Boolean]);
280 let mut row = schema.allocate();
281
282 schema.set_bool(&mut row, 0, true);
283
284 assert_eq!(schema.try_get_duration(&row, 0), None);
285 }
286}