Skip to content

Commit 5ed62f5

Browse files
committed
glib: Make ObjectBuilder a bit more efficient
Previously we were copying each parameter value potentially twice, now it is only going to be copied inside C if at all. Also allocate the array of properties on the stack if only a few properties are used.
1 parent 8e0d925 commit 5ed62f5

File tree

1 file changed

+33
-4
lines changed

1 file changed

+33
-4
lines changed

glib/src/object.rs

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,6 +1417,31 @@ impl Object {
14171417
unsafe { Object::new_internal(type_, &mut property_values) }
14181418
}
14191419

1420+
// rustdoc-stripper-ignore-next
1421+
/// Create a new instance of an object of the given type with the given properties as mutable
1422+
/// values.
1423+
///
1424+
/// # Panics
1425+
///
1426+
/// This panics if the object is not instantiable, doesn't have all the given properties or
1427+
/// property values of the wrong type are provided.
1428+
#[track_caller]
1429+
pub fn with_mut_values(type_: Type, properties: &mut [(&str, Value)]) -> Object {
1430+
#[cfg(feature = "gio")]
1431+
unsafe {
1432+
let iface_type = from_glib(gio_ffi::g_initable_get_type());
1433+
if type_.is_a(iface_type) {
1434+
panic!("Can't instantiate type '{type_}' implementing `gio::Initable`. Use `gio::Initable::new()`");
1435+
}
1436+
let iface_type = from_glib(gio_ffi::g_async_initable_get_type());
1437+
if type_.is_a(iface_type) {
1438+
panic!("Can't instantiate type '{type_}' implementing `gio::AsyncInitable`. Use `gio::AsyncInitable::new()`");
1439+
}
1440+
}
1441+
1442+
unsafe { Object::new_internal(type_, properties) }
1443+
}
1444+
14201445
// rustdoc-stripper-ignore-next
14211446
/// Create a new instance of an object of the given type with the given properties.
14221447
///
@@ -1514,27 +1539,30 @@ impl Object {
15141539
#[must_use = "builder doesn't do anything unless built"]
15151540
pub struct ObjectBuilder<'a, O> {
15161541
type_: Type,
1517-
properties: Vec<(&'a str, Value)>,
1542+
properties: smallvec::SmallVec<[(&'a str, Value); 16]>,
15181543
phantom: PhantomData<O>,
15191544
}
15201545

15211546
impl<'a, O: IsA<Object> + IsClass> ObjectBuilder<'a, O> {
1547+
#[inline]
15221548
fn new(type_: Type) -> Self {
15231549
ObjectBuilder {
15241550
type_,
1525-
properties: vec![],
1551+
properties: smallvec::SmallVec::new(),
15261552
phantom: PhantomData,
15271553
}
15281554
}
15291555

15301556
// rustdoc-stripper-ignore-next
15311557
/// Gets the type of this builder.
1558+
#[inline]
15321559
pub fn type_(&self) -> Type {
15331560
self.type_
15341561
}
15351562

15361563
// rustdoc-stripper-ignore-next
15371564
/// Set property `name` to the given value `value`.
1565+
#[inline]
15381566
pub fn property(self, name: &'a str, value: impl Into<Value>) -> Self {
15391567
let ObjectBuilder {
15401568
type_,
@@ -1558,8 +1586,9 @@ impl<'a, O: IsA<Object> + IsClass> ObjectBuilder<'a, O> {
15581586
/// This panics if the object is not instantiable, doesn't have all the given properties or
15591587
/// property values of the wrong type are provided.
15601588
#[track_caller]
1561-
pub fn build(self) -> O {
1562-
let object = Object::with_values(self.type_, &self.properties);
1589+
#[inline]
1590+
pub fn build(mut self) -> O {
1591+
let object = Object::with_mut_values(self.type_, &mut self.properties);
15631592
unsafe { object.unsafe_cast::<O>() }
15641593
}
15651594
}

0 commit comments

Comments
 (0)