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)
}
}