1use std::fmt::Display;
2
3use proc_macro_crate::{FoundCrate, crate_name};
4use proc_macro2::{Span, TokenStream};
5use quote::{format_ident, quote};
6use syn::{Attribute, FnArg, Ident, Pat, PatIdent, PatType};
7
8pub fn parse_crate_path(crate_attr: Option<&str>) -> Result<Option<syn::Path>, syn::Error> {
10 crate_attr.map(syn::parse_str).transpose()
11}
12
13pub fn zbus_path(crate_path: Option<&syn::Path>) -> TokenStream {
18 if let Some(path) = crate_path {
19 quote! { ::#path }
20 } else if let Ok(FoundCrate::Name(name)) = crate_name("zbus") {
21 let ident = format_ident!("{}", name);
22 quote! { ::#ident }
23 } else {
24 quote! { ::zbus }
25 }
26}
27
28pub fn typed_arg(arg: &FnArg) -> Option<&PatType> {
29 match arg {
30 FnArg::Typed(t) => Some(t),
31 _ => None,
32 }
33}
34
35pub fn pat_ident(pat: &PatType) -> Option<&Ident> {
36 match &*pat.pat {
37 Pat::Ident(PatIdent { ident, .. }) => Some(ident),
38 _ => None,
39 }
40}
41
42pub fn get_doc_attrs(attrs: &[Attribute]) -> Vec<&Attribute> {
43 attrs.iter().filter(|x| x.path().is_ident("doc")).collect()
44}
45
46pub fn pascal_case(s: &str) -> String {
49 let mut pascal = String::new();
50 let mut capitalize = true;
51 for ch in s.chars() {
52 if ch == '_' {
53 capitalize = true;
54 } else if capitalize {
55 pascal.push(ch.to_ascii_uppercase());
56 capitalize = false;
57 } else {
58 pascal.push(ch);
59 }
60 }
61 pascal
62}
63
64pub fn is_blank(s: &str) -> bool {
65 s.trim().is_empty()
66}
67
68#[derive(Debug, Default, Clone, PartialEq)]
72pub enum PropertyEmitsChangedSignal {
73 #[default]
74 True,
75 Invalidates,
76 Const,
77 False,
78}
79
80impl Display for PropertyEmitsChangedSignal {
81 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82 let emits_changed_signal = match self {
83 PropertyEmitsChangedSignal::True => "true",
84 PropertyEmitsChangedSignal::Const => "const",
85 PropertyEmitsChangedSignal::False => "false",
86 PropertyEmitsChangedSignal::Invalidates => "invalidates",
87 };
88 write!(f, "{emits_changed_signal}")
89 }
90}
91
92impl PropertyEmitsChangedSignal {
93 pub fn parse(s: &str, span: Span) -> syn::Result<Self> {
94 use PropertyEmitsChangedSignal::*;
95
96 match s {
97 "true" => Ok(True),
98 "invalidates" => Ok(Invalidates),
99 "const" => Ok(Const),
100 "false" => Ok(False),
101 other => Err(syn::Error::new(
102 span,
103 format!("invalid value \"{other}\" for attribute `property(emits_changed_signal)`"),
104 )),
105 }
106 }
107}