diff --git a/src/gallium/frontends/rusticl/util/properties.rs b/src/gallium/frontends/rusticl/util/properties.rs index 59cfbbdd23d..b0262fada07 100644 --- a/src/gallium/frontends/rusticl/util/properties.rs +++ b/src/gallium/frontends/rusticl/util/properties.rs @@ -1,12 +1,14 @@ +#[derive(Default)] pub struct Properties { - props: Vec<(T, T)>, + props: Vec, } -impl Properties { +/// This encapsulates a C property array, where the list is 0 terminated. +impl Properties { #[allow(clippy::not_unsafe_ptr_arg_deref)] pub fn from_ptr_raw(mut p: *const T) -> Vec where - T: PartialEq, + T: Copy + Default + PartialEq, { let mut res: Vec = Vec::new(); @@ -24,29 +26,36 @@ impl Properties { res } - #[allow(clippy::not_unsafe_ptr_arg_deref)] + /// Creates a Properties object copying from the supplied pointer. + /// + /// It returns `None` if any property is found twice. + /// + /// If `p` is null the saved list of properties will be empty. Otherwise it will be 0 + /// terminated. pub fn from_ptr(mut p: *const T) -> Option where - T: PartialEq, + T: Copy + Default + PartialEq, { let mut res = Self::default(); - if !p.is_null() { - let mut k: Vec = Vec::new(); - let mut v: Vec = Vec::new(); - unsafe { while *p != T::default() { - if k.contains(&*p) { + // Property lists are expected to be small, so no point in using HashSet or + // sorting. + if res.props.contains(&*p) { return None; } - k.push(*p); - v.push(*p.add(1)); + + res.props.push(*p); + res.props.push(*p.add(1)); + + // Advance by two as we read through a list of pairs. p = p.add(2); } } - res.props = k.iter().cloned().zip(v).collect(); + // terminate the array + res.props.push(T::default()); } Some(res) @@ -54,21 +63,20 @@ impl Properties { /// Returns true when there is no property available. pub fn is_empty(&self) -> bool { - self.props.is_empty() + self.props.len() <= 1 } pub fn iter(&self) -> impl Iterator { - self.props.iter().map(|(k, v)| (k, v)) + // TODO: use array_chuncks once stabilized + self.props + .chunks_exact(2) + .map(|elems| (&elems[0], &elems[1])) } /// Returns the amount of key/value pairs available. pub fn len(&self) -> usize { - self.props.len() - } -} - -impl Default for Properties { - fn default() -> Self { - Self { props: Vec::new() } + // only valid lengths are all uneven numbers and 0, so division by 2 gives us always the + // correct result. + self.props.len() / 2 } }