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
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
use crate::types::{Array, Str};
use crate::value::{FromValue, ToValue, Value};

macro_rules! value_i {
    ($t:ty) => {
        impl ToValue for $t {
            fn to_value(&self) -> $crate::Value {
                $crate::Value::i64(self.clone() as i64)
            }
        }

        impl FromValue for $t {
            fn from_value(v: $crate::Value) -> $t {
                v.i64_val() as $t
            }
        }
    };
    ($($t:ty),*) => {
        $(value_i!($t);)*
    }
}

macro_rules! value_f {
    ($t:ty) => {
        impl ToValue for $t {
            fn to_value(&self) -> $crate::Value {
                $crate::Value::f64(self.clone().into())
            }
        }

        impl FromValue for $t {
            fn from_value(v: $crate::Value) -> $t {
                v.f64_val() as $t
            }
        }
    };
    ($($t:ty),*) => {
        $(value_f!($t);)*
    }
}

value_i!(i8, u8, i16, u16, i32, u32, i64, u64, isize, usize);
value_f!(f32, f64);

impl ToValue for bool {
    fn to_value(&self) -> Value {
        Value::i64(*self as i64)
    }
}

impl FromValue for bool {
    fn from_value(v: Value) -> bool {
        v.i64_val() != 0
    }
}

impl ToValue for String {
    fn to_value(&self) -> Value {
        let s = Str::from(self.as_str());
        Value::from(s)
    }
}

impl FromValue for String {
    fn from_value(v: Value) -> String {
        let s = Str::from(v);
        String::from(s.as_str())
    }
}

impl ToValue for () {
    fn to_value(&self) -> Value {
        Value::unit()
    }
}

impl FromValue for &str {
    fn from_value(value: Value) -> Self {
        let len = unsafe { crate::core::mlvalues::caml_string_length(value.0) };
        let ptr = string_val!(value.0) as *mut u8;
        unsafe {
            let slice = ::std::slice::from_raw_parts_mut(ptr, len);
            ::std::str::from_utf8_unchecked_mut(slice)
        }
    }
}

impl ToValue for &str {
    fn to_value(&self) -> Value {
        let s = Str::from(*self);
        Value::from(s)
    }
}

impl<V: ToValue> ToValue for Vec<V> {
    fn to_value(&self) -> Value {
        let tmp: Vec<Value> = self.iter().map(|x| x.to_value()).collect();
        crate::array!(_ tmp).into()
    }
}

impl<V: FromValue> FromValue for Vec<V> {
    fn from_value(v: Value) -> Vec<V> {
        let arr = Array::from(v);
        let mut dst = Vec::with_capacity(arr.len());
        for i in 0..arr.len() {
            dst.push(V::from_value(arr.get(i).unwrap()))
        }
        dst
    }
}