1use super::{
4 ArtifactRevision, ArtifactSelector, IrFormatVersion, NodeFingerprintBuilder, NodeOwner,
5 NodeRoot, NodeStep, NodeUri, Sha256Digest, semantic_json,
6};
7use crate::format_version::{NormalizedFormatVersion, ScalarValue, SupportTable};
8use crate::ir::{classic, v4};
9use crate::naming::{Name, PackageName, Path};
10use serde::Serialize;
11use std::collections::HashMap;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum IndexedNodeKind {
16 Distribution,
17 Package,
18 Module,
19 TypeDefinition,
20 ValueDefinition,
21 Constructor,
22 TypeExpression,
23 ValueExpression,
24 Pattern,
25 EntryPoint,
26}
27
28#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
30pub enum NodeResolutionError {
31 #[error("artifact selector does not match the indexed distribution")]
32 ArtifactMismatch,
33 #[error("artifact selector matches multiple current or pinned distributions")]
34 AmbiguousArtifact,
35 #[error("IR format version does not match the indexed distribution")]
36 FormatVersionMismatch,
37 #[error("the requested immutable revision is unavailable in this index")]
38 RevisionUnavailable,
39 #[error("acquired snapshot bytes do not match the requested revision")]
40 RevisionMismatch,
41 #[error("the node path or positional guard is stale")]
42 StaleTarget,
43 #[error("more than one semantic node has the same address")]
44 AmbiguousTarget,
45 #[error("invalid normalized IR name: {0}")]
46 InvalidName(String),
47 #[error("cannot fingerprint a semantic child: {0}")]
48 InvalidFingerprint(String),
49 #[error("cannot decode immutable snapshot: {0}")]
50 InvalidSnapshot(String),
51}
52
53#[derive(Debug, Clone, PartialEq)]
56pub struct ResolvedNode {
57 pub kind: IndexedNodeKind,
58 pub semantic_value: serde_json::Value,
59}
60
61#[derive(Debug, Clone)]
62struct IndexedNode {
63 address: NodeUri,
64 node: ResolvedNode,
65}
66
67#[derive(Debug)]
69pub struct NodeIndex {
70 artifact: ArtifactSelector,
71 format: IrFormatVersion,
72 nodes: HashMap<(NodeRoot, Vec<NodeStep>), IndexedNode>,
73}
74
75#[derive(Default)]
81pub struct NodeCatalog {
82 current: Vec<NodeIndex>,
83 snapshots: Vec<(Sha256Digest, NodeIndex)>,
84}
85
86impl NodeCatalog {
87 pub fn new() -> Self {
88 Self::default()
89 }
90
91 pub fn add_current(&mut self, index: NodeIndex) {
92 self.current.push(index);
93 }
94
95 pub fn add_v4_json_snapshot(
97 &mut self,
98 bytes: &[u8],
99 expected: Option<&Sha256Digest>,
100 ) -> Result<Sha256Digest, NodeResolutionError> {
101 let digest = verify_snapshot_digest(bytes, expected)?;
102 let text = std::str::from_utf8(bytes)
103 .map_err(|error| NodeResolutionError::InvalidSnapshot(error.to_string()))?;
104 let (file, _) = crate::ir::json::read_ir_file(text)
105 .map_err(|error| NodeResolutionError::InvalidSnapshot(error.to_string()))?;
106 let index = NodeIndex::v4_file(&file)?;
107 self.snapshots.push((digest.clone(), index));
108 Ok(digest)
109 }
110
111 pub fn add_v3_json_snapshot(
113 &mut self,
114 bytes: &[u8],
115 expected: Option<&Sha256Digest>,
116 ) -> Result<Sha256Digest, NodeResolutionError> {
117 let digest = verify_snapshot_digest(bytes, expected)?;
118 let index = NodeIndex::v3_json(bytes)?;
119 self.snapshots.push((digest.clone(), index));
120 Ok(digest)
121 }
122
123 pub fn resolve(&self, address: &NodeUri) -> Result<IndexedNodeKind, NodeResolutionError> {
124 self.resolve_node(address).map(|node| node.kind)
125 }
126
127 pub fn resolve_node(&self, address: &NodeUri) -> Result<&ResolvedNode, NodeResolutionError> {
128 match &address.revision {
129 ArtifactRevision::Current => {
130 let mut matching = self
131 .current
132 .iter()
133 .filter(|index| index.artifact == address.artifact);
134 let index = matching
135 .next()
136 .ok_or(NodeResolutionError::ArtifactMismatch)?;
137 if matching.next().is_some() {
138 return Err(NodeResolutionError::AmbiguousArtifact);
139 }
140 index.resolve_node(address)
141 }
142 ArtifactRevision::Pinned(digest) => {
143 let mut matching = self.snapshots.iter().filter(|(candidate, index)| {
144 candidate == digest && index.artifact == address.artifact
145 });
146 let (_, index) = matching
147 .next()
148 .ok_or(NodeResolutionError::RevisionUnavailable)?;
149 if matching.next().is_some() {
150 return Err(NodeResolutionError::AmbiguousArtifact);
151 }
152 if address.format != index.format {
153 return Err(NodeResolutionError::FormatVersionMismatch);
154 }
155 let node = index
156 .nodes
157 .get(&(address.root.clone(), address.steps.clone()))
158 .ok_or(NodeResolutionError::StaleTarget)?;
159 if let Some(guard) = &address.guard
160 && node.address.guard.as_ref() != Some(guard)
161 {
162 return Err(NodeResolutionError::StaleTarget);
163 }
164 Ok(&node.node)
165 }
166 }
167 }
168}
169
170fn verify_snapshot_digest(
171 bytes: &[u8],
172 expected: Option<&Sha256Digest>,
173) -> Result<Sha256Digest, NodeResolutionError> {
174 let actual = Sha256Digest::from_bytes(bytes);
175 if expected.is_some_and(|expected| expected != &actual) {
176 return Err(NodeResolutionError::RevisionMismatch);
177 }
178 Ok(actual)
179}
180
181#[derive(Clone)]
182struct WalkContext {
183 root: NodeRoot,
184 steps: Vec<NodeStep>,
185 lineage: Option<NodeFingerprintBuilder>,
186 linked_metadata_guards: bool,
187}
188
189impl WalkContext {
190 fn root(root: NodeRoot) -> Self {
191 Self {
192 root,
193 steps: Vec::new(),
194 lineage: None,
195 linked_metadata_guards: false,
196 }
197 }
198
199 fn v4_root(root: NodeRoot, format: IrFormatVersion) -> Self {
200 Self {
201 linked_metadata_guards: format.major() == 4 && format.minor() == 1,
202 ..Self::root(root)
203 }
204 }
205
206 fn named(&self, step: NodeStep) -> Self {
207 let mut next = self.clone();
208 next.steps.push(step);
209 next
210 }
211
212 fn ordered<T: Serialize>(
213 &self,
214 step: NodeStep,
215 child: &T,
216 ) -> Result<Self, NodeResolutionError> {
217 let mut next = self.named(step.clone());
218 let mut lineage = next.lineage.unwrap_or_else(|| {
219 if self.linked_metadata_guards {
220 NodeFingerprintBuilder::for_v4_1()
221 } else {
222 NodeFingerprintBuilder::new()
223 }
224 });
225 lineage
226 .push(&step, child)
227 .map_err(|error| NodeResolutionError::InvalidFingerprint(error.to_string()))?;
228 next.lineage = Some(lineage);
229 Ok(next)
230 }
231}
232
233impl NodeIndex {
234 pub fn v4_file(file: &v4::IRFile) -> Result<Self, NodeResolutionError> {
236 let artifact = ArtifactSelector::Package(file.distribution.package_name().clone());
237 Self::v4_file_with_selector(file, artifact)
238 }
239
240 pub fn v4_file_with_selector(
242 file: &v4::IRFile,
243 artifact: ArtifactSelector,
244 ) -> Result<Self, NodeResolutionError> {
245 let scalar = match &file.format_version {
246 v4::FormatVersion::String(version) => ScalarValue::String(version.clone()),
247 v4::FormatVersion::Integer(version) => ScalarValue::Integer(u64::from(*version)),
248 };
249 let normalized =
250 NormalizedFormatVersion::from_scalar(&scalar, &SupportTable::linked_metadata())
251 .map_err(|_| NodeResolutionError::FormatVersionMismatch)?;
252 if normalized.release.major() != 4
253 || !normalized.is_supported()
254 || (file.has_linked_metadata() && normalized.release != IrFormatVersion::new(4, 1, 0))
255 {
256 return Err(NodeResolutionError::FormatVersionMismatch);
257 }
258 Self::v4_with_format(&file.distribution, artifact, normalized.release)
259 }
260
261 pub fn v4(distribution: &v4::Distribution) -> Result<Self, NodeResolutionError> {
263 let artifact = ArtifactSelector::Package(distribution.package_name().clone());
264 Self::v4_with_selector(distribution, artifact)
265 }
266
267 pub fn v4_with_selector(
269 distribution: &v4::Distribution,
270 artifact: ArtifactSelector,
271 ) -> Result<Self, NodeResolutionError> {
272 Self::v4_with_format(distribution, artifact, IrFormatVersion::new(4, 0, 0))
273 }
274
275 fn v4_with_format(
276 distribution: &v4::Distribution,
277 artifact: ArtifactSelector,
278 format: IrFormatVersion,
279 ) -> Result<Self, NodeResolutionError> {
280 if let ArtifactSelector::Package(package) = &artifact
281 && package != distribution.package_name()
282 {
283 return Err(NodeResolutionError::ArtifactMismatch);
284 }
285 let mut index = Self::new(artifact, format);
286 index.add(
287 &WalkContext::root(NodeRoot::Distribution),
288 IndexedNodeKind::Distribution,
289 distribution,
290 )?;
291 match distribution {
292 v4::Distribution::Library(library) => {
293 index.add(
294 &WalkContext::root(NodeRoot::Package),
295 IndexedNodeKind::Package,
296 &library.def,
297 )?;
298 index.v4_definition_package(NodeOwner::OwnPackage, &library.def)?;
299 for (package, spec) in &library.dependencies {
300 let package = parse_package(package)?;
301 index.add(
302 &WalkContext::root(NodeRoot::Dependency(package.clone())),
303 IndexedNodeKind::Package,
304 spec,
305 )?;
306 index.v4_specification_package(NodeOwner::Dependency(package), spec)?;
307 }
308 }
309 v4::Distribution::Specs(specs) => {
310 index.add(
311 &WalkContext::root(NodeRoot::Package),
312 IndexedNodeKind::Package,
313 &specs.spec,
314 )?;
315 index.v4_specification_package(NodeOwner::OwnPackage, &specs.spec)?;
316 for (package, spec) in &specs.dependencies {
317 let package = parse_package(package)?;
318 index.add(
319 &WalkContext::root(NodeRoot::Dependency(package.clone())),
320 IndexedNodeKind::Package,
321 spec,
322 )?;
323 index.v4_specification_package(NodeOwner::Dependency(package), spec)?;
324 }
325 }
326 v4::Distribution::Application(application) => {
327 index.add(
328 &WalkContext::root(NodeRoot::Package),
329 IndexedNodeKind::Package,
330 &application.def,
331 )?;
332 index.v4_definition_package(NodeOwner::OwnPackage, &application.def)?;
333 for (package, definition) in &application.dependencies {
334 let package = parse_package(package)?;
335 index.add(
336 &WalkContext::root(NodeRoot::Dependency(package.clone())),
337 IndexedNodeKind::Package,
338 definition,
339 )?;
340 index.v4_definition_package(NodeOwner::Dependency(package), definition)?;
341 }
342 for (key, entry_point) in &application.entry_points {
343 index.add(
344 &WalkContext::root(NodeRoot::EntryPoint(key.clone())),
345 IndexedNodeKind::EntryPoint,
346 entry_point,
347 )?;
348 }
349 }
350 }
351 Ok(index)
352 }
353
354 pub fn v3(
356 distribution: &classic::Distribution,
357 artifact: ArtifactSelector,
358 ) -> Result<Self, NodeResolutionError> {
359 let format = match &distribution.distribution {
360 classic::DistributionBody::Library(..) => IrFormatVersion::new(3, 0, 0),
361 classic::DistributionBody::Specs(..) => IrFormatVersion::new(3, 1, 0),
362 };
363 Self::v3_with_format(distribution, artifact, format)
364 }
365
366 pub fn v3_json(bytes: &[u8]) -> Result<Self, NodeResolutionError> {
368 let value: serde_json::Value = serde_json::from_slice(bytes)
369 .map_err(|error| NodeResolutionError::InvalidSnapshot(error.to_string()))?;
370 let declared = value
371 .get("formatVersion")
372 .ok_or_else(|| NodeResolutionError::InvalidSnapshot("missing formatVersion".into()))?;
373 let scalar = ScalarValue::from_json(declared)
374 .map_err(|error| NodeResolutionError::InvalidSnapshot(error.to_string()))?;
375 let normalized = NormalizedFormatVersion::from_scalar(&scalar, &SupportTable::reference())
376 .map_err(|error| NodeResolutionError::InvalidSnapshot(error.to_string()))?;
377 if !normalized.is_supported() {
378 return Err(NodeResolutionError::FormatVersionMismatch);
379 }
380 let distribution: classic::Distribution = serde_json::from_value(value)
381 .map_err(|error| NodeResolutionError::InvalidSnapshot(error.to_string()))?;
382 let package = match &distribution.distribution {
383 classic::DistributionBody::Library(package, _, _)
384 | classic::DistributionBody::Specs(package, _, _) => package,
385 };
386 let selector = ArtifactSelector::Package(PackageName::new(classic_path(package)?));
387 Self::v3_with_format(&distribution, selector, normalized.release)
388 }
389
390 fn v3_with_format(
391 distribution: &classic::Distribution,
392 artifact: ArtifactSelector,
393 format: IrFormatVersion,
394 ) -> Result<Self, NodeResolutionError> {
395 if distribution.format_version != 3 {
396 return Err(NodeResolutionError::FormatVersionMismatch);
397 }
398 if format.major() != 3
399 || matches!(
400 distribution.distribution,
401 classic::DistributionBody::Specs(..)
402 ) && format < IrFormatVersion::new(3, 1, 0)
403 {
404 return Err(NodeResolutionError::FormatVersionMismatch);
405 }
406 let mut index = Self::new(artifact, format);
407 index.add(
408 &WalkContext::root(NodeRoot::Distribution),
409 IndexedNodeKind::Distribution,
410 distribution,
411 )?;
412 let (package_path, dependencies) = match &distribution.distribution {
413 classic::DistributionBody::Library(path, dependencies, _)
414 | classic::DistributionBody::Specs(path, dependencies, _) => (path, dependencies),
415 };
416 if let ArtifactSelector::Package(selected) = &index.artifact
417 && selected.as_path() != &classic_path(package_path)?
418 {
419 return Err(NodeResolutionError::ArtifactMismatch);
420 }
421 match &distribution.distribution {
422 classic::DistributionBody::Library(_, _, package) => {
423 index.add(
424 &WalkContext::root(NodeRoot::Package),
425 IndexedNodeKind::Package,
426 package,
427 )?;
428 index.v3_definition_package(NodeOwner::OwnPackage, package)?;
429 }
430 classic::DistributionBody::Specs(_, _, package) => {
431 index.add(
432 &WalkContext::root(NodeRoot::Package),
433 IndexedNodeKind::Package,
434 package,
435 )?;
436 index.v3_specification_package(NodeOwner::OwnPackage, package)?;
437 }
438 }
439 for (path, specification) in dependencies {
440 let package = PackageName::new(classic_path(path)?);
441 index.add(
442 &WalkContext::root(NodeRoot::Dependency(package.clone())),
443 IndexedNodeKind::Package,
444 specification,
445 )?;
446 index.v3_specification_package(NodeOwner::Dependency(package), specification)?;
447 }
448 Ok(index)
449 }
450
451 fn new(artifact: ArtifactSelector, format: IrFormatVersion) -> Self {
452 Self {
453 artifact,
454 format,
455 nodes: HashMap::new(),
456 }
457 }
458
459 fn add<T: Serialize>(
460 &mut self,
461 context: &WalkContext,
462 kind: IndexedNodeKind,
463 semantic_node: &T,
464 ) -> Result<(), NodeResolutionError> {
465 let address = NodeUri::new(
466 self.artifact.clone(),
467 self.format,
468 context.root.clone(),
469 context.steps.clone(),
470 ArtifactRevision::Current,
471 context.lineage.clone().map(NodeFingerprintBuilder::finish),
472 )
473 .map_err(|error| NodeResolutionError::InvalidName(error.to_string()))?;
474 let key = (context.root.clone(), context.steps.clone());
475 let semantic_value = semantic_json(semantic_node)
476 .map_err(|error| NodeResolutionError::InvalidFingerprint(error.to_string()))?;
477 if self
478 .nodes
479 .insert(
480 key,
481 IndexedNode {
482 address,
483 node: ResolvedNode {
484 kind,
485 semantic_value,
486 },
487 },
488 )
489 .is_some()
490 {
491 return Err(NodeResolutionError::AmbiguousTarget);
492 }
493 Ok(())
494 }
495
496 pub fn resolve(&self, address: &NodeUri) -> Result<IndexedNodeKind, NodeResolutionError> {
499 self.resolve_node(address).map(|node| node.kind)
500 }
501
502 pub fn resolve_node(&self, address: &NodeUri) -> Result<&ResolvedNode, NodeResolutionError> {
503 if address.artifact != self.artifact {
504 return Err(NodeResolutionError::ArtifactMismatch);
505 }
506 if address.format != self.format {
507 return Err(NodeResolutionError::FormatVersionMismatch);
508 }
509 if !matches!(address.revision, ArtifactRevision::Current) {
510 return Err(NodeResolutionError::RevisionUnavailable);
511 }
512 let node = self
513 .nodes
514 .get(&(address.root.clone(), address.steps.clone()))
515 .ok_or(NodeResolutionError::StaleTarget)?;
516 if node.address.guard != address.guard {
517 return Err(NodeResolutionError::StaleTarget);
518 }
519 Ok(&node.node)
520 }
521
522 pub fn addresses(&self) -> impl Iterator<Item = &NodeUri> {
524 self.nodes.values().map(|node| &node.address)
525 }
526
527 pub fn nodes(&self) -> impl Iterator<Item = (&NodeUri, &ResolvedNode)> {
530 self.nodes.values().map(|node| (&node.address, &node.node))
531 }
532
533 pub fn address_for(
536 &self,
537 root: &NodeRoot,
538 steps: &[NodeStep],
539 ) -> Result<NodeUri, NodeResolutionError> {
540 self.nodes
541 .get(&(root.clone(), steps.to_vec()))
542 .map(|node| node.address.clone())
543 .ok_or(NodeResolutionError::StaleTarget)
544 }
545
546 fn v4_definition_package(
547 &mut self,
548 owner: NodeOwner,
549 package: &v4::PackageDefinition,
550 ) -> Result<(), NodeResolutionError> {
551 for (module_name, controlled) in &package.modules {
552 let module = parse_path(module_name)?;
553 let definition = &controlled.value;
554 self.add(
555 &WalkContext::root(NodeRoot::Module {
556 owner: owner.clone(),
557 module: module.clone(),
558 }),
559 IndexedNodeKind::Module,
560 definition,
561 )?;
562 for (name, controlled) in &definition.types {
563 let context = WalkContext::v4_root(
564 NodeRoot::Type {
565 owner: owner.clone(),
566 module: module.clone(),
567 name: parse_name(name)?,
568 },
569 self.format,
570 );
571 self.add(
572 &context,
573 IndexedNodeKind::TypeDefinition,
574 &controlled.value.value,
575 )?;
576 self.v4_type_definition(&context, &controlled.value.value)?;
577 }
578 for (name, controlled) in &definition.values {
579 let context = WalkContext::v4_root(
580 NodeRoot::Value {
581 owner: owner.clone(),
582 module: module.clone(),
583 name: parse_name(name)?,
584 },
585 self.format,
586 );
587 self.add(
588 &context,
589 IndexedNodeKind::ValueDefinition,
590 &controlled.value.value,
591 )?;
592 self.v4_value_definition(&context, &controlled.value.value)?;
593 }
594 }
595 Ok(())
596 }
597
598 fn v4_specification_package(
599 &mut self,
600 owner: NodeOwner,
601 package: &v4::PackageSpecification,
602 ) -> Result<(), NodeResolutionError> {
603 for (module_name, specification) in &package.modules {
604 let module = parse_path(module_name)?;
605 self.add(
606 &WalkContext::root(NodeRoot::Module {
607 owner: owner.clone(),
608 module: module.clone(),
609 }),
610 IndexedNodeKind::Module,
611 specification,
612 )?;
613 self.v4_annotations(
614 &WalkContext::v4_root(
615 NodeRoot::Module {
616 owner: owner.clone(),
617 module: module.clone(),
618 },
619 self.format,
620 ),
621 &specification.annotations,
622 )?;
623 for (name, documented) in &specification.types {
624 let context = WalkContext::v4_root(
625 NodeRoot::Type {
626 owner: owner.clone(),
627 module: module.clone(),
628 name: parse_name(name)?,
629 },
630 self.format,
631 );
632 self.add(&context, IndexedNodeKind::TypeDefinition, &documented.value)?;
633 self.v4_type_specification(&context, &documented.value)?;
634 }
635 for (name, documented) in &specification.values {
636 let context = WalkContext::v4_root(
637 NodeRoot::Value {
638 owner: owner.clone(),
639 module: module.clone(),
640 name: parse_name(name)?,
641 },
642 self.format,
643 );
644 self.add(
645 &context,
646 IndexedNodeKind::ValueDefinition,
647 &documented.value,
648 )?;
649 self.v4_value_specification(&context, &documented.value)?;
650 }
651 }
652 Ok(())
653 }
654
655 fn v4_type_definition(
656 &mut self,
657 context: &WalkContext,
658 definition: &v4::TypeDefinition,
659 ) -> Result<(), NodeResolutionError> {
660 match definition {
661 v4::TypeDefinition::TypeAliasDefinition { type_expr, .. } => {
662 self.v4_type(&context.named(NodeStep::TypeExpression), type_expr)?
663 }
664 v4::TypeDefinition::CustomTypeDefinition { constructors, .. } => {
665 for constructor in &constructors.value {
666 let child =
667 context.named(NodeStep::CustomConstructor(constructor.name.clone()));
668 self.add(&child, IndexedNodeKind::Constructor, constructor)?;
669 for (index, argument) in constructor.args.iter().enumerate() {
670 let argument_context = child
671 .ordered(NodeStep::ConstructorArgument(index), &argument.arg_type)?;
672 self.v4_type(&argument_context, &argument.arg_type)?;
673 }
674 }
675 }
676 v4::TypeDefinition::IncompleteTypeDefinition {
677 incompleteness,
678 partial_type_expr,
679 ..
680 } => {
681 if let Some(ty) = partial_type_expr {
682 self.v4_type(&context.named(NodeStep::PartialTypeExpression), ty)?;
683 }
684 if let v4::Incompleteness::Hole {
685 partial_body: Some(ty),
686 ..
687 } = incompleteness
688 {
689 self.v4_type(&context.named(NodeStep::HoleExpectedType), ty)?;
690 }
691 }
692 }
693 Ok(())
694 }
695
696 fn v4_type_specification(
697 &mut self,
698 context: &WalkContext,
699 specification: &v4::TypeSpecification,
700 ) -> Result<(), NodeResolutionError> {
701 let annotations = match specification {
702 v4::TypeSpecification::TypeAliasSpecification { annotations, .. }
703 | v4::TypeSpecification::OpaqueTypeSpecification { annotations, .. }
704 | v4::TypeSpecification::CustomTypeSpecification { annotations, .. }
705 | v4::TypeSpecification::DerivedTypeSpecification { annotations, .. } => annotations,
706 };
707 self.v4_annotations(context, annotations)?;
708 match specification {
709 v4::TypeSpecification::TypeAliasSpecification { type_expr, .. } => {
710 self.v4_type(&context.named(NodeStep::TypeExpression), type_expr)?
711 }
712 v4::TypeSpecification::CustomTypeSpecification { constructors, .. } => {
713 for constructor in constructors {
714 let child =
715 context.named(NodeStep::CustomConstructor(constructor.name.clone()));
716 self.add(&child, IndexedNodeKind::Constructor, constructor)?;
717 for (index, argument) in constructor.args.iter().enumerate() {
718 let argument_context = child
719 .ordered(NodeStep::ConstructorArgument(index), &argument.arg_type)?;
720 self.v4_type(&argument_context, &argument.arg_type)?;
721 }
722 }
723 }
724 v4::TypeSpecification::DerivedTypeSpecification { base_type, .. } => {
725 self.v4_type(&context.named(NodeStep::DerivedBaseType), base_type)?
726 }
727 v4::TypeSpecification::OpaqueTypeSpecification { .. } => {}
728 }
729 Ok(())
730 }
731
732 fn v4_type(&mut self, context: &WalkContext, ty: &v4::Type) -> Result<(), NodeResolutionError> {
733 self.add(context, IndexedNodeKind::TypeExpression, ty)?;
734 match ty {
735 v4::Type::Record(_, fields) => {
736 for field in fields {
737 self.v4_type(
738 &context.named(NodeStep::RecordField(field.name.clone())),
739 &field.tpe,
740 )?;
741 }
742 }
743 v4::Type::ExtensibleRecord(_, _, fields) => {
744 for field in fields {
745 self.v4_type(
746 &context.named(NodeStep::ExtensibleRecordField(field.name.clone())),
747 &field.tpe,
748 )?;
749 }
750 }
751 v4::Type::Function(_, parameter, result) => {
752 self.v4_type(&context.named(NodeStep::TypeFunctionParameter), parameter)?;
753 self.v4_type(&context.named(NodeStep::TypeFunctionResult), result)?;
754 }
755 v4::Type::Reference(_, _, arguments) => {
756 for (index, argument) in arguments.iter().enumerate() {
757 let child = context.ordered(NodeStep::ReferenceArgument(index), argument)?;
758 self.v4_type(&child, argument)?;
759 }
760 }
761 v4::Type::Tuple(_, elements) => {
762 for (index, element) in elements.iter().enumerate() {
763 let child = context.ordered(NodeStep::TupleElement(index), element)?;
764 self.v4_type(&child, element)?;
765 }
766 }
767 _ => {}
768 }
769 Ok(())
770 }
771
772 fn v4_value_definition(
773 &mut self,
774 context: &WalkContext,
775 definition: &v4::ValueDefinition,
776 ) -> Result<(), NodeResolutionError> {
777 for (name, ty) in &definition.input_types {
778 self.v4_type(
779 &context.named(NodeStep::ValueInputType(parse_name(name)?)),
780 ty,
781 )?;
782 }
783 if let Some(output) = &definition.output_type {
784 self.v4_type(&context.named(NodeStep::ValueOutputType), output)?;
785 }
786 match &definition.body {
787 v4::ValueBody::Expression(body) => {
788 self.v4_value(&context.named(NodeStep::Body), body)?
789 }
790 v4::ValueBody::External {
791 fallback: Some(body),
792 ..
793 } => self.v4_value(&context.named(NodeStep::ExternalFallback), body)?,
794 v4::ValueBody::Incomplete {
795 partial_body,
796 incompleteness,
797 } => {
798 if let Some(body) = partial_body {
799 self.v4_value(&context.named(NodeStep::IncompletePartialBody), body)?;
800 }
801 if let v4::Incompleteness::Hole {
802 partial_body: Some(ty),
803 ..
804 } = incompleteness
805 {
806 self.v4_type(&context.named(NodeStep::HoleExpectedType), ty)?;
807 }
808 }
809 v4::ValueBody::Native { .. } | v4::ValueBody::External { fallback: None, .. } => {}
810 }
811 Ok(())
812 }
813
814 fn v4_value_specification(
815 &mut self,
816 context: &WalkContext,
817 specification: &v4::ValueSpecification,
818 ) -> Result<(), NodeResolutionError> {
819 self.v4_annotations(context, &specification.annotations)?;
820 for (name, ty) in &specification.inputs {
821 self.v4_type(
822 &context.named(NodeStep::ValueInputType(parse_name(name)?)),
823 ty,
824 )?;
825 }
826 self.v4_type(
827 &context.named(NodeStep::ValueOutputType),
828 &specification.output,
829 )
830 }
831
832 fn v4_annotations(
833 &mut self,
834 context: &WalkContext,
835 annotations: &v4::Annotations,
836 ) -> Result<(), NodeResolutionError> {
837 for (index, entry) in annotations.entries.iter().enumerate() {
838 let entry_context = context.ordered(NodeStep::AnnotationEntry(index), entry)?;
839 let args = match entry {
840 v4::Annotation::Structured { args, .. }
841 | v4::Annotation::LinkedStructured { args, .. }
842 | v4::Annotation::PendingStructured { args, .. } => args,
843 _ => continue,
844 };
845 for (index, arg) in args.iter().enumerate() {
846 let value = match arg {
847 v4::AnnotationArgument::Positional(value)
848 | v4::AnnotationArgument::Named { value, .. } => value,
849 };
850 let arg_context =
851 entry_context.ordered(NodeStep::AnnotationArgument(index), value)?;
852 self.v4_value(&arg_context, value)?;
853 }
854 }
855 Ok(())
856 }
857
858 fn v4_value(
859 &mut self,
860 context: &WalkContext,
861 value: &v4::Value,
862 ) -> Result<(), NodeResolutionError> {
863 self.add(context, IndexedNodeKind::ValueExpression, value)?;
864 if let Some(inferred) = &value.attributes().inferred_type {
865 self.v4_type(&context.named(NodeStep::InferredType), inferred)?;
866 }
867 match value {
868 v4::Value::Apply(_, function, argument) => {
869 self.v4_value(&context.named(NodeStep::ApplyFunction), function)?;
870 self.v4_value(&context.named(NodeStep::ApplyArgument), argument)?;
871 }
872 v4::Value::Field(_, subject, _) => {
873 self.v4_value(&context.named(NodeStep::FieldSubject), subject)?
874 }
875 v4::Value::Destructure(_, pattern, subject, body) => {
876 self.v4_pattern(&context.named(NodeStep::DestructurePattern), pattern)?;
877 self.v4_value(&context.named(NodeStep::DestructureValue), subject)?;
878 self.v4_value(&context.named(NodeStep::DestructureBody), body)?;
879 }
880 v4::Value::IfThenElse(_, condition, then_value, else_value) => {
881 self.v4_value(&context.named(NodeStep::IfCondition), condition)?;
882 self.v4_value(&context.named(NodeStep::IfThen), then_value)?;
883 self.v4_value(&context.named(NodeStep::IfElse), else_value)?;
884 }
885 v4::Value::Lambda(_, pattern, body) => {
886 self.v4_pattern(&context.named(NodeStep::LambdaPattern), pattern)?;
887 self.v4_value(&context.named(NodeStep::LambdaBody), body)?;
888 }
889 v4::Value::LetDefinition(_, name, definition, body) => {
890 let child = context.named(NodeStep::LetDefinition(name.clone()));
891 self.add(
892 &child,
893 IndexedNodeKind::ValueDefinition,
894 definition.as_ref(),
895 )?;
896 self.v4_value_definition(&child, definition)?;
897 self.v4_value(&context.named(NodeStep::LetBody), body)?;
898 }
899 v4::Value::LetRecursion(_, definitions, body) => {
900 for binding in definitions {
901 let child = context.named(NodeStep::LetDefinition(binding.name().clone()));
902 self.add(
903 &child,
904 IndexedNodeKind::ValueDefinition,
905 binding.definition(),
906 )?;
907 self.v4_value_definition(&child, binding.definition())?;
908 }
909 self.v4_value(&context.named(NodeStep::LetBody), body)?;
910 }
911 v4::Value::List(_, elements) => {
912 for (index, element) in elements.iter().enumerate() {
913 let child = context.ordered(NodeStep::ListElement(index), element)?;
914 self.v4_value(&child, element)?;
915 }
916 }
917 v4::Value::Record(_, fields) => {
918 for field in fields {
919 self.v4_value(
920 &context.named(NodeStep::RecordField(field.name().clone())),
921 field.value(),
922 )?;
923 }
924 }
925 v4::Value::Tuple(_, elements) => {
926 for (index, element) in elements.iter().enumerate() {
927 let child = context.ordered(NodeStep::TupleElement(index), element)?;
928 self.v4_value(&child, element)?;
929 }
930 }
931 v4::Value::PatternMatch(_, subject, cases) => {
932 self.v4_value(&context.named(NodeStep::PatternMatchSubject), subject)?;
933 for (index, case) in cases.iter().enumerate() {
934 let case_content = (case.pattern(), case.body());
935 let pattern =
936 context.ordered(NodeStep::PatternMatchCasePattern(index), &case_content)?;
937 self.v4_pattern(&pattern, case.pattern())?;
938 let body =
939 context.ordered(NodeStep::PatternMatchCaseBody(index), &case_content)?;
940 self.v4_value(&body, case.body())?;
941 }
942 }
943 v4::Value::UpdateRecord(_, subject, fields) => {
944 self.v4_value(&context.named(NodeStep::UpdateSubject), subject)?;
945 for field in fields {
946 self.v4_value(
947 &context.named(NodeStep::UpdateField(field.name().clone())),
948 field.value(),
949 )?;
950 }
951 }
952 v4::Value::Hole(_, _, Some(expected)) => {
953 self.v4_type(&context.named(NodeStep::HoleExpectedType), expected)?
954 }
955 v4::Value::Literal(_, _)
956 | v4::Value::Constructor(_, _)
957 | v4::Value::Variable(_, _)
958 | v4::Value::Reference(_, _)
959 | v4::Value::FieldFunction(_, _)
960 | v4::Value::Unit(_)
961 | v4::Value::Hole(_, _, None) => {}
962 }
963 Ok(())
964 }
965
966 fn v4_pattern(
967 &mut self,
968 context: &WalkContext,
969 pattern: &v4::Pattern,
970 ) -> Result<(), NodeResolutionError> {
971 self.add(context, IndexedNodeKind::Pattern, pattern)?;
972 if let Some(inferred) = &pattern.attributes().inferred_type {
973 self.v4_type(&context.named(NodeStep::InferredType), inferred)?;
974 }
975 match pattern {
976 v4::Pattern::AsPattern(_, child, _) => {
977 self.v4_pattern(&context.named(NodeStep::AsPatternChild), child)?
978 }
979 v4::Pattern::TuplePattern(_, children) => {
980 for (index, child) in children.iter().enumerate() {
981 let path = context.ordered(NodeStep::PatternTupleElement(index), child)?;
982 self.v4_pattern(&path, child)?;
983 }
984 }
985 v4::Pattern::ConstructorPattern(_, _, children) => {
986 for (index, child) in children.iter().enumerate() {
987 let path =
988 context.ordered(NodeStep::PatternConstructorArgument(index), child)?;
989 self.v4_pattern(&path, child)?;
990 }
991 }
992 v4::Pattern::HeadTailPattern(_, head, tail) => {
993 self.v4_pattern(&context.named(NodeStep::HeadTailHead), head)?;
994 self.v4_pattern(&context.named(NodeStep::HeadTailTail), tail)?;
995 }
996 v4::Pattern::WildcardPattern(_)
997 | v4::Pattern::EmptyListPattern(_)
998 | v4::Pattern::LiteralPattern(_, _)
999 | v4::Pattern::UnitPattern(_) => {}
1000 }
1001 Ok(())
1002 }
1003
1004 fn v3_definition_package(
1005 &mut self,
1006 owner: NodeOwner,
1007 package: &classic::PackageDefinition<classic::Attrs, classic::Type<classic::Attrs>>,
1008 ) -> Result<(), NodeResolutionError> {
1009 for entry in &package.modules {
1010 let module = classic_path(&entry.path)?;
1011 self.add(
1012 &WalkContext::root(NodeRoot::Module {
1013 owner: owner.clone(),
1014 module: module.clone(),
1015 }),
1016 IndexedNodeKind::Module,
1017 &entry.definition.value,
1018 )?;
1019 for (name, controlled) in &entry.definition.value.types {
1020 let context = WalkContext::root(NodeRoot::Type {
1021 owner: owner.clone(),
1022 module: module.clone(),
1023 name: classic_name(name)?,
1024 });
1025 self.add(
1026 &context,
1027 IndexedNodeKind::TypeDefinition,
1028 &controlled.value.value,
1029 )?;
1030 self.v3_type_definition(&context, &controlled.value.value)?;
1031 }
1032 for (name, controlled) in &entry.definition.value.values {
1033 let context = WalkContext::root(NodeRoot::Value {
1034 owner: owner.clone(),
1035 module: module.clone(),
1036 name: classic_name(name)?,
1037 });
1038 self.add(
1039 &context,
1040 IndexedNodeKind::ValueDefinition,
1041 &controlled.value.value,
1042 )?;
1043 self.v3_value_definition(&context, &controlled.value.value)?;
1044 }
1045 }
1046 Ok(())
1047 }
1048
1049 fn v3_specification_package(
1050 &mut self,
1051 owner: NodeOwner,
1052 package: &classic::PackageSpecification<classic::Attrs>,
1053 ) -> Result<(), NodeResolutionError> {
1054 for entry in &package.modules {
1055 let module = classic_path(&entry.path)?;
1056 self.add(
1057 &WalkContext::root(NodeRoot::Module {
1058 owner: owner.clone(),
1059 module: module.clone(),
1060 }),
1061 IndexedNodeKind::Module,
1062 &entry.specification,
1063 )?;
1064 for (name, documented) in &entry.specification.types {
1065 let context = WalkContext::root(NodeRoot::Type {
1066 owner: owner.clone(),
1067 module: module.clone(),
1068 name: classic_name(name)?,
1069 });
1070 self.add(&context, IndexedNodeKind::TypeDefinition, &documented.value)?;
1071 self.v3_type_specification(&context, &documented.value)?;
1072 }
1073 for (name, documented) in &entry.specification.values {
1074 let context = WalkContext::root(NodeRoot::Value {
1075 owner: owner.clone(),
1076 module: module.clone(),
1077 name: classic_name(name)?,
1078 });
1079 self.add(
1080 &context,
1081 IndexedNodeKind::ValueDefinition,
1082 &documented.value,
1083 )?;
1084 for input in &documented.value.inputs {
1085 self.v3_type(
1086 &context.named(NodeStep::ValueInputType(classic_name(&input.name)?)),
1087 &input.ty,
1088 )?;
1089 }
1090 self.v3_type(
1091 &context.named(NodeStep::ValueOutputType),
1092 &documented.value.output,
1093 )?;
1094 }
1095 }
1096 Ok(())
1097 }
1098
1099 fn v3_type_definition(
1100 &mut self,
1101 context: &WalkContext,
1102 definition: &classic::TypeDefinition<classic::Attrs>,
1103 ) -> Result<(), NodeResolutionError> {
1104 match definition {
1105 classic::TypeDefinition::Alias(_, ty) => {
1106 self.v3_type(&context.named(NodeStep::TypeExpression), ty)?
1107 }
1108 classic::TypeDefinition::Custom(_, controlled) => {
1109 self.v3_constructors(context, &controlled.value)?
1110 }
1111 }
1112 Ok(())
1113 }
1114
1115 fn v3_type_specification(
1116 &mut self,
1117 context: &WalkContext,
1118 specification: &classic::TypeSpecification<classic::Attrs>,
1119 ) -> Result<(), NodeResolutionError> {
1120 match specification {
1121 classic::TypeSpecification::Alias(_, ty) => {
1122 self.v3_type(&context.named(NodeStep::TypeExpression), ty)?
1123 }
1124 classic::TypeSpecification::Custom(_, constructors) => {
1125 self.v3_constructors(context, constructors)?
1126 }
1127 classic::TypeSpecification::Derived(_, configuration) => self.v3_type(
1128 &context.named(NodeStep::DerivedBaseType),
1129 &configuration.base_type,
1130 )?,
1131 classic::TypeSpecification::Opaque(_) => {}
1132 }
1133 Ok(())
1134 }
1135
1136 fn v3_constructors(
1137 &mut self,
1138 context: &WalkContext,
1139 constructors: &[classic::Constructor<classic::Attrs>],
1140 ) -> Result<(), NodeResolutionError> {
1141 for constructor in constructors {
1142 let child = context.named(NodeStep::CustomConstructor(classic_name(
1143 &constructor.name,
1144 )?));
1145 self.add(&child, IndexedNodeKind::Constructor, constructor)?;
1146 for (index, (_, ty)) in constructor.args.iter().enumerate() {
1147 let argument = child.ordered(NodeStep::ConstructorArgument(index), ty)?;
1148 self.v3_type(&argument, ty)?;
1149 }
1150 }
1151 Ok(())
1152 }
1153
1154 fn v3_value_definition(
1155 &mut self,
1156 context: &WalkContext,
1157 definition: &classic::ValueDefinition<classic::Attrs, classic::Type<classic::Attrs>>,
1158 ) -> Result<(), NodeResolutionError> {
1159 for input in &definition.input_types {
1160 self.v3_type(
1161 &context.named(NodeStep::ValueInputType(classic_name(&input.name)?)),
1162 &input.ty,
1163 )?;
1164 self.v3_type(
1165 &context.named(NodeStep::ValueInputAnnotation(classic_name(&input.name)?)),
1166 &input.annotation,
1167 )?;
1168 }
1169 self.v3_type(
1170 &context.named(NodeStep::ValueOutputType),
1171 &definition.output_type,
1172 )?;
1173 self.v3_value(&context.named(NodeStep::Body), &definition.body)
1174 }
1175
1176 fn v3_type(
1177 &mut self,
1178 context: &WalkContext,
1179 ty: &classic::Type<classic::Attrs>,
1180 ) -> Result<(), NodeResolutionError> {
1181 self.add(context, IndexedNodeKind::TypeExpression, ty)?;
1182 match ty {
1183 classic::Type::Record(_, fields) => {
1184 for field in fields {
1185 self.v3_type(
1186 &context.named(NodeStep::RecordField(classic_name(&field.name)?)),
1187 &field.ty,
1188 )?;
1189 }
1190 }
1191 classic::Type::ExtensibleRecord(_, _, fields) => {
1192 for field in fields {
1193 self.v3_type(
1194 &context.named(NodeStep::ExtensibleRecordField(classic_name(&field.name)?)),
1195 &field.ty,
1196 )?;
1197 }
1198 }
1199 classic::Type::Function(_, parameter, result) => {
1200 self.v3_type(&context.named(NodeStep::TypeFunctionParameter), parameter)?;
1201 self.v3_type(&context.named(NodeStep::TypeFunctionResult), result)?;
1202 }
1203 classic::Type::Reference(_, _, arguments) => {
1204 for (index, argument) in arguments.iter().enumerate() {
1205 let child = context.ordered(NodeStep::ReferenceArgument(index), argument)?;
1206 self.v3_type(&child, argument)?;
1207 }
1208 }
1209 classic::Type::Tuple(_, elements) => {
1210 for (index, element) in elements.iter().enumerate() {
1211 let child = context.ordered(NodeStep::TupleElement(index), element)?;
1212 self.v3_type(&child, element)?;
1213 }
1214 }
1215 _ => {}
1216 }
1217 Ok(())
1218 }
1219
1220 fn v3_value(
1221 &mut self,
1222 context: &WalkContext,
1223 value: &classic::Value<classic::Attrs, classic::Type<classic::Attrs>>,
1224 ) -> Result<(), NodeResolutionError> {
1225 self.add(context, IndexedNodeKind::ValueExpression, value)?;
1226 match value {
1227 classic::Value::Apply(_, function, argument) => {
1228 self.v3_value(&context.named(NodeStep::ApplyFunction), function)?;
1229 self.v3_value(&context.named(NodeStep::ApplyArgument), argument)?;
1230 }
1231 classic::Value::Field(_, subject, _) => {
1232 self.v3_value(&context.named(NodeStep::FieldSubject), subject)?
1233 }
1234 classic::Value::Destructure(_, pattern, subject, body) => {
1235 self.v3_pattern(&context.named(NodeStep::DestructurePattern), pattern)?;
1236 self.v3_value(&context.named(NodeStep::DestructureValue), subject)?;
1237 self.v3_value(&context.named(NodeStep::DestructureBody), body)?;
1238 }
1239 classic::Value::IfThenElse(_, condition, then_value, else_value) => {
1240 self.v3_value(&context.named(NodeStep::IfCondition), condition)?;
1241 self.v3_value(&context.named(NodeStep::IfThen), then_value)?;
1242 self.v3_value(&context.named(NodeStep::IfElse), else_value)?;
1243 }
1244 classic::Value::Lambda(_, pattern, body) => {
1245 self.v3_pattern(&context.named(NodeStep::LambdaPattern), pattern)?;
1246 self.v3_value(&context.named(NodeStep::LambdaBody), body)?;
1247 }
1248 classic::Value::LetDefinition(_, name, definition, body) => {
1249 let child = context.named(NodeStep::LetDefinition(classic_name(name)?));
1250 self.add(
1251 &child,
1252 IndexedNodeKind::ValueDefinition,
1253 definition.as_ref(),
1254 )?;
1255 self.v3_value_definition(&child, definition)?;
1256 self.v3_value(&context.named(NodeStep::LetBody), body)?;
1257 }
1258 classic::Value::LetRecursion(_, definitions, body) => {
1259 for (name, definition) in definitions {
1260 let child = context.named(NodeStep::LetDefinition(classic_name(name)?));
1261 self.add(&child, IndexedNodeKind::ValueDefinition, definition)?;
1262 self.v3_value_definition(&child, definition)?;
1263 }
1264 self.v3_value(&context.named(NodeStep::LetBody), body)?;
1265 }
1266 classic::Value::List(_, elements) => {
1267 for (index, element) in elements.iter().enumerate() {
1268 let child = context.ordered(NodeStep::ListElement(index), element)?;
1269 self.v3_value(&child, element)?;
1270 }
1271 }
1272 classic::Value::Record(_, fields) => {
1273 for (name, value) in fields {
1274 self.v3_value(
1275 &context.named(NodeStep::RecordField(classic_name(name)?)),
1276 value,
1277 )?;
1278 }
1279 }
1280 classic::Value::Tuple(_, elements) => {
1281 for (index, element) in elements.iter().enumerate() {
1282 let child = context.ordered(NodeStep::TupleElement(index), element)?;
1283 self.v3_value(&child, element)?;
1284 }
1285 }
1286 classic::Value::PatternMatch(_, subject, cases) => {
1287 self.v3_value(&context.named(NodeStep::PatternMatchSubject), subject)?;
1288 for (index, (pattern, body)) in cases.iter().enumerate() {
1289 let pattern_context = context
1290 .ordered(NodeStep::PatternMatchCasePattern(index), &(pattern, body))?;
1291 self.v3_pattern(&pattern_context, pattern)?;
1292 let body_context =
1293 context.ordered(NodeStep::PatternMatchCaseBody(index), &(pattern, body))?;
1294 self.v3_value(&body_context, body)?;
1295 }
1296 }
1297 classic::Value::Update(_, subject, fields) => {
1298 self.v3_value(&context.named(NodeStep::UpdateSubject), subject)?;
1299 for (name, value) in fields {
1300 self.v3_value(
1301 &context.named(NodeStep::UpdateField(classic_name(name)?)),
1302 value,
1303 )?;
1304 }
1305 }
1306 classic::Value::Constructor(_, _)
1307 | classic::Value::FieldFunction(_, _)
1308 | classic::Value::Literal(_, _)
1309 | classic::Value::Unit(_)
1310 | classic::Value::Variable(_, _)
1311 | classic::Value::Reference(_, _) => {}
1312 }
1313 Ok(())
1314 }
1315
1316 fn v3_pattern(
1317 &mut self,
1318 context: &WalkContext,
1319 pattern: &classic::Pattern<classic::Type<classic::Attrs>>,
1320 ) -> Result<(), NodeResolutionError> {
1321 self.add(context, IndexedNodeKind::Pattern, pattern)?;
1322 match pattern {
1323 classic::Pattern::As(_, child, _) => {
1324 self.v3_pattern(&context.named(NodeStep::AsPatternChild), child)?
1325 }
1326 classic::Pattern::Tuple(_, children) => {
1327 for (index, child) in children.iter().enumerate() {
1328 let path = context.ordered(NodeStep::PatternTupleElement(index), child)?;
1329 self.v3_pattern(&path, child)?;
1330 }
1331 }
1332 classic::Pattern::Constructor(_, _, children) => {
1333 for (index, child) in children.iter().enumerate() {
1334 let path =
1335 context.ordered(NodeStep::PatternConstructorArgument(index), child)?;
1336 self.v3_pattern(&path, child)?;
1337 }
1338 }
1339 classic::Pattern::HeadTail(_, head, tail) => {
1340 self.v3_pattern(&context.named(NodeStep::HeadTailHead), head)?;
1341 self.v3_pattern(&context.named(NodeStep::HeadTailTail), tail)?;
1342 }
1343 classic::Pattern::Wildcard(_)
1344 | classic::Pattern::EmptyList(_)
1345 | classic::Pattern::Literal(_, _)
1346 | classic::Pattern::Unit(_) => {}
1347 }
1348 Ok(())
1349 }
1350}
1351
1352fn parse_package(text: &str) -> Result<PackageName, NodeResolutionError> {
1353 let package =
1354 PackageName::from_canonical_string(text).map_err(NodeResolutionError::InvalidName)?;
1355 if package.to_canonical_string() != text || package.is_empty() {
1356 return Err(NodeResolutionError::InvalidName(text.to_owned()));
1357 }
1358 Ok(package)
1359}
1360
1361fn parse_path(text: &str) -> Result<Path, NodeResolutionError> {
1362 let path = Path::from_canonical_string(text).map_err(NodeResolutionError::InvalidName)?;
1363 if path.to_canonical_string() != text || path.is_empty() {
1364 return Err(NodeResolutionError::InvalidName(text.to_owned()));
1365 }
1366 Ok(path)
1367}
1368
1369fn parse_name(text: &str) -> Result<Name, NodeResolutionError> {
1370 let name = Name::from_canonical_string(text).map_err(NodeResolutionError::InvalidName)?;
1371 if name.to_canonical_string() != text {
1372 return Err(NodeResolutionError::InvalidName(text.to_owned()));
1373 }
1374 Ok(name)
1375}
1376
1377fn classic_name(name: &classic::Name) -> Result<Name, NodeResolutionError> {
1378 let words = name
1379 .words
1380 .iter()
1381 .map(|word| crate::naming::resolve(*word).to_string())
1382 .collect::<Vec<_>>();
1383 let name = Name::from_words(words);
1384 Name::from_canonical_string(&name.to_canonical_string())
1385 .map_err(NodeResolutionError::InvalidName)
1386}
1387
1388fn classic_path(path: &classic::Path) -> Result<Path, NodeResolutionError> {
1389 Ok(Path {
1390 segments: path
1391 .segments
1392 .iter()
1393 .map(classic_name)
1394 .collect::<Result<Vec<_>, _>>()?,
1395 })
1396}