Skip to content

Commit b2f18c3

Browse files
committed
glib: Don't allow passing a construct(-only) property twice during object construction
GLib also does not allow this and would give a critical warning.
1 parent 12148df commit b2f18c3

File tree

2 files changed

+67
-24
lines changed

2 files changed

+67
-24
lines changed

glib/src/object.rs

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,18 +1365,33 @@ impl Object {
13651365
.ok_or_else(|| bool_error!("Can't retrieve class for type '{}'", type_))?;
13661366
let pspecs = klass.list_properties();
13671367

1368-
properties
1369-
.iter()
1370-
.map(|(name, value)| {
1371-
let pspec = pspecs.iter().find(|p| p.name() == *name).ok_or_else(|| {
1372-
bool_error!("Can't find property '{}' for type '{}'", name, type_)
1373-
})?;
1374-
1375-
let mut value = value.to_value();
1376-
validate_property_type(type_, true, pspec, &mut value)?;
1377-
Ok((pspec.name().as_ptr(), value))
1378-
})
1379-
.collect::<Result<smallvec::SmallVec<[_; 10]>, _>>()?
1368+
let mut validated_properties =
1369+
smallvec::SmallVec::<[_; 16]>::with_capacity(properties.len());
1370+
for (idx, (name, value)) in properties.iter().enumerate() {
1371+
let pspec = pspecs.iter().find(|p| p.name() == *name).ok_or_else(|| {
1372+
bool_error!("Can't find property '{}' for type '{}'", name, type_)
1373+
})?;
1374+
1375+
if (pspec.flags().contains(crate::ParamFlags::CONSTRUCT)
1376+
|| pspec.flags().contains(crate::ParamFlags::CONSTRUCT_ONLY))
1377+
&& properties[0..idx]
1378+
.iter()
1379+
.any(|(other_name, _)| name == other_name)
1380+
{
1381+
return Err(bool_error!(
1382+
"Can't set construct property '{}' for type '{}' twice",
1383+
name,
1384+
type_
1385+
));
1386+
}
1387+
1388+
let mut value = value.to_value();
1389+
validate_property_type(type_, true, pspec, &mut value)?;
1390+
1391+
validated_properties.push((pspec.name().as_ptr(), value));
1392+
}
1393+
1394+
validated_properties
13801395
} else {
13811396
smallvec::SmallVec::new()
13821397
};
@@ -1395,18 +1410,33 @@ impl Object {
13951410
.ok_or_else(|| bool_error!("Can't retrieve class for type '{}'", type_))?;
13961411
let pspecs = klass.list_properties();
13971412

1398-
properties
1399-
.iter()
1400-
.map(|(name, value)| {
1401-
let pspec = pspecs.iter().find(|p| p.name() == *name).ok_or_else(|| {
1402-
bool_error!("Can't find property '{}' for type '{}'", name, type_)
1403-
})?;
1404-
1405-
let mut value = value.clone();
1406-
validate_property_type(type_, true, pspec, &mut value)?;
1407-
Ok((pspec.name().as_ptr(), value))
1408-
})
1409-
.collect::<Result<smallvec::SmallVec<[_; 10]>, _>>()?
1413+
let mut validated_properties =
1414+
smallvec::SmallVec::<[_; 16]>::with_capacity(properties.len());
1415+
for (idx, (name, value)) in properties.iter().enumerate() {
1416+
let pspec = pspecs.iter().find(|p| p.name() == *name).ok_or_else(|| {
1417+
bool_error!("Can't find property '{}' for type '{}'", name, type_)
1418+
})?;
1419+
1420+
if (pspec.flags().contains(crate::ParamFlags::CONSTRUCT)
1421+
|| pspec.flags().contains(crate::ParamFlags::CONSTRUCT_ONLY))
1422+
&& properties[0..idx]
1423+
.iter()
1424+
.any(|(other_name, _)| name == other_name)
1425+
{
1426+
return Err(bool_error!(
1427+
"Can't set construct property '{}' for type '{}' twice",
1428+
name,
1429+
type_
1430+
));
1431+
}
1432+
1433+
let mut value = value.clone();
1434+
validate_property_type(type_, true, pspec, &mut value)?;
1435+
1436+
validated_properties.push((pspec.name().as_ptr(), value));
1437+
}
1438+
1439+
validated_properties
14101440
} else {
14111441
smallvec::SmallVec::new()
14121442
};

glib/src/subclass/object.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,19 @@ mod test {
527527
assert!(obj.try_set_property("child", &child).is_ok());
528528
}
529529

530+
#[test]
531+
fn test_construct_property_set_twice() {
532+
assert_eq!(
533+
Object::with_type(
534+
SimpleObject::static_type(),
535+
&[("construct-name", &"meh"), ("construct-name", &"meh2")],
536+
)
537+
.expect_err("Can't set construct property twice")
538+
.to_string(),
539+
"Can't set construct property 'construct-name' for type 'SimpleObject' twice",
540+
);
541+
}
542+
530543
#[test]
531544
fn test_signals() {
532545
use std::sync::atomic::{AtomicBool, Ordering};

0 commit comments

Comments
 (0)