ruby_sys/
array.rs

1use libc::size_t;
2use std::mem;
3
4use constant::{FL_USHIFT, FL_USER_1, FL_USER_3, FL_USER_4};
5use types::{c_long, InternalValue, RBasic, Value};
6
7extern "C" {
8    pub fn rb_ary_concat(array: Value, other_array: Value) -> Value;
9    pub fn rb_ary_dup(array: Value) -> Value;
10    pub fn rb_ary_entry(array: Value, offset: c_long) -> Value;
11    pub fn rb_ary_join(array: Value, separator: Value) -> Value;
12    pub fn rb_ary_new() -> Value;
13    pub fn rb_ary_new_capa(capacity: c_long) -> Value;
14    pub fn rb_ary_pop(array: Value) -> Value;
15    pub fn rb_ary_push(array: Value, item: Value) -> Value;
16    pub fn rb_ary_reverse(array: Value) -> Value;
17    pub fn rb_ary_shift(array: Value) -> Value;
18    pub fn rb_ary_sort_bang(array: Value) -> Value;
19    pub fn rb_ary_sort(array: Value) -> Value;
20    pub fn rb_ary_store(array: Value, index: c_long, item: Value) -> Value;
21    pub fn rb_ary_to_s(array: Value) -> Value;
22    pub fn rb_ary_unshift(array: Value, item: Value) -> Value;
23}
24
25#[repr(C)]
26enum RArrayEmbed {
27    Flag = FL_USER_1,
28    LenMask = FL_USER_4 | FL_USER_3,
29    LenShift = FL_USHIFT + 3,
30}
31
32#[repr(C)]
33struct RArrayAs {
34    heap: RArrayHeap,
35}
36
37#[repr(C)]
38struct RArrayHeap {
39    len: c_long,
40    // Really, this is a union but value is the largest item.
41    value: InternalValue,
42    ptr: InternalValue,
43}
44
45#[repr(C)]
46struct RArray {
47    basic: RBasic,
48    as_: RArrayAs,
49}
50
51pub unsafe fn rb_ary_len(value: Value) -> c_long {
52    let rarray: *const RArray = mem::transmute(value.value);
53    let flags = (*rarray).basic.flags;
54
55    if flags & (RArrayEmbed::Flag as size_t) == 0 {
56        (*rarray).as_.heap.len
57    } else {
58        ((flags as i64 >> RArrayEmbed::LenShift as i64) &
59         (RArrayEmbed::LenMask as i64 >> RArrayEmbed::LenShift as i64)) as c_long
60    }
61}