ruby_sys/
value.rs

1use libc::size_t;
2use std::mem;
3use std::convert::From;
4
5use types::{InternalValue, RBasic};
6
7const SPECIAL_SHIFT: usize = 8;
8
9// Split RubySpecialConsts and RubySpecialFlags
10
11#[cfg(not(target_arch = "x86_64"))]
12pub enum RubySpecialConsts {
13    False = 0,
14    True = 0x02,
15    Nil = 0x04,
16    Undef = 0x06,
17}
18
19#[cfg(not(target_arch = "x86_64"))]
20pub enum RubySpecialFlags {
21    ImmediateMask = 0x03,
22    FixnumFlag = 0x01,
23    FlonumMask = 0x00,
24    FlonumFlag = 0x02,
25    SymbolFlag = 0x0e,
26}
27
28#[cfg(target_arch = "x86_64")]
29pub enum RubySpecialConsts {
30    False = 0,
31    True = 0x14,
32    Nil = 0x08,
33    Undef = 0x34,
34}
35
36#[cfg(target_arch = "x86_64")]
37pub enum RubySpecialFlags {
38    ImmediateMask = 0x07,
39    FixnumFlag = 0x01,
40    FlonumMask = 0x03,
41    FlonumFlag = 0x02,
42    SymbolFlag = 0x0c,
43}
44
45#[derive(Debug, PartialEq)]
46#[link_name = "ruby_value_type"]
47#[repr(C)]
48pub enum ValueType {
49    None = 0x00,
50    Object = 0x01,
51    Class = 0x02,
52    Module = 0x03,
53    Float = 0x04,
54    RString = 0x05,
55    Regexp = 0x06,
56    Array = 0x07,
57    Hash = 0x08,
58    Struct = 0x09,
59    Bignum = 0x0a,
60    File = 0x0b,
61    Data = 0x0c,
62    Match = 0x0d,
63    Complex = 0x0e,
64    Rational = 0x0f,
65    Nil = 0x11,
66    True = 0x12,
67    False = 0x13,
68    Symbol = 0x14,
69    Fixnum = 0x15,
70    Undef = 0x1b,
71    Node = 0x1c,
72    IClass = 0x1d,
73    Zombie = 0x1e,
74    Mask = 0x1f,
75}
76
77#[repr(C)]
78#[derive(Copy, Clone, Debug, PartialEq)]
79pub struct Value {
80    pub value: InternalValue,
81}
82
83impl Value {
84    pub fn is_true(&self) -> bool {
85        self.value == (RubySpecialConsts::True as InternalValue)
86    }
87
88    pub fn is_false(&self) -> bool {
89        self.value == (RubySpecialConsts::False as InternalValue)
90    }
91
92    pub fn is_nil(&self) -> bool {
93        self.value == (RubySpecialConsts::Nil as InternalValue)
94    }
95
96    pub fn is_undef(&self) -> bool {
97        self.value == (RubySpecialConsts::Undef as InternalValue)
98    }
99
100    pub fn is_symbol(&self) -> bool {
101        (self.value & !((!0) << SPECIAL_SHIFT)) == (RubySpecialFlags::SymbolFlag as InternalValue)
102    }
103
104    pub fn is_fixnum(&self) -> bool {
105        (self.value & (RubySpecialFlags::FixnumFlag as InternalValue)) != 0
106    }
107
108    pub fn is_flonum(&self) -> bool {
109        (self.value & (RubySpecialFlags::FlonumMask as InternalValue)) ==
110        (RubySpecialFlags::FlonumFlag as InternalValue)
111    }
112
113    pub fn ty(&self) -> ValueType {
114        if self.is_immediate() {
115            if self.is_fixnum() {
116                ValueType::Fixnum
117            } else if self.is_flonum() {
118                ValueType::Float
119            } else if self.is_true() {
120                ValueType::True
121            } else if self.is_symbol() {
122                ValueType::Symbol
123            } else if self.is_undef() {
124                ValueType::Undef
125            } else {
126                self.builtin_type()
127            }
128        } else if !self.test() {
129            if self.is_nil() {
130                ValueType::Nil
131            } else if self.is_false() {
132                ValueType::False
133            } else {
134                self.builtin_type()
135            }
136        } else {
137            self.builtin_type()
138        }
139    }
140
141    fn is_immediate(&self) -> bool {
142        (self.value & (RubySpecialFlags::ImmediateMask as InternalValue)) != 0
143    }
144
145    fn test(&self) -> bool {
146        (self.value & !(RubySpecialConsts::Nil as InternalValue)) != 0
147    }
148
149    fn builtin_type(&self) -> ValueType {
150        unsafe {
151            let basic: *const RBasic = mem::transmute(self.value);
152            let masked = (*basic).flags & (ValueType::Mask as size_t);
153            mem::transmute(masked as u32)
154        }
155    }
156}
157
158impl From<InternalValue> for Value {
159    fn from(internal_value: InternalValue) -> Self {
160        Value { value: internal_value }
161    }
162}