lintel_validate/parsers/
toml_parser.rs1use miette::NamedSource;
2use serde_json::Value;
3
4use crate::diagnostics::ParseDiagnostic;
5
6use super::Parser;
7
8pub struct TomlParser;
9
10impl Parser for TomlParser {
11 fn parse(&self, content: &str, file_name: &str) -> Result<Value, ParseDiagnostic> {
12 let toml_value: toml::Value = toml::from_str(content).map_err(|e| {
13 let offset = e.span().map_or(0, |s| s.start);
14 ParseDiagnostic {
15 src: NamedSource::new(file_name, content.to_string()),
16 span: offset.into(),
17 message: e.message().to_string(),
18 }
19 })?;
20 serde_json::to_value(toml_value).map_err(|e| ParseDiagnostic {
21 src: NamedSource::new(file_name, content.to_string()),
22 span: 0.into(),
23 message: e.to_string(),
24 })
25 }
26
27 fn annotate(&self, content: &str, schema_url: &str) -> Option<String> {
28 Some(format!("# :schema {schema_url}\n{content}"))
29 }
30
31 fn strip_annotation(&self, content: &str) -> String {
32 let mut offset = 0;
33 for line in content.lines() {
34 let trimmed = line.trim();
35 if trimmed.is_empty() {
36 offset += line.len() + 1;
37 continue;
38 }
39 if !trimmed.starts_with('#') {
40 break;
41 }
42 if let Some(after_hash) = trimmed.strip_prefix('#') {
43 let after_hash = after_hash.trim();
44 let is_schema = after_hash
45 .strip_prefix(":schema")
46 .is_some_and(|rest| !rest.is_empty())
47 || after_hash
48 .strip_prefix("$schema:")
49 .is_some_and(|rest| !rest.is_empty());
50 if is_schema {
51 let line_end = offset + line.len();
52 let remove_end = if content.as_bytes().get(line_end) == Some(&b'\n') {
53 line_end + 1
54 } else {
55 line_end
56 };
57 return format!("{}{}", &content[..offset], &content[remove_end..]);
58 }
59 }
60 offset += line.len() + 1;
61 }
62 content.to_string()
63 }
64
65 fn extract_schema_uri(&self, content: &str, _value: &Value) -> Option<String> {
66 for line in content.lines() {
67 let trimmed = line.trim();
68 if trimmed.is_empty() {
69 continue;
70 }
71 if !trimmed.starts_with('#') {
72 break;
73 }
74 let after_hash = trimmed.strip_prefix('#')?.trim();
75 if let Some(uri) = after_hash.strip_prefix(":schema") {
77 let uri = uri.trim();
78 if !uri.is_empty() {
79 return Some(uri.to_string());
80 }
81 }
82 if let Some(uri) = after_hash.strip_prefix("$schema:") {
84 let uri = uri.trim();
85 if !uri.is_empty() {
86 return Some(uri.to_string());
87 }
88 }
89 }
90 None
91 }
92}