1#[macro_export]
15macro_rules! dict {
16 () => {{
17 ::nvim_oxi::Dictionary::default()
18 }};
19 ( $( $key:tt : $value:expr ),+ $(,)? ) => {{
20 let mut map: ::std::collections::BTreeMap<
21 ::std::borrow::Cow<'static, str>,
22 ::nvim_oxi::Object
23 > = ::std::collections::BTreeMap::new();
24 $(
25 let k: ::std::borrow::Cow<'static, str> = $crate::__dict_key_to_cow!($key);
26 let v: ::nvim_oxi::Object = ::nvim_oxi::Object::from($value);
27 map.insert(k, v);
28 )+
29 ::nvim_oxi::Dictionary::from_iter(map)
30 }};
31}
32
33#[doc(hidden)]
34#[macro_export]
35macro_rules! __dict_key_to_cow {
36 ($k:literal) => {
37 ::std::borrow::Cow::Borrowed($k)
38 };
39 ($k:ident) => {
40 ::std::borrow::Cow::Borrowed(::std::stringify!($k))
41 };
42 ($k:expr) => {
43 ::std::borrow::Cow::Owned(::std::convert::Into::<::std::string::String>::into($k))
44 };
45}
46
47#[macro_export]
49macro_rules! fn_from {
50 ($path:path) => {
52 ::nvim_oxi::Object::from(::nvim_oxi::Function::from_fn($path))
53 };
54 ($($tokens:tt)+) => {
56 ::nvim_oxi::Object::from(::nvim_oxi::Function::from_fn($($tokens)+))
57 };
58}
59
60#[cfg(test)]
61mod tests {
62 use nvim_oxi::Dictionary;
63 use nvim_oxi::Object;
64
65 use crate::dict::DictionaryExt as _;
66
67 #[test]
68 fn dict_macro_empty_creates_empty_dictionary() {
69 let actual = dict!();
70 assert_eq!(actual.len(), 0);
71 }
72
73 #[test]
74 fn dict_macro_creates_a_dictionary_with_basic_key_value_pairs() {
75 let actual = dict! { "foo": 1, bar: "baz", "num": 3i64 };
76 let expected = Dictionary::from_iter([
77 ("bar", Object::from("baz")),
78 ("foo", Object::from(1)),
79 ("num", Object::from(3i64)),
80 ]);
81 assert_eq!(actual, expected);
82 }
83
84 #[test]
85 fn dict_macro_creates_nested_dictionaries() {
86 let k = String::from("alpha");
87 let inner = dict! { inner_key: "value" };
88 let actual = dict! { (k): 10i64, "beta": inner.clone() };
89 let expected = Dictionary::from_iter([("alpha", Object::from(10i64)), ("beta", Object::from(inner))]);
90 assert_eq!(actual, expected);
91 }
92
93 #[test]
94 fn dictionary_ext_get_t_works_as_expected() {
95 let dict = dict! { "foo": "42" };
96 let msg = dict.get_t::<nvim_oxi::String>("bar").unwrap_err().to_string();
97 assert!(msg.starts_with("missing dict value |"), "actual: {msg}");
98 assert!(msg.contains("query=[\n \"bar\",\n]"), "actual: {msg}");
99 assert!(msg.contains("dict={ foo: \"42\" }"), "actual: {msg}");
100 assert_eq!(dict.get_t::<nvim_oxi::String>("foo").unwrap(), "42");
101
102 let dict = dict! { "foo": 42 };
103 assert_eq!(
104 dict.get_t::<nvim_oxi::String>("foo").unwrap_err().to_string(),
105 r#"value 42 of key "foo" in dict { foo: 42 } is Integer but String was expected"#
106 );
107 }
108
109 #[test]
110 fn dictionary_ext_get_dict_works_as_expected() {
111 let dict = dict! { "foo": "42" };
112 assert_eq!(dict.get_dict(&["bar"]).unwrap(), None);
113
114 let dict = dict! { "foo": 42 };
115 assert_eq!(
116 dict.get_dict(&["foo"]).unwrap_err().to_string(),
117 r#"value 42 of key "foo" in dict { foo: 42 } is Integer but Dictionary was expected"#
118 );
119
120 let expected = dict! { "bar": "42" };
121 let dict = dict! { "foo": expected.clone() };
122 assert_eq!(dict.get_dict(&["foo"]).unwrap(), Some(expected));
123 }
124}