summaryrefslogtreecommitdiff
path: root/dhall/src/lib.rs
blob: c218aeb81e376a1007c892df959ca5d04de402d4 (plain)
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#![feature(trace_macros)]
#![feature(proc_macro_hygiene)]
#![feature(slice_patterns)]
#![feature(label_break_value)]
#![cfg_attr(test, feature(custom_inner_attributes))]
#![allow(
    clippy::type_complexity,
    clippy::infallible_destructuring_match,
    clippy::many_single_char_names
)]

//! [Dhall][dhall] is a programmable configuration language that provides a non-repetitive
//! alternative to JSON and YAML.
//!
//! You can think of Dhall as: JSON/YAML + types + imports + functions
//!
//! For a description of the dhall language, examples, tutorials, and more, see the [language
//! website][dhall].
//!
//! This crate provides support for consuming dhall files the same way you would consume JSON or
//! YAML. It uses the [Serde][serde] serialization library to provide drop-in support for dhall
//! for any datatype that supports serde (and that's a lot of them !).
//!
//! This library is limited to deserializing (reading) dhall values; serializing (writing)
//! values to dhall is not supported for now.
//!
//! # Examples
//!
//! ### Custom datatype
//!
//! If you have a custom datatype for which you derived [serde::Deserialize], chances are
//! you will be able to derive [SimpleStaticType] for it as well. This gives you access to
//! a dhall representation of your datatype that can be outputted to users, and
//! allows easy type-safe deserializing.
//!
//! ```edition2018
//! use serde::Deserialize;
//! use dhall::SimpleStaticType;
//!
//! #[derive(Debug, Deserialize, SimpleStaticType)]
//! struct Point {
//!     x: usize,
//!     y: usize,
//! }
//!
//! fn main() {
//!     // Some dhall data
//!     // ./Point can be populated using Point::get_type().to_string()
//!     let data = "{ x = 1, y = 1 + 1 } : ./Point";
//!
//!     // Convert the dhall string to a Point.
//!     let point: Point =
//!             dhall::from_str_auto_type(&data)
//!                 .expect("An error ocurred !");
//!
//!     // Prints "point = Point { x: 1, y: 2 }"
//!     println!("point = {:?}", point);
//! }
//! ```
//!
//! ### Loosely typed
//!
//! If you used to consume JSON or YAML in a loosely typed way, you can continue to do so
//! with dhall. You only need to replace [serde_json::from_str] or [serde_yaml::from_str]
//! with [dhall::from_str][from_str].
//! More generally, if the [SimpleStaticType] derive doesn't suit your needs, you can still
//! deserialize any valid dhall file that serde can handle.
//!
//! [serde_json::from_str]: https://docs.serde.rs/serde_json/de/fn.from_str.html
//! [serde_yaml::from_str]: https://docs.serde.rs/serde_yaml/fn.from_str.html
//!
//! ```edition2018
//! use std::collections::BTreeMap;
//!
//! let mut map = BTreeMap::new();
//! map.insert("x".to_string(), 1);
//! map.insert("y".to_string(), 2);
//!
//! // Some dhall data
//! let data = "{ x = 1, y = 1 + 1 } : { x: Natural, y: Natural }";
//!
//! // Deserialize it to a Rust type.
//! let deserialized_map: BTreeMap<String, usize> =
//!         dhall::from_str(&data, None)
//!             .expect("Failed reading the data !");
//! assert_eq!(map, deserialized_map);
//! ```
//!
//! You can of course specify a dhall type that the input should match.
//!
//! ```edition2018
//! use std::collections::BTreeMap;
//!
//! let mut map = BTreeMap::new();
//! map.insert("x".to_string(), 1);
//! map.insert("y".to_string(), 2);
//!
//! // Some dhall data
//! let point_data = "{ x = 1, y = 1 + 1 }";
//! let point_type_data = "{ x: Natural, y: Natural }";
//!
//! // Construct a type
//! let point_type =
//!         dhall::from_str(point_type_data, None)
//!             .expect("Could not parse the Point type");
//!
//! // Deserialize it to a Rust type.
//! let deserialized_map: BTreeMap<String, usize> =
//!         dhall::from_str(&point_data, Some(&point_type))
//!             .expect("Failed reading the data !");
//! assert_eq!(map, deserialized_map);
//! ```
//!
//! [dhall]: https://dhall-lang.org/
//! [serde]: https://docs.serde.rs/serde/
//! [serde::Deserialize]: https://docs.serde.rs/serde/trait.Deserialize.html

#[cfg(test)]
#[macro_use]
mod tests;

#[cfg(test)]
mod parser;

mod binary;
mod imports;
mod normalize;
mod traits;
mod typecheck;
pub use crate::traits::Deserialize;
pub use crate::traits::SimpleStaticType;
pub use crate::traits::StaticType;
pub use dhall_generator::SimpleStaticType;
pub mod error;
pub mod expr;
pub mod serde;

pub fn from_str<'a, T: Deserialize<'a>>(
    s: &'a str,
    ty: Option<&crate::expr::Type>,
) -> crate::error::Result<T> {
    T::from_str(s, ty)
}

pub fn from_str_auto_type<'a, T: Deserialize<'a> + StaticType>(
    s: &'a str,
) -> crate::error::Result<T> {
    from_str(s, Some(&<T as StaticType>::get_static_type()))
}