codama_syn_helpers/extensions/
expr.rs1use super::ToTokensExtension;
2use syn::{Expr, ExprLit, ExprPath};
3
4pub trait ExprExtension {
5 fn get_self(&self) -> &Expr;
6
7 fn as_literal_integer<T>(&self) -> syn::Result<T>
9 where
10 T: std::str::FromStr,
11 T::Err: std::fmt::Display,
12 {
13 let this = self.get_self();
14 match this {
15 Expr::Lit(ExprLit {
16 lit: syn::Lit::Int(value),
17 ..
18 }) => value.base10_parse::<T>(),
19 _ => Err(this.error("expected a literal integer")),
20 }
21 }
22
23 fn as_literal_string(&self) -> syn::Result<String> {
25 let this = self.get_self();
26 match this {
27 Expr::Lit(ExprLit {
28 lit: syn::Lit::Str(value),
29 ..
30 }) => Ok(value.value()),
31 _ => Err(this.error("expected a literal string")),
32 }
33 }
34
35 fn as_literal_bool(&self) -> syn::Result<bool> {
37 let this = self.get_self();
38 match this {
39 Expr::Lit(ExprLit {
40 lit: syn::Lit::Bool(value),
41 ..
42 }) => Ok(value.value()),
43 _ => Err(this.error("expected a literal boolean")),
44 }
45 }
46
47 fn as_path(&self) -> syn::Result<&syn::Path> {
49 let this = self.get_self();
50 match this {
51 Expr::Path(ExprPath { path, .. }) => Ok(path),
52 _ => Err(this.error("expected a path")),
53 }
54 }
55}
56
57impl ExprExtension for Expr {
58 fn get_self(&self) -> &Expr {
59 self
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66 use crate::extensions::*;
67
68 #[test]
69 fn as_literal_integer_ok() {
70 let expr: Expr = syn::parse_quote! { 42 };
71 let result = expr.as_literal_integer::<usize>();
72 assert!(matches!(result, Ok(42usize)));
73 }
74
75 #[test]
76 fn as_literal_integer_err() {
77 let expr: Expr = syn::parse_quote! { 40 + 2 };
78 let error = expr.as_literal_integer::<usize>().unwrap_err();
79 assert_eq!(error.to_string(), "expected a literal integer");
80 }
81
82 #[test]
83 fn as_literal_string_ok() {
84 let expr: Expr = syn::parse_quote! { "hello" };
85 let result = expr.as_literal_string().unwrap();
86 assert_eq!(result, "hello");
87 }
88
89 #[test]
90 fn as_literal_string_err() {
91 let expr: Expr = syn::parse_quote! { 40 + 2 };
92 let error = expr.as_literal_string().unwrap_err();
93 assert_eq!(error.to_string(), "expected a literal string");
94 }
95
96 #[test]
97 fn as_path_ok() {
98 let expr: Expr = syn::parse_quote! { hello::world };
99 let result = expr.as_path().unwrap().to_string();
100 assert_eq!(result, "hello::world");
101 }
102
103 #[test]
104 fn as_path_err() {
105 let expr: Expr = syn::parse_quote! { 40 + 2 };
106 let error = expr.as_path().unwrap_err();
107 assert_eq!(error.to_string(), "expected a path");
108 }
109}