Coverage Report

Created: 2026-01-25 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/serde_dhall-0.13.0/src/value.rs
Line
Count
Source
1
use std::collections::{BTreeMap, HashMap};
2
use std::result::Result as StdResult;
3
4
use dhall::builtins::Builtin;
5
use dhall::operations::OpKind;
6
use dhall::semantics::{Hir, HirKind, Nir, NirKind};
7
pub use dhall::syntax::NumKind;
8
use dhall::syntax::{Expr, ExprKind, Span};
9
use dhall::Ctxt;
10
11
use crate::{Error, ErrorKind, FromDhall, Result, ToDhall};
12
13
#[derive(Debug, Clone)]
14
enum ValueKind {
15
    /// Invariant: the value must be printable with the given type.
16
    Val(SimpleValue, Option<SimpleType>),
17
    Ty(SimpleType),
18
}
19
20
#[doc(hidden)]
21
/// An arbitrary Dhall value.
22
#[derive(Debug, Clone, PartialEq, Eq)]
23
pub struct Value {
24
    kind: ValueKind,
25
}
26
27
/// A value of the kind that can be decoded by `serde_dhall`, e.g. `{ x = True, y = [1, 2, 3] }`.
28
/// This can be obtained with [`from_str()`] or [`from_file()`].
29
/// It can also be deserialized into Rust types with [`from_simple_value()`].
30
///
31
/// # Examples
32
///
33
/// ```rust
34
/// # fn main() -> serde_dhall::Result<()> {
35
/// use std::collections::BTreeMap;
36
/// use serde::Deserialize;
37
/// use serde_dhall::{from_simple_value, NumKind, SimpleValue};
38
///
39
/// #[derive(Debug, PartialEq, Eq, Deserialize)]
40
/// struct Foo {
41
///     x: bool,
42
///     y: Vec<u64>,
43
/// }
44
///
45
/// let value: SimpleValue =
46
///     serde_dhall::from_str("{ x = True, y = [1, 2, 3] }").parse()?;
47
///
48
/// assert_eq!(
49
///     value,
50
///     SimpleValue::Record({
51
///         let mut r = BTreeMap::new();
52
///         r.insert(
53
///             "x".to_string(),
54
///             SimpleValue::Num(NumKind::Bool(true))
55
///         );
56
///         r.insert(
57
///             "y".to_string(),
58
///             SimpleValue::List(vec![
59
///                 SimpleValue::Num(NumKind::Natural(1)),
60
///                 SimpleValue::Num(NumKind::Natural(2)),
61
///                 SimpleValue::Num(NumKind::Natural(3)),
62
///             ])
63
///         );
64
///         r
65
///     })
66
/// );
67
///
68
/// let foo: Foo = from_simple_value(value)?;
69
///
70
/// assert_eq!(
71
///     foo,
72
///     Foo {
73
///         x: true,
74
///         y: vec![1, 2, 3]
75
///     }
76
/// );
77
/// # Ok(())
78
/// # }
79
/// ```
80
///
81
/// ```rust
82
/// # fn main() -> serde_dhall::Result<()> {
83
/// use std::collections::BTreeMap;
84
/// use serde_dhall::{NumKind, SimpleValue};
85
///
86
/// let value: SimpleValue =
87
///     serde_dhall::from_str("{ x = 1, y = 2 }").parse()?;
88
///
89
/// let mut map = BTreeMap::new();
90
/// map.insert("x".to_string(), SimpleValue::Num(NumKind::Natural(1)));
91
/// map.insert("y".to_string(), SimpleValue::Num(NumKind::Natural(2)));
92
/// assert_eq!(value, SimpleValue::Record(map));
93
/// # Ok(())
94
/// # }
95
/// ```
96
///
97
/// [`from_str()`]: crate::from_str()
98
/// [`from_file()`]: crate::from_file()
99
/// [`from_simple_value()`]: crate::from_simple_value()
100
#[derive(Debug, Clone, PartialEq, Eq)]
101
pub enum SimpleValue {
102
    /// Numbers and booleans - `True`, `1`, `+2`, `3.24`
103
    Num(NumKind),
104
    /// A string of text - `"Hello world!"`
105
    Text(String),
106
    /// An optional value - `Some e`, `None`
107
    Optional(Option<Box<SimpleValue>>),
108
    /// A list of values - `[a, b, c, d, e]`
109
    List(Vec<SimpleValue>),
110
    /// A record value - `{ k1 = v1, k2 = v2 }`
111
    Record(BTreeMap<String, SimpleValue>),
112
    /// A union value (both the name of the variant and the variant's value) - `Left e`
113
    Union(String, Option<Box<SimpleValue>>),
114
}
115
116
/// The type of a value that can be decoded by `serde_dhall`, e.g. `{ x: Bool, y: List Natural }`.
117
///
118
/// A `SimpleType` is used when deserializing values to ensure they are of the expected type.
119
/// Rather than letting `serde` handle potential type mismatches, this uses the type-checking
120
/// capabilities of Dhall to catch errors early and cleanly indicate in the user's code where the
121
/// mismatch happened.
122
///
123
/// You would typically not manipulate `SimpleType`s by hand but rather let Rust infer it for your
124
/// datatype by deriving the [`StaticType`] trait, and using
125
/// [`Deserializer::static_type_annotation`]. If you need to supply a `SimpleType` manually, you
126
/// can either deserialize it like any other Dhall value, or construct it manually.
127
///
128
/// [`Deserializer::static_type_annotation`]: crate::Deserializer::static_type_annotation()
129
/// [`StaticType`]: crate::StaticType
130
///
131
/// # Type correspondence
132
///
133
/// The following Dhall types correspond to the following Rust types:
134
///
135
/// Dhall  | Rust
136
/// -------|------
137
/// `Bool`  | `bool`
138
/// `Natural`  | `u64`, `u32`, ...
139
/// `Integer`  | `i64`, `i32`, ...
140
/// `Double`  | `f64`, `f32`, ...
141
/// `Text`  | `String`
142
/// `List T`  | `Vec<T>`
143
/// `Optional T`  | `Option<T>`
144
/// `{ x: T, y: U }`  | structs
145
/// `{ _1: T, _2: U }`  | `(T, U)`, structs
146
/// `{ x: T, y: T }`  | `HashMap<String, T>`, structs
147
/// `< x: T \| y: U >`  | enums
148
/// `Prelude.Map.Type Text T`  | `HashMap<String, T>`, structs
149
/// `T -> U`  | unsupported
150
/// `Prelude.JSON.Type`  | unsupported
151
/// `Prelude.Map.Type T U`  | unsupported
152
///
153
/// # Examples
154
///
155
/// ```rust
156
/// # fn main() -> serde_dhall::Result<()> {
157
/// use serde_dhall::{SimpleType, StaticType};
158
///
159
/// #[derive(StaticType)]
160
/// struct Foo {
161
///     x: bool,
162
///     y: Vec<u64>,
163
/// }
164
///
165
/// let ty: SimpleType =
166
///     serde_dhall::from_str("{ x: Bool, y: List Natural }").parse()?;
167
///
168
/// assert_eq!(Foo::static_type(), ty);
169
/// # Ok(())
170
/// # }
171
/// ```
172
///
173
/// ```rust
174
/// # fn main() -> serde_dhall::Result<()> {
175
/// use std::collections::HashMap;
176
/// use serde_dhall::SimpleType;
177
///
178
/// let ty: SimpleType =
179
///     serde_dhall::from_str("{ x: Natural, y: Natural }").parse()?;
180
///
181
/// let mut map = HashMap::new();
182
/// map.insert("x".to_string(), SimpleType::Natural);
183
/// map.insert("y".to_string(), SimpleType::Natural);
184
/// assert_eq!(ty, SimpleType::Record(map));
185
/// # Ok(())
186
/// # }
187
/// ```
188
#[derive(Debug, Clone, PartialEq, Eq)]
189
pub enum SimpleType {
190
    /// Corresponds to the Dhall type `Bool`
191
    Bool,
192
    /// Corresponds to the Dhall type `Natural`
193
    Natural,
194
    /// Corresponds to the Dhall type `Integer`
195
    Integer,
196
    /// Corresponds to the Dhall type `Double`
197
    Double,
198
    /// Corresponds to the Dhall type `Text`
199
    Text,
200
    /// Corresponds to the Dhall type `Optional T`
201
    Optional(Box<SimpleType>),
202
    /// Corresponds to the Dhall type `List T`
203
    List(Box<SimpleType>),
204
    /// Corresponds to the Dhall type `{ x : T, y : U }`
205
    Record(HashMap<String, SimpleType>),
206
    /// Corresponds to the Dhall type `< x : T | y : U >`
207
    Union(HashMap<String, Option<SimpleType>>),
208
}
209
210
impl Value {
211
0
    pub(crate) fn from_nir_and_ty<'cx>(
212
0
        cx: Ctxt<'cx>,
213
0
        x: &Nir<'cx>,
214
0
        ty: &Nir<'cx>,
215
0
    ) -> Result<Self> {
216
0
        Ok(if let Ok(val) = SimpleValue::from_nir(x) {
217
            // The type must be simple if the value is simple.
218
0
            let ty = SimpleType::from_nir(ty).unwrap();
219
0
            Value {
220
0
                kind: ValueKind::Val(val, Some(ty)),
221
0
            }
222
0
        } else if let Ok(ty) = SimpleType::from_nir(x) {
223
0
            Value {
224
0
                kind: ValueKind::Ty(ty),
225
0
            }
226
        } else {
227
0
            let expr = x.to_hir_noenv().to_expr(cx, Default::default());
228
0
            return Err(Error(ErrorKind::Deserialize(format!(
229
0
                "this is neither a simple type nor a simple value: {}",
230
0
                expr
231
0
            ))));
232
        })
233
0
    }
