hdf5_metno_types/
array.rs1use std::fmt;
2use std::marker::PhantomData;
3use std::mem;
4use std::ops::Deref;
5use std::ptr;
6use std::slice;
7
8#[repr(C)]
9pub struct VarLenArray<T: Copy> {
10 len: usize,
11 ptr: *const T,
12 tag: PhantomData<T>,
13}
14
15impl<T: Copy> VarLenArray<T> {
16 pub unsafe fn from_parts(p: *const T, len: usize) -> Self {
17 let (len, ptr) = if !p.is_null() && len != 0 {
18 let dst = crate::malloc(len * mem::size_of::<T>());
19 ptr::copy_nonoverlapping(p, dst.cast(), len);
20 (len, dst)
21 } else {
22 (0, ptr::null_mut())
23 };
24 Self { len, ptr: ptr as *const _, tag: PhantomData }
25 }
26
27 #[inline]
28 pub fn from_slice(arr: &[T]) -> Self {
29 unsafe { Self::from_parts(arr.as_ptr(), arr.len()) }
30 }
31
32 #[inline]
33 pub fn as_ptr(&self) -> *const T {
34 self.ptr
35 }
36
37 #[inline]
38 pub fn len(&self) -> usize {
39 self.len as _
40 }
41
42 #[inline]
43 pub fn is_empty(&self) -> bool {
44 self.len == 0
45 }
46
47 #[inline]
48 pub fn as_slice(&self) -> &[T] {
49 self
50 }
51}
52
53impl<T: Copy> Drop for VarLenArray<T> {
54 fn drop(&mut self) {
55 if !self.ptr.is_null() {
56 unsafe {
57 crate::free(self.ptr as *mut _);
58 }
59 self.ptr = ptr::null();
60 if self.len != 0 {
61 self.len = 0;
62 }
63 }
64 }
65}
66
67impl<T: Copy> Clone for VarLenArray<T> {
68 #[inline]
69 fn clone(&self) -> Self {
70 Self::from_slice(self)
71 }
72}
73
74impl<T: Copy> Deref for VarLenArray<T> {
75 type Target = [T];
76
77 #[inline]
78 fn deref(&self) -> &[T] {
79 if self.len == 0 || self.ptr.is_null() {
80 &[]
81 } else {
82 unsafe { slice::from_raw_parts(self.as_ptr(), self.len()) }
83 }
84 }
85}
86
87impl<T: Copy> From<&[T]> for VarLenArray<T> {
88 #[inline]
89 fn from(arr: &[T]) -> Self {
90 Self::from_slice(arr)
91 }
92}
93
94impl<T: Copy> From<VarLenArray<T>> for Vec<T> {
95 #[inline]
96 fn from(v: VarLenArray<T>) -> Self {
97 v.iter().copied().collect()
98 }
99}
100
101impl<T: Copy, const N: usize> From<[T; N]> for VarLenArray<T> {
102 #[inline]
103 fn from(arr: [T; N]) -> Self {
104 unsafe { Self::from_parts(arr.as_ptr(), arr.len()) }
105 }
106}
107
108impl<T: Copy> Default for VarLenArray<T> {
109 #[inline]
110 fn default() -> Self {
111 unsafe { Self::from_parts(ptr::null(), 0) }
112 }
113}
114
115impl<T: Copy + PartialEq> PartialEq for VarLenArray<T> {
116 #[inline]
117 fn eq(&self, other: &Self) -> bool {
118 self.as_slice() == other.as_slice()
119 }
120}
121
122impl<T: Copy + Eq> Eq for VarLenArray<T> {}
123
124impl<T: Copy + PartialEq> PartialEq<[T]> for VarLenArray<T> {
125 #[inline]
126 fn eq(&self, other: &[T]) -> bool {
127 self.as_slice() == other
128 }
129}
130
131impl<T: Copy + PartialEq, const N: usize> PartialEq<[T; N]> for VarLenArray<T> {
132 #[inline]
133 fn eq(&self, other: &[T; N]) -> bool {
134 self.as_slice() == other
135 }
136}
137
138impl<T: Copy + fmt::Debug> fmt::Debug for VarLenArray<T> {
139 #[inline]
140 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
141 self.as_slice().fmt(f)
142 }
143}
144
145unsafe impl<T: Copy + Send> Send for VarLenArray<T> {}
147unsafe impl<T: Copy + Sync> Sync for VarLenArray<T> {}
149
150#[cfg(test)]
151pub mod tests {
152 use super::VarLenArray;
153
154 type S = VarLenArray<u16>;
155
156 #[test]
157 pub fn test_vla_empty_default() {
158 assert_eq!(&*S::default(), &[]);
159 assert!(S::default().is_empty());
160 assert_eq!(S::default().len(), 0);
161 }
162
163 #[test]
164 pub fn test_vla_array_traits() {
165 use std::slice;
166
167 let s = &[1u16, 2, 3];
168 let a = VarLenArray::from_slice(s);
169 assert_eq!(a.as_slice(), s);
170 assert_eq!(a.len(), 3);
171 assert!(!a.is_empty());
172 assert_eq!(unsafe { slice::from_raw_parts(a.as_ptr(), a.len()) }, s);
173 assert_eq!(&*a, s);
174 let c = a.clone();
175 assert_eq!(&*a, &*c);
176 let v: Vec<u16> = c.into();
177 assert_eq!(v, vec![1, 2, 3]);
178 assert_eq!(&*a, &*VarLenArray::from(*s));
179 let f: [u16; 3] = [1, 2, 3];
180 assert_eq!(&*a, &*VarLenArray::from(f));
181 assert_eq!(format!("{:?}", a), "[1, 2, 3]");
182 assert_eq!(a, [1, 2, 3]);
183 assert_eq!(&a, s);
184 assert_eq!(&a, a.as_slice());
185 assert_eq!(a, a);
186 let v: Vec<_> = a.iter().cloned().collect();
187 assert_eq!(v, vec![1, 2, 3]);
188 }
189}