diff --git a/components/style/gecko_bindings/sugar/ns_t_array.rs b/components/style/gecko_bindings/sugar/ns_t_array.rs index bf5e168b5ef..72a7481fe96 100644 --- a/components/style/gecko_bindings/sugar/ns_t_array.rs +++ b/components/style/gecko_bindings/sugar/ns_t_array.rs @@ -82,9 +82,9 @@ impl nsTArray { /// Resize and set the length of the array to `len`. /// - /// unsafe because the array may contain uninitialized members. + /// unsafe because this may leave the array with uninitialized elements. /// - /// This will not call constructors, if you need that, either manually add + /// This will not call constructors. If you need that, either manually add /// bindings or run the typed `EnsureCapacity` call on the gecko side. pub unsafe fn set_len(&mut self, len: u32) { // this can leak @@ -96,6 +96,8 @@ impl nsTArray { /// Resizes an array containing only POD elements /// + /// unsafe because this may leave the array with uninitialized elements. + /// /// This will not leak since it only works on POD types (and thus doesn't assert) pub unsafe fn set_len_pod(&mut self, len: u32) where @@ -105,4 +107,17 @@ impl nsTArray { let header = self.header_mut(); header.mLength = len; } + + /// Collects the given iterator into this array. + /// + /// Not unsafe because we won't leave uninitialized elements in the array. + pub fn assign_from_iter_pod(&mut self, iter: I) + where + T: Copy, + I: ExactSizeIterator + Iterator, + { + debug_assert!(iter.len() <= 0xFFFFFFFF); + unsafe { self.set_len_pod(iter.len() as u32); } + self.iter_mut().zip(iter).for_each(|(r, v)| *r = v); + } } diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 0c007710450..04e65b5fa7f 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -1373,35 +1373,22 @@ impl Clone for ${style_struct.gecko_struct_name} { } -<%def name="impl_font_settings(ident, tag_type, value_type, gecko_value_type)"> +<%def name="impl_font_settings(ident, gecko_type, tag_type, value_type, gecko_value_type)"> <% gecko_ffi_name = to_camel_case_lower(ident) %> pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { - let current_settings = &mut self.gecko.mFont.${gecko_ffi_name}; - current_settings.clear_pod(); - - unsafe { current_settings.set_len_pod(v.0.len() as u32) }; - - for (current, other) in current_settings.iter_mut().zip(v.0.iter()) { - current.mTag = other.tag.0; - current.mValue = other.value as ${gecko_value_type}; - } + let iter = v.0.iter().map(|other| structs::${gecko_type} { + mTag: other.tag.0, + mValue: other.value as ${gecko_value_type}, + }); + self.gecko.mFont.${gecko_ffi_name}.assign_from_iter_pod(iter); } pub fn copy_${ident}_from(&mut self, other: &Self) { - let current_settings = &mut self.gecko.mFont.${gecko_ffi_name}; - let other_settings = &other.gecko.mFont.${gecko_ffi_name}; - let settings_length = other_settings.len() as u32; - - current_settings.clear_pod(); - unsafe { current_settings.set_len_pod(settings_length) }; - - for (current, other) in current_settings.iter_mut().zip(other_settings.iter()) { - current.mTag = other.mTag; - current.mValue = other.mValue; - } + let iter = other.gecko.mFont.${gecko_ffi_name}.iter().map(|s| *s); + self.gecko.mFont.${gecko_ffi_name}.assign_from_iter_pod(iter); } pub fn reset_${ident}(&mut self, other: &Self) { @@ -2274,8 +2261,8 @@ fn static_assert() { // Negative numbers are invalid at parse time, but is still an // i32. - <% impl_font_settings("font_feature_settings", "FeatureTagValue", "i32", "u32") %> - <% impl_font_settings("font_variation_settings", "VariationValue", "f32", "f32") %> + <% impl_font_settings("font_feature_settings", "gfxFontFeature", "FeatureTagValue", "i32", "u32") %> + <% impl_font_settings("font_variation_settings", "gfxFontVariation", "VariationValue", "f32", "f32") %> pub fn fixup_none_generic(&mut self, device: &Device) { self.gecko.mFont.systemFont = false; @@ -3213,28 +3200,16 @@ fn static_assert() { where I: IntoIterator, I::IntoIter: ExactSizeIterator { - let v = v.into_iter(); - - unsafe { self.gecko.mScrollSnapCoordinate.set_len_pod(v.len() as u32); } - for (gecko, servo) in self.gecko.mScrollSnapCoordinate - .iter_mut() - .zip(v) { - gecko.mXPosition = servo.horizontal.into(); - gecko.mYPosition = servo.vertical.into(); - } + let iter = v.into_iter().map(|c| structs::mozilla::Position { + mXPosition: c.horizontal.into(), + mYPosition: c.vertical.into(), + }); + self.gecko.mScrollSnapCoordinate.assign_from_iter_pod(iter); } pub fn copy_scroll_snap_coordinate_from(&mut self, other: &Self) { - unsafe { - self.gecko.mScrollSnapCoordinate - .set_len_pod(other.gecko.mScrollSnapCoordinate.len() as u32); - } - - for (this, that) in self.gecko.mScrollSnapCoordinate - .iter_mut() - .zip(other.gecko.mScrollSnapCoordinate.iter()) { - *this = *that; - } + let iter = other.gecko.mScrollSnapCoordinate.iter().map(|c| *c); + self.gecko.mScrollSnapCoordinate.assign_from_iter_pod(iter); } pub fn reset_scroll_snap_coordinate(&mut self, other: &Self) { @@ -4995,12 +4970,12 @@ fn set_style_svg_path( Gecko_NewStyleSVGPath(shape_source); &mut shape_source.__bindgen_anon_1.mSVGPath.as_mut().mPtr.as_mut().unwrap() }; - unsafe { gecko_path.mPath.set_len(servo_path.commands().len() as u32) }; - debug_assert_eq!(gecko_path.mPath.len(), servo_path.commands().len()); - for (servo, gecko) in servo_path.commands().iter().zip(gecko_path.mPath.iter_mut()) { + + let iter = servo_path.commands().iter().map(|command| { // unsafe: cbindgen ensures the representation is the same. - *gecko = unsafe { transmute(*servo) }; - } + unsafe { transmute(*command) } + }); + gecko_path.mPath.assign_from_iter_pod(iter); // Setup fill-rule. // unsafe: cbindgen ensures the representation is the same. diff --git a/components/style/stylesheets/font_feature_values_rule.rs b/components/style/stylesheets/font_feature_values_rule.rs index 76170151c67..f1353744f08 100644 --- a/components/style/stylesheets/font_feature_values_rule.rs +++ b/components/style/stylesheets/font_feature_values_rule.rs @@ -179,12 +179,7 @@ impl Parse for VectorValues { #[cfg(feature = "gecko")] impl ToGeckoFontFeatureValues for VectorValues { fn to_gecko_font_feature_values(&self, array: &mut nsTArray) { - unsafe { - array.set_len_pod(self.0.len() as u32); - } - for (dest, value) in array.iter_mut().zip(self.0.iter()) { - *dest = *value; - } + array.assign_from_iter_pod(self.0.iter().map(|v| *v)); } }