1extern crate alloc;
2
3use alloc::{borrow::ToOwned as _, boxed::Box, collections::BTreeMap, format, string::String};
4use core::fmt::{self, Display};
5
6use aranya_policy_ast::{Ident, Identifier, ResultTypeKind, Span, Text, TypeKind, VType};
7use serde::{Deserialize, Serialize};
8
9#[derive(
11 Debug,
12 Clone,
13 PartialEq,
14 Eq,
15 Serialize,
16 Deserialize,
17 rkyv::Archive,
18 rkyv::Deserialize,
19 rkyv::Serialize,
20)]
21#[rkyv(serialize_bounds(
22 __S: rkyv::ser::Writer + rkyv::ser::Allocator,
23 __S::Error: rkyv::rancor::Source,
24))]
25#[rkyv(deserialize_bounds(__D::Error: rkyv::rancor::Source))]
26#[rkyv(bytecheck(
27 bounds(
28 __C: rkyv::validation::ArchiveContext,
29 __C::Error: rkyv::rancor::Source,
30 )
31))]
32pub enum ConstValue {
33 Int(i64),
35 Bool(bool),
37 String(Text),
39 Struct(#[rkyv(omit_bounds)] ConstStruct),
41 Enum(Identifier, i64),
43 Option(#[rkyv(omit_bounds)] Option<Box<Self>>),
45 Result(#[rkyv(omit_bounds)] Result<Box<Self>, Box<Self>>),
47}
48
49impl ConstValue {
50 pub const NONE: Self = Self::Option(None);
52
53 pub fn vtype(&self) -> TypeKind {
55 match self {
56 Self::Int(_) => TypeKind::Int,
57 Self::Bool(_) => TypeKind::Bool,
58 Self::String(_) => TypeKind::String,
59 Self::Enum(name, _) => TypeKind::Enum(Ident {
60 name: name.to_owned(),
61 span: Span::empty(),
62 }),
63 Self::Struct(s) => TypeKind::Struct(Ident {
64 name: s.name.clone(),
65 span: Span::empty(),
66 }),
67 Self::Option(o) => {
68 let inner_kind = match o {
69 Some(inner_value) => inner_value.vtype(),
70 None => TypeKind::Never,
71 };
72 TypeKind::Optional(Box::new(VType {
73 kind: inner_kind,
74 span: Span::empty(),
75 }))
76 }
77 Self::Result(Ok(ok)) => {
78 let ok_kind = ok.vtype();
79 TypeKind::Result(Box::new(ResultTypeKind {
80 ok: VType {
81 kind: ok_kind,
82 span: Span::empty(),
83 },
84 err: VType {
85 kind: TypeKind::Never,
86 span: Span::empty(),
87 },
88 }))
89 }
90 Self::Result(Err(err)) => {
91 let err_kind = err.vtype();
92 TypeKind::Result(Box::new(ResultTypeKind {
93 ok: VType {
94 kind: TypeKind::Never,
95 span: Span::empty(),
96 },
97 err: VType {
98 kind: err_kind,
99 span: Span::empty(),
100 },
101 }))
102 }
103 }
104 }
105
106 pub fn type_name(&self) -> String {
108 match self {
109 Self::Int(_) => String::from("Int"),
110 Self::Bool(_) => String::from("Bool"),
111 Self::String(_) => String::from("String"),
112 Self::Struct(s) => format!("Struct {}", s.name),
113 Self::Enum(name, _) => format!("Enum {}", name),
114 Self::Option(Some(inner)) => format!("Option[{}]", inner.type_name()),
115 Self::Option(None) => String::from("Option[_]"),
116 Self::Result(Ok(inner)) => format!("Result[_, {}]", inner.type_name()),
117 Self::Result(Err(inner)) => format!("Result[{}, _]", inner.type_name()),
118 }
119 }
120}
121
122impl Display for ConstValue {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 match self {
125 Self::Int(i) => write!(f, "{}", i),
126 Self::Bool(b) => write!(f, "{}", b),
127 Self::String(s) => write!(f, "\"{}\"", s),
128 Self::Struct(s) => s.fmt(f),
129 Self::Enum(name, value) => write!(f, "{name}::{value}"),
130 Self::Option(Some(v)) => write!(f, "Some({v})"),
131 Self::Option(None) => write!(f, "None"),
132 Self::Result(Ok(v)) => write!(f, "Ok({})", v),
133 Self::Result(Err(v)) => write!(f, "Err({})", v),
134 }
135 }
136}
137
138#[derive(
140 Debug,
141 Clone,
142 PartialEq,
143 Eq,
144 Serialize,
145 Deserialize,
146 rkyv::Archive,
147 rkyv::Deserialize,
148 rkyv::Serialize,
149)]
150#[rkyv(serialize_bounds(
151 __S: rkyv::ser::Writer + rkyv::ser::Allocator,
152 __S::Error: rkyv::rancor::Source,
153))]
154#[rkyv(deserialize_bounds(__D::Error: rkyv::rancor::Source))]
155#[rkyv(bytecheck(
156 bounds(
157 __C: rkyv::validation::ArchiveContext,
158 __C::Error: rkyv::rancor::Source,
159 )
160))]
161pub struct ConstStruct {
162 pub name: Identifier,
164 #[rkyv(omit_bounds)]
166 pub fields: BTreeMap<Identifier, ConstValue>,
167}
168
169impl ConstStruct {
170 pub fn empty(name: Identifier) -> Self {
172 Self {
173 name,
174 fields: BTreeMap::new(),
175 }
176 }
177}
178
179impl Display for ConstStruct {
180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181 write!(f, "{}{{", self.name)?;
182 let mut i = false;
183 for (k, v) in &self.fields {
184 if i {
185 write!(f, ", ")?;
186 }
187 i = true;
188 write!(f, "{}: {}", k, v)?;
189 }
190 write!(f, "}}")
191 }
192}