1use std::path::PathBuf;
7
8use eure_document::document::EureDocument;
9use eure_document::identifier::Identifier;
10use indexmap::IndexMap;
11use thiserror::Error;
12
13#[derive(Debug, Clone, PartialEq, Eq, Hash)]
15pub enum ResolvedSchemaUri {
16 Local(PathBuf),
19 Inline(String),
21}
22
23impl std::fmt::Display for ResolvedSchemaUri {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 match self {
26 Self::Local(p) => write!(f, "{}", p.display()),
27 Self::Inline(s) => write!(f, "<inline:{}>", s),
28 }
29 }
30}
31
32#[derive(Debug, Error, Clone, PartialEq, Eq)]
34pub enum ResolverError {
35 #[error("imported path {resolved} escapes workspace root {workspace_root}")]
36 EscapesWorkspaceRoot {
37 resolved: PathBuf,
38 workspace_root: PathBuf,
39 },
40
41 #[error("absolute schema import paths are not supported in v1: {raw_path}")]
42 AbsolutePathUnsupported { raw_path: String },
43
44 #[error("cannot import {scheme} URLs (not yet supported)")]
45 UnsupportedScheme { scheme: String },
46
47 #[error("invalid schema import URL {raw_url}: {reason}")]
48 InvalidUrl { raw_url: String, reason: String },
49
50 #[error("schema import `{raw_path}` has no local filesystem base: {base}")]
51 NonLocalBase {
52 raw_path: String,
53 base: ResolvedSchemaUri,
54 },
55}
56
57#[derive(Debug, Clone, PartialEq)]
60pub struct LoadedSchemaSet {
61 pub root_uri: ResolvedSchemaUri,
62 pub documents: IndexMap<ResolvedSchemaUri, EureDocument>,
63 pub imports: IndexMap<ResolvedSchemaUri, IndexMap<Identifier, ResolvedSchemaUri>>,
64}
65
66impl LoadedSchemaSet {
67 pub fn new(root_uri: ResolvedSchemaUri, root_doc: EureDocument) -> Self {
68 let mut documents = IndexMap::new();
69 documents.insert(root_uri.clone(), root_doc);
70 Self {
71 root_uri,
72 documents,
73 imports: IndexMap::new(),
74 }
75 }
76
77 pub fn insert_document(&mut self, uri: ResolvedSchemaUri, doc: EureDocument) {
78 self.documents.insert(uri, doc);
79 }
80
81 pub fn insert_import(
82 &mut self,
83 base: ResolvedSchemaUri,
84 alias: Identifier,
85 target: ResolvedSchemaUri,
86 ) {
87 self.imports.entry(base).or_default().insert(alias, target);
88 }
89
90 pub fn document(&self, uri: &ResolvedSchemaUri) -> Option<&EureDocument> {
91 self.documents.get(uri)
92 }
93
94 pub fn import_target(
95 &self,
96 base: &ResolvedSchemaUri,
97 alias: &Identifier,
98 ) -> Option<&ResolvedSchemaUri> {
99 self.imports.get(base)?.get(alias)
100 }
101}