1#[cfg(test)]
8mod tests;
9
10pub mod api;
11pub(crate) mod computation;
12pub mod documentation;
13pub(crate) mod engine;
14pub(crate) mod error;
15pub(crate) mod evaluation;
16pub(crate) mod formatting;
17pub(crate) mod limits;
18pub(crate) mod literals;
19pub(crate) mod parsing;
20pub(crate) mod planning;
21pub mod quality;
22pub(crate) mod registry;
23pub mod result_value;
24pub(crate) mod snapshot;
25pub(crate) mod spec_set_id;
26pub(crate) mod stdlib;
27pub(crate) mod string_distance;
28
29#[cfg(not(target_arch = "wasm32"))]
30pub mod deps;
31
32#[cfg(not(target_arch = "wasm32"))]
33pub mod mcp;
34
35#[cfg(target_arch = "wasm32")]
36pub mod wasm;
37
38pub use api::{
39 evaluate_data_value_from_json_value, parse_evaluate_data_object, resolve_evaluate_rules,
40 show_document,
41};
42pub use computation::{OperationResult, VetoType};
43pub use engine::{
44 format_repositories, resolve_effective, Engine, Errors, Repository, SpecDependency,
45 SpecVersion, EMBEDDED_STDLIB_REPOSITORY,
46};
47pub use error::{
48 EngineError, EngineErrorSource, Error, ErrorDetails, ErrorKind, RegistryErrorKind,
49 RequestErrorKind,
50};
51pub use evaluation::evaluate_data::{
52 attribute_evaluate_data_error, evaluate_data_from_entries, evaluate_data_map_from_entries,
53 evaluate_data_null_list_item, EvaluateDataValue,
54};
55pub use evaluation::explanations::{format_explanation, Cause, Explanation, ExplanationNode};
56pub use evaluation::response::{Response, RuleResult};
57
58#[deprecated(note = "use EvaluateDataValue")]
59pub type RunDataValue = EvaluateDataValue;
60#[deprecated(note = "use evaluate_data_value_from_json_value")]
61pub use api::evaluate_data_value_from_json_value as run_data_value_from_json_value;
62#[deprecated(note = "use parse_evaluate_data_object")]
63pub use api::parse_evaluate_data_object as parse_run_data_object;
64#[deprecated(note = "use resolve_evaluate_rules")]
65pub use api::resolve_evaluate_rules as resolve_run_rules;
66#[deprecated(note = "use attribute_evaluate_data_error")]
67pub use evaluation::evaluate_data::attribute_evaluate_data_error as attribute_run_data_error;
68#[deprecated(note = "use evaluate_data_from_entries")]
69pub use evaluation::evaluate_data::evaluate_data_from_entries as run_data_from_entries;
70#[deprecated(note = "use evaluate_data_map_from_entries")]
71pub use evaluation::evaluate_data::evaluate_data_map_from_entries as run_data_map_from_entries;
72#[deprecated(note = "use evaluate_data_null_list_item")]
73pub use evaluation::evaluate_data::evaluate_data_null_list_item as run_data_null_list_item;
74pub use formatting::{format_parse_result, format_source, format_specs};
75pub use indexmap::IndexMap;
76pub use limits::{
77 ResourceLimits, MAX_DATA_NAME_LENGTH, MAX_RULE_NAME_LENGTH, MAX_SPEC_NAME_LENGTH,
78};
79pub use literals::{DateGranularity, MeasureUnit, MeasureUnits, RatioUnit, RatioUnits};
80pub use parsing::ast::{DateTimeValue, EffectiveDate};
81pub use parsing::source::SourceType;
82pub use planning::execution_plan::type_detail_lines;
83pub use planning::execution_plan::{
84 Show, ShowBranch, ShowConversionTarget, ShowData, ShowExpression, ShowRule,
85};
86pub use planning::explanation::{ConversionTraceRole, SerializedConversionTraceStep};
87pub use planning::explanation::{ExplainedRule, ExplainedRuleId};
88pub use planning::semantics::{
89 numbered_row_origin, row_field_input_key, DataPath, LemmaType, ListKey, LiteralValue,
90 PathSegment, SpecIdentity, TypeSpecification, ValueKind,
91};
92pub use result_value::{
93 CalendarResult, RangeResult, RowReference, RowResult, RuleResultValue, RuleResultValueFailure,
94 SpecResult, SpecRuleResult,
95};
96pub use spec_set_id::parse_spec_set_id;
97pub use stdlib::UNITS_LEMMA;
98
99pub const API_V1_SCHEMA_JSON: &str = include_str!("../schemas/api.v1.json");
102
103#[doc(hidden)]
105pub mod __test_support {
106 pub use crate::computation::rational::{
107 checked_div, checked_mul, decimal_to_rational, rational_new,
108 };
109 pub use crate::literals::TimeValue;
110 pub use crate::planning::semantics::{
111 SemanticDateTime, SemanticTime, SemanticTimezone, TypedLiteral,
112 };
113
114 pub fn current_binding_error_json(error: &crate::Error) -> serde_json::Value {
116 serde_json::to_value(crate::EngineError::from(error))
117 .expect("BUG: EngineError must serialize")
118 }
119
120 #[cfg(not(target_arch = "wasm32"))]
121 pub use fixture_transport::FixtureTransport;
122
123 #[cfg(not(target_arch = "wasm32"))]
124 mod fixture_transport {
125 use crate::registry::{Fetch, Header, HttpResponse, HttpTransport, TransportFailure};
126 use std::collections::HashMap;
127 use std::path::{Path, PathBuf};
128
129 pub struct FixtureTransport {
133 fixtures: HashMap<String, String>,
134 }
135
136 impl FixtureTransport {
137 pub fn new(dir: impl AsRef<Path>) -> Self {
138 let dir = dir.as_ref();
139 let mut fixtures = HashMap::new();
140 collect_fixture_files(dir, dir, &mut fixtures);
141 Self { fixtures }
142 }
143
144 pub fn bundled() -> Self {
145 Self::new(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/registry_fixtures"))
146 }
147 }
148
149 impl HttpTransport for FixtureTransport {
150 fn get(&self, fetch: &Fetch) -> Result<HttpResponse, TransportFailure> {
151 match self.fixtures.get(&fetch.repository) {
152 Some(body) => Ok(HttpResponse {
153 status: 200,
154 headers: Vec::<Header>::new(),
155 body: body.clone(),
156 }),
157 None => Ok(HttpResponse {
158 status: 404,
159 headers: Vec::new(),
160 body: String::new(),
161 }),
162 }
163 }
164 }
165
166 fn read_fixture_dir(dir: &Path) -> std::fs::ReadDir {
167 std::fs::read_dir(dir)
168 .unwrap_or_else(|e| panic!("BUG: read fixture dir {}: {e}", dir.display()))
169 }
170
171 fn collect_fixture_files(dir: &Path, base: &Path, fixtures: &mut HashMap<String, String>) {
172 let mut stack = vec![(dir.to_path_buf(), read_fixture_dir(dir))];
173 while let Some((current_dir, entries)) = stack.last_mut() {
174 let Some(entry) = entries.next() else {
175 stack.pop();
176 continue;
177 };
178 let entry = entry.unwrap_or_else(|e| {
179 panic!("BUG: fixture dir entry in {}: {e}", current_dir.display())
180 });
181 let path = entry.path();
182 if path.is_dir() {
183 let subdir = read_fixture_dir(&path);
184 stack.push((path, subdir));
185 continue;
186 }
187 if path.extension().is_none_or(|e| e != "lemma") {
188 continue;
189 }
190 let relative = path.strip_prefix(base).unwrap_or_else(|_| {
191 panic!("BUG: fixture path not under base: {}", path.display())
192 });
193 let identifier = relative
194 .with_extension("")
195 .to_string_lossy()
196 .replace('\\', "/");
197 let content = std::fs::read_to_string(&path)
198 .unwrap_or_else(|e| panic!("BUG: read fixture {}: {e}", path.display()));
199 fixtures.insert(identifier, content);
200 }
201 }
202 }
203}
204
205pub use parsing::ast::{
207 try_parse_type_constraint_command, CommandArg, DataValue, LemmaData, ParentType, Span, SpecRef,
208 TimezoneValue, TypeConstraintCommand,
209};
210pub use parsing::lexer::{can_be_label, Lexer, TokenKind, COMPLETION_KEYWORD_LABELS};
211pub use parsing::source::Source;
212pub use parsing::{parse, ParseResult};
213pub use quality::Recommendation;
214
215pub use engine::Context;
217pub use parsing::ast::{LemmaRepository, LemmaSpec, RepositoryQualifier};
218pub use planning::LemmaSpecSet;
219pub use registry::{
220 Fetch, Header, HttpResponse, HttpTransport, Install, InstallStep, LemmaBase, Registries,
221 Registry, RegistryBundle, RegistryError, RepositoryInstallResult, Resolve, ResolveStep,
222 TransportFailure,
223};