1use std::fmt::Display;
2
3use crate::{CompareTypes, Type, TypeRelation, TypeSet};
4use serde::{Deserialize, Serialize};
5
6#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, Hash, Ord, PartialOrd)]
7#[serde(transparent)]
8pub struct OneOf {
9 items: Box<[Type]>,
10}
11
12impl OneOf {
13 pub fn add_ty(self, ty: Type) -> Self {
14 let OneOf { items } = self;
15 let mut items = items.into_vec();
16 Self::add_ty_inner(&mut items, ty);
17 Self {
18 items: items.into(),
19 }
20 }
21
22 pub fn iter(&self) -> impl Iterator<Item = &Type> + Clone {
23 self.into_iter()
24 }
25
26 fn add_ty_inner(this: &mut Vec<Type>, mut ty: Type) {
27 if let Type::OneOf(inner) = ty {
29 for sub_t in inner.items {
30 Self::add_ty_inner(this, sub_t);
31 }
32 return;
33 }
34
35 for this_ty in this.iter_mut() {
36 let one = std::mem::replace(this_ty, Type::Any);
37 match Type::flat_widen(one, ty) {
38 Ok(new_wide) => {
39 *this_ty = new_wide;
40 return;
41 }
42 Err((old_one, old_ty)) => {
43 *this_ty = old_one;
44 ty = old_ty;
45 }
46 }
47 }
48
49 this.push(ty);
50 }
51
52 pub fn is_empty(&self) -> bool {
53 self.items.is_empty()
54 }
55}
56
57impl IntoIterator for OneOf {
58 type Item = Type;
59 type IntoIter = std::vec::IntoIter<Type>;
60
61 fn into_iter(self) -> Self::IntoIter {
62 self.items.into_iter()
63 }
64}
65
66impl<'a> IntoIterator for &'a OneOf {
67 type Item = &'a Type;
68 type IntoIter = std::slice::Iter<'a, Type>;
69
70 fn into_iter(self) -> Self::IntoIter {
71 self.items.iter()
72 }
73}
74
75impl FromIterator<Type> for OneOf {
76 fn from_iter<I: IntoIterator<Item = Type>>(iter: I) -> Self {
77 let mut vec = Vec::new();
78 for ty in iter {
79 Self::add_ty_inner(&mut vec, ty);
80 }
81 Self { items: vec.into() }
82 }
83}
84
85impl TypeSet for OneOf {
86 fn union(self, other: Self) -> Self {
87 let OneOf { items: ts } = self;
88 let OneOf { items: us } = other;
89 let (big, small) = match ts.len() >= us.len() {
90 true => (ts, us),
91 false => (us, ts),
92 };
93 let mut out = big.into_vec();
94 for t in small {
95 Self::add_ty_inner(&mut out, t);
96 }
97 Self { items: out.into() }
98 }
99}
100
101impl CompareTypes for OneOf {
102 fn compare_types(&self, other: &Self) -> Option<TypeRelation> {
103 Some(match (self.is_empty(), other.is_empty()) {
104 (true, true) => TypeRelation::Equal,
105 (true, false) => TypeRelation::Subtype,
106 (false, true) => TypeRelation::Supertype,
107 (false, false) => match (self.is_subtype_of(other), self.is_supertype_of(other)) {
108 (true, true) => TypeRelation::Equal,
109 (true, false) => TypeRelation::Subtype,
110 (false, true) => TypeRelation::Supertype,
111 (false, false) => return None,
112 },
113 })
114 }
115
116 fn is_subtype_of(&self, other: &Self) -> bool {
117 match (self.is_empty(), other.is_empty()) {
118 (true, _) => true,
119 (_, true) => false,
120 _ => self.iter().all(|ty| ty.is_subtype_of(other)),
121 }
122 }
123
124 fn is_supertype_of(&self, other: &Self) -> bool {
125 other.is_subtype_of(self)
126 }
127
128 fn is_assignable_to(&self, dst: &Self) -> bool {
129 let dst_tys = dst;
130 let src_tys = self;
131 match (dst_tys.is_empty(), src_tys.is_empty()) {
132 (_, true) => true,
133 (true, _) => false,
134 _ => src_tys
135 .iter()
136 .any(|src_ty| dst_tys.iter().any(|dst_ty| src_ty.is_assignable_to(dst_ty))),
137 }
138 }
139}
140
141impl CompareTypes<Type> for OneOf {
142 fn compare_types(&self, other: &Type) -> Option<TypeRelation> {
143 Some(match other {
144 Type::OneOf(other) => return self.compare_types(other),
145 Type::Any => TypeRelation::Subtype,
146 _ if self.is_empty() => TypeRelation::Subtype,
148 _ => match (self.is_subtype_of(other), self.is_supertype_of(other)) {
149 (true, true) => TypeRelation::Equal,
150 (true, false) => TypeRelation::Subtype,
151 (false, true) => TypeRelation::Supertype,
152 (false, false) => return None,
153 },
154 })
155 }
156
157 fn is_subtype_of(&self, other: &Type) -> bool {
158 let sub_tys = self;
159 let super_ty = other;
160 sub_tys.iter().all(|sub_ty| sub_ty.is_subtype_of(super_ty))
161 }
162
163 fn is_supertype_of(&self, other: &Type) -> bool {
164 let super_tys = self;
165 let sub_ty = other;
166 super_tys
167 .iter()
168 .any(|super_ty| super_ty.is_supertype_of(sub_ty))
169 }
170
171 fn is_assignable_to(&self, dst: &Type) -> bool {
172 let src = self;
173
174 if src.is_empty() {
175 true
176 } else {
177 src.iter().any(|src_ty| src_ty.is_assignable_to(dst))
178 }
179 }
180}
181
182impl CompareTypes<OneOf> for Type {
183 fn compare_types(&self, other: &OneOf) -> Option<TypeRelation> {
184 Some(
185 match (self.is_subtype_of(other), self.is_supertype_of(other)) {
186 (true, true) => TypeRelation::Equal,
187 (true, false) => TypeRelation::Subtype,
188 (false, true) => TypeRelation::Supertype,
189 (false, false) => return None,
190 },
191 )
192 }
193
194 fn is_subtype_of(&self, other: &OneOf) -> bool {
195 other.is_supertype_of(self)
196 }
197
198 fn is_supertype_of(&self, other: &OneOf) -> bool {
199 other.is_subtype_of(self)
200 }
201
202 fn is_assignable_to(&self, dst: &OneOf) -> bool {
203 let src = self;
204 dst.iter().any(|dst_ty| src.is_assignable_to(dst_ty))
205 }
206}
207
208impl Display for OneOf {
209 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
210 let types = self.items.as_ref();
211 write!(f, "oneof")?;
212 let [first, rest @ ..] = types else {
213 return Ok(());
214 };
215 write!(f, "<{first}")?;
216 for t in rest {
217 write!(f, ", {t}")?;
218 }
219 f.write_str(">")
220 }
221}