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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use types::Value;

use {Object, VerifiedObject};
use std::{
  ops::Deref,
  borrow::Borrow,
  convert::AsRef,
};

/// Representation of any Ruby object while its type is unknown
///
/// As Ruby is a dynamically typed language, at some points Rutie does not know the exact Ruby type
/// of the object, for example:
///
/// - Retrieving an object from array;
///
/// - Retrieving an object from hash;
///
/// - Receiving arguments to a method;
///
/// - Initializing a new instance of a non-built-in class.
///
/// In these cases you should cast `AnyObject` to the required type.
///
/// # Examples
///
/// ### Retrieving an object from `Array`
///
/// ```
/// use rutie::{Array, Fixnum, Object, VM};
/// # VM::init();
///
/// let array = Array::new().push(Fixnum::new(1));
/// let value = array.at(0).try_convert_to::<Fixnum>(); // `Array::at()` returns `AnyObject`
///
/// assert_eq!(value, Ok(Fixnum::new(1)));
/// ```
///
/// ### Retrieving an object from `Hash`
///
/// ```
/// use rutie::{Fixnum, Hash, Object, Symbol, VM};
/// # VM::init();
///
/// let mut hash = Hash::new();
///
/// hash.store(Symbol::new("key"), Fixnum::new(1));
///
/// // `Hash::at()` returns `AnyObject`
/// let value = hash.at(&Symbol::new("key")).try_convert_to::<Fixnum>();
///
/// assert_eq!(value, Ok(Fixnum::new(1)));
/// ```
///
/// You can find more examples in `Class`, `Object` and `VerifiedObject` documentation.
#[derive(Clone, Debug)]
#[repr(C)]
pub struct AnyObject {
    value: Value,
}

impl From<Value> for AnyObject {
    fn from(value: Value) -> Self {
        AnyObject { value }
    }
}

impl Into<Value> for AnyObject {
    fn into(self) -> Value {
        self.value
    }
}

impl Borrow<Value> for AnyObject {
    fn borrow(&self) -> &Value {
        &self.value
    }
}

impl AsRef<Value> for AnyObject {
    fn as_ref(&self) -> &Value {
        &self.value
    }
}

impl AsRef<AnyObject> for AnyObject {
    #[inline]
    fn as_ref(&self) -> &Self {
        self
    }
}

impl<T: Object> From<&T> for AnyObject {
    fn from(value: &T) -> Self {
        value.to_any_object()
    }
}

impl Object for AnyObject {
    #[inline]
    fn value(&self) -> Value {
        self.value
    }
}

impl Deref for AnyObject {
    type Target = Value;

    fn deref(&self) -> &Value {
        &self.value
    }
}

// Any object can be safely converted to `AnyObject` :)
impl VerifiedObject for AnyObject {
    fn is_correct_type<T: Object>(_: &T) -> bool {
        true
    }

    fn error_message() -> &'static str {
        unreachable!()
    }
}

impl PartialEq for AnyObject {
    fn eq(&self, other: &Self) -> bool {
        self.equals(other)
    }
}