zbus_macros/
utils.rs

1use std::fmt::Display;
2
3use proc_macro2::{Span, TokenStream};
4use proc_macro_crate::{crate_name, FoundCrate};
5use quote::{format_ident, quote};
6use syn::{Attribute, FnArg, Ident, Pat, PatIdent, PatType};
7
8pub fn zbus_path() -> TokenStream {
9    if let Ok(FoundCrate::Name(name)) = crate_name("zbus") {
10        let ident = format_ident!("{}", name);
11        quote! { ::#ident }
12    } else {
13        quote! { ::zbus }
14    }
15}
16
17pub fn typed_arg(arg: &FnArg) -> Option<&PatType> {
18    match arg {
19        FnArg::Typed(t) => Some(t),
20        _ => None,
21    }
22}
23
24pub fn pat_ident(pat: &PatType) -> Option<&Ident> {
25    match &*pat.pat {
26        Pat::Ident(PatIdent { ident, .. }) => Some(ident),
27        _ => None,
28    }
29}
30
31pub fn get_doc_attrs(attrs: &[Attribute]) -> Vec<&Attribute> {
32    attrs.iter().filter(|x| x.path().is_ident("doc")).collect()
33}
34
35// Convert to pascal case, assuming snake case.
36// If `s` is already in pascal case, should yield the same result.
37pub fn pascal_case(s: &str) -> String {
38    let mut pascal = String::new();
39    let mut capitalize = true;
40    for ch in s.chars() {
41        if ch == '_' {
42            capitalize = true;
43        } else if capitalize {
44            pascal.push(ch.to_ascii_uppercase());
45            capitalize = false;
46        } else {
47            pascal.push(ch);
48        }
49    }
50    pascal
51}
52
53pub fn is_blank(s: &str) -> bool {
54    s.trim().is_empty()
55}
56
57/// Standard annotation `org.freedesktop.DBus.Property.EmitsChangedSignal`.
58///
59/// See <https://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format>.
60#[derive(Debug, Default, Clone, PartialEq)]
61pub enum PropertyEmitsChangedSignal {
62    #[default]
63    True,
64    Invalidates,
65    Const,
66    False,
67}
68
69impl Display for PropertyEmitsChangedSignal {
70    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71        let emits_changed_signal = match self {
72            PropertyEmitsChangedSignal::True => "true",
73            PropertyEmitsChangedSignal::Const => "const",
74            PropertyEmitsChangedSignal::False => "false",
75            PropertyEmitsChangedSignal::Invalidates => "invalidates",
76        };
77        write!(f, "{}", emits_changed_signal)
78    }
79}
80
81impl PropertyEmitsChangedSignal {
82    pub fn parse(s: &str, span: Span) -> syn::Result<Self> {
83        use PropertyEmitsChangedSignal::*;
84
85        match s {
86            "true" => Ok(True),
87            "invalidates" => Ok(Invalidates),
88            "const" => Ok(Const),
89            "false" => Ok(False),
90            other => Err(syn::Error::new(
91                span,
92                format!("invalid value \"{other}\" for attribute `property(emits_changed_signal)`"),
93            )),
94        }
95    }
96}