use crate::error::{self, Result};
use crate::raw::{self, Raw};
use rayforce_sys as sys;
use std::fmt;
use std::marker::PhantomData;
pub struct Value {
ptr: Raw,
_not_send: PhantomData<*mut ()>,
}
impl Value {
pub(crate) unsafe fn from_owned(ptr: Raw) -> Value {
debug_assert!(!ptr.is_null(), "from_owned: null pointer");
let ptr = if ptr.is_null() { raw::null_obj() } else { ptr };
Value {
ptr,
_not_send: PhantomData,
}
}
pub(crate) unsafe fn from_borrowed(ptr: Raw) -> Value {
sys::ray_retain(ptr);
Value {
ptr,
_not_send: PhantomData,
}
}
pub fn attrs(&self) -> u8 {
unsafe { raw::attrs(self.as_ptr()) }
}
pub fn null() -> Value {
Value {
ptr: raw::null_obj(),
_not_send: PhantomData,
}
}
#[inline]
pub(crate) fn as_ptr(&self) -> Raw {
self.ptr
}
#[inline]
pub(crate) fn into_raw(self) -> Raw {
let p = self.ptr;
std::mem::forget(self);
p
}
#[inline]
pub(crate) unsafe fn replace_ptr_consumed(&mut self, new: Raw) {
self.ptr = new;
}
#[inline]
pub fn type_code(&self) -> i8 {
unsafe { raw::type_code(self.as_ptr()) }
}
#[inline]
pub fn abs_type(&self) -> i8 {
unsafe { raw::abs_type(self.as_ptr()) }
}
#[inline]
pub fn is_atom(&self) -> bool {
unsafe { raw::is_atom(self.as_ptr()) }
}
#[inline]
pub fn is_vec(&self) -> bool {
unsafe { raw::is_vec(self.as_ptr()) }
}
#[inline]
pub fn is_null(&self) -> bool {
raw::is_null_singleton(self.as_ptr())
}
#[inline]
pub fn len_raw(&self) -> i64 {
unsafe { raw::len(self.as_ptr()) }
}
#[inline]
pub fn ref_count(&self) -> u32 {
unsafe { raw::rc(self.as_ptr()) }
}
pub fn format(&self) -> String {
unsafe {
let s = sys::ray_fmt(self.as_ptr(), 1);
if s.is_null() {
return String::new();
}
if raw::is_err(s) {
sys::ray_error_free(s);
return String::new();
}
let p = sys::ray_str_ptr(s).cast::<u8>();
let n = sys::ray_str_len(s);
let out = if p.is_null() || n == 0 {
String::new()
} else {
String::from_utf8_lossy(std::slice::from_raw_parts(p, n)).into_owned()
};
sys::ray_release(s);
out
}
}
pub fn serialize(&self) -> Result<Vec<u8>> {
unsafe {
let ser = error::check(sys::ray_ser(self.as_ptr()))?;
if ser.is_null() {
return Err(crate::error::RayError::binding("serialize returned null"));
}
let v = Value::from_owned(ser);
let p = raw::data(v.ptr) as *const u8;
let n = raw::len(v.ptr) as usize;
Ok(std::slice::from_raw_parts(p, n).to_vec())
}
}
pub fn deserialize(bytes: &[u8]) -> Result<Value> {
let buf = Value::vec(bytes);
unsafe {
let de = error::check(sys::ray_de(buf.ptr))?;
if de.is_null() {
return Err(crate::error::RayError::binding("deserialize returned null"));
}
Ok(Value::from_owned(error::materialize(de)?))
}
}
}
impl Clone for Value {
fn clone(&self) -> Value {
unsafe { sys::ray_retain(self.ptr) };
Value {
ptr: self.ptr,
_not_send: PhantomData,
}
}
}
impl Drop for Value {
fn drop(&mut self) {
unsafe { sys::ray_release(self.ptr) }
}
}
impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.format())
}
}
impl fmt::Debug for Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Value(type={}, {})", self.type_code(), self.format())
}
}