Skip to content

Commit

Permalink
🐛 zx: Prevent collisions between methods, signals and properties
Browse files Browse the repository at this point in the history
If a collision is detected and additional `_` is appended to the
identifier until there is no more collision.

Signed-off-by: Pascal Bach <[email protected]>
  • Loading branch information
Pascal Bach committed Apr 18, 2024
1 parent a132659 commit 1fcce02
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 4 deletions.
29 changes: 25 additions & 4 deletions zbus_xmlgen/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use snakecase::ascii::to_snakecase;
use std::{
collections::HashMap,
error::Error,
fmt::{Display, Formatter, Write},
process::{Command, Stdio},
Expand Down Expand Up @@ -172,11 +173,14 @@ impl<'i> GenTrait<'i> {
writeln!(w, ")]")?;
writeln!(w, "trait {name} {{")?;

let mut collision_hander = CollisionHandler::default();

let mut methods = iface.methods().to_vec();
methods.sort_by(|a, b| a.name().partial_cmp(&b.name()).unwrap());
for m in &methods {
let (inputs, output) = inputs_output_from_args(m.args());
let name = to_identifier(&to_snakecase(m.name().as_str()));
let name =
collision_hander.avoid_collision(to_identifier(&to_snakecase(m.name().as_str())));
writeln!(w)?;
writeln!(w, " /// {} method", m.name())?;
if pascal_case(&name) != m.name().as_str() {
Expand All @@ -190,7 +194,8 @@ impl<'i> GenTrait<'i> {
signals.sort_by(|a, b| a.name().partial_cmp(&b.name()).unwrap());
for signal in &signals {
let args = parse_signal_args(signal.args());
let name = to_identifier(&to_snakecase(signal.name().as_str()));
let name = collision_hander
.avoid_collision(to_identifier(&to_snakecase(signal.name().as_str())));
writeln!(w)?;
writeln!(w, " /// {} signal", signal.name())?;
if pascal_case(&name) != signal.name().as_str() {
Expand All @@ -214,18 +219,20 @@ impl<'i> GenTrait<'i> {
writeln!(w)?;
writeln!(w, " /// {} property", p.name())?;
if p.access().read() {
let getter_name = collision_hander.avoid_collision(name.clone());
writeln!(w, "{}", fn_attribute)?;
let output = to_rust_type(p.ty(), false, false);
hide_clippy_type_complexity_lint(w, p.ty().signature())?;
writeln!(w, " fn {name}(&self) -> zbus::Result<{output}>;",)?;
writeln!(w, " fn {getter_name}(&self) -> zbus::Result<{output}>;",)?;
}

if p.access().write() {
let setter_name = collision_hander.avoid_collision(format!("set_{}", &name));
writeln!(w, "{}", fn_attribute)?;
let input = to_rust_type(p.ty(), true, true);
writeln!(
w,
" fn set_{name}(&self, value: {input}) -> zbus::Result<()>;",
" fn {setter_name}(&self, value: {input}) -> zbus::Result<()>;",
)?;
}
}
Expand Down Expand Up @@ -437,6 +444,20 @@ fn to_identifier(id: &str) -> String {
}
}

#[derive(Default)]
struct CollisionHandler {
used_identifiers: HashMap<String, usize>,
}

impl CollisionHandler {
fn avoid_collision(&mut self, identifier: String) -> String {
let use_count = self.used_identifiers.entry(identifier.clone()).or_default();
let new_identifier = format!("{}{}", &identifier, "_".repeat(*use_count));
*use_count += 1;
new_identifier
}
}

// This function is the same as zbus_macros::utils::pascal_case
pub fn pascal_case(s: &str) -> String {
let mut pascal = String::new();
Expand Down
22 changes: 22 additions & 0 deletions zbus_xmlgen/tests/data/sample_object0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ trait SampleInterface0 {
calypso: &zbus::zvariant::Value<'_>,
) -> zbus::Result<()>;

/// SetWallMessage method
fn set_wall_message(&self) -> zbus::Result<()>;

/// State method
fn state(&self) -> zbus::Result<()>;

/// Changed signal
#[zbus(signal)]
fn changed(&self, new_value: bool) -> zbus::Result<()>;
Expand All @@ -68,6 +74,10 @@ trait SampleInterface0 {
#[zbus(signal)]
fn signal_value(&self, value: zbus::zvariant::Value<'_>) -> zbus::Result<()>;

/// State signal
#[zbus(signal)]
fn state_(&self) -> zbus::Result<()>;

/// Bar property
#[zbus(property)]
fn bar(&self) -> zbus::Result<u8>;
Expand All @@ -94,4 +104,16 @@ trait SampleInterface0 {
std::collections::HashMap<String, zbus::zvariant::OwnedValue>,
)>,
>;

/// State property
#[zbus(property)]
fn state__(&self) -> zbus::Result<u8>;
#[zbus(property)]
fn set_state(&self, value: u8) -> zbus::Result<()>;

/// WallMessage property
#[zbus(property)]
fn wall_message(&self) -> zbus::Result<u8>;
#[zbus(property)]
fn set_wall_message_(&self, value: u8) -> zbus::Result<()>;
}
8 changes: 8 additions & 0 deletions zbus_xmlgen/tests/data/sample_object0.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
<arg name="polyphemus" type="i"/>
<arg name="calypso" type="v"/>
</method>
<method name="SetWallMessage">
</method>
<method name="State">
</method>
<signal name="Changed">
<arg name="new_value" type="b"/>
</signal>
Expand All @@ -52,9 +56,13 @@
<signal name="SignalDictStringToValue">
<arg type="a{sv}" name="dict"/>
</signal>
<signal name="State">
</signal>
<property name="Bar" type="y" access="readwrite"/>
<property name="Foo-Bar" type="y" access="readwrite"/>
<property name="Matryoshkas" type="a(oiasta{sv})" access="read"/>
<property name="WallMessage" type="y" access="readwrite"/>
<property name="State" type="y" access="readwrite"/>
</interface>
<node name="child_of_sample_object"/>
<node name="another_child_of_sample_object"/>
Expand Down

0 comments on commit 1fcce02

Please sign in to comment.