1 #[derive(Default)] 2 pub struct Properties<T> { 3 props: Vec<T>, 4 } 5 6 /// This encapsulates a C property array, where the list is 0 terminated. 7 impl<T> Properties<T> { 8 /// Creates a Properties object copying from the supplied pointer. 9 /// 10 /// It returns `None` if any property is found twice. 11 /// 12 /// If `p` is null the saved list of properties will be empty. Otherwise it will be 0 13 /// terminated. 14 /// 15 /// # Safety 16 /// 17 /// Besides `p` being valid to be dereferenced, it also needs to point to a `T::default()` 18 /// terminated array of `T`. new(mut p: *const T) -> Option<Self> where T: Copy + Default + PartialEq,19 pub unsafe fn new(mut p: *const T) -> Option<Self> 20 where 21 T: Copy + Default + PartialEq, 22 { 23 let mut res = Self::default(); 24 if !p.is_null() { 25 unsafe { 26 while *p != T::default() { 27 // Property lists are expected to be small, so no point in using HashSet or 28 // sorting. 29 if res.get(&*p).is_some() { 30 return None; 31 } 32 33 res.props.push(*p); 34 res.props.push(*p.add(1)); 35 36 // Advance by two as we read through a list of pairs. 37 p = p.add(2); 38 } 39 } 40 41 // terminate the array 42 res.props.push(T::default()); 43 } 44 45 Some(res) 46 } 47 48 /// Returns the value for the given `key` if existent. get(&self, key: &T) -> Option<&T> where T: PartialEq,49 pub fn get(&self, key: &T) -> Option<&T> 50 where 51 T: PartialEq, 52 { 53 self.iter().find_map(|(k, v)| (k == key).then_some(v)) 54 } 55 56 /// Returns true when there is no property available. is_empty(&self) -> bool57 pub fn is_empty(&self) -> bool { 58 self.props.len() <= 1 59 } 60 iter(&self) -> impl Iterator<Item = (&T, &T)>61 pub fn iter(&self) -> impl Iterator<Item = (&T, &T)> { 62 // TODO: use array_chuncks once stabilized 63 self.props 64 .chunks_exact(2) 65 .map(|elems| (&elems[0], &elems[1])) 66 } 67 68 /// Returns the amount of key/value pairs available. len(&self) -> usize69 pub fn len(&self) -> usize { 70 // only valid lengths are all uneven numbers and 0, so division by 2 gives us always the 71 // correct result. 72 self.props.len() / 2 73 } 74 75 /// Returns a slice to the raw buffer. 76 /// 77 /// It will return an empty slice if `self` was created with a null pointer. A `T::default()` 78 /// terminated one otherwise. raw_data(&self) -> &[T]79 pub fn raw_data(&self) -> &[T] { 80 &self.props 81 } 82 } 83