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
150
151
152
153
154
155
156
157
pub mod algebraic_type;
pub mod builtin_type;
pub mod builtin_value;
pub mod convert;
pub mod product_type;
pub mod product_type_element;
pub mod product_value;
pub mod relation;
pub mod sum_type;
pub mod sum_type_variant;
pub mod sum_value;
pub mod typespace;
// mod algebraic_type_legacy_encoding;
mod algebraic_type_ref;
pub mod algebraic_value;
pub mod bsatn;
pub mod buffer;
pub mod de;
mod resolve_refs;
pub mod satn;
pub mod ser;

pub use algebraic_type::AlgebraicType;
pub use algebraic_type_ref::AlgebraicTypeRef;
pub use algebraic_value::AlgebraicValue;
pub use builtin_type::{ArrayType, BuiltinType, MapType};
pub use builtin_value::{ArrayValue, BuiltinValue, MapValue};
pub use product_type::ProductType;
pub use product_type_element::ProductTypeElement;
pub use product_value::ProductValue;
pub use sum_type::SumType;
pub use sum_type_variant::SumTypeVariant;
pub use sum_value::SumValue;
pub use typespace::{SpacetimeType, Typespace};

pub trait Value {
    type Type;
}

impl<T: Value> Value for Vec<T> {
    type Type = T::Type;
}

pub struct ValueWithType<'a, T: Value> {
    ty: TypeInSpace<'a, T::Type>,
    val: &'a T,
}

impl<T: Value> Copy for ValueWithType<'_, T> {}
impl<T: Value> Clone for ValueWithType<'_, T> {
    fn clone(&self) -> Self {
        *self
    }
}

impl<'a, T: Value> ValueWithType<'a, T> {
    pub fn new(ty: TypeInSpace<'a, T::Type>, val: &'a T) -> Self {
        Self { ty, val }
    }
    pub fn value(&self) -> &'a T {
        self.val
    }
    pub fn ty(&self) -> &'a T::Type {
        self.ty.ty
    }
    pub fn typespace(&self) -> &'a Typespace {
        self.ty.typespace
    }
    pub fn with<'b, U: Value>(&self, ty: &'b U::Type, val: &'b U) -> ValueWithType<'b, U>
    where
        'a: 'b,
    {
        ValueWithType {
            ty: self.ty.with(ty),
            val,
        }
    }
}

impl<'a, T: Value> ValueWithType<'a, Vec<T>> {
    pub fn iter(&self) -> impl Iterator<Item = ValueWithType<'_, T>> {
        self.value().iter().map(|val| ValueWithType { ty: self.ty, val })
    }
}

#[derive(Debug)]
pub struct TypeInSpace<'a, T: ?Sized> {
    typespace: &'a Typespace,
    ty: &'a T,
}

impl<T: ?Sized> Copy for TypeInSpace<'_, T> {}
impl<T: ?Sized> Clone for TypeInSpace<'_, T> {
    fn clone(&self) -> Self {
        *self
    }
}

impl<'a, T: ?Sized> TypeInSpace<'a, T> {
    pub fn new(typespace: &'a Typespace, ty: &'a T) -> Self {
        Self { typespace, ty }
    }

    pub fn ty(&self) -> &'a T {
        self.ty
    }

    pub fn typespace(&self) -> &'a Typespace {
        self.typespace
    }

    pub fn with<'b, U>(&self, ty: &'b U) -> TypeInSpace<'b, U>
    where
        'a: 'b,
    {
        TypeInSpace {
            typespace: self.typespace,
            ty,
        }
    }

    pub fn with_value<'b, V: Value<Type = T>>(&self, val: &'b V) -> ValueWithType<'b, V>
    where
        'a: 'b,
    {
        ValueWithType::new(*self, val)
    }

    pub fn resolve(&self, r: AlgebraicTypeRef) -> TypeInSpace<'a, AlgebraicType> {
        TypeInSpace {
            typespace: self.typespace,
            ty: &self.typespace[r],
        }
    }

    pub fn map<U: ?Sized>(&self, f: impl FnOnce(&'a T) -> &'a U) -> TypeInSpace<'a, U> {
        TypeInSpace {
            typespace: self.typespace,
            ty: f(self.ty),
        }
    }
}

struct FDisplay<F>(F);
impl<F: Fn(&mut std::fmt::Formatter) -> std::fmt::Result> std::fmt::Display for FDisplay<F> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self.0)(f)
    }
}
impl<F: Fn(&mut std::fmt::Formatter) -> std::fmt::Result> std::fmt::Debug for FDisplay<F> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        (self.0)(f)
    }
}
fn fmt_fn<F: Fn(&mut std::fmt::Formatter) -> std::fmt::Result>(f: F) -> FDisplay<F> {
    FDisplay(f)
}