1use alloc::borrow::{Cow, ToOwned};
2use alloc::collections::BTreeMap;
3use alloc::vec::Vec;
4use core::fmt::{Debug, Formatter};
5
6use half::f16;
7use num_bigint::{BigInt, BigUint};
8
9use crate::cowstr::CowStr;
10use crate::{DecodeError, ESExprCodec, ESExprEncodedEq, ESExprTag, ESExprTagSet};
11
12#[derive(Debug, Clone)]
15pub enum ESExpr<'a> {
16 Constructor(ESExprConstructor<'a>),
19
20 Bool(bool),
22
23 Int(Cow<'a, BigInt>),
25
26 Str(CowStr<'a>),
28
29 Float16(f16),
31
32 Float32(f32),
34
35 Float64(f64),
37
38 Array8(Cow<'a, [u8]>),
40
41 Array16(Cow<'a, [u16]>),
43
44 Array32(Cow<'a, [u32]>),
46
47 Array64(Cow<'a, [u64]>),
49
50 Array128(Cow<'a, [u128]>),
52
53 Null(Cow<'a, BigUint>),
55}
56
57impl<'a> ESExpr<'a> {
58 pub fn constructor<'b, S: Into<CowStr<'b>>, A: Into<ConstructorArgs<'a>>, K: Into<KeywordArgs<'a>>>(
60 name: S,
61 args: A,
62 kwargs: K,
63 ) -> Self
64 where
65 'b: 'a,
66 {
67 ESExpr::Constructor(ESExprConstructor {
68 name: name.into(),
69 args: args.into(),
70 kwargs: kwargs.into(),
71 })
72 }
73
74 #[must_use]
76 pub fn tag<'b>(&'b self) -> ESExprTag<'b> {
77 match self {
78 ESExpr::Constructor(ESExprConstructor { name, .. }) => ESExprTag::Constructor(name.as_borrowed()),
79 ESExpr::Bool(_) => ESExprTag::Bool,
80 ESExpr::Int(_) => ESExprTag::Int,
81 ESExpr::Str(_) => ESExprTag::Str,
82 ESExpr::Float16(_) => ESExprTag::Float16,
83 ESExpr::Float32(_) => ESExprTag::Float32,
84 ESExpr::Float64(_) => ESExprTag::Float64,
85 ESExpr::Array8(_) => ESExprTag::Array8,
86 ESExpr::Array16(_) => ESExprTag::Array16,
87 ESExpr::Array32(_) => ESExprTag::Array32,
88 ESExpr::Array64(_) => ESExprTag::Array64,
89 ESExpr::Array128(_) => ESExprTag::Array128,
90 ESExpr::Null(_) => ESExprTag::Null,
91 }
92 }
93
94 #[must_use]
96 pub fn as_owned(&self) -> ESExpr<'static> {
97 match self {
98 ESExpr::Constructor(constructor) => ESExpr::Constructor(constructor.as_owned()),
99 &ESExpr::Bool(b) => ESExpr::Bool(b),
100 ESExpr::Int(i) => ESExpr::Int(Cow::Owned(i.as_ref().clone())),
101 ESExpr::Str(s) => ESExpr::Str(s.as_owned_cowstr()),
102 &ESExpr::Float16(f) => ESExpr::Float16(f),
103 &ESExpr::Float32(f) => ESExpr::Float32(f),
104 &ESExpr::Float64(f) => ESExpr::Float64(f),
105 ESExpr::Array8(b) => ESExpr::Array8(Cow::Owned(b.as_ref().to_owned())),
106 ESExpr::Array16(b) => ESExpr::Array16(Cow::Owned(b.as_ref().to_owned())),
107 ESExpr::Array32(b) => ESExpr::Array32(Cow::Owned(b.as_ref().to_owned())),
108 ESExpr::Array64(b) => ESExpr::Array64(Cow::Owned(b.as_ref().to_owned())),
109 ESExpr::Array128(b) => ESExpr::Array128(Cow::Owned(b.as_ref().to_owned())),
110 ESExpr::Null(level) => ESExpr::Null(Cow::Owned(level.as_ref().clone())),
111 }
112 }
113
114 #[must_use]
116 pub fn into_owned(self) -> ESExpr<'static> {
117 match self {
118 ESExpr::Constructor(constructor) => ESExpr::Constructor(constructor.into_owned()),
119 ESExpr::Bool(b) => ESExpr::Bool(b),
120 ESExpr::Int(i) => ESExpr::Int(Cow::Owned(i.into_owned())),
121 ESExpr::Str(s) => ESExpr::Str(s.into_owned_cowstr()),
122 ESExpr::Float16(f) => ESExpr::Float16(f),
123 ESExpr::Float32(f) => ESExpr::Float32(f),
124 ESExpr::Float64(f) => ESExpr::Float64(f),
125 ESExpr::Array8(b) => ESExpr::Array8(Cow::Owned(b.into_owned())),
126 ESExpr::Array16(b) => ESExpr::Array16(Cow::Owned(b.into_owned())),
127 ESExpr::Array32(b) => ESExpr::Array32(Cow::Owned(b.into_owned())),
128 ESExpr::Array64(b) => ESExpr::Array64(Cow::Owned(b.into_owned())),
129 ESExpr::Array128(b) => ESExpr::Array128(Cow::Owned(b.into_owned())),
130 ESExpr::Null(level) => ESExpr::Null(Cow::Owned(level.into_owned())),
131 }
132 }
133
134 #[must_use]
136 pub fn as_borrowed<'b>(&'b self) -> ESExpr<'b>
137 where
138 'a: 'b,
139 {
140 match self {
141 ESExpr::Constructor(constructor) => ESExpr::Constructor(constructor.as_borrowed()),
142 &ESExpr::Bool(b) => ESExpr::Bool(b),
143 ESExpr::Int(i) => ESExpr::Int(Cow::Borrowed(i.as_ref())),
144 ESExpr::Str(s) => ESExpr::Str(s.as_borrowed()),
145 &ESExpr::Float16(f) => ESExpr::Float16(f),
146 &ESExpr::Float32(f) => ESExpr::Float32(f),
147 &ESExpr::Float64(f) => ESExpr::Float64(f),
148 ESExpr::Array8(b) => ESExpr::Array8(Cow::Borrowed(b.as_ref())),
149 ESExpr::Array16(b) => ESExpr::Array16(Cow::Borrowed(b.as_ref())),
150 ESExpr::Array32(b) => ESExpr::Array32(Cow::Borrowed(b.as_ref())),
151 ESExpr::Array64(b) => ESExpr::Array64(Cow::Borrowed(b.as_ref())),
152 ESExpr::Array128(b) => ESExpr::Array128(Cow::Borrowed(b.as_ref())),
153 ESExpr::Null(level) => ESExpr::Null(Cow::Borrowed(level.as_ref())),
154 }
155 }
156}
157
158impl<'a, 'b> PartialEq<ESExpr<'b>> for ESExpr<'a> {
159 fn eq(&self, other: &ESExpr<'b>) -> bool {
160 match self {
161 ESExpr::Constructor(ESExprConstructor {
162 name: name1,
163 args: args1,
164 kwargs: kwargs1,
165 }) => {
166 let ESExpr::Constructor(ESExprConstructor {
167 name: name2,
168 args: args2,
169 kwargs: kwargs2,
170 }) = other
171 else {
172 return false;
173 };
174
175 name1 == name2 &&
176 args1 == args2 && kwargs1
177 .iter()
178 .zip(kwargs2.iter())
179 .all(|((k1, v1), (k2, v2))| k1 == k2 && v1 == v2)
180 },
181 &ESExpr::Bool(b1) => matches!(other, &ESExpr::Bool(b2) if b1 == b2),
182 ESExpr::Int(i1) => matches!(other, ESExpr::Int(i2) if i1 == i2),
183 ESExpr::Str(s1) => matches!(other, ESExpr::Str(s2) if s1 == s2),
184 &ESExpr::Float16(f1) => matches!(other, &ESExpr::Float16(f2) if f1.to_bits() == f2.to_bits()),
185 &ESExpr::Float32(f1) => matches!(other, &ESExpr::Float32(f2) if f1.to_bits() == f2.to_bits()),
186 &ESExpr::Float64(f1) => matches!(other, &ESExpr::Float64(f2) if f1.to_bits() == f2.to_bits()),
187 ESExpr::Array8(a1) => matches!(other, ESExpr::Array8(a2) if a1 == a2),
188 ESExpr::Array16(a1) => matches!(other, ESExpr::Array16(a2) if a1 == a2),
189 ESExpr::Array32(a1) => matches!(other, ESExpr::Array32(a2) if a1 == a2),
190 ESExpr::Array64(a1) => matches!(other, ESExpr::Array64(a2) if a1 == a2),
191 ESExpr::Array128(a1) => matches!(other, ESExpr::Array128(a2) if a1 == a2),
192 ESExpr::Null(l1) => matches!(other, ESExpr::Null(l2) if l1 == l2),
193 }
194 }
195}
196
197impl<'a> Eq for ESExpr<'a> {}
198
199impl<'a> ESExprEncodedEq for ESExpr<'a> {
200 fn is_encoded_eq(&self, other: &Self) -> bool {
201 self == other
202 }
203}
204
205
206impl<'a> ESExprCodec<'a> for ESExpr<'a> {
207 const TAGS: ESExprTagSet = ESExprTagSet::All;
208
209 fn encode_esexpr(&'a self) -> ESExpr<'a> {
210 self.as_borrowed()
211 }
212
213 fn decode_esexpr(expr: ESExpr<'a>) -> Result<Self, DecodeError> {
214 Ok(expr)
215 }
216}
217
218#[derive(Debug, Clone, PartialEq, Eq)]
220pub struct ESExprStatic(ESExpr<'static>);
221
222impl ESExprStatic {
223 pub fn new(e: ESExpr<'static>) -> Self {
225 ESExprStatic(e)
226 }
227
228 pub fn into_inner(self) -> ESExpr<'static> {
230 self.0
231 }
232}
233
234impl ESExprEncodedEq for ESExprStatic {
235 fn is_encoded_eq(&self, other: &Self) -> bool {
236 self == other
237 }
238}
239
240impl<'a> ESExprCodec<'a> for ESExprStatic {
241 const TAGS: ESExprTagSet = ESExprTagSet::All;
242
243 fn encode_esexpr(&'a self) -> ESExpr<'a> {
244 self.0.as_borrowed()
245 }
246
247 fn decode_esexpr(expr: ESExpr<'a>) -> Result<Self, DecodeError> {
248 Ok(ESExprStatic(expr.into_owned()))
249 }
250}
251
252#[derive(Debug, Clone, PartialEq, Eq)]
254pub struct ESExprConstructor<'a> {
255 pub name: CowStr<'a>,
257
258 pub args: ConstructorArgs<'a>,
260
261 pub kwargs: KeywordArgs<'a>,
263}
264
265impl<'a> ESExprConstructor<'a> {
266 fn into_owned(self) -> ESExprConstructor<'static> {
267 ESExprConstructor {
268 name: self.name.as_owned_cowstr(),
269 args: self.args.into_owned(),
270 kwargs: self.kwargs.into_owned(),
271 }
272 }
273
274 fn as_owned(&self) -> ESExprConstructor<'static> {
275 ESExprConstructor {
276 name: self.name.as_owned_cowstr(),
277 args: self.args.as_owned(),
278 kwargs: self.kwargs.as_owned(),
279 }
280 }
281
282 fn as_borrowed<'b>(&'b self) -> ESExprConstructor<'b> {
283 ESExprConstructor {
284 name: self.name.as_borrowed(),
285 args: self.args.as_borrowed(),
286 kwargs: self.kwargs.as_borrowed(),
287 }
288 }
289}
290
291#[derive(Debug, Clone, PartialEq, Eq)]
293pub struct ConstructorArgs<'a> {
294 args: ConstructorArgsInner<'a>,
295}
296
297impl<'a> ConstructorArgs<'a> {
298 pub fn iter(&'a self) -> ConstructorArgsIntoIter<'a> {
300 self.as_borrowed().into_iter()
301 }
302
303 #[must_use]
305 pub fn len(&self) -> usize {
306 self.args.as_slice().len()
307 }
308
309 #[must_use]
311 pub fn is_empty(&self) -> bool {
312 self.args.as_slice().is_empty()
313 }
314
315 fn into_owned(self) -> ConstructorArgs<'static> {
316 ConstructorArgs {
317 args: ConstructorArgsInner::Owned(self.into_iter().map(ESExpr::into_owned).collect()),
318 }
319 }
320
321 fn as_owned(&self) -> ConstructorArgs<'static> {
322 ConstructorArgs {
323 args: ConstructorArgsInner::Owned(self.into_iter().map(ESExpr::into_owned).collect()),
324 }
325 }
326
327 fn as_borrowed(&self) -> ConstructorArgs {
328 ConstructorArgs {
329 args: match &self.args {
330 ConstructorArgsInner::Owned(args) => ConstructorArgsInner::Borrowed(args),
331 ConstructorArgsInner::Borrowed(args) => ConstructorArgsInner::Borrowed(args),
332 },
333 }
334 }
335}
336
337impl<'a> From<Vec<ESExpr<'a>>> for ConstructorArgs<'a> {
338 fn from(args: Vec<ESExpr<'a>>) -> Self {
339 ConstructorArgs {
340 args: ConstructorArgsInner::Owned(args),
341 }
342 }
343}
344
345impl<'a> From<&'a [ESExpr<'a>]> for ConstructorArgs<'a> {
346 fn from(args: &'a [ESExpr<'a>]) -> Self {
347 ConstructorArgs {
348 args: ConstructorArgsInner::Borrowed(args),
349 }
350 }
351}
352
353impl<'a, const N: usize> From<[ESExpr<'a>; N]> for ConstructorArgs<'a> {
354 fn from(args: [ESExpr<'a>; N]) -> Self {
355 ConstructorArgs {
356 args: ConstructorArgsInner::Owned(args.to_vec()),
357 }
358 }
359}
360
361impl<'a> From<ConstructorArgs<'a>> for Vec<ESExpr<'a>> {
362 fn from(args: ConstructorArgs<'a>) -> Self {
363 match args.args {
364 ConstructorArgsInner::Owned(args) => args,
365 ConstructorArgsInner::Borrowed(args) => args.iter().map(ESExpr::as_borrowed).collect(),
366 }
367 }
368}
369
370impl<'a> IntoIterator for ConstructorArgs<'a> {
371 type Item = ESExpr<'a>;
372 type IntoIter = ConstructorArgsIntoIter<'a>;
373
374 fn into_iter(self) -> Self::IntoIter {
375 ConstructorArgsIntoIter {
376 inner_iter: match self.args {
377 ConstructorArgsInner::Owned(args) => ConstructorArgsInnerIntoIter::Owned(args.into_iter()),
378 ConstructorArgsInner::Borrowed(args) => ConstructorArgsInnerIntoIter::Borrowed(args.iter()),
379 },
380 }
381 }
382}
383
384impl<'a> IntoIterator for &'a ConstructorArgs<'a> {
385 type Item = ESExpr<'a>;
386 type IntoIter = ConstructorArgsIntoIter<'a>;
387
388 fn into_iter(self) -> Self::IntoIter {
389 self.as_borrowed().into_iter()
390 }
391}
392
393#[derive(Clone)]
396enum ConstructorArgsInner<'a> {
397 Owned(Vec<ESExpr<'a>>),
399
400 Borrowed(&'a [ESExpr<'a>]),
402}
403
404impl<'a> ConstructorArgsInner<'a> {
405 fn as_slice(&self) -> &[ESExpr<'a>] {
406 match self {
407 ConstructorArgsInner::Owned(args) => args,
408 ConstructorArgsInner::Borrowed(args) => args,
409 }
410 }
411}
412
413impl<'a> Debug for ConstructorArgsInner<'a> {
414 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
415 self.as_slice().fmt(f)
416 }
417}
418
419impl<'a> PartialEq for ConstructorArgsInner<'a> {
420 fn eq(&self, other: &Self) -> bool {
421 self.as_slice() == other.as_slice()
422 }
423}
424
425impl<'a> Eq for ConstructorArgsInner<'a> {}
426
427#[must_use]
428pub struct ConstructorArgsIntoIter<'a> {
429 inner_iter: ConstructorArgsInnerIntoIter<'a>,
430}
431
432impl<'a> Iterator for ConstructorArgsIntoIter<'a> {
433 type Item = ESExpr<'a>;
434
435 fn next(&mut self) -> Option<Self::Item> {
436 self.inner_iter.next()
437 }
438}
439
440enum ConstructorArgsInnerIntoIter<'a> {
441 Owned(alloc::vec::IntoIter<ESExpr<'a>>),
442 Borrowed(alloc::slice::Iter<'a, ESExpr<'a>>),
443}
444
445impl<'a> Iterator for ConstructorArgsInnerIntoIter<'a> {
446 type Item = ESExpr<'a>;
447
448 fn next(&mut self) -> Option<Self::Item> {
449 match self {
450 ConstructorArgsInnerIntoIter::Owned(iter) => iter.next(),
451 ConstructorArgsInnerIntoIter::Borrowed(iter) => iter.next().map(ESExpr::as_borrowed),
452 }
453 }
454}
455
456#[derive(Clone, Debug, PartialEq, Eq)]
458pub struct KeywordArgs<'a> {
459 kwargs: KeywordArgsInner<'a>,
460}
461
462impl<'a> KeywordArgs<'a> {
463 pub fn iter(&'a self) -> KeywordArgsIntoIter<'a> {
465 self.into_iter()
466 }
467
468 #[must_use]
470 pub fn len(&self) -> usize {
471 self.kwargs.as_map().len()
472 }
473
474 #[must_use]
476 pub fn is_empty(&self) -> bool {
477 self.kwargs.as_map().is_empty()
478 }
479
480 fn into_owned(self) -> KeywordArgs<'static> {
481 KeywordArgs {
482 kwargs: KeywordArgsInner::Owned(
483 self.into_iter()
484 .map(|(k, v)| (k.into_owned_cowstr(), v.into_owned()))
485 .collect(),
486 ),
487 }
488 }
489
490 fn as_owned(&self) -> KeywordArgs<'static> {
491 KeywordArgs {
492 kwargs: KeywordArgsInner::Owned(
493 self.iter()
494 .map(|(k, v)| (k.into_owned_cowstr(), v.into_owned()))
495 .collect(),
496 ),
497 }
498 }
499
500 fn as_borrowed(&self) -> KeywordArgs {
501 KeywordArgs {
502 kwargs: match &self.kwargs {
503 KeywordArgsInner::Owned(kwargs) => KeywordArgsInner::Borrowed(kwargs),
504 KeywordArgsInner::Borrowed(kwargs) => KeywordArgsInner::Borrowed(kwargs),
505 },
506 }
507 }
508}
509
510impl<'a> From<BTreeMap<CowStr<'a>, ESExpr<'a>>> for KeywordArgs<'a> {
511 fn from(kwargs: BTreeMap<CowStr<'a>, ESExpr<'a>>) -> Self {
512 KeywordArgs {
513 kwargs: KeywordArgsInner::Owned(kwargs),
514 }
515 }
516}
517
518impl<'a> From<&'a BTreeMap<CowStr<'a>, ESExpr<'a>>> for KeywordArgs<'a> {
519 fn from(kwargs: &'a BTreeMap<CowStr<'a>, ESExpr<'a>>) -> Self {
520 KeywordArgs {
521 kwargs: KeywordArgsInner::Borrowed(kwargs),
522 }
523 }
524}
525
526impl<'a, const N: usize> From<[(CowStr<'a>, ESExpr<'a>); N]> for KeywordArgs<'a> {
527 fn from(value: [(CowStr<'a>, ESExpr<'a>); N]) -> Self {
528 KeywordArgs {
529 kwargs: KeywordArgsInner::Owned(BTreeMap::from(value)),
530 }
531 }
532}
533
534impl<'a> From<KeywordArgs<'a>> for BTreeMap<CowStr<'a>, ESExpr<'a>> {
535 fn from(kwargs: KeywordArgs<'a>) -> Self {
536 match kwargs.kwargs {
537 KeywordArgsInner::Owned(kwargs) => kwargs,
538 KeywordArgsInner::Borrowed(kwargs) => {
539 kwargs.iter().map(|(k, v)| (k.as_owned_cowstr(), v.clone())).collect()
540 },
541 }
542 }
543}
544
545impl<'a> IntoIterator for KeywordArgs<'a> {
546 type Item = (CowStr<'a>, ESExpr<'a>);
547 type IntoIter = KeywordArgsIntoIter<'a>;
548
549 fn into_iter(self) -> Self::IntoIter {
550 KeywordArgsIntoIter {
551 inner_iter: match self.kwargs {
552 KeywordArgsInner::Owned(kwargs) => KeywordArgsInnerIntoIter::Owned(kwargs.into_iter()),
553 KeywordArgsInner::Borrowed(kwargs) => KeywordArgsInnerIntoIter::Borrowed(kwargs.iter()),
554 },
555 }
556 }
557}
558
559impl<'a> IntoIterator for &'a KeywordArgs<'a> {
560 type Item = (CowStr<'a>, ESExpr<'a>);
561 type IntoIter = KeywordArgsIntoIter<'a>;
562
563 fn into_iter(self) -> Self::IntoIter {
564 self.as_borrowed().into_iter()
565 }
566}
567
568#[derive(Clone)]
569pub enum KeywordArgsInner<'a> {
570 Owned(BTreeMap<CowStr<'a>, ESExpr<'a>>),
571 Borrowed(&'a BTreeMap<CowStr<'a>, ESExpr<'a>>),
572}
573
574impl<'a> KeywordArgsInner<'a> {
575 fn as_map(&self) -> &BTreeMap<CowStr<'a>, ESExpr<'a>> {
576 match self {
577 KeywordArgsInner::Owned(kwargs) => kwargs,
578 KeywordArgsInner::Borrowed(kwargs) => kwargs,
579 }
580 }
581}
582
583impl<'a> Debug for KeywordArgsInner<'a> {
584 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
585 self.as_map().fmt(f)
586 }
587}
588
589impl<'a> PartialEq for KeywordArgsInner<'a> {
590 fn eq(&self, other: &Self) -> bool {
591 self.as_map() == other.as_map()
592 }
593}
594
595impl<'a> Eq for KeywordArgsInner<'a> {}
596
597#[must_use]
598pub struct KeywordArgsIntoIter<'a> {
599 inner_iter: KeywordArgsInnerIntoIter<'a>,
600}
601
602impl<'a> Iterator for KeywordArgsIntoIter<'a> {
603 type Item = (CowStr<'a>, ESExpr<'a>);
604
605 fn next(&mut self) -> Option<Self::Item> {
606 self.inner_iter.next()
607 }
608}
609
610enum KeywordArgsInnerIntoIter<'a> {
611 Owned(alloc::collections::btree_map::IntoIter<CowStr<'a>, ESExpr<'a>>),
612 Borrowed(alloc::collections::btree_map::Iter<'a, CowStr<'a>, ESExpr<'a>>),
613}
614
615impl<'a> Iterator for KeywordArgsInnerIntoIter<'a> {
616 type Item = (CowStr<'a>, ESExpr<'a>);
617
618 fn next(&mut self) -> Option<Self::Item> {
619 match self {
620 KeywordArgsInnerIntoIter::Owned(iter) => iter.next(),
621 KeywordArgsInnerIntoIter::Borrowed(iter) => {
622 iter.next().map(|(k, v)| (k.as_borrowed(), ESExpr::as_borrowed(v)))
623 },
624 }
625 }
626}