1 | use defmt_parser::Level; |
2 | use proc_macro::TokenStream; |
3 | use quote::quote; |
4 | use syn::{parse_macro_input, punctuated::Punctuated}; |
5 | |
6 | use crate::{construct, function_like::log}; |
7 | |
8 | use self::args::Args; |
9 | |
10 | mod args; |
11 | |
12 | pub(crate) fn eq(args: TokenStream) -> TokenStream { |
13 | expand(args, binop:BinOp::Eq) |
14 | } |
15 | |
16 | pub(crate) fn ne(args: TokenStream) -> TokenStream { |
17 | expand(args, binop:BinOp::Ne) |
18 | } |
19 | |
20 | fn expand(args: TokenStream, binop: BinOp) -> TokenStream { |
21 | let args = parse_macro_input!(args as Args); |
22 | |
23 | let left = args.left; |
24 | let right = args.right; |
25 | |
26 | let mut formatting_args = Punctuated::new(); |
27 | |
28 | let extra_string = if let Some(log_args) = args.log_args { |
29 | if let Some(args) = log_args.formatting_args { |
30 | formatting_args.extend(args); |
31 | } |
32 | format!(": {}" , log_args.format_string.value()) |
33 | } else { |
34 | String::new() |
35 | }; |
36 | |
37 | let vals = match binop { |
38 | BinOp::Eq => &["left_val" , "right_val" ][..], |
39 | BinOp::Ne => &["left_val" ][..], |
40 | }; |
41 | |
42 | for val in vals { |
43 | formatting_args.push(construct::variable(val)); |
44 | } |
45 | |
46 | let panic_msg = match binop { |
47 | BinOp::Eq => format!( |
48 | "panicked at 'assertion failed: `(left == right)` {}' |
49 | left: ` {{:? }}` |
50 | right: ` {{:? }}`" , |
51 | extra_string |
52 | ), |
53 | BinOp::Ne => format!( |
54 | "panicked at 'assertion failed: `(left != right)` {}' |
55 | left/right: ` {{:? }}`" , |
56 | extra_string |
57 | ), |
58 | }; |
59 | |
60 | let log_args = log::Args { |
61 | format_string: construct::string_literal(&panic_msg), |
62 | formatting_args: Some(formatting_args), |
63 | }; |
64 | let log_stmt = log::expand_parsed(Level::Error, log_args); |
65 | |
66 | let mut cond = quote!(*left_val == *right_val); |
67 | if binop == BinOp::Eq { |
68 | cond = quote!(!(#cond)); |
69 | } |
70 | |
71 | quote!( |
72 | // evaluate arguments first |
73 | match (&(#left), &(#right)) { |
74 | (left_val, right_val) => { |
75 | // following `core::assert_eq!` |
76 | if #cond { |
77 | #log_stmt; |
78 | defmt::export::panic() |
79 | } |
80 | } |
81 | } |
82 | ) |
83 | .into() |
84 | } |
85 | |
86 | #[derive (PartialEq)] |
87 | enum BinOp { |
88 | Eq, |
89 | Ne, |
90 | } |
91 | |