1use core::{cmp::Ordering, hash::Hash};
20
21use alloc::{
22 borrow::{Cow, ToOwned},
23 format,
24 string::{String, ToString},
25};
26use smallstr::SmallString;
27use smallvec::SmallVec;
28
29pub use parser::{ParseError, ParseErrorKind};
31
32#[derive(Clone)]
48pub struct LookupName {
49 registry: Registry,
50 idx: usize,
51 pallet: Option<String>,
55}
56
57impl Hash for LookupName {
58 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
59 LookupNameInner::hash(self.idx, &self.registry, state)
60 }
61}
62
63impl Default for LookupName {
66 fn default() -> Self {
67 let unit_type = LookupNameInner::Unnamed { params: Params::new() };
70 Self { registry: Registry::from_iter([unit_type]), idx: 0, pallet: None }
71 }
72}
73
74impl PartialOrd for LookupName {
75 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
76 Some(self.cmp(other))
77 }
78}
79
80impl Ord for LookupName {
81 fn cmp(&self, other: &Self) -> Ordering {
82 if let o @ (Ordering::Greater | Ordering::Less) = self.pallet.cmp(&other.pallet) {
83 return o;
84 }
85
86 let a_idx = self.idx;
87 let a_registry = &self.registry;
88 let b_idx = other.idx;
89 let b_registry = &other.registry;
90
91 LookupNameInner::cmp(a_idx, a_registry, b_idx, b_registry)
92 }
93}
94
95impl PartialEq for LookupName {
96 fn eq(&self, other: &Self) -> bool {
97 if self.pallet != other.pallet {
98 return false;
99 }
100
101 let a_idx = self.idx;
102 let a_registry = &self.registry;
103 let b_idx = other.idx;
104 let b_registry = &other.registry;
105
106 LookupNameInner::eq(a_idx, a_registry, b_idx, b_registry)
107 }
108}
109
110impl Eq for LookupName {}
111
112impl core::fmt::Debug for LookupName {
113 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
114 write!(f, "{}", self.def())
115 }
116}
117
118impl core::fmt::Display for LookupName {
119 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
120 write!(f, "{}", self.def())
121 }
122}
123
124impl core::str::FromStr for LookupName {
125 type Err = ParseError;
126 fn from_str(s: &str) -> Result<Self, Self::Err> {
127 Self::parse(s)
128 }
129}
130
131impl core::convert::From<crate::InsertName> for LookupName {
132 fn from(value: crate::InsertName) -> Self {
133 let param_ids = value.params.iter().enumerate().map(|(idx, _)| idx + 1).collect();
134
135 let params_iter = value.params.into_iter().map(|param_name| LookupNameInner::Named {
136 name: param_name.into(),
137 params: Default::default(),
138 });
139
140 let registry_iter =
141 core::iter::once(LookupNameInner::Named { name: value.name.into(), params: param_ids })
142 .chain(params_iter);
143
144 LookupName { registry: SmallVec::from_iter(registry_iter), idx: 0, pallet: value.pallet }
145 }
146}
147
148impl core::convert::TryFrom<&str> for LookupName {
149 type Error = ParseError;
150 fn try_from(s: &str) -> Result<Self, Self::Error> {
151 Self::parse(s)
152 }
153}
154
155impl core::convert::TryFrom<String> for LookupName {
156 type Error = ParseError;
157 fn try_from(s: String) -> Result<Self, Self::Error> {
158 Self::parse(&s)
159 }
160}
161
162impl serde::Serialize for LookupName {
163 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
164 where
165 S: serde::Serializer,
166 {
167 serializer.serialize_str(&self.to_string())
168 }
169}
170
171impl<'de> serde::Deserialize<'de> for LookupName {
172 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
173 where
174 D: serde::Deserializer<'de>,
175 {
176 use serde::de::Error;
177 let s = <Cow<'de, str>>::deserialize(deserializer)?;
178 LookupName::parse(&s)
179 .map_err(|e| D::Error::custom(format!("Could not deserialize into LookupName: {e}")))
180 }
181}
182
183impl LookupName {
184 pub fn parse(input: &str) -> Result<LookupName, ParseError> {
186 use yap::IntoTokens;
187 let mut tokens = input.into_tokens();
188 let mut registry = Registry::new();
189
190 parser::parse_type_name(&mut tokens, &mut registry)?;
191
192 Ok(LookupName {
193 idx: registry.len() - 1,
196 registry,
197 pallet: None,
198 })
199 }
200
201 pub fn unnamed<'a>(input: impl IntoIterator<Item = &'a LookupName>) -> LookupName {
203 let mut name = LookupName {
204 registry: SmallVec::from_iter([
205 LookupNameInner::Unnamed { params: SmallVec::new() },
207 ]),
208 idx: 0,
209 pallet: None,
210 };
211
212 let ids = input.into_iter().map(|id| name.insert_def(id.def(), &[])).collect();
214
215 name.registry[0] = LookupNameInner::Unnamed { params: ids };
217 name
218 }
219
220 pub fn array(inner: &LookupName, len: usize) -> LookupName {
222 let mut name = LookupName {
223 registry: SmallVec::from_iter([
224 LookupNameInner::Array { param: 0, length: 0 },
226 ]),
227 idx: 0,
228 pallet: None,
229 };
230
231 let inner_idx = name.insert_def(inner.def(), &[]);
232 name.registry[0] = LookupNameInner::Array { param: inner_idx, length: len };
233 name
234 }
235
236 pub fn in_pallet(mut self, pallet_name: impl Into<String>) -> LookupName {
238 self.pallet = Some(pallet_name.into());
239 self
240 }
241
242 pub fn name(&self) -> Option<&str> {
245 match self.def() {
246 LookupNameDef::Named(named) => Some(named.name),
247 _ => None,
248 }
249 }
250
251 pub(crate) fn pallet(&self) -> Option<&str> {
253 self.pallet.as_deref()
254 }
255
256 pub(crate) fn take_pallet(&mut self) -> Option<String> {
258 self.pallet.take()
259 }
260
261 pub(crate) fn with_substitution(
264 mut self,
265 ident: &str,
266 replacement: LookupNameDef<'_>,
267 ) -> LookupName {
268 let original_len = self.registry.len();
269
270 let indexes_to_replace: SmallVec<[_;2]> = self.registry
272 .iter()
273 .enumerate()
274 .filter(|(_, ty)| matches!(ty, LookupNameInner::Named { name, params } if params.is_empty() && name == ident))
275 .map(|(idx,_)| idx)
276 .collect();
277
278 if indexes_to_replace.is_empty() {
280 return self;
281 }
282
283 let replacement_idx = self.insert_def(replacement, &indexes_to_replace);
285
286 let update_param = |param: &mut usize| {
288 if indexes_to_replace.contains(param) {
289 *param = replacement_idx;
290 }
291 };
292 let update_params = |params: &mut Params| {
293 for param in params.iter_mut() {
294 update_param(param);
295 }
296 };
297
298 for (idx, inner) in self.registry.iter_mut().enumerate() {
300 if idx >= original_len {
301 break;
303 }
304 if indexes_to_replace.contains(&idx) {
305 continue;
307 }
308
309 match inner {
310 LookupNameInner::Named { params, .. } => update_params(params),
311 LookupNameInner::Unnamed { params } => update_params(params),
312 LookupNameInner::Array { param, .. } => update_param(param),
313 }
314 }
315
316 update_param(&mut self.idx);
318
319 self
320 }
321
322 pub(crate) fn def(&self) -> LookupNameDef<'_> {
324 self.def_at(self.idx)
325 }
326
327 fn insert_def(&mut self, ty: LookupNameDef<'_>, free_idxs: &[usize]) -> usize {
329 let (idx, registry) = match ty {
330 LookupNameDef::Named(t) => (t.idx, &t.handle.registry),
331 LookupNameDef::Unnamed(t) => (t.idx, &t.handle.registry),
332 LookupNameDef::Array(t) => (t.idx, &t.handle.registry),
333 };
334
335 self.insert_entry_from_other_registry(idx, registry, &mut &*free_idxs)
336 }
337
338 fn insert_entry_from_other_registry(
341 &mut self,
342 idx: usize,
343 registry: &Registry,
344 free_idxs: &mut &[usize],
345 ) -> usize {
346 let idx_to_use = free_idxs.first().map(|idx| {
347 *free_idxs = &free_idxs[1..];
348 *idx
349 });
350
351 let new_inner = match ®istry.get(idx).expect("type index used which doesn't exist") {
352 LookupNameInner::Named { name, params } => {
353 let new_params = params
354 .iter()
355 .map(|idx: &usize| {
356 self.insert_entry_from_other_registry(*idx, registry, free_idxs)
357 })
358 .collect();
359 LookupNameInner::Named { name: name.clone(), params: new_params }
360 }
361 LookupNameInner::Unnamed { params } => {
362 let new_params = params
363 .iter()
364 .map(|idx: &usize| {
365 self.insert_entry_from_other_registry(*idx, registry, free_idxs)
366 })
367 .collect();
368 LookupNameInner::Unnamed { params: new_params }
369 }
370 LookupNameInner::Array { param, length } => {
371 let new_param = self.insert_entry_from_other_registry(*param, registry, free_idxs);
372 LookupNameInner::Array { param: new_param, length: *length }
373 }
374 };
375
376 if let Some(idx_to_use) = idx_to_use {
378 self.registry[idx_to_use] = new_inner;
379 idx_to_use
380 } else {
381 let new_idx = self.registry.len();
382 self.registry.push(new_inner);
383 new_idx
384 }
385 }
386
387 fn def_at(&self, idx: usize) -> LookupNameDef<'_> {
389 let entry = self.registry.get(idx).expect("idx should exist in registry");
390
391 match entry {
392 LookupNameInner::Named { name, params } => {
393 LookupNameDef::Named(NamedTypeDef { idx, name, params, handle: self })
394 }
395 LookupNameInner::Unnamed { params } => {
396 LookupNameDef::Unnamed(UnnamedTypeDef { idx, params, handle: self })
397 }
398 LookupNameInner::Array { param, length } => LookupNameDef::Array(ArrayTypeDef {
399 idx,
400 param: *param,
401 length: *length,
402 handle: self,
403 }),
404 }
405 }
406}
407
408#[derive(Debug, Copy, Clone)]
410pub enum LookupNameDef<'tn> {
411 Named(NamedTypeDef<'tn>),
414 Unnamed(UnnamedTypeDef<'tn>),
416 Array(ArrayTypeDef<'tn>),
418}
419
420impl<'a> core::fmt::Display for LookupNameDef<'a> {
421 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
422 match self {
423 LookupNameDef::Named(named) => {
424 write!(f, "{}", named.name())?;
425 if !named.params.is_empty() {
426 write!(f, "<")?;
427 let mut fst = true;
428 for param in named.param_defs() {
429 if !fst {
430 write!(f, ", ")?;
431 }
432 fst = false;
433 write!(f, "{}", param)?;
434 }
435 write!(f, ">")?;
436 }
437 }
438 LookupNameDef::Unnamed(unnamed) => {
439 write!(f, "(")?;
440 if !unnamed.params.is_empty() {
441 let mut fst = true;
442 for param in unnamed.param_defs() {
443 if !fst {
444 write!(f, ", ")?;
445 }
446 fst = false;
447 write!(f, "{}", param)?;
448 }
449 }
450 write!(f, ")")?;
451 }
452 LookupNameDef::Array(array) => {
453 write!(f, "[{}; {}]", array.param_def(), array.length())?;
454 }
455 }
456 Ok(())
457 }
458}
459
460impl<'tn> LookupNameDef<'tn> {
461 pub fn into_type_name(self) -> LookupName {
463 match self {
464 LookupNameDef::Named(v) => v.into_type_name(),
465 LookupNameDef::Unnamed(v) => v.into_type_name(),
466 LookupNameDef::Array(v) => v.into_type_name(),
467 }
468 }
469
470 #[cfg(test)]
471 fn unwrap_named(self) -> NamedTypeDef<'tn> {
472 match self {
473 LookupNameDef::Named(a) => a,
474 _ => panic!("Cannot unwrap '{self:?}' into an NamedName"),
475 }
476 }
477
478 #[cfg(test)]
479 fn unwrap_unnamed(self) -> UnnamedTypeDef<'tn> {
480 match self {
481 LookupNameDef::Unnamed(a) => a,
482 _ => panic!("Cannot unwrap '{self:?}' into an UnnamedName"),
483 }
484 }
485
486 #[cfg(test)]
487 fn unwrap_array(self) -> ArrayTypeDef<'tn> {
488 match self {
489 LookupNameDef::Array(a) => a,
490 _ => panic!("Cannot unwrap '{self:?}' into an ArrayName"),
491 }
492 }
493}
494
495#[derive(Debug, Copy, Clone)]
497pub struct NamedTypeDef<'tn> {
498 name: &'tn str,
499 params: &'tn Params,
500 handle: &'tn LookupName,
501 idx: usize,
502}
503
504impl<'tn> NamedTypeDef<'tn> {
505 pub fn into_type_name(self) -> LookupName {
507 LookupName {
508 pallet: self.handle.pallet.to_owned(),
509 registry: self.handle.registry.clone(),
510 idx: self.idx,
511 }
512 }
513
514 pub fn name(&self) -> &'tn str {
516 self.name
517 }
518
519 pub fn param_defs(&self) -> impl Iterator<Item = LookupNameDef<'tn>> {
521 self.params.iter().map(|idx| self.handle.def_at(*idx))
522 }
523}
524
525#[derive(Debug, Copy, Clone)]
527pub struct UnnamedTypeDef<'tn> {
528 params: &'tn Params,
529 handle: &'tn LookupName,
530 idx: usize,
531}
532
533impl<'tn> UnnamedTypeDef<'tn> {
534 pub fn into_type_name(self) -> LookupName {
536 LookupName {
537 pallet: self.handle.pallet.to_owned(),
538 registry: self.handle.registry.clone(),
539 idx: self.idx,
540 }
541 }
542
543 pub fn param_defs(&self) -> impl ExactSizeIterator<Item = LookupNameDef<'tn>> {
545 self.params.iter().map(|idx| self.handle.def_at(*idx))
546 }
547}
548
549#[derive(Debug, Copy, Clone)]
551pub struct ArrayTypeDef<'tn> {
552 param: usize,
553 length: usize,
554 handle: &'tn LookupName,
555 idx: usize,
556}
557
558impl<'tn> ArrayTypeDef<'tn> {
559 pub fn into_type_name(self) -> LookupName {
561 LookupName {
562 pallet: self.handle.pallet.to_owned(),
563 registry: self.handle.registry.clone(),
564 idx: self.idx,
565 }
566 }
567
568 pub fn length(&self) -> usize {
570 self.length
571 }
572 pub fn param_def(&self) -> LookupNameDef<'tn> {
574 self.handle.def_at(self.param)
575 }
576}
577
578type Registry = SmallVec<[LookupNameInner; 2]>;
580type Params = SmallVec<[usize; 2]>;
581type NameStr = SmallString<[u8; 16]>;
582
583#[derive(Clone, Debug)]
585pub enum LookupNameInner {
586 Named {
589 name: NameStr,
591 params: Params,
593 },
594 Unnamed {
596 params: Params,
598 },
599 Array {
601 param: usize,
603 length: usize,
605 },
606}
607
608macro_rules! ord_eq {
610 ($a:expr) => {
611 if let o @ (Ordering::Greater | Ordering::Less) = $a {
612 return o;
613 }
614 };
615 ($a:expr, $b:expr) => {
616 if let o @ (Ordering::Greater | Ordering::Less) = $a.cmp(&$b) {
617 return o;
618 }
619 };
620}
621
622impl LookupNameInner {
623 fn cmp(
624 a_idx: usize,
625 a_registry: &Registry,
626 b_idx: usize,
627 b_registry: &Registry,
628 ) -> core::cmp::Ordering {
629 let a = &a_registry[a_idx];
630 let b = &b_registry[b_idx];
631
632 match (a, b) {
633 (
635 LookupNameInner::Named { name: a_name, params: a_params },
636 LookupNameInner::Named { name: b_name, params: b_params },
637 ) => {
638 ord_eq!(a_name, b_name);
639 ord_eq!(a_params.len(), b_params.len());
640
641 for (a_param, b_param) in a_params.iter().zip(b_params.iter()) {
642 ord_eq!(LookupNameInner::cmp(*a_param, a_registry, *b_param, b_registry));
643 }
644 }
645 (
646 LookupNameInner::Unnamed { params: a_params },
647 LookupNameInner::Unnamed { params: b_params },
648 ) => {
649 ord_eq!(a_params.len(), b_params.len());
650
651 for (a_param, b_param) in a_params.iter().zip(b_params.iter()) {
652 ord_eq!(LookupNameInner::cmp(*a_param, a_registry, *b_param, b_registry));
653 }
654 }
655 (
656 LookupNameInner::Array { param: a_param, length: a_len },
657 LookupNameInner::Array { param: b_param, length: b_len },
658 ) => {
659 ord_eq!(a_len, b_len);
660 ord_eq!(LookupNameInner::cmp(*a_param, a_registry, *b_param, b_registry));
661 }
662 (LookupNameInner::Named { .. }, _) => return Ordering::Greater,
664 (LookupNameInner::Unnamed { .. }, _) => return Ordering::Greater,
665 (LookupNameInner::Array { .. }, _) => return Ordering::Greater,
666 }
667 Ordering::Equal
668 }
669
670 fn eq(a_idx: usize, a_registry: &Registry, b_idx: usize, b_registry: &Registry) -> bool {
671 LookupNameInner::cmp(a_idx, a_registry, b_idx, b_registry).is_eq()
672 }
673
674 fn hash<H: core::hash::Hasher>(idx: usize, registry: &Registry, state: &mut H) {
675 let inner = ®istry[idx];
676 match inner {
677 LookupNameInner::Array { param, length } => {
678 0u8.hash(state);
679 LookupNameInner::hash(*param, registry, state);
680 length.hash(state);
681 }
682 LookupNameInner::Named { name, params } => {
683 1u8.hash(state);
684 name.hash(state);
685 for param in params {
686 LookupNameInner::hash(*param, registry, state);
687 }
688 }
689 LookupNameInner::Unnamed { params } => {
690 2u8.hash(state);
691 for param in params {
692 LookupNameInner::hash(*param, registry, state);
693 }
694 }
695 }
696 }
697}
698
699mod parser {
701 use super::*;
702 use yap::{types::StrTokens, TokenLocation, Tokens};
703
704 #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
706 #[error("Error parsing string into type name at character {loc}: {err}")]
707 pub struct ParseError {
708 pub loc: usize,
710 pub err: ParseErrorKind,
712 }
713
714 impl ParseError {
715 pub fn new_at<E: Into<ParseErrorKind>>(err: E, loc: usize) -> Self {
717 Self { loc, err: err.into() }
718 }
719 }
720
721 #[allow(missing_docs)]
723 #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
724 pub enum ParseErrorKind {
725 #[error("The string did not look like a type name at all.")]
726 InvalidName,
727 #[error("A closing `)` was missing when attempting to parse a tuple type name.")]
728 ClosingParenMissing,
729 #[error(
730 "A closing `>` was missing when attempting to parse the generics of a named type."
731 )]
732 ClosingAngleBracketMissing,
733 #[error("A closing `]` was missing when attempting to parse an array type.")]
734 ClosingSquareBracketMissing,
735 #[error("The length of the array is invalid; expecting an unsigned integer.")]
736 InvalidUnsignedInt,
737 }
738
739 pub fn parse_type_name(
740 input: &mut StrTokens<'_>,
741 registry: &mut Registry,
742 ) -> Result<(), ParseError> {
743 let loc = input.location();
744 try_parse_type_name(input, registry)
745 .unwrap_or_else(|| Err(ParseError::new_at(ParseErrorKind::InvalidName, loc.offset())))
746 }
747
748 fn try_parse_type_name(
749 input: &mut StrTokens<'_>,
750 registry: &mut Registry,
751 ) -> Option<Result<(), ParseError>> {
752 yap::one_of!(input;
753 parse_unnamed_into_type_name(input, registry),
754 parse_array_into_type_name(input, registry),
755 parse_named_into_type_name(input, registry),
756 parse_slice_into_type_name(input, registry),
757 )
758 }
759
760 fn parse_named_into_type_name(
762 input: &mut StrTokens<'_>,
763 registry: &mut Registry,
764 ) -> Option<Result<(), ParseError>> {
765 let name = parse_path(input);
766 if name.is_empty() {
767 return None;
768 }
769
770 skip_whitespace(input);
771 if !input.token('<') {
772 registry.push(LookupNameInner::Named {
774 name: NameStr::from_str(&name),
775 params: Params::new(),
776 });
777 return Some(Ok(()));
778 }
779
780 let params = match parse_comma_separated_type_names(input, registry) {
781 Ok(params) => params,
782 Err(err) => return Some(Err(err)),
783 };
784
785 if !input.token('>') {
786 let loc = input.location().offset();
787 Some(Err(ParseError::new_at(ParseErrorKind::ClosingAngleBracketMissing, loc)))
788 } else {
789 registry.push(LookupNameInner::Named { name: NameStr::from_str(&name), params });
790 Some(Ok(()))
791 }
792 }
793
794 fn parse_unnamed_into_type_name(
796 input: &mut StrTokens<'_>,
797 registry: &mut Registry,
798 ) -> Option<Result<(), ParseError>> {
799 if !input.token('(') {
800 return None;
801 }
802
803 let params = match parse_comma_separated_type_names(input, registry) {
804 Ok(params) => params,
805 Err(err) => return Some(Err(err)),
806 };
807
808 if !input.token(')') {
809 let loc = input.location().offset();
810 Some(Err(ParseError::new_at(ParseErrorKind::ClosingParenMissing, loc)))
811 } else {
812 registry.push(LookupNameInner::Unnamed { params });
813 Some(Ok(()))
814 }
815 }
816
817 fn parse_array_into_type_name(
819 input: &mut StrTokens<'_>,
820 registry: &mut Registry,
821 ) -> Option<Result<(), ParseError>> {
822 if !input.token('[') {
823 return None;
824 }
825
826 skip_whitespace(input);
827 let param = match parse_type_name(input, registry) {
828 Ok(()) => registry.len() - 1,
829 Err(e) => return Some(Err(e)),
830 };
831
832 skip_whitespace(input);
833 input.token(';');
834 skip_whitespace(input);
835
836 let loc = input.location().offset();
837 let length: usize =
838 match input.take_while(|toks| toks.is_numeric()).parse::<usize, String>() {
839 Ok(n) => n,
840 Err(_) => {
841 return Some(Err(ParseError::new_at(ParseErrorKind::InvalidUnsignedInt, loc)))
842 }
843 };
844
845 if !input.token(']') {
846 let loc = input.location().offset();
847 Some(Err(ParseError::new_at(ParseErrorKind::ClosingSquareBracketMissing, loc)))
848 } else {
849 registry.push(LookupNameInner::Array { param, length });
850 Some(Ok(()))
851 }
852 }
853
854 fn parse_slice_into_type_name(
857 input: &mut StrTokens<'_>,
858 registry: &mut Registry,
859 ) -> Option<Result<(), ParseError>> {
860 if !input.tokens("&[".chars()) {
861 return None;
862 }
863
864 skip_whitespace(input);
865 let param = match parse_type_name(input, registry) {
866 Ok(()) => registry.len() - 1,
867 Err(e) => return Some(Err(e)),
868 };
869 skip_whitespace(input);
870
871 if !input.token(']') {
872 let loc = input.location().offset();
873 Some(Err(ParseError::new_at(ParseErrorKind::ClosingSquareBracketMissing, loc)))
874 } else {
875 registry.push(LookupNameInner::Named {
876 name: NameStr::from_str("Vec"),
877 params: SmallVec::from_iter([param]),
878 });
879 Some(Ok(()))
880 }
881 }
882
883 fn parse_comma_separated_type_names(
885 input: &mut StrTokens<'_>,
886 registry: &mut Registry,
887 ) -> Result<Params, ParseError> {
888 skip_whitespace(input);
889
890 let mut params_iter = input.sep_by(
891 |toks| {
892 let res = try_parse_type_name(toks, registry)?;
894 Some(res.map(|()| registry.len() - 1))
896 },
897 |toks| toks.surrounded_by(|toks| toks.token(','), |toks| skip_whitespace(toks)),
898 );
899
900 let mut params = Params::new();
901 for res in params_iter.as_iter() {
902 let idx = res?;
903 params.push(idx);
904 }
905
906 skip_whitespace(input);
907 input.token(',');
909 skip_whitespace(input);
910
911 Ok(params)
912 }
913
914 fn parse_path<'a>(input: &mut StrTokens<'a>) -> Cow<'a, str> {
916 let path_str = str_slice_from(input, |toks| {
917 toks.sep_by(
918 |t| {
919 if t.peek()? == '<' {
922 let mut counter = 0;
923 while let Some(tok) = t.next() {
924 if tok == '<' {
925 counter += 1;
926 } else if tok == '>' {
927 counter -= 1;
928 if counter == 0 {
929 return Some(());
930 }
931 }
932 }
933 }
934
935 let fst_char = t.next()?;
937 if !(fst_char.is_alphabetic() || fst_char == '_') {
938 return None;
939 }
940 t.skip_while(|c| c.is_alphanumeric() || *c == '_');
942 Some(())
943 },
944 |t| {
945 t.surrounded_by(|t| t.tokens("::".chars()), |t| skip_whitespace(t))
947 },
948 )
949 .consume();
950 });
951
952 normalize_whitespace(path_str)
953 }
954
955 pub fn normalize_whitespace(str: &str) -> Cow<'_, str> {
970 let idx = idx_after_closing_angle_bracket(&mut str.chars()).unwrap_or(0);
972 let trait_as_part = &str[0..idx];
973 let path_part = &str[idx..];
974
975 let change_in_trait_as_part = trait_as_part.chars().any(|c| c.is_whitespace() && c != ' ');
979 let remove_in_trait_as_part = trait_as_part
981 .chars()
982 .zip(trait_as_part.chars().skip(1))
983 .filter(|(a, b)| a.is_whitespace() && b.is_whitespace())
984 .count();
985 let remove_in_path_part = path_part.chars().filter(|c| c.is_whitespace()).count();
987
988 if remove_in_trait_as_part == 0 && remove_in_path_part == 0 && !change_in_trait_as_part {
990 return Cow::Borrowed(str);
991 }
992
993 let mut new_s =
994 String::with_capacity(str.len() - remove_in_path_part - remove_in_trait_as_part);
995
996 let mut prev_is_whitespace = false;
998 for c in trait_as_part.chars() {
999 if c.is_whitespace() {
1000 if !prev_is_whitespace {
1001 prev_is_whitespace = true;
1002 new_s.push(' ');
1003 }
1004 } else {
1005 prev_is_whitespace = false;
1006 new_s.push(c);
1007 }
1008 }
1009
1010 path_part.chars().filter(|c| !c.is_whitespace()).for_each(|c| new_s.push(c));
1012
1013 Cow::Owned(new_s)
1014 }
1015
1016 fn idx_after_closing_angle_bracket(s: &mut impl Iterator<Item = char>) -> Option<usize> {
1018 let mut idx = 0;
1019 let mut counter = 0;
1020 for tok in s {
1021 idx += 1;
1022 if tok == '<' {
1023 counter += 1;
1024 } else if tok == '>' {
1025 counter -= 1;
1026 if counter == 0 {
1027 return Some(idx);
1028 }
1029 }
1030 }
1031 None
1032 }
1033
1034 fn skip_whitespace(input: &mut StrTokens<'_>) {
1036 input.skip_while(|t| t.is_whitespace());
1037 }
1038
1039 fn str_slice_from<'a, F>(input: &mut StrTokens<'a>, f: F) -> &'a str
1041 where
1042 F: FnOnce(&mut StrTokens<'a>),
1043 {
1044 let before = input.remaining();
1045 f(input);
1046 let leftover = input.remaining().len();
1047
1048 &before[..before.len() - leftover]
1049 }
1050}
1051
1052#[cfg(test)]
1053mod test {
1054 use super::*;
1055 use alloc::borrow::ToOwned;
1056 use alloc::string::ToString;
1057 use alloc::vec;
1058 use alloc::vec::Vec;
1059
1060 fn expect_parse(input: &str) -> LookupName {
1061 match LookupName::parse(input) {
1062 Ok(tn) => tn,
1063 Err(e) => panic!("parsing '{input}' failed: {e}"),
1064 }
1065 }
1066
1067 fn expect_parse_fail(input: &str) {
1068 match LookupName::parse(input) {
1069 Ok(tn) => panic!("parsing '{input}' is expected to have failed, but got {tn:?}"),
1070 Err(_e) => {}
1071 }
1072 }
1073
1074 #[test]
1075 fn basic_eq_and_hash_works() {
1076 let cmps = [
1077 (expect_parse("&[u8]"), expect_parse("Vec<u8>"), true),
1079 (expect_parse("&[Foo]"), expect_parse("Vec<Foo>"), true),
1080 (expect_parse("path::to::Foo"), expect_parse("path::to::Foo"), true),
1082 (expect_parse("Foo<u8>"), expect_parse("Foo<u8>"), true),
1083 (expect_parse("Foo<u8>"), expect_parse("Foo<bool>"), false),
1084 (expect_parse("Foo<u8>"), expect_parse("Foo<u8, bool>"), false),
1085 (expect_parse("path::to::Foo").in_pallet("bar"), expect_parse("path::to::Foo"), false),
1086 (
1087 expect_parse("path::to::Foo").in_pallet("bar"),
1088 expect_parse("path::to::Foo").in_pallet("bar"),
1089 true,
1090 ),
1091 (
1092 expect_parse("path::for::Foo").in_pallet("bar"),
1093 expect_parse("path::to::Foo").in_pallet("bar"),
1094 false,
1095 ),
1096 (expect_parse("path::for::Foo"), expect_parse("path::to::Foo"), false),
1097 (expect_parse("[u8; 32]"), expect_parse("[u8; 32]"), true),
1099 (expect_parse("[u8; 32]"), expect_parse("[u8; 28]"), false),
1100 (expect_parse("[u8; 32]"), expect_parse("[u16; 32]"), false),
1101 (expect_parse("()"), expect_parse("()"), true),
1103 (expect_parse("(bool,)"), expect_parse("(bool,)"), true),
1104 (expect_parse("(char, u8, String)"), expect_parse("(char, u8, String)"), true),
1105 (expect_parse("(char, u8, String)"), expect_parse("(char, u8, String, bool)"), false),
1106 (expect_parse("(u8, char, String)"), expect_parse("(char, u8, String)"), false),
1107 ];
1108
1109 for (a, b, expected) in cmps {
1110 assert_eq!(a == b, expected, "{a} should equal {b}: {expected}");
1111
1112 if expected {
1114 let mut set = hashbrown::HashSet::with_capacity(1024);
1120 set.insert(&a);
1121 set.insert(&b);
1122 assert_eq!(set.len(), 1, "hash mismatch between {a} and {b}");
1123 }
1124 }
1125 }
1126
1127 #[test]
1128 fn eq_works_with_different_registries() {
1129 let a = LookupName {
1132 registry: SmallVec::from_iter([
1133 LookupNameInner::Named { name: "Foo".into(), params: SmallVec::from_iter([1]) },
1134 LookupNameInner::Array { param: 2, length: 32 },
1135 LookupNameInner::Unnamed { params: SmallVec::from_iter([]) },
1136 ]),
1137 idx: 0,
1138 pallet: None,
1139 };
1140 let b = LookupName {
1141 registry: SmallVec::from_iter([
1142 LookupNameInner::Array { param: 1, length: 32 },
1143 LookupNameInner::Unnamed { params: SmallVec::from_iter([]) },
1144 LookupNameInner::Named { name: "Foo".into(), params: SmallVec::from_iter([0]) },
1145 LookupNameInner::Array { param: 0, length: 128 },
1147 ]),
1148 idx: 2,
1149 pallet: None,
1150 };
1151
1152 assert_eq!(a, b);
1153
1154 let mut set = hashbrown::HashSet::with_capacity(1024);
1156 set.insert(&a);
1157 set.insert(&b);
1158 assert_eq!(set.len(), 1, "hash mismatch between {a} and {b}");
1159 }
1160
1161 #[test]
1162 fn parse_succeeds() {
1163 expect_parse("()");
1164 expect_parse("(Foo)"); expect_parse("(Foo,)");
1166 expect_parse("(Foo, usize, i32)");
1167 expect_parse("(a,b,c,)");
1168
1169 expect_parse("path::to::Foo"); expect_parse("path_with_underscore::to::Foo"); expect_parse("_path_starting_underscore::to::Foo"); expect_parse("<Wibble as Bar<u32>>::to::Foo"); expect_parse("<Wibble as Bar<u32>> ::to::\n Foo"); expect_parse("Foo");
1175 expect_parse("Foo<>");
1176 expect_parse("Foo<A>");
1177 expect_parse("Foo<A, b, (), (Wibble)>");
1178
1179 expect_parse("[usize;32]");
1180 expect_parse("[a::b::Foo<T,A,B> ;32]");
1181 expect_parse("[bool; 32]");
1182
1183 expect_parse("&[bool]");
1184 expect_parse("&[ u8]");
1185 expect_parse("&[a::b::Foo<T,A,B> ]");
1186 }
1187
1188 #[test]
1189 fn parse_fails() {
1190 expect_parse_fail("3thing");
1192 expect_parse_fail("(bool,3)");
1193
1194 expect_parse_fail("[usize; Foo]");
1196
1197 expect_parse_fail("(Foo, Bar");
1199 expect_parse_fail("[Foo; 32");
1200 expect_parse_fail("Foo<A, B");
1201 }
1202
1203 #[test]
1204 fn with_substitution_works() {
1205 let cases = [
1211 ("Foo<T>", "T", "(A,B,C)", "Foo<(A, B, C)>"),
1212 ("T", "T", "Vec<u64>", "Vec<u64>"),
1213 ("(T, T, u32, T, T)", "T", "[u64; 3]", "([u64; 3], [u64; 3], u32, [u64; 3], [u64; 3])"),
1214 ("Vec<T>", "T", "U", "Vec<U>"),
1215 ("Foo<T, (A, [T; 32])>", "T", "U", "Foo<U, (A, [U; 32])>"),
1216 ("Foo<T, (A, [T; 32])>", "T", "(A,B,C)", "Foo<(A, B, C), (A, [(A, B, C); 32])>"),
1217 ("(T<A>, T)", "T", "U", "(T<A>, U)"),
1219 ];
1220
1221 for (original, find, replace_with, expected) in cases {
1222 let original_ty = LookupName::parse(original).unwrap();
1223 let replacement = LookupName::parse(replace_with).unwrap();
1224 let new_ty = original_ty.with_substitution(find, replacement.def());
1225 assert_eq!(expected, new_ty.to_string());
1226 }
1227 }
1228
1229 #[test]
1230 fn parses_into_expected_shape() {
1231 let tn = expect_parse("Foo");
1232 let def = tn.def().unwrap_named();
1233 assert!(def.name() == "Foo" && def.param_defs().count() == 0);
1234
1235 let tn = expect_parse("Foo<A>");
1236 let def = tn.def().unwrap_named();
1237 assert!(
1238 def.name() == "Foo" && def.param_defs().next().unwrap().unwrap_named().name() == "A"
1239 );
1240
1241 let tn = expect_parse("()");
1242 let def = tn.def().unwrap_unnamed();
1243 assert!(def.param_defs().count() == 0);
1244
1245 let tn = expect_parse("(bool, u32, Bar<A>)");
1246 let param_names: Vec<String> = tn
1247 .def()
1248 .unwrap_unnamed()
1249 .param_defs()
1250 .map(|p| p.unwrap_named().name().to_owned())
1251 .collect();
1252 assert_eq!(param_names, vec!["bool", "u32", "Bar"]);
1253
1254 let tn = expect_parse("[Foo; 16]");
1255 let def = tn.def().unwrap_array();
1256 assert!(def.length() == 16 && def.param_def().unwrap_named().name() == "Foo");
1257
1258 let tn = expect_parse("&[u8]");
1259 let def = tn.def().unwrap_named();
1260 assert!(
1261 def.name() == "Vec" && def.param_defs().next().unwrap().unwrap_named().name() == "u8"
1262 );
1263 }
1264
1265 #[test]
1266 fn parsing_complex_nested_type_works() {
1267 let tn = expect_parse("Foo<(Option<Wibble<[(u8, Bar);12],Compact<()>>>,bool)>");
1268
1269 let foo = tn.def().unwrap_named();
1271 assert_eq!(foo.name(), "Foo");
1272
1273 let foo_params: Vec<_> = foo.param_defs().collect();
1275 assert_eq!(foo_params.len(), 1);
1276
1277 let foo_tuple = foo_params[0].unwrap_unnamed();
1279 assert_eq!(foo_tuple.param_defs().count(), 2);
1280
1281 let foo_tuple_params: Vec<_> = foo_tuple.param_defs().collect();
1283 assert_eq!(foo_tuple_params.len(), 2);
1284 assert_eq!(foo_tuple_params[0].unwrap_named().name(), "Option");
1285 assert_eq!(foo_tuple_params[1].unwrap_named().name(), "bool");
1286
1287 let option_params: Vec<_> = foo_tuple_params[0].unwrap_named().param_defs().collect();
1289 assert_eq!(option_params.len(), 1);
1290
1291 let wibble = option_params[0].unwrap_named();
1293 assert_eq!(wibble.name(), "Wibble");
1294
1295 let wibble_params: Vec<_> = wibble.param_defs().collect();
1297 assert_eq!(wibble_params.len(), 2);
1298
1299 let arr = wibble_params[0].unwrap_array();
1301 assert_eq!(arr.length(), 12);
1302 assert_eq!(arr.param_def().unwrap_unnamed().param_defs().count(), 2);
1303 }
1304
1305 #[test]
1306 fn displaying_types_works() {
1307 let ty_name_strs = [
1308 "u32",
1309 "Foo",
1310 "Foo<T>",
1311 "Foo<A, B, C>",
1312 "[u8; 32]",
1313 "[Foo<A>; 32]",
1314 "()",
1315 "(A, B, C)",
1316 "Foo<(A, B, C<D>), [u8; 32], Bar<T>>",
1317 ];
1318
1319 for ty_name_str in ty_name_strs {
1320 let ty_name = LookupName::parse(ty_name_str).unwrap();
1321 assert_eq!(ty_name.to_string(), ty_name_str);
1322 }
1323 }
1324
1325 #[test]
1326 fn parsing_weird_paths_works() {
1327 let cases = [
1328 ("<Foo as Bar>::Item<A, B>", "<Foo as Bar>::Item<A, B>", vec!["A", "B"]),
1329 ("<Foo \tas \n\nBar>::Item", "<Foo as Bar>::Item", vec![]),
1330 (
1331 "<<Foo<Thing> \tas \n\nBar<A,B>> as Wibble>::Item",
1332 "<<Foo<Thing> as Bar<A,B>> as Wibble>::Item",
1333 vec![],
1334 ),
1335 ("_underscorefirst::Foo", "_underscorefirst::Foo", vec![]),
1336 ("underscore_in_path::Foo", "underscore_in_path::Foo", vec![]),
1337 ];
1338
1339 for (actual, expected, expected_params) in cases {
1340 let name = LookupName::parse(actual)
1341 .unwrap_or_else(|_| panic!("should be able to parse '{actual}'"));
1342
1343 let actual_params: Vec<String> =
1344 name.def().unwrap_named().param_defs().map(|p| p.to_string()).collect();
1345
1346 assert_eq!(actual_params, expected_params);
1347 assert_eq!(name.to_string(), expected);
1348 }
1349 }
1350
1351 #[test]
1352 fn normalize_whitespace_works() {
1353 let cases = &[
1354 ("T:: Something", Cow::Owned("T::Something".to_string())),
1356 ("T ::Something", Cow::Owned("T::Something".to_string())),
1357 ("<Foo\n\t as \nBar>", Cow::Owned("<Foo as Bar>".to_string())),
1359 ("<Foo as\nBar>", Cow::Owned("<Foo as Bar>".to_string())),
1361 (
1363 "<T\t as \n\n\tfoo>:: path\n :: Something",
1364 Cow::Owned("<T as foo>::path::Something".to_string()),
1365 ),
1366 (
1367 "<<Foo as\tbar>::Wibble \t \nas\nBob> ::path::\nTo",
1368 Cow::Owned("<<Foo as bar>::Wibble as Bob>::path::To".to_string()),
1369 ),
1370 (
1371 "<<Foo as bar>::Wibble as Bob>::path::To",
1372 Cow::Borrowed("<<Foo as bar>::Wibble as Bob>::path::To"),
1373 ),
1374 ];
1375
1376 for (input, output) in cases {
1377 assert_eq!(&parser::normalize_whitespace(input), output);
1378 }
1379 }
1380
1381 #[test]
1382 fn unnamed_lookup_name() {
1383 let entries = [
1384 LookupName::parse("u32").unwrap(),
1385 LookupName::parse("Foo<A, B, C>").unwrap(),
1386 LookupName::parse("(bool, char)").unwrap(),
1387 LookupName::parse("[u8; 32]").unwrap(),
1388 ];
1389
1390 let tuple = LookupName::unnamed(&entries);
1391 let expected = LookupName::parse("(u32, Foo<A,B,C>, (bool, char), [u8; 32])").unwrap();
1392
1393 assert_eq!(tuple, expected);
1394 }
1395
1396 #[test]
1397 fn array_lookup_name() {
1398 let inners = [
1399 LookupName::parse("u32").unwrap(),
1400 LookupName::parse("Foo<A, B, C>").unwrap(),
1401 LookupName::parse("(bool, char)").unwrap(),
1402 LookupName::parse("[u8; 32]").unwrap(),
1403 ];
1404
1405 for inner in inners {
1406 let array = LookupName::array(&inner, 32);
1407 let expected = LookupName::parse(&format!("[{inner}; 32]")).unwrap();
1408 assert_eq!(array, expected);
1409 }
1410 }
1411
1412 #[test]
1413 fn to_from_insert_name() {
1414 let cases = [
1415 "Foo<A, B, C>",
1416 "Bar",
1417 "foo::bar::Wibble",
1418 "foo::bar::Wibble<A>",
1419 "<Bar as Foo>::Something",
1420 ];
1421
1422 for case in cases {
1423 let lookup_name = LookupName::parse(case).expect("parses ok");
1424 let insert_name: crate::InsertName =
1425 lookup_name.clone().try_into().expect("converts to InsertName ok");
1426 let lookup_name_again: LookupName = insert_name.into();
1427
1428 assert_eq!(
1429 lookup_name, lookup_name_again,
1430 "mismatch between {lookup_name} and {lookup_name_again}"
1431 );
1432 }
1433 }
1434}