1 | use std::fmt::Display; |
2 | |
3 | use proc_macro2::{Span, TokenStream}; |
4 | use proc_macro_crate::{crate_name, FoundCrate}; |
5 | use quote::{format_ident, quote}; |
6 | use syn::{Attribute, FnArg, Ident, Pat, PatIdent, PatType}; |
7 | |
8 | pub fn zbus_path() -> TokenStream { |
9 | if let Ok(FoundCrate::Name(name: String)) = crate_name(orig_name:"zbus" ) { |
10 | let ident: Ident = format_ident!(" {}" , name); |
11 | quote! { ::#ident } |
12 | } else { |
13 | quote! { ::zbus } |
14 | } |
15 | } |
16 | |
17 | pub fn typed_arg(arg: &FnArg) -> Option<&PatType> { |
18 | match arg { |
19 | FnArg::Typed(t: &PatType) => Some(t), |
20 | _ => None, |
21 | } |
22 | } |
23 | |
24 | pub fn pat_ident(pat: &PatType) -> Option<&Ident> { |
25 | match &*pat.pat { |
26 | Pat::Ident(PatIdent { ident: &Ident, .. }) => Some(ident), |
27 | _ => None, |
28 | } |
29 | } |
30 | |
31 | pub fn get_doc_attrs(attrs: &[Attribute]) -> Vec<&Attribute> { |
32 | attrs.iter().filter(|x: &&Attribute| 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. |
37 | pub fn pascal_case(s: &str) -> String { |
38 | let mut pascal: String = String::new(); |
39 | let mut capitalize: bool = true; |
40 | for ch: char 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 | |
53 | pub 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)] |
61 | pub enum PropertyEmitsChangedSignal { |
62 | #[default] |
63 | True, |
64 | Invalidates, |
65 | Const, |
66 | False, |
67 | } |
68 | |
69 | impl Display for PropertyEmitsChangedSignal { |
70 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
71 | let emits_changed_signal: &'static str = 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 | |
81 | impl 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: &str => Err(syn::Error::new( |
91 | span, |
92 | message:format!("invalid value \"{other}\" for attribute `property(emits_changed_signal)`" ), |
93 | )), |
94 | } |
95 | } |
96 | } |
97 | |