1use proc_macro::TokenStream;
50use quote::quote;
51use syn::{parse_macro_input, DeriveInput, Type};
52
53#[proc_macro_attribute]
125pub fn midds_string(args: TokenStream, input: TokenStream) -> TokenStream {
126 let input = parse_macro_input!(input as DeriveInput);
127 let struct_name = &input.ident;
128 let vis = &input.vis;
129
130 let (bound, regex_pattern) = if args.is_empty() {
132 (128, None)
133 } else {
134 let args_str = args.to_string();
136
137 if args_str.contains("regex") {
139 let parts: Vec<&str> = args_str.split(',').collect();
141 assert!(parts.len() == 2, "Expected format: bound, regex = \"pattern\"");
142
143 let bound_str = parts[0].trim();
144 let bound: u32 = bound_str.parse().expect("Invalid bound");
145
146 let regex_part = parts[1].trim();
147 assert!(regex_part.starts_with("regex"), "Second argument must be regex = \"pattern\"");
148
149 let eq_pos = regex_part.find('=').expect("Expected = after regex");
151 let pattern_part = regex_part[eq_pos + 1..].trim();
152
153 let pattern = if pattern_part.starts_with("r#\"") && pattern_part.ends_with("\"#") {
155 &pattern_part[3..pattern_part.len() - 2]
156 } else if pattern_part.starts_with("r\"") && pattern_part.ends_with('"') {
157 &pattern_part[2..pattern_part.len() - 1]
158 } else if pattern_part.starts_with('"') && pattern_part.ends_with('"') {
159 &pattern_part[1..pattern_part.len() - 1]
160 } else {
161 panic!("Regex pattern must be quoted (use \"pattern\" or r\"pattern\")");
162 };
163
164 (bound, Some(pattern.to_string()))
165 } else {
166 let bound: u32 = args_str.parse().expect("Invalid bound");
168 (bound, None)
169 }
170 };
171
172 let attrs: Vec<_> = input
174 .attrs
175 .iter()
176 .filter(|attr| !attr.path().is_ident("midds_string"))
177 .collect();
178
179 let error_name = quote::format_ident!("{}Error", struct_name);
181
182 let validation_error_variant = if regex_pattern.is_some() {
184 quote! { InvalidFormat, }
185 } else {
186 quote! {}
187 };
188
189 let validation_error_display = if let Some(ref pattern) = regex_pattern {
190 quote! {
191 #error_name::InvalidFormat => write!(f, "String does not match required format: {}", #pattern),
192 }
193 } else {
194 quote! {}
195 };
196
197 let validation_pattern_method = if let Some(ref pattern) = regex_pattern {
198 quote! {
199 #[cfg(feature = "std")]
200 pub fn validation_pattern() -> Option<&'static str> {
201 Some(#pattern)
202 }
203
204 #[cfg(not(feature = "std"))]
205 pub fn validation_pattern() -> Option<&'static str> {
206 None
207 }
208 }
209 } else {
210 quote! {
211 pub fn validation_pattern() -> Option<&'static str> {
212 None
213 }
214 }
215 };
216
217
218
219 let validation_method = if regex_pattern.is_some() {
220 quote! {
221 #[cfg(feature = "std")]
223 pub fn validate(&self) -> Result<(), #error_name> {
224 if let Some(pattern) = Self::validation_pattern() {
225 let regex = ::regex::Regex::new(pattern)
226 .expect("Invalid regex pattern in midds_string macro");
227 if !regex.is_match(self.as_str()) {
228 return Err(#error_name::InvalidFormat);
229 }
230 }
231 Ok(())
232 }
233 }
234 } else {
235 quote! {}
236 };
237
238 let regex_validation_in_from_str = if regex_pattern.is_some() {
239 quote! {
240 #[cfg(feature = "std")]
242 {
243 if let Some(pattern) = Self::validation_pattern() {
244 let regex = ::regex::Regex::new(pattern)
245 .expect("Invalid regex pattern in midds_string macro");
246 if !regex.is_match(&normalized) {
247 return Err(#error_name::InvalidFormat);
248 }
249 }
250 }
251 }
252 } else {
253 quote! {}
254 };
255
256 let expanded = quote! {
257 #[derive(Debug, Clone)]
259 #vis enum #error_name {
260 InvalidUtf8,
261 TooLong,
262 #validation_error_variant
263 }
264
265 impl core::fmt::Display for #error_name {
266 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
267 match self {
268 #error_name::InvalidUtf8 => write!(f, "Invalid UTF-8 sequence"),
269 #error_name::TooLong => write!(f, "String too long, maximum {} bytes", #bound),
270 #validation_error_display
271 }
272 }
273 }
274
275 #[cfg(feature = "std")]
276 impl std::error::Error for #error_name {}
277
278 #(#attrs)*
279 #[cfg_attr(feature = "js", ::wasm_bindgen::prelude::wasm_bindgen)]
280 #[derive(
281 Clone,
282 PartialEq,
283 Eq,
284 ::parity_scale_codec::Encode,
285 ::parity_scale_codec::Decode,
286 ::parity_scale_codec::DecodeWithMemTracking,
287 ::scale_info::TypeInfo,
288 ::parity_scale_codec::MaxEncodedLen,
289 ::sp_runtime::RuntimeDebug
290 )]
291 #[cfg_attr(feature = "js", derive(::serde::Serialize, ::serde::Deserialize))]
292 #vis struct #struct_name(::sp_runtime::BoundedVec<u8, ::frame_support::traits::ConstU32<#bound>>);
293
294 impl ::core::str::FromStr for #struct_name {
295 type Err = #error_name;
296
297 fn from_str(s: &str) -> Result<Self, Self::Err> {
298 #[cfg(feature = "std")]
300 let normalized = s.replace([' ', '-', '_'], "");
301
302 #[cfg(not(feature = "std"))]
303 let normalized = s.to_string();
304
305 let bytes = normalized.as_bytes();
306 if bytes.len() > #bound as usize {
307 return Err(#error_name::TooLong);
308 }
309
310 #regex_validation_in_from_str
311
312 ::sp_runtime::BoundedVec::try_from(bytes.to_vec())
313 .map(#struct_name)
314 .map_err(|_| #error_name::TooLong)
315 }
316 }
317
318 impl #struct_name {
319 pub fn new() -> Self {
320 Self(::sp_runtime::BoundedVec::new())
321 }
322
323 #validation_pattern_method
325
326 #validation_method
327
328
329 pub fn from_utf8(bytes: Vec<u8>) -> Result<Self, #error_name> {
330 let s = core::str::from_utf8(&bytes).map_err(|_| #error_name::InvalidUtf8)?;
331
332 <Self as ::core::str::FromStr>::from_str(s)
334 }
335
336 pub fn as_str(&self) -> &str {
337 core::str::from_utf8(&self.0).expect("Valid UTF-8 checked on construction")
338 }
339
340 pub fn as_bytes(&self) -> &[u8] {
341 &self.0
342 }
343
344 pub fn len(&self) -> usize {
345 self.0.len()
346 }
347
348 pub fn is_empty(&self) -> bool {
349 self.0.is_empty()
350 }
351
352 pub fn capacity(&self) -> usize {
353 #bound as usize
354 }
355
356 pub fn max_capacity(&self) -> usize {
357 #bound as usize
358 }
359
360 pub fn remaining_capacity(&self) -> usize {
361 self.capacity() - self.len()
362 }
363
364 pub fn push_str(&mut self, s: &str) -> Result<(), #error_name> {
365 let current = self.as_str();
367 let combined = format!("{}{}", current, s);
368
369 let normalized_instance = <Self as ::core::str::FromStr>::from_str(&combined)?;
371
372 *self = normalized_instance;
374
375 Ok(())
376 }
377
378 pub fn push(&mut self, ch: char) -> Result<(), #error_name> {
379 let mut buf = [0; 4];
380 let s = ch.encode_utf8(&mut buf);
381 self.push_str(s)
382 }
383
384 pub fn pop(&mut self) -> Option<char> {
385 if self.is_empty() {
386 return None;
387 }
388
389 let s = self.as_str();
390 let mut chars = s.chars();
391 let last_char = chars.next_back()?;
392 let new_len = s.len() - last_char.len_utf8();
393 self.0.truncate(new_len);
394 Some(last_char)
395 }
396
397 pub fn clear(&mut self) {
398 self.0.clear();
399 }
400
401 pub fn truncate(&mut self, new_len: usize) {
402 if new_len <= self.len() {
403 let s = self.as_str();
404 if let Some((byte_index, _)) = s.char_indices().nth(new_len) {
405 self.0.truncate(byte_index);
406 } else {
407 self.0.truncate(new_len.min(s.len()));
408 }
409 }
410 }
411
412 pub fn into_string(self) -> String {
413 String::from_utf8(self.0.into_inner()).expect("Invalid UTF-8")
414 }
415
416
417 pub fn into_inner(self) -> ::sp_runtime::BoundedVec<u8, ::frame_support::traits::ConstU32<#bound>> {
418 self.0
419 }
420
421 pub fn get(&self, range: core::ops::Range<usize>) -> Option<&str> {
422 self.as_str().get(range)
423 }
424 }
425
426 impl Default for #struct_name {
427 fn default() -> Self {
428 Self::new()
429 }
430 }
431
432 impl core::fmt::Display for #struct_name {
433 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
434 write!(f, "{}", self.as_str())
435 }
436 }
437
438 impl core::ops::Deref for #struct_name {
439 type Target = str;
440
441 fn deref(&self) -> &Self::Target {
442 self.as_str()
443 }
444 }
445
446 impl AsRef<str> for #struct_name {
447 fn as_ref(&self) -> &str {
448 self.as_str()
449 }
450 }
451
452 impl AsRef<[u8]> for #struct_name {
453 fn as_ref(&self) -> &[u8] {
454 self.as_bytes()
455 }
456 }
457
458 impl From<#struct_name> for String {
459 fn from(ms: #struct_name) -> String {
460 ms.into_string()
461 }
462 }
463
464 impl TryFrom<String> for #struct_name {
465 type Error = #error_name;
466
467 fn try_from(s: String) -> Result<Self, Self::Error> {
468 Self::from_utf8(s.into_bytes())
469 }
470 }
471
472 impl TryFrom<&str> for #struct_name {
473 type Error = #error_name;
474
475 fn try_from(s: &str) -> Result<Self, Self::Error> {
476 <#struct_name as ::core::str::FromStr>::from_str(s)
477 }
478 }
479
480 impl PartialEq<str> for #struct_name {
481 fn eq(&self, other: &str) -> bool {
482 self.as_str() == other
483 }
484 }
485
486 impl PartialEq<&str> for #struct_name {
487 fn eq(&self, other: &&str) -> bool {
488 self.as_str() == *other
489 }
490 }
491
492 impl PartialEq<String> for #struct_name {
493 fn eq(&self, other: &String) -> bool {
494 self.as_str() == other.as_str()
495 }
496 }
497
498 #[cfg(feature = "js")]
499 #[::wasm_bindgen::prelude::wasm_bindgen]
500 impl #struct_name {
501 #[::wasm_bindgen::prelude::wasm_bindgen(constructor)]
502 pub fn js_new() -> #struct_name {
503 Self::new()
504 }
505
506 #[::wasm_bindgen::prelude::wasm_bindgen(getter)]
507 pub fn value(&self) -> String {
508 self.as_str().to_string()
509 }
510
511 #[::wasm_bindgen::prelude::wasm_bindgen(setter)]
512 pub fn set_value(&mut self, value: &str) -> Result<(), ::wasm_bindgen::JsError> {
513 *self = <#struct_name as ::core::str::FromStr>::from_str(value).map_err(|e| ::wasm_bindgen::JsError::new(&e.to_string()))?;
514 Ok(())
515 }
516
517 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "fromString")]
518 pub fn js_from_string(s: &str) -> Result<#struct_name, ::wasm_bindgen::JsError> {
519 <#struct_name as ::core::str::FromStr>::from_str(s).map_err(|e| ::wasm_bindgen::JsError::new(&e.to_string()))
520 }
521
522 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "toString")]
523 pub fn js_to_string(&self) -> String {
524 self.as_str().to_string()
525 }
526
527 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "pushStr")]
528 pub fn js_push_str(&mut self, s: &str) -> Result<(), ::wasm_bindgen::JsError> {
529 self.push_str(s).map_err(|e| ::wasm_bindgen::JsError::new(&e.to_string()))
530 }
531
532 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "length")]
533 pub fn js_length(&self) -> usize {
534 self.len()
535 }
536
537 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "capacity")]
538 pub fn js_capacity(&self) -> usize {
539 self.capacity()
540 }
541
542 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "maxCapacity")]
543 pub fn js_max_capacity(&self) -> usize {
544 self.max_capacity()
545 }
546
547 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "remainingCapacity")]
548 pub fn js_remaining_capacity(&self) -> usize {
549 self.remaining_capacity()
550 }
551
552 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "isEmpty")]
553 pub fn js_is_empty(&self) -> bool {
554 self.is_empty()
555 }
556
557 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "clear")]
558 pub fn js_clear(&mut self) {
559 self.clear()
560 }
561
562 }
563 };
564
565 TokenStream::from(expanded)
566}
567
568#[proc_macro_attribute]
642pub fn midds_collection(args: TokenStream, input: TokenStream) -> TokenStream {
643 let input = parse_macro_input!(input as DeriveInput);
644 let struct_name = &input.ident;
645 let vis = &input.vis;
646
647 let args_str = args.to_string();
649 let args_parts: Vec<&str> = args_str.split(',').map(str::trim).collect();
650
651 assert!(args_parts.len() == 2, "midds_collection expects exactly 2 arguments: type and bound");
652
653 let inner_type = args_parts[0];
654 let bound_str = args_parts[1];
655 let bound: u32 = bound_str.parse().expect("Invalid bound, expected number");
656
657 let inner_type_ident: Type = syn::parse_str(inner_type).expect("Invalid inner type");
659
660 let attrs: Vec<_> = input
662 .attrs
663 .iter()
664 .filter(|attr| !attr.path().is_ident("midds_collection"))
665 .collect();
666
667 let error_name = quote::format_ident!("{}Error", struct_name);
669
670 let expanded = quote! {
671 #[derive(Debug, Clone)]
673 #vis enum #error_name {
674 TooManyItems,
675 InvalidItem,
676 }
677
678 impl core::fmt::Display for #error_name {
679 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
680 match self {
681 #error_name::TooManyItems => write!(f, "Too many items, maximum {} items", #bound),
682 #error_name::InvalidItem => write!(f, "Invalid item in collection"),
683 }
684 }
685 }
686
687 #[cfg(feature = "std")]
688 impl std::error::Error for #error_name {}
689
690 #(#attrs)*
691 #[cfg_attr(feature = "js", ::wasm_bindgen::prelude::wasm_bindgen)]
692 #[derive(
693 Clone,
694 PartialEq,
695 Eq,
696 ::parity_scale_codec::Encode,
697 ::parity_scale_codec::Decode,
698 ::parity_scale_codec::DecodeWithMemTracking,
699 ::scale_info::TypeInfo,
700 ::parity_scale_codec::MaxEncodedLen,
701 ::sp_runtime::RuntimeDebug
702 )]
703 #[cfg_attr(feature = "js", derive(::serde::Serialize, ::serde::Deserialize))]
704 #vis struct #struct_name(::sp_runtime::BoundedVec<#inner_type_ident, ::frame_support::traits::ConstU32<#bound>>);
705
706 impl #struct_name {
707 pub fn new() -> Self {
708 Self(::sp_runtime::BoundedVec::new())
709 }
710
711 pub fn with_capacity(_capacity: usize) -> Self {
712 Self(::sp_runtime::BoundedVec::new())
714 }
715
716 pub fn try_from_vec(vec: Vec<#inner_type_ident>) -> Result<Self, #error_name> {
717 if vec.len() > #bound as usize {
718 return Err(#error_name::TooManyItems);
719 }
720
721 ::sp_runtime::BoundedVec::try_from(vec)
722 .map(#struct_name)
723 .map_err(|_| #error_name::TooManyItems)
724 }
725
726 pub fn len(&self) -> usize {
727 self.0.len()
728 }
729
730 pub fn is_empty(&self) -> bool {
731 self.0.is_empty()
732 }
733
734 pub fn capacity(&self) -> usize {
735 #bound as usize
736 }
737
738 pub fn max_capacity(&self) -> usize {
739 #bound as usize
740 }
741
742 pub fn remaining_capacity(&self) -> usize {
743 self.capacity() - self.len()
744 }
745
746 pub fn push(&mut self, item: #inner_type_ident) -> Result<(), #error_name> {
747 self.0.try_push(item).map_err(|_| #error_name::TooManyItems)
748 }
749
750 pub fn pop(&mut self) -> Option<#inner_type_ident> {
751 self.0.pop()
752 }
753
754 pub fn insert(&mut self, index: usize, item: #inner_type_ident) -> Result<(), #error_name> {
755 if self.len() >= #bound as usize {
756 return Err(#error_name::TooManyItems);
757 }
758 self.0.try_insert(index, item).map_err(|_| #error_name::TooManyItems)
759 }
760
761 pub fn remove(&mut self, index: usize) -> #inner_type_ident {
762 self.0.remove(index)
763 }
764
765 pub fn clear(&mut self) {
766 self.0.clear();
767 }
768
769 pub fn get(&self, index: usize) -> Option<&#inner_type_ident> {
770 self.0.get(index)
771 }
772
773 pub fn get_mut(&mut self, index: usize) -> Option<&mut #inner_type_ident> {
774 self.0.get_mut(index)
775 }
776
777 pub fn iter(&self) -> impl Iterator<Item = &#inner_type_ident> {
778 self.0.iter()
779 }
780
781 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut #inner_type_ident> {
782 self.0.iter_mut()
783 }
784
785 pub fn as_slice(&self) -> &[#inner_type_ident] {
786 &self.0
787 }
788
789 pub fn as_mut_slice(&mut self) -> &mut [#inner_type_ident] {
790 self.0.as_mut()
791 }
792
793 pub fn into_vec(self) -> Vec<#inner_type_ident> {
794 self.0.into_inner()
795 }
796
797 pub fn into_inner(self) -> ::sp_runtime::BoundedVec<#inner_type_ident, ::frame_support::traits::ConstU32<#bound>> {
798 self.0
799 }
800
801 pub fn extend_from_slice(&mut self, slice: &[#inner_type_ident]) -> Result<(), #error_name>
802 where
803 #inner_type_ident: Clone
804 {
805 if self.len() + slice.len() > #bound as usize {
806 return Err(#error_name::TooManyItems);
807 }
808
809 for item in slice {
810 self.0.try_push(item.clone()).map_err(|_| #error_name::TooManyItems)?;
811 }
812 Ok(())
813 }
814
815 }
816
817 impl Default for #struct_name {
818 fn default() -> Self {
819 Self::new()
820 }
821 }
822
823 impl core::ops::Deref for #struct_name {
824 type Target = [#inner_type_ident];
825
826 fn deref(&self) -> &Self::Target {
827 &self.0
828 }
829 }
830
831 impl AsRef<[#inner_type_ident]> for #struct_name {
832 fn as_ref(&self) -> &[#inner_type_ident] {
833 &self.0
834 }
835 }
836
837 impl AsMut<[#inner_type_ident]> for #struct_name {
838 fn as_mut(&mut self) -> &mut [#inner_type_ident] {
839 self.0.as_mut()
840 }
841 }
842
843 impl From<#struct_name> for Vec<#inner_type_ident> {
844 fn from(collection: #struct_name) -> Vec<#inner_type_ident> {
845 collection.into_vec()
846 }
847 }
848
849 impl TryFrom<Vec<#inner_type_ident>> for #struct_name {
850 type Error = #error_name;
851
852 fn try_from(vec: Vec<#inner_type_ident>) -> Result<Self, Self::Error> {
853 Self::try_from_vec(vec)
854 }
855 }
856
857 impl<'a> IntoIterator for &'a #struct_name {
858 type Item = &'a #inner_type_ident;
859 type IntoIter = core::slice::Iter<'a, #inner_type_ident>;
860
861 fn into_iter(self) -> Self::IntoIter {
862 self.0.iter()
863 }
864 }
865
866 impl<'a> IntoIterator for &'a mut #struct_name {
867 type Item = &'a mut #inner_type_ident;
868 type IntoIter = core::slice::IterMut<'a, #inner_type_ident>;
869
870 fn into_iter(self) -> Self::IntoIter {
871 self.0.iter_mut()
872 }
873 }
874
875 impl IntoIterator for #struct_name {
876 type Item = #inner_type_ident;
877 type IntoIter = alloc::vec::IntoIter<#inner_type_ident>;
878
879 fn into_iter(self) -> Self::IntoIter {
880 self.0.into_inner().into_iter()
881 }
882 }
883
884 #[cfg(feature = "js")]
885 #[::wasm_bindgen::prelude::wasm_bindgen]
886 impl #struct_name {
887 #[::wasm_bindgen::prelude::wasm_bindgen(constructor)]
888 pub fn js_new() -> #struct_name {
889 Self::new()
890 }
891
892 #[::wasm_bindgen::prelude::wasm_bindgen(getter)]
894 pub fn items(&self) -> ::wasm_bindgen::JsValue {
895 ::wasm_bindgen::JsValue::NULL
897 }
898
899 #[::wasm_bindgen::prelude::wasm_bindgen(setter)]
900 pub fn set_items(&mut self, items: ::wasm_bindgen::JsValue) -> Result<(), ::wasm_bindgen::JsError> {
901 Err(::wasm_bindgen::JsError::new("Use fromArray() method instead"))
903 }
904
905 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "pushItem")]
907 pub fn js_push_item(&mut self, item: #inner_type_ident) -> Result<(), ::wasm_bindgen::JsError> {
908 self.push(item).map_err(|e| ::wasm_bindgen::JsError::new(&e.to_string()))
909 }
910
911 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "popItem")]
912 pub fn js_pop_item(&mut self) -> Option<#inner_type_ident> {
913 self.pop()
914 }
915
916 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "getItem")]
917 pub fn js_get_item(&self, index: usize) -> Option<#inner_type_ident>
918 where
919 #inner_type_ident: Clone
920 {
921 self.get(index).cloned()
922 }
923
924 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "insertItem")]
925 pub fn js_insert_item(&mut self, index: usize, item: #inner_type_ident) -> Result<(), ::wasm_bindgen::JsError> {
926 self.insert(index, item).map_err(|e| ::wasm_bindgen::JsError::new(&e.to_string()))
927 }
928
929 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "removeItem")]
930 pub fn js_remove_item(&mut self, index: usize) -> Result<#inner_type_ident, ::wasm_bindgen::JsError> {
931 if index >= self.len() {
932 return Err(::wasm_bindgen::JsError::new("Index out of bounds"));
933 }
934 Ok(self.remove(index))
935 }
936
937 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "length")]
938 pub fn js_length(&self) -> usize {
939 self.len()
940 }
941
942 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "capacity")]
943 pub fn js_capacity(&self) -> usize {
944 self.capacity()
945 }
946
947 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "maxCapacity")]
948 pub fn js_max_capacity(&self) -> usize {
949 self.max_capacity()
950 }
951
952 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "remainingCapacity")]
953 pub fn js_remaining_capacity(&self) -> usize {
954 self.remaining_capacity()
955 }
956
957 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "isEmpty")]
958 pub fn js_is_empty(&self) -> bool {
959 self.is_empty()
960 }
961
962 #[::wasm_bindgen::prelude::wasm_bindgen(js_name = "clear")]
963 pub fn js_clear(&mut self) {
964 self.clear()
965 }
966
967
968 }
971 };
972
973 TokenStream::from(expanded)
974}