1use std::ptr;
5
6use reifydb_type::value::{duration::Duration, r#type::Type};
7
8use crate::encoded::{row::EncodedRow, schema::RowSchema};
9
10impl RowSchema {
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(), 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: &EncodedRow, 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).expect("stored duration must be valid")
51 }
52 }
53
54 pub fn try_get_duration(&self, row: &EncodedRow, 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::RowSchema;
68
69 #[test]
70 fn test_set_get_duration() {
71 let schema = RowSchema::testing(&[Type::Duration]);
72 let mut row = schema.allocate();
73
74 let value = Duration::from_seconds(-7200).unwrap();
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 = RowSchema::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).unwrap();
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 = RowSchema::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 = RowSchema::testing(&[Type::Duration]);
104
105 let test_durations = [
106 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(), ];
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 = RowSchema::testing(&[Type::Duration]);
125
126 let negative_durations = [
127 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(), ];
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 = RowSchema::testing(&[Type::Duration]);
144 let mut row = schema.allocate();
145
146 let complex_duration = Duration::new(
148 6, 15, 123456789, )
152 .unwrap();
153 schema.set_duration(&mut row, 0, complex_duration.clone());
154 assert_eq!(schema.get_duration(&row, 0), complex_duration);
155 }
156
157 #[test]
158 fn test_mixed_with_other_types() {
159 let schema = RowSchema::testing(&[Type::Duration, Type::Boolean, Type::Duration, Type::Int8]);
160 let mut row = schema.allocate();
161
162 let duration1 = Duration::from_hours(24).unwrap();
163 let duration2 = Duration::from_minutes(-30).unwrap();
164
165 schema.set_duration(&mut row, 0, duration1.clone());
166 schema.set_bool(&mut row, 1, true);
167 schema.set_duration(&mut row, 2, duration2.clone());
168 schema.set_i64(&mut row, 3, 987654321);
169
170 assert_eq!(schema.get_duration(&row, 0), duration1);
171 assert_eq!(schema.get_bool(&row, 1), true);
172 assert_eq!(schema.get_duration(&row, 2), duration2);
173 assert_eq!(schema.get_i64(&row, 3), 987654321);
174 }
175
176 #[test]
177 fn test_undefined_handling() {
178 let schema = RowSchema::testing(&[Type::Duration, Type::Duration]);
179 let mut row = schema.allocate();
180
181 let duration = Duration::from_days(100).unwrap();
182 schema.set_duration(&mut row, 0, duration.clone());
183
184 assert_eq!(schema.try_get_duration(&row, 0), Some(duration));
185 assert_eq!(schema.try_get_duration(&row, 1), None);
186
187 schema.set_none(&mut row, 0);
188 assert_eq!(schema.try_get_duration(&row, 0), None);
189 }
190
191 #[test]
192 fn test_large_values() {
193 let schema = RowSchema::testing(&[Type::Duration]);
194 let mut row = schema.allocate();
195
196 let large_duration = Duration::new(
198 120, 3650, 123456789012345, )
202 .unwrap();
203 schema.set_duration(&mut row, 0, large_duration.clone());
204 assert_eq!(schema.get_duration(&row, 0), large_duration);
205 }
206
207 #[test]
208 fn test_precision_preservation() {
209 let schema = RowSchema::testing(&[Type::Duration]);
210 let mut row = schema.allocate();
211
212 let precise_duration = Duration::new(
214 5, 20, 999999999, )
218 .unwrap();
219 schema.set_duration(&mut row, 0, precise_duration.clone());
220
221 let retrieved = schema.get_duration(&row, 0);
222 assert_eq!(retrieved, precise_duration);
223
224 let orig_months = precise_duration.get_months();
225 let orig_days = precise_duration.get_days();
226 let orig_nanos = precise_duration.get_nanos();
227 let ret_months = retrieved.get_months();
228 let ret_days = retrieved.get_days();
229 let ret_nanos = retrieved.get_nanos();
230 assert_eq!(orig_months, ret_months);
231 assert_eq!(orig_days, ret_days);
232 assert_eq!(orig_nanos, ret_nanos);
233 }
234
235 #[test]
236 fn test_common_durations() {
237 let schema = RowSchema::testing(&[Type::Duration]);
238
239 let common_durations = [
241 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(), ];
251
252 for duration in common_durations {
253 let mut row = schema.allocate();
254 schema.set_duration(&mut row, 0, duration.clone());
255 assert_eq!(schema.get_duration(&row, 0), duration);
256 }
257 }
258
259 #[test]
260 fn test_boundary_values() {
261 let schema = RowSchema::testing(&[Type::Duration]);
262
263 let boundary_durations = [
265 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(), ];
272
273 for duration in boundary_durations {
274 let mut row = schema.allocate();
275 schema.set_duration(&mut row, 0, duration.clone());
276 assert_eq!(schema.get_duration(&row, 0), duration);
277 }
278 }
279
280 #[test]
281 fn test_try_get_duration_wrong_type() {
282 let schema = RowSchema::testing(&[Type::Boolean]);
283 let mut row = schema.allocate();
284
285 schema.set_bool(&mut row, 0, true);
286
287 assert_eq!(schema.try_get_duration(&row, 0), None);
288 }
289}