osom_primitives_proc_macros/
lib.rs1#![doc(hidden)]
3#![deny(warnings)]
4#![warn(clippy::all, clippy::pedantic)]
5
6use quote::quote;
7
8#[proc_macro]
12pub fn try_unpack(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
13 let expression = match syn::parse::<syn::Expr>(tokens) {
14 Ok(ok) => ok,
15 Err(err) => {
16 return err.into_compile_error().into();
17 }
18 };
19
20 quote! {
21 {
22 use ::osom_primitives::cresult::CResult;
23
24 match { #expression } {
25 CResult::Ok(ok) => ok,
26 CResult::Err(err) => {
27 return CResult::Err(err);
28 }
29 }
30 }
31 }
32 .into()
33}
34
35#[proc_macro]
39pub fn offset(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
40 let expression = match syn::parse::<syn::Expr>(tokens) {
41 Ok(ok) => ok,
42 Err(err) => {
43 return err.into_compile_error().into();
44 }
45 };
46
47 let org_expr = unpack_brackets(&expression);
48 let (sign, expr) = unpack_negative_sign(org_expr);
49
50 match expr {
51 syn::Expr::Lit(expr_lit) => match &expr_lit.lit {
52 syn::Lit::Int(lit_int) => {
53 let Ok(value) = lit_int.base10_parse::<i32>() else {
54 return quote! {
55 compile_error!("Invalid literal integer.");
56 }
57 .into();
58 };
59
60 let real_value = value * sign;
61
62 quote! {
63 {
64 const {
65 match ::osom_primitives::offset::Offset::try_from_i32(#real_value) {
66 Ok(val) => val,
67 Err(_) => panic!("The literal value is out of [Offset::MIN_OFFSET..Offset::MAX_OFFSET] range."),
68 }
69 }
70 }
71 }.into()
72 }
73 _ => quote! {
74 compile_error!("Expected literal integer.");
75 }
76 .into(),
77 },
78 _ => quote! {
79 {
80 ::osom_primitives::offset::Offset::try_from_i32(#org_expr).unwrap()
81 }
82 }
83 .into(),
84 }
85}
86
87fn unpack_brackets(expr: &syn::Expr) -> &syn::Expr {
88 match expr {
89 syn::Expr::Paren(expr_paren) => unpack_brackets(&expr_paren.expr),
90 expr => expr,
91 }
92}
93
94fn unpack_negative_sign(expr: &syn::Expr) -> (i32, &syn::Expr) {
95 match expr {
96 syn::Expr::Unary(expr_unary) => {
97 match expr_unary.op {
98 syn::UnOp::Neg(_) => {}
99 _ => {
100 panic!("Invalid unary expression, expected either positive or negative integer.");
101 }
102 }
103 (-1, &expr_unary.expr)
104 }
105 expr => (1, expr),
106 }
107}