cmark_writer_macros/
lib.rs1extern crate proc_macro;
2use proc_macro::TokenStream;
3use quote::quote;
4use syn::{parse_macro_input, DeriveInput};
5
6#[proc_macro_attribute]
39pub fn custom_node(_attr: TokenStream, item: TokenStream) -> TokenStream {
40 let input = parse_macro_input!(item as DeriveInput);
41 let name = &input.ident;
42
43 let expanded = quote! {
44 #input
45
46 impl ::cmark_writer::ast::CustomNode for #name {
47 fn write(
48 &self,
49 writer: &mut dyn ::cmark_writer::ast::CustomNodeWriter,
50 ) -> ::cmark_writer::error::WriteResult<()> {
51 self.write_custom(writer)
52 }
53
54 fn clone_box(&self) -> Box<dyn ::cmark_writer::ast::CustomNode> {
55 Box::new(self.clone())
56 }
57
58 fn eq_box(&self, other: &dyn ::cmark_writer::ast::CustomNode) -> bool {
59 if let Some(other) = other.as_any().downcast_ref::<Self>() {
60 self == other
61 } else {
62 false
63 }
64 }
65
66 fn is_block(&self) -> bool {
67 self.is_block_custom()
68 }
69
70 fn as_any(&self) -> &dyn std::any::Any {
71 self
72 }
73 }
74 };
75
76 TokenStream::from(expanded)
77}
78
79#[proc_macro_attribute]
90pub fn custom_error(attr: TokenStream, item: TokenStream) -> TokenStream {
91 let attr_str = attr.to_string();
92 let input = parse_macro_input!(item as DeriveInput);
93 let name = &input.ident;
94
95 let format = if attr_str.starts_with("format") {
97 let format_str = attr_str
98 .replace("format", "")
99 .replace("=", "")
100 .trim()
101 .trim_matches('"')
102 .to_string();
103 format_str
104 } else {
105 "{}".to_string()
107 };
108
109 let expanded = quote! {
110 #input
111
112 impl #name {
113 pub fn new(message: &'static str) -> Self {
114 Self(message)
115 }
116
117 pub fn into_error(self) -> ::cmark_writer::error::WriteError {
118 let mut error_factory = ::cmark_writer::error::StructureError::new(#format);
119
120 let arg = self.0.to_string();
121 error_factory = error_factory.arg(arg);
122
123 <::cmark_writer::error::StructureError as ::cmark_writer::error::CustomErrorFactory>::create_error(&error_factory)
124 }
125 }
126
127 impl From<#name> for ::cmark_writer::error::WriteError {
128 fn from(factory: #name) -> Self {
129 factory.into_error()
130 }
131 }
132
133 impl ::cmark_writer::error::CustomErrorFactory for #name {
134 fn create_error(&self) -> ::cmark_writer::error::WriteError {
135 let mut error_factory = ::cmark_writer::error::StructureError::new(#format);
136
137 let arg = self.0.to_string();
138 error_factory = error_factory.arg(arg);
139
140 <::cmark_writer::error::StructureError as ::cmark_writer::error::CustomErrorFactory>::create_error(&error_factory)
141 }
142 }
143 };
144
145 TokenStream::from(expanded)
146}
147
148#[proc_macro_attribute]
159pub fn coded_error(_attr: TokenStream, item: TokenStream) -> TokenStream {
160 let input = parse_macro_input!(item as DeriveInput);
161 let name = &input.ident;
162
163 let expanded = quote! {
164 #input
165
166 impl #name {
167 pub fn new(message: &str, code: &str) -> Self {
168 Self(message.to_string(), code.to_string())
169 }
170
171 pub fn into_error(self) -> ::cmark_writer::error::WriteError {
172 let coded_error = ::cmark_writer::error::CodedError::new(self.0, self.1);
173 <::cmark_writer::error::CodedError as ::cmark_writer::error::CustomErrorFactory>::create_error(&coded_error)
174 }
175 }
176
177 impl From<#name> for ::cmark_writer::error::WriteError {
178 fn from(factory: #name) -> Self {
179 factory.into_error()
180 }
181 }
182
183 impl ::cmark_writer::error::CustomErrorFactory for #name {
184 fn create_error(&self) -> ::cmark_writer::error::WriteError {
185 let coded_error = ::cmark_writer::error::CodedError::new(self.0.clone(), self.1.clone());
186 <::cmark_writer::error::CodedError as ::cmark_writer::error::CustomErrorFactory>::create_error(&coded_error)
187 }
188 }
189 };
190
191 TokenStream::from(expanded)
192}