summaryrefslogtreecommitdiff
path: root/serde_dhall/src/static_type.rs
blob: bc5f366551eee4f77f5f7a99c5b732afc7343484 (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
use dhall::{STyKind, SimpleType};

use crate::Type;

/// A Rust type that can be represented as a Dhall type.
///
/// A typical example is `Option<bool>`,
/// represented by the dhall expression `Optional Bool`.
///
/// This trait can and should be automatically derived.
///
/// The representation needs to be independent of the value.
/// For this reason, something like `HashMap<String, bool>` cannot implement
/// [StaticType] because each different value would
/// have a different Dhall record type.
pub trait StaticType {
    fn static_type() -> Type;
}

macro_rules! derive_builtin {
    ($rust_ty:ty, $dhall_ty:ident) => {
        impl StaticType for $rust_ty {
            fn static_type() -> Type {
                Type::from_simple_type(SimpleType::new(STyKind::$dhall_ty))
            }
        }
    };
}

derive_builtin!(bool, Bool);
derive_builtin!(usize, Natural);
derive_builtin!(u64, Natural);
derive_builtin!(u32, Natural);
derive_builtin!(isize, Integer);
derive_builtin!(i64, Integer);
derive_builtin!(i32, Integer);
derive_builtin!(f64, Double);
derive_builtin!(f32, Double);
derive_builtin!(String, Text);

impl<A, B> StaticType for (A, B)
where
    A: StaticType,
    B: StaticType,
{
    fn static_type() -> Type {
        Type::make_record_type(
            vec![
                ("_1".to_owned(), A::static_type()),
                ("_2".to_owned(), B::static_type()),
            ]
            .into_iter(),
        )
    }
}

impl<T, E> StaticType for std::result::Result<T, E>
where
    T: StaticType,
    E: StaticType,
{
    fn static_type() -> Type {
        Type::make_union_type(
            vec![
                ("Ok".to_owned(), Some(T::static_type())),
                ("Err".to_owned(), Some(E::static_type())),
            ]
            .into_iter(),
        )
    }
}

impl<T> StaticType for Option<T>
where
    T: StaticType,
{
    fn static_type() -> Type {
        Type::make_optional_type(T::static_type())
    }
}

impl<T> StaticType for Vec<T>
where
    T: StaticType,
{
    fn static_type() -> Type {
        Type::make_list_type(T::static_type())
    }
}

impl<'a, T> StaticType for &'a T
where
    T: StaticType,
{
    fn static_type() -> Type {
        T::static_type()
    }
}