cratestack_parser/load/
mod.rs1mod attribute;
5mod collisions;
6mod diagnostics;
7mod file_io;
8mod graph;
9mod import_rules;
10mod imports;
11mod merge;
12mod part_rules;
13mod parts;
14mod paths;
15mod sources;
16
17use std::path::{Path, PathBuf};
18use std::sync::Arc;
19
20use cratestack_core::Schema;
21
22use crate::diagnostics::SchemaError;
23
24pub use self::diagnostics::load_schema_diagnostics;
25pub use self::sources::{FsSources, OverlaySources, SchemaSources, canonical_schema_path};
26
27#[derive(Default, Clone, Copy)]
29pub struct LoadOptions<'a> {
30 pub follow_part_of: bool,
33 pub sources: Option<&'a dyn SchemaSources>,
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub enum FileRole {
40 Root,
41 Part,
42 Import,
43 ImportPart,
44}
45
46#[derive(Debug, Clone)]
48pub struct SchemaFile {
49 pub display: String,
51 pub relative: String,
53 pub path: PathBuf,
55 pub source: Arc<str>,
56 pub base: usize,
58 pub role: FileRole,
59}
60
61#[derive(Debug, Clone)]
63pub struct LoadedSchema {
64 pub schema: Schema,
65 pub files: Vec<SchemaFile>,
66}
67
68impl LoadedSchema {
69 pub fn root(&self) -> &SchemaFile {
70 &self.files[0]
71 }
72
73 pub fn locate(&self, offset: usize) -> Option<(&SchemaFile, usize)> {
75 self.files
76 .iter()
77 .find(|file| file.base <= offset && offset <= file.base + file.source.len())
78 .map(|file| (file, offset - file.base))
79 }
80
81 pub fn is_single_file(&self) -> bool {
82 self.files.len() == 1
83 }
84}
85
86pub struct LoadDiagnostics {
89 pub schema: Option<LoadedSchema>,
90 pub errors: Vec<SchemaError>,
91 pub files: Vec<PathBuf>,
92 pub named: Vec<(String, PathBuf)>,
96}
97
98pub fn load_schema(
101 path: impl AsRef<Path>,
102 options: &LoadOptions<'_>,
103) -> Result<LoadedSchema, SchemaError> {
104 let diagnostics = load_schema_diagnostics(path, options);
105 match diagnostics.schema {
106 Some(loaded) => Ok(loaded),
107 None => Err(diagnostics
108 .errors
109 .into_iter()
110 .next()
111 .expect("a load without a schema reports an error")),
112 }
113}