1use std::cell::RefCell;
2
3use proc_macro2::Span;
4use proc_macro2::TokenStream;
5use quote::quote_spanned;
6use quote::{quote, ToTokens};
7use syn::parse::ParseStream;
8use syn::punctuated::Punctuated;
9use syn::spanned::Spanned as _;
10use syn::Token;
11
12use rune_core::protocol::Protocol;
13
14use super::RUNE;
15
16#[derive(Default)]
18#[must_use = "Attributes must be used or explicitly ignored"]
19pub(crate) struct FieldAttrs {
20 pub(crate) id: Option<Span>,
23 pub(crate) iter: Option<Span>,
25 pub(crate) skip: Option<Span>,
27 pub(crate) option: Option<Span>,
29 pub(crate) meta: Option<Span>,
31 pub(crate) span: Option<Span>,
33 pub(crate) parse_with: Option<syn::Ident>,
35 pub(crate) protocols: Vec<FieldProtocol>,
37 pub(crate) copy: bool,
40 pub(crate) field: bool,
42}
43
44impl FieldAttrs {
45 pub(crate) fn skip(&self) -> bool {
47 self.skip.is_some() || self.id.is_some()
48 }
49}
50
51#[derive(Default)]
53#[must_use = "Attributes must be used or explicitly ignored"]
54pub(crate) struct ConstValueFieldAttrs {
55 pub(crate) with: Option<syn::Path>,
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
61pub(crate) enum ParseKind {
62 Default,
64 MetaOnly,
66}
67
68impl Default for ParseKind {
69 fn default() -> Self {
70 Self::Default
71 }
72}
73
74#[derive(Default)]
76#[must_use = "Attributes must be used or explicitly ignored"]
77pub(crate) struct TypeAttr {
78 pub(crate) name: Option<syn::Ident>,
80 pub(crate) module: Option<syn::Path>,
82 pub(crate) install_with: Option<syn::Path>,
84 pub(crate) parse: ParseKind,
86 pub(crate) item: Option<syn::Path>,
88 pub(crate) constructor: Option<Span>,
90 pub(crate) docs: Vec<syn::Expr>,
92 pub(crate) impl_params: Option<syn::punctuated::Punctuated<syn::TypeParam, Token![,]>>,
94}
95
96#[derive(Default)]
98#[must_use = "Attributes must be used or explicitly ignored"]
99pub(crate) struct ConstValueTypeAttr {
100 pub(crate) module: Option<syn::Path>,
102}
103
104#[derive(Default)]
106#[must_use = "Attributes must be used or explicitly ignored"]
107pub(crate) struct VariantAttrs {
108 pub(crate) constructor: Option<Span>,
110 pub(crate) docs: Vec<syn::Expr>,
112}
113
114#[derive(Clone, Copy)]
115pub(crate) enum GenerateTarget<'a> {
116 Named {
117 field_ident: &'a syn::Ident,
118 field_name: &'a syn::LitStr,
119 },
120 Numbered {
121 field_index: &'a syn::LitInt,
122 },
123}
124
125#[derive(Clone)]
126pub(crate) struct Generate<'a> {
127 pub(crate) tokens: &'a Tokens,
128 pub(crate) attrs: &'a FieldAttrs,
129 pub(crate) protocol: &'a FieldProtocol,
130 pub(crate) field: &'a syn::Field,
131 pub(crate) ty: &'a syn::Type,
132 pub(crate) target: GenerateTarget<'a>,
133}
134
135pub(crate) struct FieldProtocol {
136 pub(crate) generate: fn(Generate<'_>) -> TokenStream,
137 custom: Option<syn::Path>,
138}
139
140#[derive(Default)]
141pub(crate) struct Context {
142 pub(crate) errors: RefCell<Vec<syn::Error>>,
143 pub(crate) module: Option<syn::Path>,
144}
145
146impl Context {
147 pub(crate) fn new() -> Self {
149 Self::default()
150 }
151
152 pub(crate) fn with_crate() -> Self {
155 let mut crate_module = syn::Path {
156 leading_colon: None,
157 segments: Punctuated::default(),
158 };
159 crate_module
160 .segments
161 .push(syn::PathSegment::from(<Token![crate]>::default()));
162
163 Self {
164 errors: RefCell::new(Vec::new()),
165 module: Some(crate_module),
166 }
167 }
168
169 pub(super) fn build(f: impl FnOnce(&Self) -> Result<TokenStream, ()>) -> TokenStream {
171 let cx = Self::new();
172 cx.build_inner(f)
173 }
174
175 pub(super) fn build_with_crate(
177 f: impl FnOnce(&Self) -> Result<TokenStream, ()>,
178 ) -> TokenStream {
179 let cx = Self::with_crate();
180 cx.build_inner(f)
181 }
182
183 fn build_inner(self, f: impl FnOnce(&Self) -> Result<TokenStream, ()>) -> TokenStream {
184 fn to_compile_errors<I>(errors: I) -> TokenStream
185 where
186 I: IntoIterator<Item = syn::Error>,
187 {
188 let mut stream = TokenStream::default();
189
190 for error in errors {
191 stream.extend(error.into_compile_error());
192 }
193
194 stream
195 }
196
197 let Ok(builder) = f(&self) else {
198 return to_compile_errors(self.errors.into_inner());
199 };
200
201 let errors = self.errors.into_inner();
202
203 if !errors.is_empty() {
204 return to_compile_errors(errors);
205 }
206
207 builder
208 }
209
210 pub(crate) fn error(&self, error: syn::Error) {
212 self.errors.borrow_mut().push(error)
213 }
214
215 pub(crate) fn has_errors(&self) -> bool {
217 !self.errors.borrow().is_empty()
218 }
219
220 pub(crate) fn field_ident<'a>(&self, field: &'a syn::Field) -> Result<&'a syn::Ident, ()> {
222 let Some(ident) = &field.ident else {
223 self.error(syn::Error::new_spanned(
224 field,
225 "Unnamed fields are not supported",
226 ));
227 return Err(());
228 };
229
230 Ok(ident)
231 }
232
233 pub(crate) fn const_value_field_attrs(&self, input: &[syn::Attribute]) -> ConstValueFieldAttrs {
234 let mut attr = ConstValueFieldAttrs::default();
235
236 for a in input {
237 if !a.path().is_ident("const_value") {
238 continue;
239 }
240
241 let result = a.parse_nested_meta(|meta| {
242 if meta.path.is_ident("with") {
243 meta.input.parse::<Token![=]>()?;
244 attr.with = Some(meta.input.parse::<syn::Path>()?);
245 return Ok(());
246 }
247
248 Err(syn::Error::new_spanned(
249 &meta.path,
250 "Unsupported field attribute",
251 ))
252 });
253
254 if let Err(e) = result {
255 self.error(e);
256 };
257 }
258
259 attr
260 }
261
262 pub(crate) fn field_attrs(&self, input: &[syn::Attribute]) -> FieldAttrs {
264 macro_rules! generate_assign {
265 ($proto:ident, $op:tt) => {
266 |g| {
267 let Generate {
268 ty,
269 target,
270 field,
271 protocol,
272 ..
273 } = g;
274
275 let protocol_field = g.tokens.protocol(&Protocol::$proto);
276
277 match target {
278 GenerateTarget::Named { field_ident, field_name } => {
279 if let Some(custom) = &protocol.custom {
280 quote_spanned! { field.span() =>
281 module.field_function(&#protocol_field, #field_name, #custom)?;
282 }
283 } else {
284 quote_spanned! { field.span() =>
285 module.field_function(&#protocol_field, #field_name, |s: &mut Self, value: #ty| {
286 s.#field_ident $op value;
287 })?;
288 }
289 }
290 }
291 GenerateTarget::Numbered { field_index } => {
292 if let Some(custom) = &protocol.custom {
293 quote_spanned! { field.span() =>
294 module.index_function(&#protocol_field, #field_index, #custom)?;
295 }
296 } else {
297 quote_spanned! { field.span() =>
298 module.index_function(&#protocol_field, #field_index, |s: &mut Self, value: #ty| {
299 s.#field_index $op value;
300 })?;
301 }
302 }
303 }
304 }
305 }
306 };
307 }
308
309 macro_rules! generate {
310 ($proto:ident, $op:tt) => {
311 |g| {
312 let Generate {
313 ty,
314 target,
315 field,
316 protocol,
317 ..
318 } = g;
319
320 let protocol_field = g.tokens.protocol(&Protocol::$proto);
321
322 match target {
323 GenerateTarget::Named { field_ident, field_name } => {
324 if let Some(custom) = &protocol.custom {
325 quote_spanned! { field.span() =>
326 module.field_function(&#protocol_field, #field_name, #custom)?;
327 }
328 } else {
329 quote_spanned! { field.span() =>
330 module.field_function(&#protocol_field, #field_name, |s: &mut Self, value: #ty| {
331 s.#field_ident $op value
332 })?;
333 }
334 }
335 }
336 GenerateTarget::Numbered { field_index } => {
337 if let Some(custom) = &protocol.custom {
338 quote_spanned! { field.span() =>
339 module.index_function(&#protocol_field, #field_index, #custom)?;
340 }
341 } else {
342 quote_spanned! { field.span() =>
343 module.index_function(&#protocol_field, #field_index, |s: &mut Self, value: #ty| {
344 s.#field_index $op value
345 })?;
346 }
347 }
348 }
349 }
350 }
351 };
352 }
353
354 let mut attr = FieldAttrs::default();
355
356 for a in input {
357 if !a.path().is_ident(RUNE) {
358 continue;
359 }
360
361 let result = a.parse_nested_meta(|meta| {
362 macro_rules! field_functions {
363 (
364 $(
365 $assign:literal, $assign_proto:ident, [$($assign_op:tt)*],
366 $op:literal, $op_proto:ident, [$($op_op:tt)*],
367 )*
368 ) => {{
369 $(
370 if meta.path.is_ident($assign) {
371 attr.protocols.push(FieldProtocol {
372 custom: self.parse_field_custom(meta.input)?,
373 generate: generate_assign!($assign_proto, $($assign_op)*),
374 });
375
376 return Ok(());
377 }
378
379 if meta.path.is_ident($op) {
380 attr.protocols.push(FieldProtocol {
381 custom: self.parse_field_custom(meta.input)?,
382 generate: generate!($op_proto, $($op_op)*),
383 });
384
385 return Ok(());
386 }
387 )*
388 }};
389 }
390
391 if meta.path.is_ident("id") {
392 attr.id = Some(meta.path.span());
393 return Ok(());
394 }
395
396 if meta.path.is_ident("iter") {
397 attr.iter = Some(meta.path.span());
398 return Ok(());
399 }
400
401 if meta.path.is_ident("skip") {
402 attr.skip = Some(meta.path.span());
403 return Ok(());
404 }
405
406 if meta.path.is_ident("option") {
407 attr.option = Some(meta.path.span());
408 return Ok(());
409 }
410
411 if meta.path.is_ident("meta") {
412 attr.meta = Some(meta.path.span());
413 return Ok(());
414 }
415
416 if meta.path.is_ident("span") {
417 attr.span = Some(meta.path.span());
418 return Ok(());
419 }
420
421 if meta.path.is_ident("copy") {
422 attr.copy = true;
423 return Ok(());
424 }
425
426 if meta.path.is_ident("parse_with") {
427 if let Some(old) = &attr.parse_with {
428 let mut error = syn::Error::new_spanned(
429 &meta.path,
430 "#[rune(parse_with = \"..\")] can only be used once",
431 );
432
433 error.combine(syn::Error::new_spanned(old, "previously defined here"));
434 return Err(error);
435 }
436
437 meta.input.parse::<Token![=]>()?;
438 let s = meta.input.parse::<syn::LitStr>()?;
439 attr.parse_with = Some(syn::Ident::new(&s.value(), s.span()));
440 return Ok(());
441 }
442
443 if meta.path.is_ident("get") {
444 attr.field = true;
445 attr.protocols.push(FieldProtocol {
446 custom: self.parse_field_custom(meta.input)?,
447 generate: |g| {
448 let Generate {
449 target,
450 ..
451 } = g;
452
453 let Tokens {
454 try_clone,
455 vm_try,
456 vm_result,
457 ..
458 } = g.tokens;
459
460 match target {
461 GenerateTarget::Named { field_ident, field_name } => {
462 let access = if g.attrs.copy {
463 quote!(s.#field_ident)
464 } else {
465 quote!(#vm_try!(#try_clone::try_clone(&s.#field_ident)))
466 };
467
468 let protocol = g.tokens.protocol(&Protocol::GET);
469
470 quote_spanned! { g.field.span() =>
471 module.field_function(&#protocol, #field_name, |s: &Self| #vm_result::Ok(#access))?;
472 }
473 }
474 GenerateTarget::Numbered { field_index } => {
475 let access = if g.attrs.copy {
476 quote!(s.#field_index)
477 } else {
478 quote!(#vm_try!(#try_clone::try_clone(&s.#field_index)))
479 };
480
481 let protocol = g.tokens.protocol(&Protocol::GET);
482
483 quote_spanned! { g.field.span() =>
484 module.index_function(&#protocol, #field_index, |s: &Self| #vm_result::Ok(#access))?;
485 }
486 }
487 }
488 },
489 });
490
491 return Ok(());
492 }
493
494 if meta.path.is_ident("set") {
495 attr.protocols.push(FieldProtocol {
496 custom: self.parse_field_custom(meta.input)?,
497 generate: |g| {
498 let Generate {
499 ty,
500 target,
501 ..
502 } = g;
503
504 let protocol = g.tokens.protocol(&Protocol::SET);
505
506 match target {
507 GenerateTarget::Named { field_ident, field_name } => {
508 quote_spanned! { g.field.span() =>
509 module.field_function(&#protocol, #field_name, |s: &mut Self, value: #ty| {
510 s.#field_ident = value;
511 })?;
512 }
513 }
514 GenerateTarget::Numbered { field_index } => {
515 quote_spanned! { g.field.span() =>
516 module.index_function(&#protocol, #field_index, |s: &mut Self, value: #ty| {
517 s.#field_index = value;
518 })?;
519 }
520 }
521 }
522 },
523 });
524
525 return Ok(());
526 }
527
528 field_functions! {
529 "add_assign", ADD_ASSIGN, [+=], "add", ADD, [+],
530 "sub_assign", SUB_ASSIGN, [-=], "sub", SUB, [-],
531 "div_assign", DIV_ASSIGN, [/=], "div", DIV, [/],
532 "mul_assign", MUL_ASSIGN, [*=], "mul", MUL, [*],
533 "rem_assign", REM_ASSIGN, [%=], "rem", REM, [%],
534 "bit_and_assign", BIT_AND_ASSIGN, [&=], "bit_and", BIT_AND, [&],
535 "bit_or_assign", BIT_OR_ASSIGN, [|=], "bit_or", BIT_OR, [|],
536 "bit_xor_assign", BIT_XOR_ASSIGN, [^=], "bit_xor", BIT_XOR, [^],
537 "shl_assign", SHL_ASSIGN, [<<=], "shl", SHL, [<<],
538 "shr_assign", SHR_ASSIGN, [>>=], "shr", SHR, [>>],
539 }
540
541 Err(syn::Error::new_spanned(&meta.path, "Unsupported attribute"))
542 });
543
544 if let Err(e) = result {
545 self.error(e);
546 }
547 }
548
549 attr
550 }
551
552 pub(crate) fn const_value_type_attrs(&self, input: &[syn::Attribute]) -> ConstValueTypeAttr {
553 let mut attr = ConstValueTypeAttr::default();
554
555 for a in input {
556 if !a.path().is_ident("const_value") {
557 continue;
558 }
559
560 let result = a.parse_nested_meta(|meta| {
561 if meta.path.is_ident("module") || meta.path.is_ident("crate") {
562 if meta.input.parse::<Option<Token![=]>>()?.is_some() {
563 attr.module = Some(parse_path_compat(meta.input)?);
564 } else {
565 attr.module = Some(syn::parse_quote!(crate));
566 }
567
568 return Ok(());
569 }
570
571 Err(syn::Error::new_spanned(
572 &meta.path,
573 "Unsupported type attribute",
574 ))
575 });
576
577 if let Err(e) = result {
578 self.error(e);
579 };
580 }
581
582 attr
583 }
584
585 pub(crate) fn type_attrs(&self, input: &[syn::Attribute]) -> TypeAttr {
587 let mut attr = TypeAttr::default();
588
589 for a in input {
590 if a.path().is_ident("doc") {
591 if let syn::Meta::NameValue(meta) = &a.meta {
592 attr.docs.push(meta.value.clone());
593 }
594
595 continue;
596 }
597
598 if !a.path().is_ident(RUNE) {
599 continue;
600 }
601
602 let result = a.parse_nested_meta(|meta| {
603 if meta.path.is_ident("parse") {
604 meta.input.parse::<Token![=]>()?;
605 let s: syn::LitStr = meta.input.parse()?;
606
607 match s.value().as_str() {
608 "meta_only" => {
609 attr.parse = ParseKind::MetaOnly;
610 }
611 other => {
612 return Err(syn::Error::new(
613 meta.input.span(),
614 format!("Unsupported `#[rune(parse = ..)]` argument `{}`", other),
615 ));
616 }
617 };
618
619 return Ok(());
620 }
621
622 if meta.path.is_ident("item") {
623 meta.input.parse::<Token![=]>()?;
624 attr.item = Some(meta.input.parse()?);
625 return Ok(());
626 }
627
628 if meta.path.is_ident("name") {
629 meta.input.parse::<Token![=]>()?;
630 attr.name = Some(meta.input.parse()?);
631 return Ok(());
632 }
633
634 if meta.path.is_ident("module") || meta.path.is_ident("crate") {
635 if meta.input.parse::<Option<Token![=]>>()?.is_some() {
636 attr.module = Some(parse_path_compat(meta.input)?);
637 } else {
638 attr.module = Some(syn::parse_quote!(crate));
639 }
640
641 return Ok(());
642 }
643
644 if meta.path.is_ident("install_with") {
645 meta.input.parse::<Token![=]>()?;
646 attr.install_with = Some(parse_path_compat(meta.input)?);
647 return Ok(());
648 }
649
650 if meta.path.is_ident("constructor") {
651 if attr.constructor.is_some() {
652 return Err(syn::Error::new(
653 meta.path.span(),
654 "#[rune(constructor)] must only be used once",
655 ));
656 }
657
658 attr.constructor = Some(meta.path.span());
659 return Ok(());
660 }
661
662 if meta.path.is_ident("impl_params") {
663 meta.input.parse::<Token![=]>()?;
664 let content;
665 syn::bracketed!(content in meta.input);
666 attr.impl_params =
667 Some(syn::punctuated::Punctuated::parse_terminated(&content)?);
668 return Ok(());
669 }
670
671 Err(syn::Error::new_spanned(
672 &meta.path,
673 "Unsupported type attribute",
674 ))
675 });
676
677 if let Err(e) = result {
678 self.error(e);
679 };
680 }
681
682 attr
683 }
684
685 pub(crate) fn variant_attr(&self, input: &[syn::Attribute]) -> VariantAttrs {
687 let mut attr = VariantAttrs::default();
688
689 for a in input {
690 if a.path().is_ident("doc") {
691 if let syn::Meta::NameValue(meta) = &a.meta {
692 attr.docs.push(meta.value.clone());
693 }
694
695 continue;
696 }
697
698 if !a.path().is_ident(RUNE) {
699 continue;
700 }
701
702 let result = a.parse_nested_meta(|meta| {
703 if meta.path.is_ident("constructor") {
704 if attr.constructor.is_some() {
705 return Err(syn::Error::new(
706 meta.path.span(),
707 "#[rune(constructor)] must only be used once",
708 ));
709 }
710
711 attr.constructor = Some(meta.path.span());
712 } else {
713 return Err(syn::Error::new_spanned(&meta.path, "Unsupported attribute"));
714 }
715
716 Ok(())
717 });
718
719 if let Err(e) = result {
720 self.error(e);
721 }
722 }
723
724 attr
725 }
726
727 fn parse_field_custom(&self, input: ParseStream<'_>) -> Result<Option<syn::Path>, syn::Error> {
729 if !input.peek(Token![=]) {
730 return Ok(None);
731 };
732
733 input.parse::<Token![=]>()?;
734 Ok(Some(parse_path_compat(input)?))
735 }
736
737 pub(crate) fn tokens_with_module(&self, module: Option<&syn::Path>) -> Tokens {
738 let mut core = syn::Path {
739 leading_colon: Some(<Token![::]>::default()),
740 segments: Punctuated::default(),
741 };
742 core.segments.push(syn::PathSegment::from(syn::Ident::new(
743 "core",
744 Span::call_site(),
745 )));
746
747 let mut alloc = syn::Path {
748 leading_colon: Some(<Token![::]>::default()),
749 segments: Punctuated::default(),
750 };
751 alloc.segments.push(syn::PathSegment::from(syn::Ident::new(
752 "alloc",
753 Span::call_site(),
754 )));
755
756 let mut default_module;
757
758 let m = match module {
759 Some(module) => module,
760 None => match &self.module {
761 Some(module) => module,
762 None => {
763 default_module = syn::Path {
764 leading_colon: None,
765 segments: Punctuated::default(),
766 };
767 default_module
768 .segments
769 .push(syn::PathSegment::from(syn::Ident::new(
770 RUNE,
771 Span::call_site(),
772 )));
773 &default_module
774 }
775 },
776 };
777
778 let core = &core;
779
780 Tokens {
781 alloc: path(m, ["alloc"]),
782 any_marker_t: path(m, ["__private", "AnyMarker"]),
783 any_t: path(m, ["Any"]),
784 any_type_info: path(m, ["runtime", "AnyTypeInfo"]),
785 arc: path(m, ["__private", "Arc"]),
786 compile_error: path(m, ["compile", "Error"]),
787 const_construct_t: path(m, ["runtime", "ConstConstruct"]),
788 const_value: path(m, ["runtime", "ConstValue"]),
789 context_error: path(m, ["compile", "ContextError"]),
790 double_ended_iterator: path(core, ["iter", "DoubleEndedIterator"]),
791 fmt: path(core, ["fmt"]),
792 from_const_value_t: path(m, ["runtime", "FromConstValue"]),
793 from_value: path(m, ["runtime", "FromValue"]),
794 hash: path(m, ["Hash"]),
795 id: path(m, ["parse", "Id"]),
796 install_with: path(m, ["__private", "InstallWith"]),
797 into_iterator: path(core, ["iter", "IntoIterator"]),
798 item: path(m, ["Item"]),
799 iterator: path(core, ["iter", "Iterator"]),
800 macro_context: path(m, ["macros", "MacroContext"]),
801 maybe_type_of: path(m, ["runtime", "MaybeTypeOf"]),
802 meta: path(m, ["compile", "meta"]),
803 module: path(m, ["__private", "Module"]),
804 named: path(m, ["compile", "Named"]),
805 non_null: path(core, ["ptr", "NonNull"]),
806 object: path(m, ["runtime", "Object"]),
807 opaque: path(m, ["parse", "Opaque"]),
808 option_spanned: path(m, ["ast", "OptionSpanned"]),
809 option: path(core, ["option", "Option"]),
810 owned_tuple: path(m, ["runtime", "OwnedTuple"]),
811 parse: path(m, ["parse", "Parse"]),
812 parser: path(m, ["parse", "Parser"]),
813 protocol: path(m, ["runtime", "Protocol"]),
814 raw_value_guard: path(m, ["runtime", "RawValueGuard"]),
815 result: path(core, ["result", "Result"]),
816 runtime_error: path(m, ["runtime", "RuntimeError"]),
817 span: path(m, ["ast", "Span"]),
818 spanned: path(m, ["ast", "Spanned"]),
819 string: path(m, ["alloc", "String"]),
820 to_const_value_t: path(m, ["runtime", "ToConstValue"]),
821 to_tokens: path(m, ["macros", "ToTokens"]),
822 to_value: path(m, ["runtime", "ToValue"]),
823 token_stream: path(m, ["macros", "TokenStream"]),
824 try_clone: path(m, ["alloc", "clone", "TryClone"]),
825 try_from: path(core, ["convert", "TryFrom"]),
826 tuple: path(m, ["runtime", "Tuple"]),
827 type_hash_t: path(m, ["runtime", "TypeHash"]),
828 type_name: path(core, ["any", "type_name"]),
829 type_of: path(m, ["runtime", "TypeOf"]),
830 type_value: path(m, ["runtime", "TypeValue"]),
831 unsafe_to_mut: path(m, ["runtime", "UnsafeToMut"]),
832 unsafe_to_ref: path(m, ["runtime", "UnsafeToRef"]),
833 unsafe_to_value: path(m, ["runtime", "UnsafeToValue"]),
834 value_mut_guard: path(m, ["runtime", "ValueMutGuard"]),
835 value_ref_guard: path(m, ["runtime", "ValueRefGuard"]),
836 value: path(m, ["runtime", "Value"]),
837 vec: path(m, ["alloc", "Vec"]),
838 vm_result: path(m, ["runtime", "VmResult"]),
839 vm_try: path(m, ["vm_try"]),
840 write: path(core, ["write"]),
841 }
842 }
843}
844
845fn parse_path_compat(input: ParseStream<'_>) -> syn::Result<syn::Path> {
846 if input.peek(syn::LitStr) {
847 let path = input
848 .parse::<syn::LitStr>()?
849 .parse_with(syn::Path::parse_mod_style)?;
850
851 return Err(syn::Error::new_spanned(
852 &path,
853 format_args!(
854 "String literals are no longer supported here, use a path like `{}`",
855 path.to_token_stream()
856 ),
857 ));
858 }
859
860 syn::Path::parse_mod_style(input)
861}
862
863fn path<const N: usize>(base: &syn::Path, path: [&'static str; N]) -> syn::Path {
864 let mut base = base.clone();
865
866 for s in path {
867 let ident = syn::Ident::new(s, base.span());
868 base.segments.push(syn::PathSegment::from(ident));
869 }
870
871 base
872}
873
874pub(crate) struct Tokens {
875 pub(crate) alloc: syn::Path,
876 pub(crate) any_marker_t: syn::Path,
877 pub(crate) any_t: syn::Path,
878 pub(crate) any_type_info: syn::Path,
879 pub(crate) arc: syn::Path,
880 pub(crate) compile_error: syn::Path,
881 pub(crate) const_construct_t: syn::Path,
882 pub(crate) const_value: syn::Path,
883 pub(crate) context_error: syn::Path,
884 pub(crate) double_ended_iterator: syn::Path,
885 pub(crate) fmt: syn::Path,
886 pub(crate) from_const_value_t: syn::Path,
887 pub(crate) from_value: syn::Path,
888 pub(crate) hash: syn::Path,
889 pub(crate) id: syn::Path,
890 pub(crate) install_with: syn::Path,
891 pub(crate) into_iterator: syn::Path,
892 pub(crate) item: syn::Path,
893 pub(crate) iterator: syn::Path,
894 pub(crate) macro_context: syn::Path,
895 pub(crate) maybe_type_of: syn::Path,
896 pub(crate) meta: syn::Path,
897 pub(crate) module: syn::Path,
898 pub(crate) named: syn::Path,
899 pub(crate) non_null: syn::Path,
900 pub(crate) object: syn::Path,
901 pub(crate) opaque: syn::Path,
902 pub(crate) option_spanned: syn::Path,
903 pub(crate) option: syn::Path,
904 pub(crate) owned_tuple: syn::Path,
905 pub(crate) parse: syn::Path,
906 pub(crate) parser: syn::Path,
907 pub(crate) protocol: syn::Path,
908 pub(crate) raw_value_guard: syn::Path,
909 pub(crate) result: syn::Path,
910 pub(crate) runtime_error: syn::Path,
911 pub(crate) span: syn::Path,
912 pub(crate) spanned: syn::Path,
913 pub(crate) string: syn::Path,
914 pub(crate) to_const_value_t: syn::Path,
915 pub(crate) to_tokens: syn::Path,
916 pub(crate) to_value: syn::Path,
917 pub(crate) token_stream: syn::Path,
918 pub(crate) try_clone: syn::Path,
919 pub(crate) try_from: syn::Path,
920 pub(crate) tuple: syn::Path,
921 pub(crate) type_hash_t: syn::Path,
922 pub(crate) type_name: syn::Path,
923 pub(crate) type_of: syn::Path,
924 pub(crate) type_value: syn::Path,
925 pub(crate) unsafe_to_mut: syn::Path,
926 pub(crate) unsafe_to_ref: syn::Path,
927 pub(crate) unsafe_to_value: syn::Path,
928 pub(crate) value_mut_guard: syn::Path,
929 pub(crate) value_ref_guard: syn::Path,
930 pub(crate) value: syn::Path,
931 pub(crate) vec: syn::Path,
932 pub(crate) vm_result: syn::Path,
933 pub(crate) vm_try: syn::Path,
934 pub(crate) write: syn::Path,
935}
936
937impl Tokens {
938 pub(crate) fn protocol(&self, sym: &Protocol) -> TokenStream {
940 let mut stream = TokenStream::default();
941 self.protocol.to_tokens(&mut stream);
942 <Token![::]>::default().to_tokens(&mut stream);
943 syn::Ident::new(sym.name, Span::call_site()).to_tokens(&mut stream);
944 stream
945 }
946}