pub trait IsEql {
// Required method
fn is_eql(&self, other: Value) -> bool;
}
Expand description
Trait for a Ruby-compatible #eql?
method.
Automatically implemented for any type implementing Eq
and
TryConvert
.
See also Dup
, Inspect
, typed_data::Cmp
, and
typed_data::Hash
.
§Examples
use std::hash::Hasher;
use magnus::{
function, gc, method, prelude::*, typed_data, value::Opaque, DataTypeFunctions, Error,
Ruby, TypedData, Value,
};
#[derive(TypedData)]
#[magnus(class = "Pair", free_immediately, mark)]
struct Pair {
#[magnus(opaque_attr_reader)]
a: Opaque<Value>,
#[magnus(opaque_attr_reader)]
b: Opaque<Value>,
}
impl Pair {
fn new(a: Value, b: Value) -> Self {
Self {
a: a.into(),
b: b.into(),
}
}
}
impl DataTypeFunctions for Pair {
fn mark(&self, marker: &gc::Marker) {
marker.mark(self.a);
marker.mark(self.b);
}
}
impl std::hash::Hash for Pair {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_i64(
self.a()
.hash()
.expect("#hash should not fail")
.to_i64()
.expect("#hash result guaranteed to be <= i64"),
);
state.write_i64(
self.b()
.hash()
.expect("#hash should not fail")
.to_i64()
.expect("#hash result guaranteed to be <= i64"),
);
}
}
impl PartialEq for Pair {
fn eq(&self, other: &Self) -> bool {
self.a().eql(other.a()).unwrap_or(false) && self.b().eql(other.b()).unwrap_or(false)
}
}
impl Eq for Pair {}
fn example(ruby: &Ruby) -> Result<(), Error> {
let class = ruby.define_class("Pair", ruby.class_object())?;
class.define_singleton_method("new", function!(Pair::new, 2))?;
class.define_method("hash", method!(<Pair as typed_data::Hash>::hash, 0))?;
class.define_method("eql?", method!(<Pair as typed_data::IsEql>::is_eql, 1))?;
let a = Pair::new(
ruby.str_new("foo").as_value(),
ruby.integer_from_i64(1).as_value(),
);
let hash = ruby.hash_new();
hash.aset(a, "test value")?;
let b = Pair::new(
ruby.str_new("foo").as_value(),
ruby.integer_from_i64(1).as_value(),
);
assert_eq!("test value", hash.fetch::<_, String>(b)?);
let c = Pair::new(
ruby.str_new("bar").as_value(),
ruby.integer_from_i64(2).as_value(),
);
assert!(hash.get(c).is_none());
Ok(())
}