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