1use core::convert::TryInto;
2
3use crate::{
4 sys,
5 value::{FromValue, ToValue, Value},
6 Raw, Runtime, Tag,
7};
8
9unsafe impl<T: ToValue> ToValue for &T {
10 fn to_value(&self, rt: &Runtime) -> Value {
11 ToValue::to_value(*self, rt)
12 }
13}
14
15macro_rules! value_i {
16 ($t:ty) => {
17 unsafe impl ToValue for $t {
18 fn to_value(&self, _rt: &Runtime) -> $crate::Value {
19 unsafe { $crate::Value::int(*self as crate::Int) }
20 }
21 }
22
23 unsafe impl FromValue for $t {
24 fn from_value(v: $crate::Value) -> $t {
25 unsafe { v.int_val() as $t }
26 }
27 }
28 };
29 ($($t:ty),*) => {
30 $(value_i!($t);)*
31 }
32}
33
34macro_rules! value_f {
35 ($t:ty) => {
36 unsafe impl ToValue for $t {
37 fn to_value(&self, _rt: &Runtime) -> $crate::Value {
38 unsafe { $crate::Value::double(*self as crate::Float) }
39 }
40 }
41
42 unsafe impl FromValue for $t {
43 fn from_value(v: $crate::Value) -> $t {
44 unsafe { v.double_val () as $t }
45 }
46 }
47 };
48 ($($t:ty),*) => {
49 $(value_f!($t);)*
50 }
51}
52
53value_i!(i8, u8, i16, u16, crate::Int, crate::Uint);
54value_f!(f32, f64);
55
56unsafe impl ToValue for i64 {
57 fn to_value(&self, _rt: &Runtime) -> crate::Value {
58 unsafe { Value::int64(*self) }
59 }
60}
61
62unsafe impl FromValue for i64 {
63 fn from_value(v: Value) -> i64 {
64 unsafe { v.int64_val() }
65 }
66}
67
68unsafe impl ToValue for u64 {
69 fn to_value(&self, _rt: &Runtime) -> crate::Value {
70 unsafe { Value::int64(*self as i64) }
71 }
72}
73
74unsafe impl FromValue for u64 {
75 fn from_value(v: Value) -> u64 {
76 unsafe { v.int64_val() as u64 }
77 }
78}
79
80unsafe impl ToValue for i32 {
81 fn to_value(&self, _rt: &Runtime) -> crate::Value {
82 unsafe { Value::int32(*self) }
83 }
84}
85
86unsafe impl FromValue for i32 {
87 fn from_value(v: Value) -> i32 {
88 unsafe { v.int32_val() }
89 }
90}
91
92unsafe impl ToValue for u32 {
93 fn to_value(&self, _rt: &Runtime) -> crate::Value {
94 unsafe { Value::int32(*self as i32) }
95 }
96}
97
98unsafe impl FromValue for u32 {
99 fn from_value(v: Value) -> u32 {
100 unsafe { v.int32_val() as u32 }
101 }
102}
103
104struct Incr(usize);
105
106impl Incr {
107 fn get(&mut self) -> usize {
108 let i = self.0;
109 self.0 = i + 1;
110 i
111 }
112}
113
114macro_rules! tuple_impl {
115 ($($t:ident: $n:tt),*) => {
116 unsafe impl<$($t: FromValue),*> FromValue for ($($t,)*) {
117 fn from_value(v: Value) -> ($($t,)*) {
118 let mut i = Incr(0);
119 #[allow(unused)]
120 (
121 $(
122 $t::from_value(unsafe { v.field(i.get()) }),
123 )*
124 )
125 }
126 }
127
128 unsafe impl<$($t: ToValue),*> ToValue for ($($t,)*) {
129 fn to_value(&self, rt: &Runtime) -> crate::Value {
130 #[allow(unused)]
131 let mut len = 0;
132 $(
133 #[allow(unused)]
134 {
135 len = $n + 1;
136 }
137 )*
138
139 unsafe {
140 let mut v = $crate::Value::alloc(len, Tag(0));
141 $(
142 v.store_field(rt, $n, &self.$n);
143 )*
144
145 v
146 }
147 }
148 }
149 };
150}
151
152tuple_impl!(A: 0);
153tuple_impl!(A: 0, B: 1);
154tuple_impl!(A: 0, B: 1, C: 2);
155tuple_impl!(A: 0, B: 1, C: 2, D: 3);
156tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4);
157tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5);
158tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6);
159tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7);
160tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8);
161tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9);
162tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9, K: 10);
163tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9, K: 10, L: 11);
164tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9, K: 10, L: 11, M: 12);
165tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9, K: 10, L: 11, M: 12, N: 13);
166tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9, K: 10, L: 11, M: 12, N: 13, O: 14);
167tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9, K: 10, L: 11, M: 12, N: 13, O: 14, P: 15);
168tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9, K: 10, L: 11, M: 12, N: 13, O: 14, P: 15, Q: 16);
169tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9, K: 10, L: 11, M: 12, N: 13, O: 14, P: 15, Q: 16, R: 17);
170tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9, K: 10, L: 11, M: 12, N: 13, O: 14, P: 15, Q: 16, R: 17, S: 18);
171tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9, K: 10, L: 11, M: 12, N: 13, O: 14, P: 15, Q: 16, R: 17, S: 18, T: 19);
172tuple_impl!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9, K: 10, L: 11, M: 12, N: 13, O: 14, P: 15, Q: 16, R: 17, S: 18, T: 19, U: 20);
173
174unsafe impl ToValue for bool {
175 fn to_value(&self, _rt: &Runtime) -> Value {
176 unsafe { Value::int(*self as isize) }
177 }
178}
179
180unsafe impl FromValue for bool {
181 fn from_value(v: Value) -> bool {
182 unsafe { v.int_val() != 0 }
183 }
184}
185
186#[cfg(not(feature = "no-std"))]
187unsafe impl ToValue for String {
188 fn to_value(&self, _rt: &Runtime) -> Value {
189 unsafe { Value::string(self.as_str()) }
190 }
191}
192
193#[cfg(not(feature = "no-std"))]
194unsafe impl FromValue for String {
195 fn from_value(value: Value) -> String {
196 unsafe { value.string_val().into() }
197 }
198}
199
200unsafe impl ToValue for () {
201 fn to_value(&self, _rt: &Runtime) -> Value {
202 Value::unit()
203 }
204}
205
206unsafe impl FromValue for () {
207 fn from_value(_value: Value) {}
208}
209
210unsafe impl<T: FromValue> FromValue for Option<T> {
211 fn from_value(value: Value) -> Option<T> {
212 if value.raw().0 == sys::NONE {
213 return None;
214 }
215
216 unsafe { Some(T::from_value(value.field(0))) }
217 }
218}
219
220unsafe impl<T: ToValue> ToValue for Option<T> {
221 fn to_value(&self, rt: &Runtime) -> Value {
222 match self {
223 Some(y) => unsafe { Value::some(rt, y) },
224 None => Value::none(),
225 }
226 }
227}
228
229unsafe impl<'a> FromValue for &'a str {
230 fn from_value(value: Value) -> &'a str {
231 unsafe {
232 let len = sys::caml_string_length(value.raw().0);
233 let ptr = sys::string_val(value.raw().0);
234 let slice = ::core::slice::from_raw_parts(ptr, len);
235 ::core::str::from_utf8(slice).expect("Invalid UTF-8")
236 }
237 }
238}
239
240unsafe impl ToValue for &str {
241 fn to_value(&self, _rt: &Runtime) -> Value {
242 unsafe { Value::string(self) }
243 }
244}
245
246unsafe impl<'a> FromValue for &'a mut str {
247 fn from_value(value: Value) -> &'a mut str {
248 unsafe {
249 let len = sys::caml_string_length(value.raw().0);
250 let ptr = sys::string_val(value.raw().0);
251 let slice = ::core::slice::from_raw_parts_mut(ptr, len);
252 ::core::str::from_utf8_mut(slice).expect("Invalid UTF-8")
253 }
254 }
255}
256
257unsafe impl ToValue for &mut str {
258 fn to_value(&self, _rt: &Runtime) -> Value {
259 unsafe { Value::string(self) }
260 }
261}
262
263unsafe impl<'a> FromValue for &'a [u8] {
264 fn from_value(value: Value) -> &'a [u8] {
265 unsafe {
266 let len = sys::caml_string_length(value.raw().0);
267 let ptr = sys::string_val(value.raw().0);
268 ::core::slice::from_raw_parts(ptr, len)
269 }
270 }
271}
272
273unsafe impl ToValue for &[u8] {
274 fn to_value(&self, _rt: &Runtime) -> Value {
275 unsafe { Value::bytes(self) }
276 }
277}
278
279unsafe impl<'a> FromValue for &'a mut [u8] {
280 fn from_value(value: Value) -> &'a mut [u8] {
281 unsafe {
282 let len = sys::caml_string_length(value.raw().0);
283 let ptr = sys::string_val(value.raw().0);
284 ::core::slice::from_raw_parts_mut(ptr, len)
285 }
286 }
287}
288
289unsafe impl ToValue for &mut [u8] {
290 fn to_value(&self, _rt: &Runtime) -> Value {
291 unsafe { Value::bytes(self) }
292 }
293}
294
295unsafe impl<const N: usize> FromValue for [u8; N] {
296 fn from_value(value: Value) -> Self {
297 unsafe {
298 let len = sys::caml_string_length(value.raw().0);
299 assert!(len == N);
300 let ptr = sys::string_val(value.raw().0);
301 ::core::slice::from_raw_parts(ptr, len).try_into().unwrap()
302 }
303 }
304}
305
306unsafe impl<const N: usize> ToValue for [u8; N] {
307 fn to_value(&self, _rt: &Runtime) -> Value {
308 unsafe { Value::bytes(self) }
309 }
310}
311
312#[cfg(not(feature = "no-std"))]
313unsafe impl<V: FromValue> FromValue for Box<V> {
314 fn from_value(v: Value) -> Box<V> {
315 Box::new(V::from_value(v))
316 }
317}
318
319#[cfg(not(feature = "no-std"))]
320unsafe impl<V: ToValue> ToValue for Box<V> {
321 fn to_value(&self, rt: &Runtime) -> Value {
322 (**self).to_value(rt)
323 }
324}
325
326#[cfg(not(feature = "no-std"))]
327unsafe impl<V: 'static + ToValue> ToValue for Vec<V> {
328 fn to_value(&self, rt: &Runtime) -> Value {
329 let len = self.len();
330
331 if (core::any::TypeId::of::<f32>() == core::any::TypeId::of::<V>()
332 || core::any::TypeId::of::<f64>() == core::any::TypeId::of::<V>())
333 && sys::FLAT_FLOAT_ARRAY
334 {
335 let mut arr = unsafe { Value::alloc_double_array(len) };
336 for (i, v) in self.iter().enumerate() {
337 unsafe {
338 arr.store_double_field(i, v.to_value(rt).double_val());
339 }
340 }
341 arr
342 } else {
343 let mut arr = unsafe { Value::alloc(len, 0.into()) };
344 for (i, v) in self.iter().enumerate() {
345 unsafe {
346 arr.store_field(rt, i, v);
347 }
348 }
349 arr
350 }
351 }
352}
353
354#[cfg(not(feature = "no-std"))]
355unsafe impl<V: FromValue> FromValue for Vec<V> {
356 fn from_value(v: Value) -> Vec<V> {
357 unsafe {
358 let len = crate::sys::caml_array_length(v.raw().0);
359 let is_double = sys::caml_is_double_array(v.raw().0) == 1 && sys::FLAT_FLOAT_ARRAY;
360 let mut dst = Vec::with_capacity(len);
361 if is_double {
362 let mut tmp = Value::double(0.0);
363 for i in 0..len {
364 tmp.store_double_val(v.double_field(i));
365 dst.push(V::from_value(Value::new(tmp.raw().0)));
366 }
367 } else {
368 for i in 0..len {
369 dst.push(V::from_value(Value::new(*crate::sys::field(v.raw().0, i))))
370 }
371 }
372 dst
373 }
374 }
375}
376
377unsafe impl<'a> FromValue for &'a [Raw] {
378 fn from_value(value: Value) -> &'a [Raw] {
379 unsafe {
380 ::core::slice::from_raw_parts(
381 crate::sys::field(value.raw().0, 0) as *mut Raw,
382 crate::sys::wosize_val(value.raw().0),
383 )
384 }
385 }
386}
387
388unsafe impl<'a> FromValue for &'a mut [Raw] {
389 fn from_value(value: Value) -> &'a mut [Raw] {
390 unsafe {
391 ::core::slice::from_raw_parts_mut(
392 crate::sys::field(value.raw().0, 0) as *mut Raw,
393 crate::sys::wosize_val(value.raw().0),
394 )
395 }
396 }
397}
398
399#[cfg(not(feature = "no-std"))]
400unsafe impl<K: Ord + FromValue, V: FromValue> FromValue for std::collections::BTreeMap<K, V> {
401 fn from_value(v: Value) -> std::collections::BTreeMap<K, V> {
402 let mut dest = std::collections::BTreeMap::new();
403 unsafe {
404 let mut tmp = v;
405 while tmp.raw().0 != crate::sys::EMPTY_LIST {
406 let (k, v) = FromValue::from_value(tmp.field(0));
407 dest.insert(k, v);
408 tmp = tmp.field(1);
409 }
410 }
411
412 dest
413 }
414}
415
416#[cfg(not(feature = "no-std"))]
417unsafe impl<K: ToValue, V: ToValue> ToValue for std::collections::BTreeMap<K, V> {
418 fn to_value(&self, rt: &Runtime) -> Value {
419 let mut list = crate::List::empty();
420
421 for (k, v) in self.iter().rev() {
422 let k_ = k.to_value(rt);
423 let v_ = v.to_value(rt);
424 list = unsafe { list.add(rt, &(k_, v_)) };
425 }
426
427 list.to_value(rt)
428 }
429}
430
431#[cfg(not(feature = "no-std"))]
432unsafe impl<T: FromValue> FromValue for std::collections::LinkedList<T> {
433 fn from_value(v: Value) -> std::collections::LinkedList<T> {
434 let mut dest: std::collections::LinkedList<T> = std::collections::LinkedList::new();
435
436 unsafe {
437 let mut tmp = v;
438 while tmp.raw().0 != crate::sys::EMPTY_LIST {
439 let t = T::from_value(tmp.field(0));
440 dest.push_back(t);
441 tmp = tmp.field(1);
442 }
443 }
444
445 dest
446 }
447}
448
449#[cfg(not(feature = "no-std"))]
450unsafe impl<T: ToValue> ToValue for std::collections::LinkedList<T> {
451 fn to_value(&self, rt: &Runtime) -> Value {
452 let mut list = crate::List::empty();
453
454 for v in self.iter().rev() {
455 let v_ = v.to_value(rt);
456 list = unsafe { list.add(rt, &v_) };
457 }
458
459 list.to_value(rt)
460 }
461}