1use std::{collections::VecDeque, fmt::Debug};
2
3use arc_gc::{
4 arc::{GCArc, GCArcWeak},
5 traceable::GCTraceable,
6};
7
8use crate::lambda::runnable::RuntimeError;
9
10use super::object::{OnionObject, OnionObjectCell, OnionStaticObject};
11
12#[derive(Clone)]
13pub struct OnionPair {
14 key: OnionObject, value: OnionObject, }
17
18impl GCTraceable<OnionObjectCell> for OnionPair {
19 fn collect(&self, queue: &mut VecDeque<GCArcWeak<OnionObjectCell>>) {
20 self.key.collect(queue);
21 self.value.collect(queue);
22 }
23}
24
25impl Debug for OnionPair {
26 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27 write!(f, "{:?} : {:?}", self.key, self.value)
28 }
29}
30
31impl OnionPair {
32 pub fn new(key: OnionObject, value: OnionObject) -> Self {
33 OnionPair {
34 key: key.into(),
35 value: value.into(),
36 }
37 }
38
39 pub fn new_static(key: &OnionStaticObject, value: &OnionStaticObject) -> OnionStaticObject {
40 OnionObject::Pair(
41 OnionPair {
42 key: key.weak().clone(),
43 value: value.weak().clone(),
44 }
45 .into(),
46 )
47 .consume_and_stabilize()
48 }
49
50 #[inline(always)]
51 pub fn get_key(&self) -> &OnionObject {
52 &self.key
53 }
54
55 #[inline(always)]
56 pub fn get_value(&self) -> &OnionObject {
57 &self.value
58 }
59
60 pub fn upgrade(&self, collected: &mut Vec<GCArc<OnionObjectCell>>) {
61 self.key.upgrade(collected);
62 self.value.upgrade(collected)
63 }
64}
65
66impl OnionPair {
67 pub fn equals(&self, other: &OnionObject) -> Result<bool, RuntimeError> {
68 match other {
69 OnionObject::Pair(pair) => {
70 if self.key.equals(&pair.key)? && self.value.equals(&pair.value)? {
71 return Ok(true);
72 }
73 }
74 _ => {}
75 }
76 Ok(false)
77 }
78
79 pub fn with_attribute<F, R>(&self, key: &OnionObject, f: &F) -> Result<R, RuntimeError>
80 where
81 F: Fn(&OnionObject) -> Result<R, RuntimeError>,
82 {
83 self.value
84 .with_attribute(key, f)
85 .or_else(|_| self.key.with_attribute(key, f))
86 }
87}
88
89impl OnionPair {
90 pub fn reconstruct_container(&self) -> Result<OnionObject, RuntimeError> {
91 Ok(OnionObject::Pair(
92 OnionPair {
93 key: self.key.clone(),
94 value: self.value.clone(),
95 }
96 .into(),
97 ))
98 }
99}