1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//! Stav, a statically typed, eager and total configuration language.
//!
//! A Stav program is a set of `.stav` files written in block syntax. This
//! crate is the whole language: it parses, formats, type checks and
//! evaluates programs, merges the contributions of every file by priority,
//! and turns the result into a [`Value`] that renders to JSON, TOML or YAML
//! or converts to Rust types through serde.
//!
//! Evaluation always terminates, reads nothing except the files the host
//! serves, and gives the same value for the same inputs. The whole program
//! is type checked before any of it is evaluated. The crate performs no
//! I/O of its own.
//!
//! # Embedding
//!
//! A [`Host`] is what the embedding program contributes: a [`Loader`] that
//! serves source files, and optionally a prelude, standard modules, symbol
//! types and host modules. A [`RootSpec`] names the root struct, the entry
//! files and the import roots. [`check`] loads and type checks the program,
//! [`Checked::eval`] evaluates it into an [`Evaluated`] value, and
//! [`Evaluated::get`] converts an attribute into any type that implements
//! [`serde::Deserialize`]. Every failure is reported as [`Diagnostics`].
//!
//! ```
//! use serde::Deserialize;
//! use stav::{AttrPath, Format, Host, ImportRoot, Limits, MemoryLoader, RootSpec};
//!
//! #[derive(Deserialize)]
//! struct Server {
//! name: String,
//! port: u16,
//! }
//!
//! let source = "struct Server {\n name: Str\n port: Int where 1..=65535 = 80\n}\n\
//! struct Root { server: Server }\n\
//! server { name = \"web\", port = 8080 }\n";
//! let host = Host::new(MemoryLoader::new().with_file("app/main.stav", source));
//! let root = RootSpec {
//! root_struct: "Root".to_owned(),
//! entries: vec!["app/main.stav".into()],
//! import_roots: vec![ImportRoot::new("app")],
//! };
//! let evaluated = stav::check(&host, &root)?.eval(&Limits::default())?;
//!
//! let server: Server = evaluated.get(&AttrPath::new(["server"]))?;
//! assert_eq!((server.name.as_str(), server.port), ("web", 8080));
//! assert_eq!(
//! evaluated.render(Format::Toml)?,
//! "[server]\nname = \"web\"\nport = 8080\n"
//! );
//! # Ok::<(), stav::Diagnostics>(())
//! ```
//!
//! # Other entry points
//!
//! [`lex`] splits source text into tokens, [`parse`] builds a lossless
//! [`SyntaxTree`] with a typed view in [`ast`], and [`format()`] lays source
//! text out in its canonical form.
pub use ;
pub use ConvertError;
pub use ;
pub use ;
pub use format;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
/// Compiles the Rust examples of the repository's README as doctests.
;