234
235
    /// Converts a Value into a SimpleValue.
236
0
    pub(crate) fn to_simple_value(&self) -> Option<SimpleValue> {
237
0
        match &self.kind {
238
0
            ValueKind::Val(val, _) => Some(val.clone()),
239
0
            _ => None,
240
        }
241
0
    }
242
243
    /// Converts a Value into a SimpleType.
244
0
    pub(crate) fn to_simple_type(&self) -> Option<SimpleType> {
245
0
        match &self.kind {
246
0
            ValueKind::Ty(ty) => Some(ty.clone()),
247
0
            _ => None,
248
        }
249
0
    }
250
251
    /// Converts a value back to the corresponding AST expression.
252
0
    pub(crate) fn to_expr(&self) -> Expr {
253
0
        match &self.kind {
254
0
            ValueKind::Val(val, ty) => val.to_expr(ty.as_ref()).unwrap(),
255
0
            ValueKind::Ty(ty) => ty.to_expr(),
256
        }
257
0
    }
258
}
259
260
#[derive(Debug)]
261
struct NotSimpleValue;
262
263
impl SimpleValue {
264
0
    fn from_nir(nir: &Nir) -> StdResult<Self, NotSimpleValue> {
265
0
        Ok(match nir.kind() {
266
0
            NirKind::Num(lit) => SimpleValue::Num(lit.clone()),
267
0
            NirKind::TextLit(x) => SimpleValue::Text(
268
0
                x.as_text()
269
0
                    .expect("Normal form should ensure the text is a string"),
270
0
            ),
271
0
            NirKind::EmptyOptionalLit(_) => SimpleValue::Optional(None),
272
0
            NirKind::NEOptionalLit(x) => {
273
0
                SimpleValue::Optional(Some(Box::new(Self::from_nir(x)?)))
274
            }
275
0
            NirKind::EmptyListLit(t) => {
276
                // Detect and handle the special records that make assoc maps
277
0
                if let NirKind::RecordType(kts) = t.kind() {
278
0
                    if kts.len() == 2
279
0
                        && kts.contains_key("mapKey")
280
0
                        && kts.contains_key("mapValue")
281
                    {
282
0
                        return Ok(SimpleValue::Record(Default::default()));
283
0
                    }
284
0
                }
285
0
                SimpleValue::List(vec![])
286
            }
287
0
            NirKind::NEListLit(xs) => {
288
                // Detect and handle the special records that make assoc maps
289
0
                if let NirKind::RecordLit(kvs) = xs[0].kind() {
290
0
                    if kvs.len() == 2
291
0
                        && kvs.contains_key("mapKey")
292
0
                        && kvs.contains_key("mapValue")
293
                    {
294
0
                        let convert_entry = |x: &Nir| match x.kind() {
295
0
                            NirKind::RecordLit(kvs) => {
296
0
                                let k = match kvs.get("mapKey").unwrap().kind()
297
                                {
298
0
                                    NirKind::TextLit(t)
299
0
                                        if t.as_text().is_some() =>
300
                                    {
301
0
                                        t.as_text().unwrap()
302
                                    }
303
                                    // TODO
304
0
                                    _ => panic!(
305
                                        "Expected `mapKey` to be a text \
306
                                         literal"
307
                                    ),
308
                                };
309
0
                                let v = Self::from_nir(
310
0
                                    kvs.get("mapValue").unwrap(),
311
0
                                )?;
312
0
                                Ok((k, v))
313
                            }
314
0
                            _ => unreachable!("Internal type error"),
315
0
                        };
316
                        return Ok(SimpleValue::Record(
317
0
                            xs.iter()
318
0
                                .map(convert_entry)
319
0
                                .collect::<StdResult<_, _>>()?,
320
                        ));
321
0
                    }
322
0
                }
323
                SimpleValue::List(
324
0
                    xs.iter()
325
0
                        .map(Self::from_nir)
326
0
                        .collect::<StdResult<_, _>>()?,
327
                )
328
            }
329
0
            NirKind::RecordLit(kvs) => SimpleValue::Record(
330
0
                kvs.iter()
331
0
                    .map(|(k, v)| Ok((k.to_string(), Self::from_nir(v)?)))
332
0
                    .collect::<StdResult<_, _>>()?,
333
            ),
334
0
            NirKind::UnionLit(field, x, _) => SimpleValue::Union(
335
0
                field.into(),
336
0
                Some(Box::new(Self::from_nir(x)?)),
337
            ),
338
0
            NirKind::UnionConstructor(field, ty)
339
0
                if ty.get(field).map(|f| f.is_some()) == Some(false) =>
340
            {
341
0
                SimpleValue::Union(field.into(), None)
342
            }
343
0
            _ => return Err(NotSimpleValue),
344
        })
345
0
    }
346
347
    // Converts this to `Hir`, using the optional type annotation. Without the type, things like
348
    // empty lists and unions will fail to convert.
349
0
    fn to_hir<'cx>(&self, ty: Option<&SimpleType>) -> Result<Hir<'cx>> {
350
        use SimpleType as T;
351
        use SimpleValue as V;
352
0
        let hir = |k| Hir::new(HirKind::Expr(k), Span::Artificial);
353
0
        let type_error = || {
354
0
            Error(ErrorKind::Serialize(format!(
355
0
                "expected a value of type {}, found {:?}",
356
0
                ty.unwrap().to_expr(),
357
0
                self
358
0
            )))
359
0
        };
360
0
        let type_missing = || {
361
0
            Error(ErrorKind::Serialize(format!(
362
0
                "cannot serialize value without a type annotation: {:?}",
363
0
                self
364
0
            )))
365
0
        };
366
0
        let kind = match (self, ty) {
367
0
            (V::Num(num @ NumKind::Bool(_)), Some(T::Bool))
368
0
            | (V::Num(num @ NumKind::Natural(_)), Some(T::Natural))
369
0
            | (V::Num(num @ NumKind::Integer(_)), Some(T::Integer))
370
0
            | (V::Num(num @ NumKind::Double(_)), Some(T::Double))
371
0
            | (V::Num(num), None) => ExprKind::Num(num.clone()),
372
0
            (V::Text(v), Some(T::Text)) | (V::Text(v), None) => {
373
0
                ExprKind::TextLit(v.clone().into())
374
            }
375
376
0
            (V::Optional(None), None) => return Err(type_missing()),
377
0
            (V::Optional(None), Some(T::Optional(t))) => {
378
0
                ExprKind::Op(OpKind::App(
379
0
                    hir(ExprKind::Builtin(Builtin::OptionalNone)),
380
0
                    t.to_hir(),
381
0
                ))
382
            }
383
0
            (V::Optional(Some(v)), None) => ExprKind::SomeLit(v.to_hir(None)?),
384
0
            (V::Optional(Some(v)), Some(T::Optional(t))) => {
385
0
                ExprKind::SomeLit(v.to_hir(Some(t))?)
386
            }
387
388
0
            (V::List(v), None) if v.is_empty() => return Err(type_missing()),
389
0
            (V::List(v), Some(T::List(t))) if v.is_empty() => {
390
0
                ExprKind::EmptyListLit(hir(ExprKind::Op(OpKind::App(
391
0
                    hir(ExprKind::Builtin(Builtin::List)),
392
0
                    t.to_hir(),
393
0
                ))))
394
            }
395
0
            (V::List(v), None) => ExprKind::NEListLit(
396
0
                v.iter().map(|v| v.to_hir(None)).collect::<Result<_>>()?,
397
            ),
398
0
            (V::List(v), Some(T::List(t))) => ExprKind::NEListLit(
399
0
                v.iter().map(|v| v.to_hir(Some(t))).collect::<Result<_>>()?,
400
            ),
401
402
0
            (V::Record(v), None) => ExprKind::RecordLit(
403
0
                v.iter()
404
0
                    .map(|(k, v)| Ok((k.clone().into(), v.to_hir(None)?)))
405
0
                    .collect::<Result<_>>()?,
406
            ),
407
0
            (V::Record(v), Some(T::Record(t))) => ExprKind::RecordLit(
408
0
                v.iter()
409
0
                    .map(|(k, v)| match t.get(k) {
410
0
                        Some(t) => Ok((k.clone().into(), v.to_hir(Some(t))?)),
411
0
                        None => Err(type_error()),
412
0
                    })
413
0
                    .collect::<Result<_>>()?,
414
            ),
415
416
0
            (V::Union(..), None) => return Err(type_missing()),
417
0
            (V::Union(variant, Some(v)), Some(T::Union(t))) => {
418
0
                match t.get(variant) {
419
0
                    Some(Some(variant_t)) => ExprKind::Op(OpKind::App(
420
0
                        hir(ExprKind::Op(OpKind::Field(
421
0
                            ty.unwrap().to_hir(),
422
0
                            variant.clone().into(),
423
0
                        ))),
424
0
                        v.to_hir(Some(variant_t))?,
425
                    )),
426
0
                    _ => return Err(type_error()),
427
                }
428
            }
429
0
            (V::Union(variant, None), Some(T::Union(t))) => {
430
0
                match t.get(variant) {
431
0
                    Some(None) => ExprKind::Op(OpKind::Field(
432
0
                        ty.unwrap().to_hir(),
433
0
                        variant.clone().into(),
434
0
                    )),
435
0
                    _ => return Err(type_error()),
436
                }
437
            }
438
439
0
            (_, Some(_)) => return Err(type_error()),
440
        };
441
0
        Ok(hir(kind))
442
0
    }
443
0
    pub(crate) fn into_value(self, ty: Option<&SimpleType>) -> Result<Value> {
444
        // Check that the value is printable with the given type.
445
0
        self.to_hir(ty)?;
446
0
        Ok(Value {
447
0
            kind: ValueKind::Val(self, ty.cloned()),
448
0
        })
449
0
    }
450
451
    /// Converts back to the corresponding AST expression.
452
0
    pub(crate) fn to_expr(&self, ty: Option<&SimpleType>) -> Result<Expr> {
453
0
        Ctxt::with_new(|cx| {
454
0
            Ok(self.to_hir(ty)?.to_expr(cx, Default::default()))
455
0
        })
456
0
    }
457
}
458
459
#[derive(Debug)]
460
struct NotSimpleType;
461
462
impl SimpleType {
463
0
    fn from_nir(nir: &Nir) -> StdResult<Self, NotSimpleType> {
464
0
        Ok(match nir.kind() {
465
0
            NirKind::BuiltinType(b) => match b {
466
0
                Builtin::Bool => SimpleType::Bool,
467
0
                Builtin::Natural => SimpleType::Natural,
468
0
                Builtin::Integer => SimpleType::Integer,
469
0
                Builtin::Double => SimpleType::Double,
470
0
                Builtin::Text => SimpleType::Text,
471
0
                _ => unreachable!(),
472
            },
473
0
            NirKind::OptionalType(t) => {
474
0
                SimpleType::Optional(Box::new(Self::from_nir(t)?))
475
            }
476
0
            NirKind::ListType(t) => {
477
0
                SimpleType::List(Box::new(Self::from_nir(t)?))
478
            }
479
0
            NirKind::RecordType(kts) => SimpleType::Record(
480
0
                kts.iter()
481
0
                    .map(|(k, v)| Ok((k.into(), Self::from_nir(v)?)))
482
0
                    .collect::<StdResult<_, _>>()?,
483
            ),
484
0
            NirKind::UnionType(kts) => SimpleType::Union(
485
0
                kts.iter()
486
0
                    .map(|(k, v)| {
487
                        Ok((
488
0
                            k.into(),
489
0
                            v.as_ref().map(Self::from_nir).transpose()?,
490
                        ))
491
0
                    })
492
0
                    .collect::<StdResult<_, _>>()?,
493
            ),
494
0
            _ => return Err(NotSimpleType),
495
        })
496
0
    }
497
498
0
    pub(crate) fn to_hir<'cx>(&self) -> Hir<'cx> {
499
0
        let hir = |k| Hir::new(HirKind::Expr(k), Span::Artificial);
500
0
        hir(match self {
501
0
            SimpleType::Bool => ExprKind::Builtin(Builtin::Bool),
502
0
            SimpleType::Natural => ExprKind::Builtin(Builtin::Natural),
503
0
            SimpleType::Integer => ExprKind::Builtin(Builtin::Integer),
504
0
            SimpleType::Double => ExprKind::Builtin(Builtin::Double),
505
0
            SimpleType::Text => ExprKind::Builtin(Builtin::Text),
506
0
            SimpleType::Optional(t) => ExprKind::Op(OpKind::App(
507
0
                hir(ExprKind::Builtin(Builtin::Optional)),
508
0
                t.to_hir(),
509
0
            )),
510
0
            SimpleType::List(t) => ExprKind::Op(OpKind::App(
511
0
                hir(ExprKind::Builtin(Builtin::List)),
512
0
                t.to_hir(),
513
0
            )),
514
0
            SimpleType::Record(kts) => ExprKind::RecordType(
515
0
                kts.iter()
516
0
                    .map(|(k, t)| (k.as_str().into(), t.to_hir()))
517
0
                    .collect(),
518
            ),
519
0
            SimpleType::Union(kts) => ExprKind::UnionType(
520
0
                kts.iter()
521
0
                    .map(|(k, t)| {
522
0
                        (k.as_str().into(), t.as_ref().map(|t| t.to_hir()))
523
0
                    })
524
0
                    .collect(),
525
            ),
526
        })
527
0
    }
528
529
    /// Converts back to the corresponding AST expression.
530
0
    pub(crate) fn to_expr(&self) -> Expr {
531
0
        Ctxt::with_new(|cx| self.to_hir().to_expr(cx, Default::default()))
532
0
    }
533
}
534
535
impl crate::deserialize::Sealed for Value {}
536
impl crate::deserialize::Sealed for SimpleType {}
537
impl crate::serialize::Sealed for Value {}
538
impl crate::serialize::Sealed for SimpleType {}
539
540
impl FromDhall for Value {
541
0
    fn from_dhall(v: &Value) -> Result<Self> {
542
0
        Ok(v.clone())
543
0
    }
544
}
545
impl FromDhall for SimpleType {
546
0
    fn from_dhall(v: &Value) -> Result<Self> {
547
0
        v.to_simple_type().ok_or_else(|| {
548
0
            Error(ErrorKind::Deserialize(format!(
549
0
                "this cannot be deserialized into a simple type: {}",
550
0
                v
551
0
            )))
552
0
        })
553
0
    }
554
}
555
impl ToDhall for Value {
556
0
    fn to_dhall(&self, _ty: Option<&SimpleType>) -> Result<Value> {
557
0
        Ok(self.clone())
558
0
    }
559
}
560
impl ToDhall for SimpleType {
561
0
    fn to_dhall(&self, _ty: Option<&SimpleType>) -> Result<Value> {
562
0
        Ok(Value {
563
0
            kind: ValueKind::Ty(self.clone()),
564
0
        })
565
0
    }
566
}
567
568
impl Eq for ValueKind {}
569
impl PartialEq for ValueKind {
570
0
    fn eq(&self, other: &Self) -> bool {
571
        use ValueKind::*;
572
0
        match (self, other) {
573
0
            (Val(a, _), Val(b, _)) => a == b,
574
0
            (Ty(a), Ty(b)) => a == b,
575
0
            _ => false,
576
        }
577
0
    }
578
}
579
impl std::fmt::Display for Value {
580
0
    fn fmt(
581
0
        &self,
582
0
        f: &mut std::fmt::Formatter,
583
0
    ) -> StdResult<(), std::fmt::Error> {
584
0
        self.to_expr().fmt(f)
585
0
    }
586
}
587
588
impl std::fmt::Display for SimpleType {
589
0
    fn fmt(
590
0
        &self,
591
0
        f: &mut std::fmt::Formatter,
592
0
    ) -> StdResult<(), std::fmt::Error> {
593
0
        self.to_expr().fmt(f)
594
0
    }
595
}
596
597
#[test]
598
fn test_display_simpletype() {
599
    use SimpleType::*;
600
    let ty = List(Box::new(Optional(Box::new(Natural))));
601
    assert_eq!(ty.to_string(), "List (Optional Natural)".to_string())
602
}
603
604
#[test]
605
fn test_display_value() {
606
    use SimpleType::*;
607
    let ty = List(Box::new(Optional(Box::new(Natural))));
608
    let val = SimpleValue::List(vec![]);
609
    let val = Value {
610
        kind: ValueKind::Val(val, Some(ty)),
611
    };
612
    assert_eq!(val.to_string(), "[] : List (Optional Natural)".to_string())
613
}