despatma_lib/
key_value.rs1use proc_macro2::TokenTree;
2use syn::parse::{Parse, ParseStream, Result};
3use syn::{parse_str, Ident, Token};
4
5#[cfg_attr(any(test, feature = "extra-traits"), derive(Debug))]
18pub struct KeyValue {
19 pub key: Ident,
20 pub equal_token: Token![=],
21 pub value: TokenTree,
22}
23
24impl Parse for KeyValue {
26 fn parse(input: ParseStream) -> Result<Self> {
27 let key = input.parse()?;
28
29 if input.is_empty() || input.peek(Token![,]) {
31 return Ok(KeyValue {
32 key,
33 equal_token: Default::default(),
34 value: parse_str("default")?,
35 });
36 }
37
38 Ok(KeyValue {
40 key,
41 equal_token: input.parse()?,
42 value: input.parse()?,
43 })
44 }
45}
46
47#[cfg(any(test, feature = "extra-traits"))]
49impl PartialEq for KeyValue {
50 fn eq(&self, other: &Self) -> bool {
51 self.key == other.key && format!("{}", self.value) == format!("{}", other.value)
52 }
53}
54#[cfg(any(test, feature = "extra-traits"))]
55impl Eq for KeyValue {}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use pretty_assertions::assert_eq;
61 use syn::parse_str;
62
63 type Result = std::result::Result<(), Box<dyn std::error::Error>>;
64
65 #[test]
66 fn parse() -> Result {
67 let actual: KeyValue = parse_str("some_key = \"value\"")?;
68 let expected = KeyValue {
69 key: parse_str("some_key")?,
70 equal_token: Default::default(),
71 value: parse_str("\"value\"")?,
72 };
73
74 assert_eq!(actual, expected);
75 Ok(())
76 }
77
78 #[test]
79 fn parse_missing_value() -> Result {
80 let actual: KeyValue = parse_str("bool_key")?;
81 let expected = KeyValue {
82 key: parse_str("bool_key")?,
83 equal_token: Default::default(),
84 value: parse_str("default")?,
85 };
86
87 assert_eq!(actual, expected);
88 Ok(())
89 }
90
91 #[test]
92 fn parse_attribute_item_complex_stream() -> Result {
93 let actual: KeyValue = parse_str("tmpl = {trait To {};}")?;
94 let expected = KeyValue {
95 key: parse_str("tmpl")?,
96 equal_token: Default::default(),
97 value: parse_str("{trait To {};}")?,
98 };
99
100 assert_eq!(actual, expected);
101 Ok(())
102 }
103
104 #[test]
106 #[should_panic(expected = "expected token")]
107 fn parse_attribute_item_complex_stream_extra() {
108 parse_str::<KeyValue>("tmpl = {trait To {};}, key").unwrap();
109 }
110
111 #[test]
112 #[should_panic(expected = "expected identifier")]
113 fn missing_key() {
114 parse_str::<KeyValue>("= true").unwrap();
115 }
116
117 #[test]
118 #[should_panic(expected = "expected `=`")]
119 fn missing_equal_sign() {
120 parse_str::<KeyValue>("key value").unwrap();
121 }
122
123 #[test]
124 #[should_panic(expected = "expected token tree")]
125 fn missing_value() {
126 parse_str::<KeyValue>("key = ").unwrap();
127 }
128}