reifydb_core/value/container/
temporal.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the AGPL-3.0-or-later, see license.md file
3
4use std::{any::TypeId, fmt::Debug, mem::transmute_copy, ops::Deref};
5
6use reifydb_type::{Date, DateTime, Duration, IsTemporal, Time, Value};
7use serde::{Deserialize, Serialize};
8
9use crate::{BitVec, CowVec};
10
11#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
12pub struct TemporalContainer<T>
13where
14	T: IsTemporal,
15{
16	data: CowVec<T>,
17	bitvec: BitVec,
18}
19
20impl<T> Deref for TemporalContainer<T>
21where
22	T: IsTemporal,
23{
24	type Target = [T];
25
26	fn deref(&self) -> &Self::Target {
27		self.data.as_slice()
28	}
29}
30
31impl<T> TemporalContainer<T>
32where
33	T: IsTemporal + Clone + Debug + Default,
34{
35	pub fn new(data: Vec<T>, bitvec: BitVec) -> Self {
36		debug_assert_eq!(data.len(), bitvec.len());
37		Self {
38			data: CowVec::new(data),
39			bitvec,
40		}
41	}
42
43	pub fn with_capacity(capacity: usize) -> Self {
44		Self {
45			data: CowVec::with_capacity(capacity),
46			bitvec: BitVec::with_capacity(capacity),
47		}
48	}
49
50	pub fn from_vec(data: Vec<T>) -> Self {
51		let len = data.len();
52		Self {
53			data: CowVec::new(data),
54			bitvec: BitVec::repeat(len, true),
55		}
56	}
57
58	pub fn len(&self) -> usize {
59		debug_assert_eq!(self.data.len(), self.bitvec.len());
60		self.data.len()
61	}
62
63	pub fn capacity(&self) -> usize {
64		debug_assert!(self.data.capacity() >= self.bitvec.capacity());
65		self.data.capacity().min(self.bitvec.capacity())
66	}
67
68	pub fn is_empty(&self) -> bool {
69		self.data.is_empty()
70	}
71
72	pub fn push(&mut self, value: T) {
73		self.data.push(value);
74		self.bitvec.push(true);
75	}
76
77	pub fn push_undefined(&mut self) {
78		self.data.push(T::default());
79		self.bitvec.push(false);
80	}
81
82	pub fn get(&self, index: usize) -> Option<&T> {
83		if index < self.len() && self.is_defined(index) {
84			self.data.get(index)
85		} else {
86			None
87		}
88	}
89
90	pub fn bitvec(&self) -> &BitVec {
91		&self.bitvec
92	}
93
94	pub fn bitvec_mut(&mut self) -> &mut BitVec {
95		&mut self.bitvec
96	}
97
98	pub fn is_defined(&self, idx: usize) -> bool {
99		idx < self.len() && self.bitvec.get(idx)
100	}
101
102	pub fn is_fully_defined(&self) -> bool {
103		self.bitvec.count_ones() == self.len()
104	}
105
106	pub fn data(&self) -> &CowVec<T> {
107		&self.data
108	}
109
110	pub fn data_mut(&mut self) -> &mut CowVec<T> {
111		&mut self.data
112	}
113
114	pub fn as_string(&self, index: usize) -> String {
115		if index < self.len() && self.is_defined(index) {
116			self.data[index].to_string()
117		} else {
118			"Undefined".to_string()
119		}
120	}
121
122	pub fn get_value(&self, index: usize) -> Value
123	where
124		T: 'static,
125	{
126		if index < self.len() && self.is_defined(index) {
127			let value = &self.data[index];
128
129			if TypeId::of::<T>() == TypeId::of::<Date>() {
130				let date_val = unsafe { transmute_copy::<T, Date>(value) };
131				Value::Date(date_val)
132			} else if TypeId::of::<T>() == TypeId::of::<DateTime>() {
133				let datetime_val = unsafe { transmute_copy::<T, DateTime>(value) };
134				Value::DateTime(datetime_val)
135			} else if TypeId::of::<T>() == TypeId::of::<Time>() {
136				let time_val = unsafe { transmute_copy::<T, Time>(value) };
137				Value::Time(time_val)
138			} else if TypeId::of::<T>() == TypeId::of::<Duration>() {
139				let duration_val = unsafe { transmute_copy::<T, Duration>(value) };
140				Value::Duration(duration_val)
141			} else {
142				Value::Undefined
143			}
144		} else {
145			Value::Undefined
146		}
147	}
148
149	pub fn extend(&mut self, other: &Self) -> crate::Result<()> {
150		self.data.extend(other.data.iter().cloned());
151		self.bitvec.extend(&other.bitvec);
152		Ok(())
153	}
154
155	pub fn extend_from_undefined(&mut self, len: usize) {
156		self.data.extend(std::iter::repeat(T::default()).take(len));
157		self.bitvec.extend(&BitVec::repeat(len, false));
158	}
159
160	pub fn iter(&self) -> impl Iterator<Item = Option<T>> + '_
161	where
162		T: Copy,
163	{
164		self.data.iter().zip(self.bitvec.iter()).map(|(&v, defined)| {
165			if defined {
166				Some(v)
167			} else {
168				None
169			}
170		})
171	}
172
173	pub fn slice(&self, start: usize, end: usize) -> Self {
174		let new_data: Vec<T> = self.data.iter().skip(start).take(end - start).cloned().collect();
175		let new_bitvec: Vec<bool> = self.bitvec.iter().skip(start).take(end - start).collect();
176		Self {
177			data: CowVec::new(new_data),
178			bitvec: BitVec::from_slice(&new_bitvec),
179		}
180	}
181
182	pub fn filter(&mut self, mask: &BitVec) {
183		let mut new_data = Vec::with_capacity(mask.count_ones());
184		let mut new_bitvec = BitVec::with_capacity(mask.count_ones());
185
186		for (i, keep) in mask.iter().enumerate() {
187			if keep && i < self.len() {
188				new_data.push(self.data[i].clone());
189				new_bitvec.push(self.bitvec.get(i));
190			}
191		}
192
193		self.data = CowVec::new(new_data);
194		self.bitvec = new_bitvec;
195	}
196
197	pub fn reorder(&mut self, indices: &[usize]) {
198		let mut new_data = Vec::with_capacity(indices.len());
199		let mut new_bitvec = BitVec::with_capacity(indices.len());
200
201		for &idx in indices {
202			if idx < self.len() {
203				new_data.push(self.data[idx].clone());
204				new_bitvec.push(self.bitvec.get(idx));
205			} else {
206				new_data.push(T::default());
207				new_bitvec.push(false);
208			}
209		}
210
211		self.data = CowVec::new(new_data);
212		self.bitvec = new_bitvec;
213	}
214
215	pub fn take(&self, num: usize) -> Self {
216		Self {
217			data: self.data.take(num),
218			bitvec: self.bitvec.take(num),
219		}
220	}
221}
222
223impl<T> Default for TemporalContainer<T>
224where
225	T: IsTemporal + Clone + Debug + Default,
226{
227	fn default() -> Self {
228		Self::with_capacity(0)
229	}
230}
231
232#[cfg(test)]
233mod tests {
234	use super::*;
235
236	#[test]
237	fn test_date_container() {
238		let dates = vec![
239			Date::from_ymd(2023, 1, 1).unwrap(),
240			Date::from_ymd(2023, 6, 15).unwrap(),
241			Date::from_ymd(2023, 12, 31).unwrap(),
242		];
243		let container = TemporalContainer::from_vec(dates.clone());
244
245		assert_eq!(container.len(), 3);
246		assert_eq!(container.get(0), Some(&dates[0]));
247		assert_eq!(container.get(1), Some(&dates[1]));
248		assert_eq!(container.get(2), Some(&dates[2]));
249
250		// All should be defined
251		for i in 0..3 {
252			assert!(container.is_defined(i));
253		}
254	}
255
256	#[test]
257	fn test_datetime_container() {
258		let datetimes = vec![
259			DateTime::from_timestamp(1000000000).unwrap(),
260			DateTime::from_timestamp(2000000000).unwrap(),
261		];
262		let container = TemporalContainer::from_vec(datetimes.clone());
263
264		assert_eq!(container.len(), 2);
265		assert_eq!(container.get(0), Some(&datetimes[0]));
266		assert_eq!(container.get(1), Some(&datetimes[1]));
267	}
268
269	#[test]
270	fn test_time_container() {
271		let times = vec![
272			Time::from_hms(9, 0, 0).unwrap(),
273			Time::from_hms(12, 30, 45).unwrap(),
274			Time::from_hms(23, 59, 59).unwrap(),
275		];
276		let container = TemporalContainer::from_vec(times.clone());
277
278		assert_eq!(container.len(), 3);
279		assert_eq!(container.get(0), Some(&times[0]));
280		assert_eq!(container.get(1), Some(&times[1]));
281		assert_eq!(container.get(2), Some(&times[2]));
282	}
283
284	#[test]
285	fn test_interval_container() {
286		let durations = vec![Duration::from_days(30), Duration::from_hours(24)];
287		let container = TemporalContainer::from_vec(durations.clone());
288
289		assert_eq!(container.len(), 2);
290		assert_eq!(container.get(0), Some(&durations[0]));
291		assert_eq!(container.get(1), Some(&durations[1]));
292	}
293
294	#[test]
295	fn test_with_capacity() {
296		let container: TemporalContainer<Date> = TemporalContainer::with_capacity(10);
297		assert_eq!(container.len(), 0);
298		assert!(container.is_empty());
299		assert!(container.capacity() >= 10);
300	}
301
302	#[test]
303	fn test_push_with_undefined() {
304		let mut container: TemporalContainer<Date> = TemporalContainer::with_capacity(3);
305
306		container.push(Date::from_ymd(2023, 1, 1).unwrap());
307		container.push_undefined();
308		container.push(Date::from_ymd(2023, 12, 31).unwrap());
309
310		assert_eq!(container.len(), 3);
311		assert_eq!(container.get(0), Some(&Date::from_ymd(2023, 1, 1).unwrap()));
312		assert_eq!(container.get(1), None); // undefined
313		assert_eq!(container.get(2), Some(&Date::from_ymd(2023, 12, 31).unwrap()));
314
315		assert!(container.is_defined(0));
316		assert!(!container.is_defined(1));
317		assert!(container.is_defined(2));
318	}
319
320	#[test]
321	fn test_extend() {
322		let mut container1 = TemporalContainer::from_vec(vec![
323			Date::from_ymd(2023, 1, 1).unwrap(),
324			Date::from_ymd(2023, 6, 15).unwrap(),
325		]);
326		let container2 = TemporalContainer::from_vec(vec![Date::from_ymd(2023, 12, 31).unwrap()]);
327
328		container1.extend(&container2).unwrap();
329
330		assert_eq!(container1.len(), 3);
331		assert_eq!(container1.get(0), Some(&Date::from_ymd(2023, 1, 1).unwrap()));
332		assert_eq!(container1.get(1), Some(&Date::from_ymd(2023, 6, 15).unwrap()));
333		assert_eq!(container1.get(2), Some(&Date::from_ymd(2023, 12, 31).unwrap()));
334	}
335
336	#[test]
337	fn test_extend_from_undefined() {
338		let mut container = TemporalContainer::from_vec(vec![Date::from_ymd(2023, 1, 1).unwrap()]);
339		container.extend_from_undefined(2);
340
341		assert_eq!(container.len(), 3);
342		assert_eq!(container.get(0), Some(&Date::from_ymd(2023, 1, 1).unwrap()));
343		assert_eq!(container.get(1), None); // undefined
344		assert_eq!(container.get(2), None); // undefined
345	}
346
347	#[test]
348	fn test_iter() {
349		let dates = vec![
350			Date::from_ymd(2023, 1, 1).unwrap(),
351			Date::from_ymd(2023, 6, 15).unwrap(),
352			Date::from_ymd(2023, 12, 31).unwrap(),
353		];
354		let bitvec = BitVec::from_slice(&[true, false, true]); // middle value undefined
355		let container = TemporalContainer::new(dates.clone(), bitvec);
356
357		let collected: Vec<Option<Date>> = container.iter().collect();
358		assert_eq!(collected, vec![Some(dates[0]), None, Some(dates[2])]);
359	}
360
361	#[test]
362	fn test_slice() {
363		let container = TemporalContainer::from_vec(vec![
364			Time::from_hms(9, 0, 0).unwrap(),
365			Time::from_hms(12, 0, 0).unwrap(),
366			Time::from_hms(15, 0, 0).unwrap(),
367			Time::from_hms(18, 0, 0).unwrap(),
368		]);
369		let sliced = container.slice(1, 3);
370
371		assert_eq!(sliced.len(), 2);
372		assert_eq!(sliced.get(0), Some(&Time::from_hms(12, 0, 0).unwrap()));
373		assert_eq!(sliced.get(1), Some(&Time::from_hms(15, 0, 0).unwrap()));
374	}
375
376	#[test]
377	fn test_filter() {
378		let mut container = TemporalContainer::from_vec(vec![
379			Date::from_ymd(2023, 1, 1).unwrap(),
380			Date::from_ymd(2023, 2, 1).unwrap(),
381			Date::from_ymd(2023, 3, 1).unwrap(),
382			Date::from_ymd(2023, 4, 1).unwrap(),
383		]);
384		let mask = BitVec::from_slice(&[true, false, true, false]);
385
386		container.filter(&mask);
387
388		assert_eq!(container.len(), 2);
389		assert_eq!(container.get(0), Some(&Date::from_ymd(2023, 1, 1).unwrap()));
390		assert_eq!(container.get(1), Some(&Date::from_ymd(2023, 3, 1).unwrap()));
391	}
392
393	#[test]
394	fn test_reorder() {
395		let mut container = TemporalContainer::from_vec(vec![
396			Date::from_ymd(2023, 1, 1).unwrap(),
397			Date::from_ymd(2023, 6, 15).unwrap(),
398			Date::from_ymd(2023, 12, 31).unwrap(),
399		]);
400		let indices = [2, 0, 1];
401
402		container.reorder(&indices);
403
404		assert_eq!(container.len(), 3);
405		assert_eq!(container.get(0), Some(&Date::from_ymd(2023, 12, 31).unwrap())); // was index 2
406		assert_eq!(container.get(1), Some(&Date::from_ymd(2023, 1, 1).unwrap())); // was index 0
407		assert_eq!(container.get(2), Some(&Date::from_ymd(2023, 6, 15).unwrap())); // was index 1
408	}
409
410	#[test]
411	fn test_default() {
412		let container: TemporalContainer<Date> = TemporalContainer::default();
413		assert_eq!(container.len(), 0);
414		assert!(container.is_empty());
415	}
416}