1 // Copyright (c) Facebook, Inc. and its affiliates.
3 // This source code is licensed under the MIT license found in the
4 // LICENSE file in the "hack" directory of this source tree.
7 use std::fmt::{self, Debug};
8 use std::marker::PhantomData;
10 use std::ops::{Index, IndexMut};
16 const STRING_TAG: u8 = 252;
17 const DOUBLE_TAG: u8 = 253;
19 pub trait IntoOcamlRep {
20 fn into_ocamlrep<'a>(self, arena: &mut Arena<'a>) -> Value<'a>;
24 pub struct BlockBuilder<'arena: 'builder, 'builder>(&'builder mut [Value<'arena>]);
26 impl<'a, 'b> BlockBuilder<'a, 'b> {
27 pub fn new(size: usize, tag: u8, block: &'b mut [Value<'a>]) -> Self {
31 let header_bytes = size << 10 | (tag as usize);
32 let header = Value::bits(header_bytes);
37 pub fn build(self) -> Value<'a> {
38 Value::bits(unsafe { mem::transmute(self.0.as_ptr().offset(1)) })
42 impl<'a, 'b> Index<usize> for BlockBuilder<'a, 'b> {
43 type Output = Value<'a>;
45 fn index(&self, index: usize) -> &Self::Output {
50 impl IndexMut<usize> for BlockBuilder<'_, '_> {
51 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
52 &mut self.0[index + 1]
57 pub struct Block<'arena>(&'arena [Value<'arena>]);
60 fn header_bits(&self) -> usize {
64 fn size(&self) -> usize {
65 self.header_bits() >> 10
69 self.header_bits() as u8
72 fn as_str(&self) -> Option<Cow<str>> {
73 if self.tag() != STRING_TAG {
77 let size = self.size() * mem::size_of::<usize>();
78 let ptr: *mut u8 = mem::transmute(self.0.as_ptr().offset(1));
79 let last_byte = ptr.offset(size as isize - 1);
80 let padding = *last_byte;
81 let size = size - padding as usize - 1;
82 std::slice::from_raw_parts(ptr, size)
84 Some(String::from_utf8_lossy(slice))
87 fn as_float(&self) -> Option<f64> {
88 if self.tag() != DOUBLE_TAG {
91 Some(f64::from_bits(self.0[1].0 as u64))
94 fn as_values(&self) -> Option<&[Value]> {
95 if self.tag() == STRING_TAG || self.tag() == DOUBLE_TAG {
102 impl<'a> Index<usize> for Block<'a> {
103 type Output = Value<'a>;
105 fn index(&self, index: usize) -> &Self::Output {
110 impl Debug for Block<'_> {
111 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112 if self.tag() == STRING_TAG {
113 write!(f, "{:?}", self.as_str().unwrap())
114 } else if self.tag() == DOUBLE_TAG {
115 write!(f, "{:?}", self.as_float().unwrap())
117 write!(f, "{:?}", self.as_values().unwrap())
123 #[derive(Clone, Copy)]
124 pub struct Value<'arena>(usize, PhantomData<&'arena ()>);
127 fn is_immediate(&self) -> bool {
131 pub fn int(value: isize) -> Value<'static> {
132 Value(((value as usize) << 1) | 1, PhantomData)
135 fn bits(value: usize) -> Value<'a> {
136 Value(value, PhantomData)
139 fn as_int(&self) -> isize {
140 if !self.is_immediate() {
143 (self.0 as isize) >> 1
146 fn as_block(&self) -> Option<Block<'a>> {
147 if self.is_immediate() {
151 let ptr: *const Value = mem::transmute(self.0);
152 let header = ptr.offset(-1);
153 let size = ((*header).0 >> 10) + 1;
154 std::slice::from_raw_parts(header, size)
159 /// This method is unsafe because it decouples the value from the lifetime
160 /// of the arena. Take care that the returned value does not outlive the
162 pub unsafe fn as_usize(&self) -> usize {
167 impl Debug for Value<'_> {
168 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
169 match self.as_block() {
170 None => write!(f, "{}", self.as_int()),
171 Some(block) => write!(f, "{:?}", block),
176 impl IntoOcamlRep for bool {
177 fn into_ocamlrep<'a>(self, _arena: &mut Arena<'a>) -> Value<'a> {
178 Value::int(self as isize)
182 impl IntoOcamlRep for char {
183 fn into_ocamlrep<'a>(self, _arena: &mut Arena<'a>) -> Value<'a> {
184 Value::int(self as isize)
188 impl IntoOcamlRep for isize {
189 fn into_ocamlrep<'a>(self, _arena: &mut Arena<'a>) -> Value<'a> {
194 impl IntoOcamlRep for usize {
195 fn into_ocamlrep<'a>(self, _arena: &mut Arena<'a>) -> Value<'a> {
196 Value::int(self as isize)
200 impl IntoOcamlRep for u64 {
201 fn into_ocamlrep<'a>(self, _arena: &mut Arena<'a>) -> Value<'a> {
202 Value::int(self as isize)
206 impl IntoOcamlRep for i64 {
207 fn into_ocamlrep<'a>(self, _arena: &mut Arena<'a>) -> Value<'a> {
208 Value::int(self as isize)
212 impl IntoOcamlRep for u32 {
213 fn into_ocamlrep<'a>(self, _arena: &mut Arena<'a>) -> Value<'a> {
214 Value::int(self as isize)
218 impl IntoOcamlRep for i32 {
219 fn into_ocamlrep<'a>(self, _arena: &mut Arena<'a>) -> Value<'a> {
220 Value::int(self as isize)
224 impl<T: IntoOcamlRep> IntoOcamlRep for Option<T> {
225 fn into_ocamlrep<'a>(self, arena: &mut Arena<'a>) -> Value<'a> {
227 None => Value::int(0),
229 let val = arena.add(val);
230 let mut block = arena.block_with_size(1);
238 impl<T: IntoOcamlRep> IntoOcamlRep for Vec<T> {
239 fn into_ocamlrep<'a>(self, arena: &mut Arena<'a>) -> Value<'a> {
240 let mut hd = arena.add(());
241 for val in self.into_iter().rev() {
242 let val = arena.add(val);
243 let mut current_block = arena.block_with_size(2);
244 current_block[0] = val;
245 current_block[1] = hd;
246 hd = current_block.build();
252 impl IntoOcamlRep for String {
253 fn into_ocamlrep<'a>(self, arena: &mut Arena<'a>) -> Value<'a> {
254 self.as_str().into_ocamlrep(arena)
258 impl IntoOcamlRep for &str {
259 fn into_ocamlrep<'a>(self, arena: &mut Arena<'a>) -> Value<'a> {
260 let bytes_in_word = mem::size_of::<usize>();
261 let blocks_length = 1 + (self.len() / bytes_in_word);
262 let padding: usize = bytes_in_word - 1 - (self.len() % bytes_in_word);
263 let mut block = arena.block_with_size_and_tag(blocks_length, STRING_TAG);
265 block[blocks_length - 1] = Value::bits(padding << ((bytes_in_word - 1) * 8));
267 let slice: &mut [u8] = unsafe {
268 let ptr: *mut u8 = mem::transmute(block.0.as_ptr().offset(1));
269 std::slice::from_raw_parts_mut(ptr, self.len())
271 slice.copy_from_slice(self.as_bytes());
277 impl IntoOcamlRep for f64 {
278 fn into_ocamlrep<'a>(self, arena: &mut Arena<'a>) -> Value<'a> {
279 let mut block = arena.block_with_size_and_tag(1, DOUBLE_TAG);
280 block[0] = Value::bits(self.to_bits() as usize);
285 impl IntoOcamlRep for () {
286 fn into_ocamlrep<'a>(self, arena: &mut Arena<'a>) -> Value<'a> {
287 0isize.into_ocamlrep(arena)
291 impl<T: IntoOcamlRep> IntoOcamlRep for Box<T> {
292 fn into_ocamlrep<'a>(self, arena: &mut Arena<'a>) -> Value<'a> {
293 (*self).into_ocamlrep(arena)
297 impl<T0, T1> IntoOcamlRep for (T0, T1)
302 fn into_ocamlrep<'a>(self, arena: &mut Arena<'a>) -> Value<'a> {
303 let v0 = arena.add(self.0);
304 let v1 = arena.add(self.1);
305 let mut block = arena.block_with_size(2);
312 impl<T0, T1, T2> IntoOcamlRep for (T0, T1, T2)
318 fn into_ocamlrep<'a>(self, arena: &mut Arena<'a>) -> Value<'a> {
319 let v0 = arena.add(self.0);
320 let v1 = arena.add(self.1);
321 let v2 = arena.add(self.2);
322 let mut block = arena.block_with_size(3);
330 impl<T0, T1, T2, T3> IntoOcamlRep for (T0, T1, T2, T3)
337 fn into_ocamlrep<'a>(self, arena: &mut Arena<'a>) -> Value<'a> {
338 let v0 = arena.add(self.0);
339 let v1 = arena.add(self.1);
340 let v2 = arena.add(self.2);
341 let v3 = arena.add(self.3);
342 let mut block = arena.block_with_size(4);
351 impl<T0, T1, T2, T3, T4> IntoOcamlRep for (T0, T1, T2, T3, T4)
359 fn into_ocamlrep<'a>(self, arena: &mut Arena<'a>) -> Value<'a> {
360 let v0 = arena.add(self.0);
361 let v1 = arena.add(self.1);
362 let v2 = arena.add(self.2);
363 let v3 = arena.add(self.3);
364 let v4 = arena.add(self.4);
365 let mut block = arena.block_with_size(5);
375 impl<T0, T1, T2, T3, T4, T5> IntoOcamlRep for (T0, T1, T2, T3, T4, T5)
384 fn into_ocamlrep<'a>(self, arena: &mut Arena<'a>) -> Value<'a> {
385 let v0 = arena.add(self.0);
386 let v1 = arena.add(self.1);
387 let v2 = arena.add(self.2);
388 let v3 = arena.add(self.3);
389 let v4 = arena.add(self.4);
390 let v5 = arena.add(self.5);
391 let mut block = arena.block_with_size(6);
402 impl<T0, T1, T2, T3, T4, T5, T6> IntoOcamlRep for (T0, T1, T2, T3, T4, T5, T6)
412 fn into_ocamlrep<'a>(self, arena: &mut Arena<'a>) -> Value<'a> {
413 let v0 = arena.add(self.0);
414 let v1 = arena.add(self.1);
415 let v2 = arena.add(self.2);
416 let v3 = arena.add(self.3);
417 let v4 = arena.add(self.4);
418 let v5 = arena.add(self.5);
419 let v6 = arena.add(self.6);
420 let mut block = arena.block_with_size(7);
432 impl<T0, T1, T2, T3, T4, T5, T6, T7> IntoOcamlRep for (T0, T1, T2, T3, T4, T5, T6, T7)
443 fn into_ocamlrep<'a>(self, arena: &mut Arena<'a>) -> Value<'a> {
444 let v0 = arena.add(self.0);
445 let v1 = arena.add(self.1);
446 let v2 = arena.add(self.2);
447 let v3 = arena.add(self.3);
448 let v4 = arena.add(self.4);
449 let v5 = arena.add(self.5);
450 let v6 = arena.add(self.6);
451 let v7 = arena.add(self.7);
452 let mut block = arena.block_with_size(8);