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
use super::Value;
use downcast_rs::Downcast;

#[typetag::serde(tag = "StackVmObject")]
pub trait StackVmObject:
    StackVmObjectClone + std::fmt::Debug + std::fmt::Display + Downcast
{
    fn add(&self, r: Value) -> Result<Value, String>;
}
downcast_rs::impl_downcast!(StackVmObject);

pub trait StackVmObjectClone {
    fn clone_box(&self) -> Box<dyn StackVmObject>;
}

impl<T> StackVmObjectClone for T
where
    T: 'static + StackVmObject + Clone,
{
    fn clone_box(&self) -> Box<dyn StackVmObject> {
        Box::new(self.clone())
    }
}

impl Clone for Box<dyn StackVmObject> {
    fn clone(&self) -> Box<dyn StackVmObject> {
        self.clone_box()
    }
}

#[typetag::serde]
impl StackVmObject for String {
    fn add(&self, r: Value) -> Result<Value, String> {
        let s: String = match r {
            Value::Object(o) => match o.downcast::<String>() {
                Ok(s) => format!("{}{}", self, s),
                Err(_) => return Err(format!("Can only add two strings together",)),
            },
            _ => return Err(format!("Can only add two strings together")),
        };
        Ok(Value::Object(Box::new(s)))
    }
}