1use super::parse_cfg::*;
17use itertools::Itertools;
18use proc_macro2::{Span, TokenStream};
19use quote::{quote, ToTokens};
20use std::{
21 borrow::Borrow,
22 collections::{hash_map::RandomState, HashMap, HashSet},
23};
24use syn::{
25 parenthesized,
26 parse::{Parse, ParseStream},
27 punctuated::Punctuated,
28 spanned::Spanned,
29 token,
30 token::Bracket,
31 AngleBracketedGenericArguments, AttrStyle, Error, Field, FieldsNamed, GenericArgument,
32 GenericParam, Ident, ItemStruct, LitInt, Path, PathArguments, PathSegment, Result, Token, Type,
33 TypePath, Visibility,
34};
35
36mod kw {
37 syn::custom_keyword!(wip);
38 syn::custom_keyword!(blocking);
39 syn::custom_keyword!(consumes);
40 syn::custom_keyword!(sends);
41 syn::custom_keyword!(message_capacity);
42 syn::custom_keyword!(signal_capacity);
43 syn::custom_keyword!(can_receive_priority_messages);
44}
45
46#[derive(Clone, Debug)]
47pub(crate) enum SubSysAttrItem {
48 Wip(kw::wip),
51 Blocking(kw::blocking),
54 Sends(Sends),
56 Consumes(Consumes),
58 MessageChannelCapacity(ChannelCapacity<kw::message_capacity>),
60 SignalChannelCapacity(ChannelCapacity<kw::signal_capacity>),
62 CanReceivePriorityMessages(kw::can_receive_priority_messages),
64}
65
66impl Parse for SubSysAttrItem {
67 fn parse(input: ParseStream) -> Result<Self> {
68 let lookahead = input.lookahead1();
69 Ok(if lookahead.peek(kw::wip) {
70 Self::Wip(input.parse::<kw::wip>()?)
71 } else if lookahead.peek(kw::blocking) {
72 Self::Blocking(input.parse::<kw::blocking>()?)
73 } else if lookahead.peek(kw::sends) {
74 Self::Sends(input.parse::<Sends>()?)
75 } else if lookahead.peek(kw::message_capacity) {
76 Self::MessageChannelCapacity(input.parse::<ChannelCapacity<kw::message_capacity>>()?)
77 } else if lookahead.peek(kw::signal_capacity) {
78 Self::SignalChannelCapacity(input.parse::<ChannelCapacity<kw::signal_capacity>>()?)
79 } else if lookahead.peek(kw::can_receive_priority_messages) {
80 Self::CanReceivePriorityMessages(input.parse::<kw::can_receive_priority_messages>()?)
81 } else {
82 Self::Consumes(input.parse::<Consumes>()?)
83 })
84 }
85}
86
87impl ToTokens for SubSysAttrItem {
88 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
89 let ts = match self {
90 Self::Wip(wip) => {
91 quote! { #wip }
92 },
93 Self::Blocking(blocking) => {
94 quote! { #blocking }
95 },
96 Self::Sends(_) => {
97 quote! {}
98 },
99 Self::Consumes(_) => {
100 quote! {}
101 },
102 Self::MessageChannelCapacity(_) => {
103 quote! {}
104 },
105 Self::SignalChannelCapacity(_) => {
106 quote! {}
107 },
108 Self::CanReceivePriorityMessages(can_receive_priority_messages) => {
109 quote! { #can_receive_priority_messages }
110 },
111 };
112 tokens.extend(ts.into_iter());
113 }
114}
115
116#[derive(Clone, Debug)]
119pub(crate) struct SubSysField {
120 pub(crate) name: Ident,
122 pub(crate) generic: Ident,
126 pub(crate) message_to_consume: Option<Path>,
128 pub(crate) messages_to_send: Vec<Path>,
130 pub(crate) blocking: bool,
133 pub(crate) wip: bool,
137 pub(crate) message_capacity: Option<usize>,
139 pub(crate) signal_capacity: Option<usize>,
141 pub(crate) can_receive_priority_messages: bool,
143
144 pub(crate) feature_gates: Option<CfgPredicate>,
145}
146
147impl SubSysField {
148 pub(crate) fn dummy_msg_name(&self) -> Ident {
149 Ident::new(format!("{}Message", self.generic).as_str(), self.name.span())
150 }
151
152 pub(crate) fn message_to_consume(&self) -> Path {
155 if let Some(ref consumes) = self.message_to_consume {
156 consumes.clone()
157 } else {
158 Path::from(self.dummy_msg_name())
159 }
160 }
161
162 pub(crate) fn gen_dummy_message_ty(&self) -> TokenStream {
167 if self.message_to_consume.is_none() {
168 let dummy_msg_ident = self.dummy_msg_name();
169 quote! {
170 #[doc =
171 r###"A dummy implementation to satisfy the current internal structure
172 and cannot be constructed delibarately, since it's not meant to be sent or used at all"###]
173 #[derive(Debug, Clone, Copy)]
174 pub enum #dummy_msg_ident {}
175 }
176 } else {
177 TokenStream::new()
178 }
179 }
180}
181
182fn try_type_to_path(ty: &Type, span: Span) -> Result<Path> {
184 match ty {
185 Type::Path(path) => Ok(path.path.clone()),
186 _ => Err(Error::new(span, "Type must be a path expression.")),
187 }
188}
189
190fn flatten_type(ty: &Type, span: Span) -> Result<Vec<Ident>> {
192 match ty {
193 syn::Type::Array(ar) => flatten_type(&ar.elem, span),
194 syn::Type::Paren(par) => flatten_type(&par.elem, span),
195 syn::Type::Path(type_path) => type_path
196 .path
197 .segments
198 .iter()
199 .map(|seg| flatten_path_segments(seg, span.clone()))
200 .flatten_ok()
201 .collect::<Result<Vec<_>>>(),
202 syn::Type::Tuple(tup) => tup
203 .elems
204 .iter()
205 .map(|element| flatten_type(element, span.clone()))
206 .flatten_ok()
207 .collect::<Result<Vec<_>>>(),
208 _ => Err(Error::new(span, format!("Unsupported type: {:?}", ty))),
209 }
210}
211
212fn flatten_path_segments(path_segment: &PathSegment, span: Span) -> Result<Vec<Ident>> {
214 let mut result = vec![path_segment.ident.clone()];
215
216 match &path_segment.arguments {
217 syn::PathArguments::AngleBracketed(args) => {
218 let mut recursive_idents = args
219 .args
220 .iter()
221 .map(|generic_argument| match generic_argument {
222 syn::GenericArgument::Type(ty) => flatten_type(ty, span.clone()),
223 _ => Err(Error::new(
224 span,
225 format!(
226 "Field has a generic with an unsupported parameter {:?}",
227 generic_argument
228 ),
229 )),
230 })
231 .flatten_ok()
232 .collect::<Result<Vec<_>>>()?;
233 result.append(&mut recursive_idents);
234 },
235 syn::PathArguments::None => {},
236 _ =>
237 return Err(Error::new(
238 span,
239 format!(
240 "Field has a generic with an unsupported path {:?}",
241 path_segment.arguments
242 ),
243 )),
244 }
245
246 Ok(result)
247}
248
249macro_rules! extract_variant {
250 ($unique:expr, $variant:ident ; default = $fallback:expr) => {
251 extract_variant!($unique, $variant).unwrap_or_else(|| $fallback)
252 };
253 ($unique:expr, $variant:ident ; err = $err:expr) => {
254 extract_variant!($unique, $variant).ok_or_else(|| Error::new(Span::call_site(), $err))
255 };
256 ($unique:expr, $variant:ident take) => {
257 $unique.values().find_map(|item| {
258 if let SubSysAttrItem::$variant(value) = item {
259 Some(value.clone())
260 } else {
261 None
262 }
263 })
264 };
265 ($unique:expr, $variant:ident) => {
266 $unique.values().find_map(|item| {
267 if let SubSysAttrItem::$variant(_) = item {
268 Some(true)
269 } else {
270 None
271 }
272 })
273 };
274}
275
276#[derive(Debug, Clone)]
277pub(crate) struct Sends {
278 #[allow(dead_code)]
279 pub(crate) keyword_sends: kw::sends,
280 #[allow(dead_code)]
281 pub(crate) colon: Token![:],
282 #[allow(dead_code)]
283 pub(crate) bracket: Option<Bracket>,
284 pub(crate) sends: Punctuated<Path, Token![,]>,
285}
286
287impl Parse for Sends {
288 fn parse(input: syn::parse::ParseStream) -> Result<Self> {
289 let content;
290 let keyword_sends = input.parse()?;
291 let colon = input.parse()?;
292 let (bracket, sends) = if !input.peek(syn::token::Bracket) {
293 let mut sends = Punctuated::new();
294 sends.push_value(input.parse::<Path>()?);
295 (None, sends)
296 } else {
297 let bracket = Some(syn::bracketed!(content in input));
298 let sends = Punctuated::parse_terminated(&content)?;
299 (bracket, sends)
300 };
301 Ok(Self { keyword_sends, colon, bracket, sends })
302 }
303}
304
305#[derive(Debug, Clone)]
306pub(crate) struct Consumes {
307 #[allow(dead_code)]
308 pub(crate) keyword_consumes: Option<kw::consumes>,
309 #[allow(dead_code)]
310 pub(crate) colon: Option<Token![:]>,
311 pub(crate) consumes: Path,
312}
313
314impl Parse for Consumes {
315 fn parse(input: syn::parse::ParseStream) -> Result<Self> {
316 let lookahead = input.lookahead1();
317 Ok(if lookahead.peek(kw::consumes) {
318 Self {
319 keyword_consumes: Some(input.parse()?),
320 colon: input.parse()?,
321 consumes: input.parse()?,
322 }
323 } else {
324 Self { keyword_consumes: None, colon: None, consumes: input.parse()? }
325 })
326 }
327}
328
329#[derive(Debug, Clone)]
330pub(crate) struct ChannelCapacity<T: Parse> {
331 #[allow(dead_code)]
332 tag: T,
333 #[allow(dead_code)]
334 colon_token: token::Colon,
335 value: usize,
336}
337
338impl<T: Parse> Parse for ChannelCapacity<T> {
339 fn parse(input: syn::parse::ParseStream) -> Result<Self> {
340 Ok(Self {
341 tag: input.parse::<T>()?,
342 colon_token: input.parse()?,
343 value: input.parse::<LitInt>()?.base10_parse::<usize>()?,
344 })
345 }
346}
347
348#[derive(Debug, Clone)]
351pub(crate) struct SubSystemAttrItems {
352 pub(crate) wip: bool,
355 pub(crate) blocking: bool,
358 pub(crate) consumes: Option<Consumes>,
360 pub(crate) sends: Option<Sends>,
361 pub(crate) message_capacity: Option<ChannelCapacity<kw::message_capacity>>,
363 pub(crate) signal_capacity: Option<ChannelCapacity<kw::signal_capacity>>,
365 pub(crate) can_receive_priority_messages: bool,
367}
368
369impl Parse for SubSystemAttrItems {
370 fn parse(input: syn::parse::ParseStream) -> Result<Self> {
371 let span = input.span();
372
373 let content;
374 let _paren_token = parenthesized!(content in input);
375
376 let items = content.call(Punctuated::<SubSysAttrItem, Token![,]>::parse_terminated)?;
377
378 let mut unique = HashMap::<
379 std::mem::Discriminant<SubSysAttrItem>,
380 SubSysAttrItem,
381 RandomState,
382 >::default();
383
384 for item in items {
385 if let Some(first) = unique.insert(std::mem::discriminant(&item), item.clone()) {
386 let mut e =
387 Error::new(item.span(), "Duplicate definition of subsystem attribute found");
388 e.combine(Error::new(first.span(), "previously defined here."));
389 return Err(e)
390 }
391 }
392
393 let sends = extract_variant!(unique, Sends take);
395 let consumes = extract_variant!(unique, Consumes take);
396 if sends.as_ref().map(|sends| sends.sends.is_empty()).unwrap_or(true) && consumes.is_none()
397 {
398 return Err(Error::new(
399 span,
400 "Must have at least one of `consumes: [..]` and `sends: [..]`.",
401 ))
402 }
403
404 let blocking = extract_variant!(unique, Blocking; default = false);
405 let wip = extract_variant!(unique, Wip; default = false);
406 let message_capacity = extract_variant!(unique, MessageChannelCapacity take );
407 let signal_capacity = extract_variant!(unique, SignalChannelCapacity take );
408 let can_receive_priority_messages =
409 extract_variant!(unique, CanReceivePriorityMessages; default = false);
410
411 Ok(Self {
412 blocking,
413 wip,
414 sends,
415 consumes,
416 message_capacity,
417 signal_capacity,
418 can_receive_priority_messages,
419 })
420 }
421}
422
423#[derive(Debug, Clone)]
425pub(crate) struct BaggageField {
426 pub(crate) field_name: Ident,
427 pub(crate) field_ty: Type,
428 pub(crate) generic_types: Vec<Ident>,
429 pub(crate) vis: Visibility,
430}
431
432#[derive(Clone, Debug)]
433pub(crate) struct OrchestraInfo {
434 pub(crate) support_crate: Path,
436
437 pub(crate) subsystems: Vec<SubSysField>,
439 pub(crate) baggage: Vec<BaggageField>,
442 pub(crate) message_wrapper: Ident,
444 pub(crate) orchestra_name: Ident,
447
448 pub(crate) message_channel_capacity: usize,
450 pub(crate) signal_channel_capacity: usize,
452 pub(crate) boxed_messages: bool,
454
455 pub(crate) extern_signal_ty: Path,
457
458 pub(crate) extern_event_ty: Path,
460
461 pub(crate) outgoing_ty: Option<Path>,
464
465 pub(crate) extern_error_ty: Path,
467}
468
469pub(crate) struct SubsystemConfigSet<'a> {
471 pub(crate) enabled_subsystems: Vec<&'a SubSysField>,
473
474 pub(crate) feature_gate: TokenStream,
477}
478
479impl<'a> SubsystemConfigSet<'a> {
480 pub(crate) fn subsystem_names_without_wip(&self) -> Vec<Ident> {
481 subsystem_names_without_wip(&self.enabled_subsystems)
482 }
483
484 pub(crate) fn subsystem_generic_types(&self) -> Vec<Ident> {
485 subsystem_generic_types(&self.enabled_subsystems)
486 }
487
488 pub(crate) fn channel_names_without_wip(
489 &self,
490 suffix: impl Into<Option<&'static str>>,
491 ) -> Vec<Ident> {
492 channel_names_without_wip(&self.enabled_subsystems, suffix)
493 }
494
495 pub(crate) fn consumes_without_wip(&self) -> Vec<Path> {
496 consumes_without_wip(&self.enabled_subsystems)
497 }
498
499 pub(crate) fn message_channel_capacities_without_wip(
500 &self,
501 default_capacity: usize,
502 ) -> Vec<LitInt> {
503 message_channel_capacities_without_wip(&self.enabled_subsystems, default_capacity)
504 }
505
506 pub(crate) fn signal_channel_capacities_without_wip(
507 &self,
508 default_capacity: usize,
509 ) -> Vec<LitInt> {
510 signal_channel_capacities_without_wip(&self.enabled_subsystems, default_capacity)
511 }
512
513 pub(crate) fn can_receive_priority_messages_without_wip(&self) -> Vec<syn::LitBool> {
514 can_receive_priority_messages_without_wip(&self.enabled_subsystems)
515 }
516}
517
518impl OrchestraInfo {
519 pub(crate) fn support_crate_name(&self) -> &Path {
520 &self.support_crate
521 }
522
523 pub(crate) fn variant_names(&self) -> Vec<Ident> {
524 self.subsystems.iter().map(|ssf| ssf.generic.clone()).collect::<Vec<_>>()
525 }
526
527 pub(crate) fn variant_names_without_wip(&self) -> Vec<Ident> {
528 self.subsystems
529 .iter()
530 .filter(|ssf| !ssf.wip)
531 .map(|ssf| ssf.generic.clone())
532 .collect::<Vec<_>>()
533 }
534
535 pub(crate) fn variant_names_only_wip(&self) -> Vec<Ident> {
536 self.subsystems
537 .iter()
538 .filter(|ssf| ssf.wip)
539 .map(|ssf| ssf.generic.clone())
540 .collect::<Vec<_>>()
541 }
542
543 pub(crate) fn subsystems(&self) -> &[SubSysField] {
544 self.subsystems.as_slice()
545 }
546
547 pub(crate) fn feature_gates(&self) -> Vec<TokenStream> {
548 self.subsystems
549 .iter()
550 .map(|s| s.feature_gates.clone().map_or(quote! {}, |fg| quote! { #[cfg(#fg)] }))
551 .collect::<Vec<_>>()
552 }
553
554 pub(crate) fn feature_gated_subsystem_sets(&self) -> Vec<SubsystemConfigSet> {
558 let features_raw_powerset = self
562 .subsystems
563 .iter()
564 .filter_map(|s| s.feature_gates.clone())
565 .unique()
567 .powerset()
568 .collect_vec();
569
570 let res = features_raw_powerset
572 .iter()
573 .zip(features_raw_powerset.iter().rev())
574 .map(|(enabled_cfgs, disabled_cfgs)| {
575 let output_feature_gate = if disabled_cfgs.is_empty() {
577 quote! { #[cfg(all(#(#enabled_cfgs),*))] }
578 } else {
579 quote! { #[cfg(all(#(#enabled_cfgs,)* not(any(#(#disabled_cfgs),*))))] }
580 };
581
582 let enabled = self
583 .subsystems
584 .iter()
585 .filter(|subsys| {
586 subsys
589 .feature_gates
590 .as_ref()
591 .map_or(true, |cfg| enabled_cfgs.contains(&cfg))
592 })
593 .collect();
594
595 SubsystemConfigSet {
596 enabled_subsystems: enabled,
597 feature_gate: output_feature_gate,
598 }
599 })
600 .collect();
601 res
602 }
603
604 pub(crate) fn subsystem_names_without_wip(&self) -> Vec<Ident> {
605 subsystem_names_without_wip(&self.subsystems)
606 }
607
608 pub(crate) fn baggage(&self) -> &[BaggageField] {
609 self.baggage.as_slice()
610 }
611
612 pub(crate) fn baggage_names(&self) -> Vec<Ident> {
613 self.baggage.iter().map(|bag| bag.field_name.clone()).collect::<Vec<_>>()
614 }
615 pub(crate) fn baggage_decl(&self) -> Vec<TokenStream> {
616 self.baggage
617 .iter()
618 .map(|bag| {
619 let BaggageField { vis, field_ty, field_name, .. } = bag;
620 quote! { #vis #field_name: #field_ty }
621 })
622 .collect::<Vec<TokenStream>>()
623 }
624
625 pub(crate) fn baggage_generic_types(&self) -> Vec<Ident> {
626 self.baggage
627 .iter()
628 .flat_map(|bag| bag.generic_types.clone())
629 .collect::<Vec<_>>()
630 }
631
632 pub(crate) fn any_message(&self) -> Vec<Path> {
633 self.subsystems.iter().map(|ssf| ssf.message_to_consume()).collect::<Vec<_>>()
634 }
635
636 pub(crate) fn channel_names_without_wip(
637 &self,
638 suffix: impl Into<Option<&'static str>>,
639 ) -> Vec<Ident> {
640 channel_names_without_wip(&self.subsystems, suffix)
641 }
642
643 pub(crate) fn consumes_without_wip(&self) -> Vec<Path> {
644 consumes_without_wip(&self.subsystems)
645 }
646
647 pub(crate) fn box_message_if_needed(&self, message_ty: &Path, span: Span) -> Path {
648 if self.boxed_messages {
649 let mut boxed_message = PathSegment::from(Ident::new("Box", span.clone()));
650 boxed_message.arguments =
651 PathArguments::AngleBracketed(AngleBracketedGenericArguments {
652 colon2_token: None,
653 lt_token: Token),
654 args: Punctuated::from_iter(std::iter::once(GenericArgument::Type(
655 Type::Path(TypePath { path: message_ty.clone(), qself: None }),
656 ))),
657 gt_token: Token),
658 });
659 Path::from(boxed_message)
660 } else {
661 message_ty.clone()
662 }
663 }
664}
665
666#[derive(Debug, Clone)]
668pub(crate) struct OrchestraGuts {
669 pub(crate) name: Ident,
670 pub(crate) subsystems: Vec<SubSysField>,
671 pub(crate) baggage: Vec<BaggageField>,
672}
673
674impl OrchestraGuts {
675 pub(crate) fn parse_fields(
676 name: Ident,
677 baggage_generics: HashSet<Ident>,
678 fields: FieldsNamed,
679 ) -> Result<Self> {
680 let n = fields.named.len();
681 let mut subsystems = Vec::with_capacity(n);
682 let mut baggage = Vec::with_capacity(n);
683
684 let mut unique_subsystem_idents = HashSet::<Ident>::new();
688 for Field { attrs, vis, ident, ty, .. } in fields.named.into_iter() {
689 let mut subsystem_attr =
691 attrs.iter().filter(|attr| attr.style == AttrStyle::Outer).filter_map(|attr| {
692 let span = attr.path.span();
693 attr.path.get_ident().filter(|ident| *ident == "subsystem").map(move |_ident| {
694 let attr_tokens = attr.tokens.clone();
695 (attr_tokens, span)
696 })
697 });
698
699 let cfg_attr =
700 attrs.iter().filter(|attr| attr.style == AttrStyle::Outer).filter_map(|attr| {
701 let span = attr.path.span();
702 attr.path.get_ident().filter(|ident| *ident == "cfg").map(move |_ident| {
703 let attr_tokens = attr.tokens.clone();
704
705 (attr_tokens, span)
706 })
707 });
708
709 let mut feature_gates: Option<CfgPredicate> = None;
710 for (cfg_token_stream, _span) in cfg_attr {
711 let cfg_predicate = syn::parse2::<CfgExpressionRoot>(cfg_token_stream)?.predicate;
712 feature_gates = match feature_gates {
713 Some(cfg) => Some(cfg.merge(cfg_predicate)),
714 None => Some(cfg_predicate),
715 };
716 }
717 feature_gates.iter_mut().for_each(CfgPredicate::sort_recursive);
719
720 let ident = ident.ok_or_else(|| {
721 Error::new(
722 ty.span(),
723 "Missing identifier for field, only named fields are expected.",
724 )
725 })?;
726
727 if let Some((attr_tokens, span)) = subsystem_attr.next() {
728 if let Some((_attr_tokens2, span2)) = subsystem_attr.next() {
730 return Err({
731 let mut err = Error::new(span, "The first subsystem annotation is at");
732 err.combine(Error::new(span2, "but another here for the same field."));
733 err
734 })
735 }
736
737 let span = attr_tokens.span();
738
739 let attr_tokens = attr_tokens.clone();
740 let subsystem_attrs: SubSystemAttrItems = syn::parse2(attr_tokens.clone())?;
741
742 let field_ty = try_type_to_path(&ty, span)?;
743 let generic = field_ty
744 .get_ident()
745 .ok_or_else(|| {
746 Error::new(
747 field_ty.span(),
748 "Must be an identifier, not a path. It will be used as a generic.",
749 )
750 })?
751 .clone();
752 if let Some(previous) = unique_subsystem_idents.get(&generic) {
754 let mut e = Error::new(generic.span(), "Duplicate subsystem names");
755 e.combine(Error::new(previous.span(), "previously defined here."));
756 return Err(e)
757 }
758 unique_subsystem_idents.insert(generic.clone());
759
760 let SubSystemAttrItems {
761 wip,
762 blocking,
763 consumes,
764 sends,
765 message_capacity,
766 signal_capacity,
767 can_receive_priority_messages,
768 ..
769 } = subsystem_attrs;
770
771 let sends = if let Some(sends) = sends {
773 Vec::from_iter(sends.sends.iter().cloned())
774 } else {
775 vec![]
776 };
777 let consumes = consumes.map(|consumes| consumes.consumes);
778 let message_capacity = message_capacity.map(|capacity| capacity.value);
779 let signal_capacity = signal_capacity.map(|capacity| capacity.value);
780
781 subsystems.push(SubSysField {
782 name: ident,
783 generic,
784 message_to_consume: consumes,
785 messages_to_send: sends,
786 wip,
787 blocking,
788 message_capacity,
789 signal_capacity,
790 feature_gates,
791 can_receive_priority_messages,
792 });
793 } else {
794 let flattened = flatten_type(&ty, ident.span())?;
796 let generic_types = flattened
797 .iter()
798 .filter(|flat_ident| baggage_generics.contains(flat_ident))
799 .cloned()
800 .collect::<Vec<_>>();
801 baggage.push(BaggageField { field_name: ident, generic_types, field_ty: ty, vis });
802 }
803 }
804 Ok(Self { name, subsystems, baggage })
805 }
806}
807
808impl Parse for OrchestraGuts {
809 fn parse(input: ParseStream) -> Result<Self> {
810 let ds: ItemStruct = input.parse()?;
811 match ds.fields {
812 syn::Fields::Named(named) => {
813 let name = ds.ident.clone();
814
815 let mut orig_generics = ds.generics;
818
819 let mut baggage_generic_idents = HashSet::with_capacity(orig_generics.params.len());
821 orig_generics.params = orig_generics
822 .params
823 .into_iter()
824 .map(|mut generic| {
825 match generic {
826 GenericParam::Type(ref mut param) => {
827 baggage_generic_idents.insert(param.ident.clone());
828 param.eq_token = None;
829 param.default = None;
830 },
831 _ => {},
832 }
833 generic
834 })
835 .collect();
836
837 Self::parse_fields(name, baggage_generic_idents, named)
838 },
839 syn::Fields::Unit => Err(Error::new(
840 ds.fields.span(),
841 "Must be a struct with named fields. Not an unit struct.",
842 )),
843 syn::Fields::Unnamed(unnamed) => Err(Error::new(
844 unnamed.span(),
845 "Must be a struct with named fields. Not an unnamed fields struct.",
846 )),
847 }
848 }
849}
850
851pub(crate) fn subsystem_names_without_wip<'a, T: Borrow<SubSysField>>(
852 subsystems: &[T],
853) -> Vec<Ident> {
854 subsystems
855 .iter()
856 .map(|e| e.borrow())
857 .filter(|ssf| !ssf.wip)
858 .map(|ssf| ssf.name.clone())
859 .collect::<Vec<_>>()
860}
861
862pub(crate) fn subsystem_generic_types<'a, T: Borrow<SubSysField>>(subsystems: &[T]) -> Vec<Ident> {
863 subsystems
864 .iter()
865 .map(|e| e.borrow())
866 .filter(|ssf| !ssf.wip)
867 .map(|ssf| ssf.generic.clone())
868 .collect::<Vec<_>>()
869}
870
871pub(crate) fn channel_names_without_wip<'a, T: Borrow<SubSysField>>(
872 subsystems: &[T],
873 suffix: impl Into<Option<&'static str>>,
874) -> Vec<Ident> {
875 let suffix = suffix.into().unwrap_or("");
876 subsystems
877 .iter()
878 .map(|e| e.borrow())
879 .filter(|ssf| !ssf.wip)
880 .map(|ssf| Ident::new(&(ssf.name.to_string() + suffix), ssf.name.span()))
881 .collect::<Vec<_>>()
882}
883
884pub(crate) fn message_channel_capacities_without_wip(
885 subsystems: &Vec<&SubSysField>,
886 default_capacity: usize,
887) -> Vec<LitInt> {
888 subsystems
889 .iter()
890 .filter(|ssf| !ssf.wip)
891 .map(|ssf| {
892 LitInt::new(
893 &(ssf.message_capacity.unwrap_or(default_capacity).to_string()),
894 ssf.message_capacity.span(),
895 )
896 })
897 .collect::<Vec<_>>()
898}
899
900pub(crate) fn signal_channel_capacities_without_wip(
901 subsystems: &Vec<&SubSysField>,
902 default_capacity: usize,
903) -> Vec<LitInt> {
904 subsystems
905 .iter()
906 .filter(|ssf| !ssf.wip)
907 .map(|ssf| {
908 LitInt::new(
909 &(ssf.signal_capacity.unwrap_or(default_capacity).to_string()),
910 ssf.signal_capacity.span(),
911 )
912 })
913 .collect::<Vec<_>>()
914}
915
916pub(crate) fn consumes_without_wip<'a, T: Borrow<SubSysField>>(subsystems: &[T]) -> Vec<Path> {
917 subsystems
918 .iter()
919 .map(|e| e.borrow())
920 .filter(|ssf| !ssf.wip)
921 .map(|ssf| ssf.message_to_consume())
922 .collect::<Vec<_>>()
923}
924
925pub(crate) fn can_receive_priority_messages_without_wip(
926 subsystems: &Vec<&SubSysField>,
927) -> Vec<syn::LitBool> {
928 subsystems
929 .iter()
930 .filter(|ssf| !ssf.wip)
931 .map(|ssf| syn::LitBool::new(ssf.can_receive_priority_messages, ssf.name.span()))
932 .collect::<Vec<_>>()
933}