1#![allow(unused_imports)]
2#![allow(unused_variables)]
3
4use crate::ast::{
5 ConstDef, Definition, EnumDef, EnumFallback, EnumVariant, EventDef, EventFallback, FunctionDef,
6 FunctionFallback, FunctionPart, InlineEnum, InlineStruct, NewtypeDef, ServiceDef, ServiceItem,
7 StructDef, StructFallback, StructField, TypeNameOrInline,
8};
9use crate::{Parser, Schema, Span};
10use std::collections::HashMap;
11use std::mem;
12use thiserror::Error;
13
14type Result<'a, T> = std::result::Result<T, ResolveLinkError<'a>>;
15type ResolveResult<'a> = Result<'a, ResolvedLink<'a>>;
16
17#[derive(Debug, Copy, Clone)]
18pub struct LinkResolver<'a> {
19 schemas: &'a HashMap<String, Schema>,
20 schema: &'a Schema,
21}
22
23impl<'a> LinkResolver<'a> {
24 pub fn new(parser: &'a Parser, schema: &'a Schema) -> Self {
25 Self::from_parts(parser.schemas(), schema)
26 }
27
28 pub(crate) fn from_parts(schemas: &'a HashMap<String, Schema>, schema: &'a Schema) -> Self {
29 Self { schemas, schema }
30 }
31
32 pub fn with_schema(self, schema: &'a Schema) -> Self {
33 Self::from_parts(self.schemas, schema)
34 }
35
36 pub fn with_schema_name(self, schema: &str) -> Self {
37 let schema = self.schemas.get(schema).expect("valid schema name");
38 self.with_schema(schema)
39 }
40
41 pub fn schema(self) -> &'a Schema {
42 self.schema
43 }
44
45 pub fn convert_broken_link(mut link: &str) -> Option<&str> {
46 if (link != " ") && (link != "x") && (link != "X") {
47 if link.starts_with('`') && link.ends_with('`') && (link.len() > 1) {
48 link = &link[1..link.len() - 1];
49 }
50
51 Self::is_doc_link(link).then_some(link)
52 } else {
53 None
54 }
55 }
56
57 pub fn resolve(mut self, link: &'a str) -> ResolveResult<'a> {
58 if !Self::is_doc_link(link) {
59 return Ok(ResolvedLink::Foreign);
60 }
61
62 let mut components = Components::new(link);
63
64 if let Some(schema) = components.schema()? {
65 if schema != "self" {
66 if self
67 .schema
68 .imports()
69 .iter()
70 .all(|import| import.schema_name().value() != schema)
71 {
72 return Err(ResolveLinkError::SchemaNotFound(schema));
73 }
74
75 let schema = self
76 .schemas
77 .get(schema)
78 .ok_or(ResolveLinkError::SchemaNotFound(schema))?;
79
80 self.schema = schema;
81 }
82 }
83
84 self.resolve_def(components)
85 }
86
87 pub fn convert_broken_link_if_valid(self, link: &str) -> Option<&str> {
88 match Self::convert_broken_link(link) {
89 Some(link) => match self.resolve(link) {
90 Ok(_) => Some(link),
91 Err(_) => None,
92 },
93
94 None => None,
95 }
96 }
97
98 fn is_doc_link(link: &str) -> bool {
99 !link.is_empty()
100 && link
101 .chars()
102 .all(|c| (c == ':') || (c == '_') || c.is_ascii_alphanumeric())
103 }
104
105 fn resolve_def(self, mut components: Components<'a>) -> ResolveResult<'a> {
106 let Some(name) = components.next()? else {
107 return Ok(ResolvedLink::Schema(self.schema));
108 };
109
110 let def = self
111 .schema
112 .definitions()
113 .iter()
114 .find(|def| def.name().value() == name)
115 .ok_or(ResolveLinkError::DefinitionNotFound(self.schema, name))?;
116
117 match def {
118 Definition::Struct(struct_def) => self.resolve_struct(struct_def, components),
119 Definition::Enum(enum_def) => self.resolve_enum(enum_def, components),
120 Definition::Service(svc) => self.resolve_service(svc, components),
121
122 Definition::Const(const_def) => {
123 if components.next()?.is_none() {
124 Ok(ResolvedLink::Const(self.schema, const_def))
125 } else {
126 Err(ResolveLinkError::LinkIntoConst(const_def))
127 }
128 }
129
130 Definition::Newtype(newtype) => {
131 if components.next()?.is_none() {
132 Ok(ResolvedLink::Newtype(self.schema, newtype))
133 } else {
134 Err(ResolveLinkError::LinkIntoNewtype(newtype))
135 }
136 }
137 }
138 }
139
140 fn resolve_struct(
141 self,
142 struct_def: &'a StructDef,
143 components: Components<'a>,
144 ) -> ResolveResult<'a> {
145 let Some(name) = components.finish(ResolveLinkError::LinkIntoField)? else {
146 return Ok(ResolvedLink::Struct(self.schema, struct_def));
147 };
148
149 if let Some(field) = struct_def
150 .fields()
151 .iter()
152 .find(|field| field.name().value() == name)
153 {
154 return Ok(ResolvedLink::Field(self.schema, struct_def, field));
155 }
156
157 if let Some(fallback) = struct_def.fallback() {
158 if fallback.name().value() == name {
159 return Ok(ResolvedLink::FallbackField(
160 self.schema,
161 struct_def,
162 fallback,
163 ));
164 }
165 }
166
167 Err(ResolveLinkError::FieldNotFound(struct_def, name))
168 }
169
170 fn resolve_inline_struct(
171 self,
172 inline_struct: &'a InlineStruct,
173 components: Components<'a>,
174 ok_struct: impl FnOnce(&'a InlineStruct) -> ResolvedLink<'a>,
175 ok_field: impl FnOnce(&'a InlineStruct, &'a StructField) -> ResolvedLink<'a>,
176 ok_fallback: impl FnOnce(&'a InlineStruct, &'a StructFallback) -> ResolvedLink<'a>,
177 ) -> ResolveResult<'a> {
178 let Some(name) = components.finish(ResolveLinkError::LinkIntoField)? else {
179 return Ok(ok_struct(inline_struct));
180 };
181
182 if let Some(field) = inline_struct
183 .fields()
184 .iter()
185 .find(|field| field.name().value() == name)
186 {
187 return Ok(ok_field(inline_struct, field));
188 }
189
190 if let Some(fallback) = inline_struct.fallback() {
191 if fallback.name().value() == name {
192 return Ok(ok_fallback(inline_struct, fallback));
193 }
194 }
195
196 Err(ResolveLinkError::InlineFieldNotFound(name))
197 }
198
199 fn resolve_enum(self, enum_def: &'a EnumDef, components: Components<'a>) -> ResolveResult<'a> {
200 let Some(name) = components.finish(ResolveLinkError::LinkIntoVariant)? else {
201 return Ok(ResolvedLink::Enum(self.schema, enum_def));
202 };
203
204 if let Some(var) = enum_def
205 .variants()
206 .iter()
207 .find(|var| var.name().value() == name)
208 {
209 return Ok(ResolvedLink::Variant(self.schema, enum_def, var));
210 }
211
212 if let Some(fallback) = enum_def.fallback() {
213 if fallback.name().value() == name {
214 return Ok(ResolvedLink::FallbackVariant(
215 self.schema,
216 enum_def,
217 fallback,
218 ));
219 }
220 }
221
222 Err(ResolveLinkError::VariantNotFound(enum_def, name))
223 }
224
225 fn resolve_inline_enum(
226 self,
227 inline_enum: &'a InlineEnum,
228 components: Components<'a>,
229 ok_enum: impl FnOnce(&'a InlineEnum) -> ResolvedLink<'a>,
230 ok_variant: impl FnOnce(&'a InlineEnum, &'a EnumVariant) -> ResolvedLink<'a>,
231 ok_fallback: impl FnOnce(&'a InlineEnum, &'a EnumFallback) -> ResolvedLink<'a>,
232 ) -> ResolveResult<'a> {
233 let Some(name) = components.finish(ResolveLinkError::LinkIntoVariant)? else {
234 return Ok(ok_enum(inline_enum));
235 };
236
237 if let Some(var) = inline_enum
238 .variants()
239 .iter()
240 .find(|var| var.name().value() == name)
241 {
242 return Ok(ok_variant(inline_enum, var));
243 }
244
245 if let Some(fallback) = inline_enum.fallback() {
246 if fallback.name().value() == name {
247 return Ok(ok_fallback(inline_enum, fallback));
248 }
249 }
250
251 Err(ResolveLinkError::InlineVariantNotFound(name))
252 }
253
254 fn resolve_service(
255 self,
256 svc: &'a ServiceDef,
257 mut components: Components<'a>,
258 ) -> ResolveResult<'a> {
259 let Some(name) = components.next()? else {
260 return Ok(ResolvedLink::Service(self.schema, svc));
261 };
262
263 if let Some(item) = svc.items().iter().find(|item| item.name().value() == name) {
264 match item {
265 ServiceItem::Function(func) => return self.resolve_function(svc, func, components),
266 ServiceItem::Event(ev) => return self.resolve_event(svc, ev, components),
267 }
268 }
269
270 if let Some(fallback) = svc.function_fallback() {
271 if fallback.name().value() == name {
272 return Ok(ResolvedLink::FunctionFallback(self.schema, svc, fallback));
273 }
274 }
275
276 if let Some(fallback) = svc.event_fallback() {
277 if fallback.name().value() == name {
278 return Ok(ResolvedLink::EventFallback(self.schema, svc, fallback));
279 }
280 }
281
282 Err(ResolveLinkError::ItemNotFound(svc, name))
283 }
284
285 fn resolve_function(
286 self,
287 svc: &'a ServiceDef,
288 func: &'a FunctionDef,
289 mut components: Components<'a>,
290 ) -> ResolveResult<'a> {
291 let Some(name) = components.next()? else {
292 return Ok(ResolvedLink::Function(self.schema, svc, func));
293 };
294
295 match name {
296 "args" => match func.args() {
297 Some(args) => self.resolve_type_name_or_inline(
298 args.part_type(),
299 components,
300 |inline_struct| {
301 ResolvedLink::FunctionArgsStruct(
302 self.schema,
303 svc,
304 func,
305 args,
306 inline_struct,
307 )
308 },
309 |inline_struct, field| {
310 ResolvedLink::FunctionArgsField(
311 self.schema,
312 svc,
313 func,
314 args,
315 inline_struct,
316 field,
317 )
318 },
319 |inline_struct, fallback| {
320 ResolvedLink::FunctionArgsFallbackField(
321 self.schema,
322 svc,
323 func,
324 args,
325 inline_struct,
326 fallback,
327 )
328 },
329 |inline_enum| {
330 ResolvedLink::FunctionArgsEnum(self.schema, svc, func, args, inline_enum)
331 },
332 |inline_enum, var| {
333 ResolvedLink::FunctionArgsVariant(
334 self.schema,
335 svc,
336 func,
337 args,
338 inline_enum,
339 var,
340 )
341 },
342 |inline_enum, fallback| {
343 ResolvedLink::FunctionArgsFallbackVariant(
344 self.schema,
345 svc,
346 func,
347 args,
348 inline_enum,
349 fallback,
350 )
351 },
352 ResolveLinkError::NoFunctionArgsInlineType(func),
353 ),
354
355 None => Err(ResolveLinkError::NoFunctionArgsInlineType(func)),
356 },
357
358 "ok" => match func.ok() {
359 Some(ok) => self.resolve_type_name_or_inline(
360 ok.part_type(),
361 components,
362 |inline_struct| {
363 ResolvedLink::FunctionOkStruct(self.schema, svc, func, ok, inline_struct)
364 },
365 |inline_struct, field| {
366 ResolvedLink::FunctionOkField(
367 self.schema,
368 svc,
369 func,
370 ok,
371 inline_struct,
372 field,
373 )
374 },
375 |inline_struct, fallback| {
376 ResolvedLink::FunctionOkFallbackField(
377 self.schema,
378 svc,
379 func,
380 ok,
381 inline_struct,
382 fallback,
383 )
384 },
385 |inline_enum| {
386 ResolvedLink::FunctionOkEnum(self.schema, svc, func, ok, inline_enum)
387 },
388 |inline_enum, var| {
389 ResolvedLink::FunctionOkVariant(
390 self.schema,
391 svc,
392 func,
393 ok,
394 inline_enum,
395 var,
396 )
397 },
398 |inline_enum, fallback| {
399 ResolvedLink::FunctionOkFallbackVariant(
400 self.schema,
401 svc,
402 func,
403 ok,
404 inline_enum,
405 fallback,
406 )
407 },
408 ResolveLinkError::NoFunctionOkInlineType(func),
409 ),
410
411 None => Err(ResolveLinkError::NoFunctionOkInlineType(func)),
412 },
413
414 "err" => match func.err() {
415 Some(err) => self.resolve_type_name_or_inline(
416 err.part_type(),
417 components,
418 |inline_struct| {
419 ResolvedLink::FunctionErrStruct(self.schema, svc, func, err, inline_struct)
420 },
421 |inline_struct, field| {
422 ResolvedLink::FunctionErrField(
423 self.schema,
424 svc,
425 func,
426 err,
427 inline_struct,
428 field,
429 )
430 },
431 |inline_struct, fallback| {
432 ResolvedLink::FunctionErrFallbackField(
433 self.schema,
434 svc,
435 func,
436 err,
437 inline_struct,
438 fallback,
439 )
440 },
441 |inline_enum| {
442 ResolvedLink::FunctionErrEnum(self.schema, svc, func, err, inline_enum)
443 },
444 |inline_enum, var| {
445 ResolvedLink::FunctionErrVariant(
446 self.schema,
447 svc,
448 func,
449 err,
450 inline_enum,
451 var,
452 )
453 },
454 |inline_enum, fallback| {
455 ResolvedLink::FunctionErrFallbackVariant(
456 self.schema,
457 svc,
458 func,
459 err,
460 inline_enum,
461 fallback,
462 )
463 },
464 ResolveLinkError::NoFunctionErrInlineType(func),
465 ),
466
467 None => Err(ResolveLinkError::NoFunctionErrInlineType(func)),
468 },
469
470 _ => Err(ResolveLinkError::InvalidFunctionPart(name)),
471 }
472 }
473
474 fn resolve_event(
475 self,
476 svc: &'a ServiceDef,
477 ev: &'a EventDef,
478 mut components: Components<'a>,
479 ) -> ResolveResult<'a> {
480 let Some(name) = components.next()? else {
481 return Ok(ResolvedLink::Event(self.schema, svc, ev));
482 };
483
484 if name != "args" {
485 return Err(ResolveLinkError::InvalidEventPart(name));
486 }
487
488 match ev.event_type() {
489 Some(ty) => self.resolve_type_name_or_inline(
490 ty,
491 components,
492 |inline_struct| ResolvedLink::EventStruct(self.schema, svc, ev, inline_struct),
493 |inline_struct, field| {
494 ResolvedLink::EventField(self.schema, svc, ev, inline_struct, field)
495 },
496 |inline_struct, fallback| {
497 ResolvedLink::EventFallbackField(self.schema, svc, ev, inline_struct, fallback)
498 },
499 |inline_enum| ResolvedLink::EventEnum(self.schema, svc, ev, inline_enum),
500 |inline_enum, var| {
501 ResolvedLink::EventVariant(self.schema, svc, ev, inline_enum, var)
502 },
503 |inline_enum, fallback| {
504 ResolvedLink::EventFallbackVariant(self.schema, svc, ev, inline_enum, fallback)
505 },
506 ResolveLinkError::NoEventInlineType(ev),
507 ),
508
509 None => Err(ResolveLinkError::NoEventInlineType(ev)),
510 }
511 }
512
513 #[allow(clippy::too_many_arguments)]
514 fn resolve_type_name_or_inline(
515 self,
516 ty: &'a TypeNameOrInline,
517 components: Components<'a>,
518 ok_struct: impl FnOnce(&'a InlineStruct) -> ResolvedLink<'a>,
519 ok_field: impl FnOnce(&'a InlineStruct, &'a StructField) -> ResolvedLink<'a>,
520 ok_struct_fallback: impl FnOnce(&'a InlineStruct, &'a StructFallback) -> ResolvedLink<'a>,
521 ok_enum: impl FnOnce(&'a InlineEnum) -> ResolvedLink<'a>,
522 ok_variant: impl FnOnce(&'a InlineEnum, &'a EnumVariant) -> ResolvedLink<'a>,
523 ok_enum_fallback: impl FnOnce(&'a InlineEnum, &'a EnumFallback) -> ResolvedLink<'a>,
524 err_no_inline_type: ResolveLinkError<'a>,
525 ) -> ResolveResult<'a> {
526 match ty {
527 TypeNameOrInline::TypeName(_) => Err(err_no_inline_type),
528
529 TypeNameOrInline::Struct(inline_struct) => self.resolve_inline_struct(
530 inline_struct,
531 components,
532 ok_struct,
533 ok_field,
534 ok_struct_fallback,
535 ),
536
537 TypeNameOrInline::Enum(inline_enum) => self.resolve_inline_enum(
538 inline_enum,
539 components,
540 ok_enum,
541 ok_variant,
542 ok_enum_fallback,
543 ),
544 }
545 }
546}
547
548#[derive(Debug, Copy, Clone)]
549pub enum ResolvedLink<'a> {
550 Foreign,
551 Schema(&'a Schema),
552 Struct(&'a Schema, &'a StructDef),
553 Field(&'a Schema, &'a StructDef, &'a StructField),
554 FallbackField(&'a Schema, &'a StructDef, &'a StructFallback),
555 Enum(&'a Schema, &'a EnumDef),
556 Variant(&'a Schema, &'a EnumDef, &'a EnumVariant),
557 FallbackVariant(&'a Schema, &'a EnumDef, &'a EnumFallback),
558 Service(&'a Schema, &'a ServiceDef),
559 Function(&'a Schema, &'a ServiceDef, &'a FunctionDef),
560
561 FunctionArgsStruct(
562 &'a Schema,
563 &'a ServiceDef,
564 &'a FunctionDef,
565 &'a FunctionPart,
566 &'a InlineStruct,
567 ),
568
569 FunctionArgsField(
570 &'a Schema,
571 &'a ServiceDef,
572 &'a FunctionDef,
573 &'a FunctionPart,
574 &'a InlineStruct,
575 &'a StructField,
576 ),
577
578 FunctionArgsFallbackField(
579 &'a Schema,
580 &'a ServiceDef,
581 &'a FunctionDef,
582 &'a FunctionPart,
583 &'a InlineStruct,
584 &'a StructFallback,
585 ),
586
587 FunctionArgsEnum(
588 &'a Schema,
589 &'a ServiceDef,
590 &'a FunctionDef,
591 &'a FunctionPart,
592 &'a InlineEnum,
593 ),
594
595 FunctionArgsVariant(
596 &'a Schema,
597 &'a ServiceDef,
598 &'a FunctionDef,
599 &'a FunctionPart,
600 &'a InlineEnum,
601 &'a EnumVariant,
602 ),
603
604 FunctionArgsFallbackVariant(
605 &'a Schema,
606 &'a ServiceDef,
607 &'a FunctionDef,
608 &'a FunctionPart,
609 &'a InlineEnum,
610 &'a EnumFallback,
611 ),
612
613 FunctionOkStruct(
614 &'a Schema,
615 &'a ServiceDef,
616 &'a FunctionDef,
617 &'a FunctionPart,
618 &'a InlineStruct,
619 ),
620
621 FunctionOkField(
622 &'a Schema,
623 &'a ServiceDef,
624 &'a FunctionDef,
625 &'a FunctionPart,
626 &'a InlineStruct,
627 &'a StructField,
628 ),
629
630 FunctionOkFallbackField(
631 &'a Schema,
632 &'a ServiceDef,
633 &'a FunctionDef,
634 &'a FunctionPart,
635 &'a InlineStruct,
636 &'a StructFallback,
637 ),
638
639 FunctionOkEnum(
640 &'a Schema,
641 &'a ServiceDef,
642 &'a FunctionDef,
643 &'a FunctionPart,
644 &'a InlineEnum,
645 ),
646
647 FunctionOkVariant(
648 &'a Schema,
649 &'a ServiceDef,
650 &'a FunctionDef,
651 &'a FunctionPart,
652 &'a InlineEnum,
653 &'a EnumVariant,
654 ),
655
656 FunctionOkFallbackVariant(
657 &'a Schema,
658 &'a ServiceDef,
659 &'a FunctionDef,
660 &'a FunctionPart,
661 &'a InlineEnum,
662 &'a EnumFallback,
663 ),
664
665 FunctionErrStruct(
666 &'a Schema,
667 &'a ServiceDef,
668 &'a FunctionDef,
669 &'a FunctionPart,
670 &'a InlineStruct,
671 ),
672
673 FunctionErrField(
674 &'a Schema,
675 &'a ServiceDef,
676 &'a FunctionDef,
677 &'a FunctionPart,
678 &'a InlineStruct,
679 &'a StructField,
680 ),
681
682 FunctionErrFallbackField(
683 &'a Schema,
684 &'a ServiceDef,
685 &'a FunctionDef,
686 &'a FunctionPart,
687 &'a InlineStruct,
688 &'a StructFallback,
689 ),
690
691 FunctionErrEnum(
692 &'a Schema,
693 &'a ServiceDef,
694 &'a FunctionDef,
695 &'a FunctionPart,
696 &'a InlineEnum,
697 ),
698
699 FunctionErrVariant(
700 &'a Schema,
701 &'a ServiceDef,
702 &'a FunctionDef,
703 &'a FunctionPart,
704 &'a InlineEnum,
705 &'a EnumVariant,
706 ),
707
708 FunctionErrFallbackVariant(
709 &'a Schema,
710 &'a ServiceDef,
711 &'a FunctionDef,
712 &'a FunctionPart,
713 &'a InlineEnum,
714 &'a EnumFallback,
715 ),
716
717 FunctionFallback(&'a Schema, &'a ServiceDef, &'a FunctionFallback),
718 Event(&'a Schema, &'a ServiceDef, &'a EventDef),
719 EventStruct(&'a Schema, &'a ServiceDef, &'a EventDef, &'a InlineStruct),
720
721 EventField(
722 &'a Schema,
723 &'a ServiceDef,
724 &'a EventDef,
725 &'a InlineStruct,
726 &'a StructField,
727 ),
728
729 EventFallbackField(
730 &'a Schema,
731 &'a ServiceDef,
732 &'a EventDef,
733 &'a InlineStruct,
734 &'a StructFallback,
735 ),
736
737 EventEnum(&'a Schema, &'a ServiceDef, &'a EventDef, &'a InlineEnum),
738
739 EventVariant(
740 &'a Schema,
741 &'a ServiceDef,
742 &'a EventDef,
743 &'a InlineEnum,
744 &'a EnumVariant,
745 ),
746
747 EventFallbackVariant(
748 &'a Schema,
749 &'a ServiceDef,
750 &'a EventDef,
751 &'a InlineEnum,
752 &'a EnumFallback,
753 ),
754
755 EventFallback(&'a Schema, &'a ServiceDef, &'a EventFallback),
756 Const(&'a Schema, &'a ConstDef),
757 Newtype(&'a Schema, &'a NewtypeDef),
758}
759
760#[derive(Error, Debug, Copy, Clone)]
762pub enum ResolveLinkError<'a> {
763 #[error("invalid format")]
764 InvalidFormat,
765
766 #[error("schema `{0}` not found")]
767 SchemaNotFound(&'a str),
768
769 #[error("definition `{1}` not found in schema `{schema}`", schema = .0.name())]
770 DefinitionNotFound(&'a Schema, &'a str),
771
772 #[error("field `{1}` not found in struct `{ty}`", ty = .0.name().value())]
773 FieldNotFound(&'a StructDef, &'a str),
774
775 #[error("field `{0}` not found in inline struct")]
776 InlineFieldNotFound(&'a str),
777
778 #[error("cannot link into field `{0}`")]
779 LinkIntoField(&'a str),
780
781 #[error("variant `{1}` not found in enum `{ty}`", ty = .0.name().value())]
782 VariantNotFound(&'a EnumDef, &'a str),
783
784 #[error("variant `{0}` not found in inline enum")]
785 InlineVariantNotFound(&'a str),
786
787 #[error("cannot link into variant `{0}`")]
788 LinkIntoVariant(&'a str),
789
790 #[error("item `{1}` not found in service `{svc}`", svc = .0.name().value())]
791 ItemNotFound(&'a ServiceDef, &'a str),
792
793 #[error("invalid function part `{0}`")]
794 InvalidFunctionPart(&'a str),
795
796 #[error("`args` of function `{func}` isn't an inline type", func = .0.name().value())]
797 NoFunctionArgsInlineType(&'a FunctionDef),
798
799 #[error("`ok` of function `{func}` isn't an inline type", func = .0.name().value())]
800 NoFunctionOkInlineType(&'a FunctionDef),
801
802 #[error("`err` of function `{func}` isn't an inline type", func = .0.name().value())]
803 NoFunctionErrInlineType(&'a FunctionDef),
804
805 #[error("invalid event part `{0}`")]
806 InvalidEventPart(&'a str),
807
808 #[error("event `{ev}` has no inline type", ev = .0.name().value())]
809 NoEventInlineType(&'a EventDef),
810
811 #[error("cannot link into constant `{const}`", const = .0.name().value())]
812 LinkIntoConst(&'a ConstDef),
813
814 #[error("cannot link into newtype `{ty}`", ty = .0.name().value())]
815 LinkIntoNewtype(&'a NewtypeDef),
816}
817
818struct Components<'a> {
819 link: &'a str,
820}
821
822impl<'a> Components<'a> {
823 fn new(link: &'a str) -> Self {
824 Self { link }
825 }
826
827 fn schema(&mut self) -> Result<'a, Option<&'a str>> {
828 match self.link.strip_prefix("::") {
829 Some(rest) => {
830 self.link = rest;
831
832 self.next()?
833 .map(Some)
834 .ok_or(ResolveLinkError::InvalidFormat)
835 }
836
837 None => Ok(None),
838 }
839 }
840
841 fn next(&mut self) -> Result<'a, Option<&'a str>> {
842 match self.link.split_once("::") {
843 Some((component, rest)) => {
844 if component.is_empty() || rest.is_empty() {
845 Err(ResolveLinkError::InvalidFormat)
846 } else {
847 self.link = rest;
848 Ok(Some(component))
849 }
850 }
851
852 None => {
853 if self.link.is_empty() {
854 Ok(None)
855 } else {
856 Ok(Some(mem::take(&mut self.link)))
857 }
858 }
859 }
860 }
861
862 fn finish(
863 self,
864 err: impl FnOnce(&'a str) -> ResolveLinkError<'a>,
865 ) -> Result<'a, Option<&'a str>> {
866 if self.link.is_empty() {
867 Ok(None)
868 } else if let Some((component, _)) = self.link.split_once("::") {
869 Err(err(component))
870 } else {
871 Ok(Some(self.link))
872 }
873 }
874}