use std::{
mem,
os::raw::c_char,
};
use crate::prelude::*;
pub unsafe trait Rosy: Sized {
const ID: *const c_char;
#[inline]
fn unique_object_id() -> Option<u128> {
None
}
#[inline]
fn class() -> Class {
Class::rust_object()
}
#[inline]
#[allow(unused_variables)]
fn cast<A: Object>(obj: A) -> Option<RosyObject<Self>> {
if A::unique_id() == Self::unique_object_id() {
unsafe { Some(RosyObject::cast_unchecked(obj)) }
} else {
None
}
}
fn mark(&self);
#[inline]
fn free(self: Box<Self>) {
drop(self);
}
#[inline]
fn size(&self) -> usize {
mem::size_of_val(self)
}
}
unsafe impl<R: Rosy> Rosy for &[R] {
const ID: *const c_char = b"rust_slice\0".as_ptr() as _;
#[inline]
fn mark(&self) {
self.iter().for_each(Rosy::mark);
}
#[inline]
fn size(&self) -> usize {
self.iter().fold(0, |cur, r| cur + r.size())
}
}
unsafe impl<R: Rosy> Rosy for &mut [R] {
const ID: *const c_char = b"rust_mut_slice\0".as_ptr() as _;
#[inline]
fn mark(&self) {
self.iter().for_each(Rosy::mark);
}
#[inline]
fn size(&self) -> usize {
self.iter().fold(0, |cur, r| cur + r.size())
}
}
unsafe impl<R: Rosy> Rosy for Vec<R> {
const ID: *const c_char = b"rust_vec\0".as_ptr() as _;
#[inline]
fn unique_object_id() -> Option<u128> {
let inner = R::unique_object_id()?;
let base = u128::from_le_bytes(*b"built-in Vec<T> ");
Some(inner.rotate_right(1) ^ base)
}
#[inline]
fn mark(&self) {
self.iter().for_each(Rosy::mark);
}
#[inline]
fn size(&self) -> usize {
self.iter().fold(0, |cur, r| cur + r.size())
}
}
unsafe impl Rosy for &str {
const ID: *const c_char = b"rust_str\0".as_ptr() as _;
#[inline]
fn mark(&self) {}
#[inline]
fn size(&self) -> usize {
mem::size_of_val(*self)
}
}
unsafe impl Rosy for std::string::String {
const ID: *const c_char = b"rust_string\0".as_ptr() as _;
#[inline]
fn unique_object_id() -> Option<u128> {
Some((!0) - 0xff)
}
#[inline]
fn mark(&self) {}
#[inline]
fn size(&self) -> usize {
self.as_str().size()
}
}