knuffel/
ast.rs

1//! Structures that represent abstract syntax tree (AST) of the KDL document
2//!
3//! All of these types are parameterized by the `S` type which is a span type
4//! (perhaps implements [`Span`](crate::traits::Span). The idea is that most of
5//! the time spans are used for errors (either at parsing time, or at runtime),
6//! and original source is somewhere around to show in error snippets. So it's
7//! faster to only track byte offsets and calculate line number and column when
8//! printing code snippet. So use [`span::Span`](crate::traits::Span).
9//!
10//! But sometimes you will not have KDL source around, or performance of
11//! priting matters (i.e. you log source spans). In that case, span should
12//! contain line and column numbers for things, use
13//! [`LineSpan`](crate::span::LineSpan) for that.
14
15use std::collections::BTreeMap;
16use std::convert::Infallible;
17use std::fmt;
18use std::str::FromStr;
19
20use crate::span::Spanned;
21
22/// A shortcut for nodes children that includes span of enclosing braces `{..}`
23pub type SpannedChildren<S> = Spanned<Vec<SpannedNode<S>>, S>;
24/// KDL names with span information are represented using this type
25pub type SpannedName<S> = Spanned<Box<str>, S>;
26/// A KDL node with span of the whole node (including children)
27pub type SpannedNode<S> = Spanned<Node<S>, S>;
28
29/// Single node of the KDL document
30#[derive(Debug, Clone)]
31#[cfg_attr(feature="minicbor", derive(minicbor::Encode, minicbor::Decode))]
32pub struct Node<S> {
33    /// A type name if specified in parenthesis
34    #[cfg_attr(feature="minicbor", n(0))]
35    pub type_name: Option<Spanned<TypeName, S>>,
36    /// A node name
37    #[cfg_attr(feature="minicbor", n(1))]
38    pub node_name: SpannedName<S>,
39    /// Positional arguments
40    #[cfg_attr(feature="minicbor", n(2))]
41    pub arguments: Vec<Value<S>>,
42    /// Named properties
43    #[cfg_attr(feature="minicbor", n(3))]
44    pub properties: BTreeMap<SpannedName<S>, Value<S>>,
45    /// Node's children. This field is not none if there are braces `{..}`
46    #[cfg_attr(feature="minicbor", n(4))]
47    pub children: Option<SpannedChildren<S>>,
48}
49
50/// KDL document root
51#[derive(Debug, Clone)]
52#[cfg_attr(feature="minicbor", derive(minicbor::Encode, minicbor::Decode))]
53pub struct Document<S> {
54    /// Nodes of the document
55    #[cfg_attr(feature="minicbor", n(0))]
56    pub nodes: Vec<SpannedNode<S>>,
57}
58
59#[derive(Debug, Clone, PartialEq, Eq)]
60#[cfg_attr(feature="minicbor", derive(minicbor::Encode, minicbor::Decode))]
61#[cfg_attr(feature="minicbor", cbor(index_only))]
62pub(crate) enum Radix {
63    #[cfg_attr(feature="minicbor", n(2))]
64    Bin,
65    #[cfg_attr(feature="minicbor", n(16))]
66    Hex,
67    #[cfg_attr(feature="minicbor", n(8))]
68    Oct,
69    #[cfg_attr(feature="minicbor", n(10))]
70    Dec,
71}
72
73/// Potentially unlimited size integer value
74#[derive(Debug, Clone, PartialEq, Eq)]
75#[cfg_attr(feature="minicbor", derive(minicbor::Encode, minicbor::Decode))]
76pub struct Integer(
77    #[cfg_attr(feature="minicbor", n(0))]
78    pub(crate) Radix,
79    #[cfg_attr(feature="minicbor", n(1))]
80    pub(crate) Box<str>,
81);
82
83/// Potentially unlimited precision decimal value
84#[derive(Debug, Clone, PartialEq, Eq)]
85#[cfg_attr(feature="minicbor", derive(minicbor::Encode, minicbor::Decode))]
86#[cfg_attr(feature="minicbor", cbor(transparent))]
87pub struct Decimal(
88    #[cfg_attr(feature="minicbor", n(0))]
89    pub(crate) Box<str>,
90);
91
92/// Possibly typed KDL scalar value
93#[derive(Debug, Clone)]
94#[cfg_attr(feature="minicbor", derive(minicbor::Encode, minicbor::Decode))]
95pub struct Value<S> {
96    /// A type name if specified in parenthesis
97    #[cfg_attr(feature="minicbor", n(0))]
98    pub type_name: Option<Spanned<TypeName, S>>,
99    /// The actual value literal
100    #[cfg_attr(feature="minicbor", n(1))]
101    pub literal: Spanned<Literal, S>,
102}
103
104/// Type identifier
105#[derive(Debug, Clone, PartialEq, Eq)]
106pub struct TypeName(TypeNameInner);
107
108#[derive(Debug, Clone, PartialEq, Eq)]
109enum TypeNameInner {
110    Builtin(BuiltinType),
111    Custom(Box<str>),
112}
113
114/// Known type identifier described by the KDL specification
115#[non_exhaustive]
116#[derive(Debug, Clone, PartialEq, Eq)]
117pub enum BuiltinType {
118    /// `u8`: 8-bit unsigned integer type
119    U8,
120    /// `i8`: 8-bit signed integer type
121    I8,
122    /// `u16`: 16-bit unsigned integer type
123    U16,
124    /// `i16`: 16-bit signed integer type
125    I16,
126    /// `u32`: 32-bit unsigned integer type
127    U32,
128    /// `i32`: 32-bit signed integer type
129    I32,
130    /// `u64`: 64-bit unsigned integer type
131    U64,
132    /// `i64`: 64-bit signed integer type
133    I64,
134    /// `usize`: platform-dependent unsigned integer type
135    Usize,
136    /// `isize`: platform-dependent signed integer type
137    Isize,
138    /// `f32`: 32-bit floating point number
139    F32,
140    /// `f64`: 64-bit floating point number
141    F64,
142    /// `base64` denotes binary bytes type encoded using base64 encoding
143    Base64,
144}
145
146/// Scalar KDL value
147#[derive(Debug, Clone, PartialEq, Eq)]
148#[cfg_attr(feature="minicbor", derive(minicbor::Encode, minicbor::Decode))]
149pub enum Literal {
150    /// Null value
151    #[cfg_attr(feature="minicbor", n(0))]
152    Null,
153    /// Boolean value
154    #[cfg_attr(feature="minicbor", n(1))]
155    Bool(
156        #[cfg_attr(feature="minicbor", n(0))]
157        bool
158    ),
159    /// Integer value
160    #[cfg_attr(feature="minicbor", n(2))]
161    Int(
162        #[cfg_attr(feature="minicbor", n(0))]
163        Integer
164    ),
165    /// Decimal (or floating point) value
166    #[cfg_attr(feature="minicbor", n(3))]
167    Decimal(
168        #[cfg_attr(feature="minicbor", n(0))]
169        Decimal
170    ),
171    /// String value
172    #[cfg_attr(feature="minicbor", n(4))]
173    String(
174        #[cfg_attr(feature="minicbor", n(0))]
175        Box<str>
176    ),
177}
178
179impl<S> Node<S> {
180    /// Returns node children
181    pub fn children(&self)
182        -> impl Iterator<Item=&Spanned<Node<S>, S>> +
183                ExactSizeIterator
184    {
185        self.children.as_ref().map(|c| c.iter()).unwrap_or_else(|| [].iter())
186    }
187}
188
189impl BuiltinType {
190    /// Returns string representation of the builtin type as defined by KDL
191    /// specification
192    pub const fn as_str(&self) -> &'static str {
193        use BuiltinType::*;
194        match self {
195            U8 => "u8",
196            I8 => "i8",
197            U16 => "u16",
198            I16 => "i16",
199            U32 => "u32",
200            I32 => "i32",
201            U64 => "u64",
202            I64 => "i64",
203            Usize => "usize",
204            Isize => "isize",
205            F32 => "f32",
206            F64 => "f64",
207            Base64 => "base64",
208        }
209    }
210    /// Returns `TypeName` structure for the builtin type
211    pub const fn as_type(self) -> TypeName {
212        TypeName(TypeNameInner::Builtin(self))
213    }
214}
215
216impl TypeName {
217    pub(crate) fn from_string(val: Box<str>) -> TypeName {
218        use TypeNameInner::*;
219
220        match BuiltinType::from_str(&val[..]) {
221            Ok(b) => TypeName(Builtin(b)),
222            _ => TypeName(Custom(val)),
223        }
224    }
225    /// Returns string represenation of the type name
226    pub fn as_str(&self) -> &str {
227        match &self.0 {
228            TypeNameInner::Builtin(t) => t.as_str(),
229            TypeNameInner::Custom(t) => t.as_ref(),
230        }
231    }
232    /// Returns `BuiltinType` enum for the type if typename matches builtin
233    /// type
234    ///
235    /// Note: checking for `is_none()` is not forward compatible. In future we
236    /// may add additional builtin type. Always use `as_str` for types that
237    /// aren't yet builtin.
238    pub const fn as_builtin(&self) -> Option<&BuiltinType> {
239        match &self.0 {
240            TypeNameInner::Builtin(t) => Some(t),
241            TypeNameInner::Custom(_) => None,
242        }
243    }
244}
245
246impl FromStr for BuiltinType {
247    type Err = ();
248    fn from_str(s: &str) -> Result<BuiltinType, ()> {
249        use BuiltinType::*;
250        match s {
251            "u8" => Ok(U8),
252            "i8" => Ok(I8),
253            "u16" => Ok(U16),
254            "i16" => Ok(I16),
255            "u32" => Ok(U32),
256            "i32" => Ok(I32),
257            "u64" => Ok(U64),
258            "i64" => Ok(I64),
259            "f32" => Ok(F32),
260            "f64" => Ok(F64),
261            "base64" => Ok(Base64),
262            _ => Err(())
263        }
264    }
265}
266
267impl FromStr for TypeName {
268    type Err = Infallible;
269    fn from_str(s: &str) -> Result<TypeName, Infallible> {
270        use TypeNameInner::*;
271        match BuiltinType::from_str(s) {
272            Ok(b) => Ok(TypeName(Builtin(b))),
273            Err(()) => Ok(TypeName(Custom(s.into()))),
274        }
275    }
276}
277
278impl std::ops::Deref for TypeName {
279    type Target = str;
280    fn deref(&self) -> &str {
281        self.as_str()
282    }
283}
284
285impl fmt::Display for TypeName {
286    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
287        self.as_str().fmt(f)
288    }
289}
290
291impl Into<TypeName> for BuiltinType {
292    fn into(self) -> TypeName {
293        self.as_type()
294    }
295}
296
297#[cfg(feature="minicbor")]
298mod cbor {
299    use super::TypeName;
300    use minicbor::{Decoder, Encoder};
301    use minicbor::encode::Encode;
302    use minicbor::decode::Decode;
303
304    impl<'d, C> Decode<'d, C> for TypeName {
305        fn decode(d: &mut Decoder<'d>, _ctx: &mut C)
306            -> Result<Self, minicbor::decode::Error>
307        {
308            d.str().and_then(|s| s.parse().map_err(|e| match e {}))
309        }
310    }
311    impl<C> Encode<C> for TypeName {
312        fn encode<W>(&self, e: &mut Encoder<W>, ctx: &mut C)
313            -> Result<(), minicbor::encode::Error<W::Error>>
314            where W: minicbor::encode::write::Write
315        {
316            self.as_str().encode(e, ctx)
317        }
318    }
319}