soroban_env_common/
object.rsuse crate::xdr::{Duration, ScVal, TimePoint};
use crate::{
impl_val_wrapper_base, num, val::ValConvert, Compare, Convert, Env, Tag, TryFromVal, Val,
};
use core::{cmp::Ordering, fmt::Debug};
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct Object(pub(crate) Val);
impl_val_wrapper_base!(Object);
impl ValConvert for Object {
fn is_val_type(v: Val) -> bool {
v.is_object()
}
unsafe fn unchecked_from_val(v: Val) -> Self {
Object(v)
}
}
impl Object {
#[inline(always)]
pub const fn get_handle(&self) -> u32 {
self.as_val().get_major()
}
#[inline(always)]
pub const fn from_handle_and_tag(handle: u32, tag: Tag) -> Self {
debug_assert!(tag.is_object());
unsafe { Object(Val::from_major_minor_and_tag(handle, 0, tag)) }
}
}
impl<E: Env> Compare<Object> for E {
type Error = E::Error;
fn compare(&self, a: &Object, b: &Object) -> Result<Ordering, Self::Error> {
self.compare(&a.to_val(), &b.to_val())
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct ScValObject(ScVal);
impl From<ScValObject> for ScVal {
fn from(value: ScValObject) -> Self {
value.0
}
}
impl<E> TryFromVal<E, Object> for ScValObject
where
E: Env + Convert<Object, ScValObject>,
{
type Error = <E as Convert<Object, ScValObject>>::Error;
fn try_from_val(env: &E, val: &Object) -> Result<Self, Self::Error> {
env.convert(*val)
}
}
impl<'a, E> TryFromVal<E, ScValObjRef<'a>> for Object
where
E: Env + Convert<ScValObjRef<'a>, Object>,
{
type Error = crate::Error;
fn try_from_val(env: &E, v: &ScValObjRef<'a>) -> Result<Self, Self::Error> {
match env.convert(*v) {
Ok(obj) => Ok(obj),
Err(e) => Err(e.into()),
}
}
}
impl ScValObject {
pub fn classify(value: ScVal) -> Result<ScValObject, ScVal> {
if ScValObjRef::classify(&value).is_some() {
Ok(ScValObject(value))
} else {
Err(value)
}
}
pub unsafe fn unchecked_from_val(value: ScVal) -> ScValObject {
ScValObject(value)
}
}
impl AsRef<ScVal> for ScValObject {
fn as_ref(&self) -> &ScVal {
&self.0
}
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct ScValObjRef<'a>(&'a ScVal);
impl<'a> From<ScValObjRef<'a>> for &'a ScVal {
fn from(val: ScValObjRef<'a>) -> Self {
val.0
}
}
impl AsRef<ScVal> for ScValObjRef<'_> {
fn as_ref(&self) -> &ScVal {
self.0
}
}
impl<'a> ScValObjRef<'a> {
pub fn classify(value: &'a ScVal) -> Option<Self> {
match value {
ScVal::Bool(_)
| ScVal::Void
| ScVal::Error(_)
| ScVal::U32(_)
| ScVal::I32(_)
| ScVal::LedgerKeyContractInstance
| ScVal::LedgerKeyNonce(_)
| ScVal::ContractInstance(_) => None,
ScVal::Bytes(_)
| ScVal::String(_)
| ScVal::Vec(_)
| ScVal::Map(_)
| ScVal::Address(_) => Some(ScValObjRef(value)),
ScVal::U64(u) | ScVal::Timepoint(TimePoint(u)) | ScVal::Duration(Duration(u)) => {
if num::is_small_u64(*u) {
None
} else {
Some(ScValObjRef(value))
}
}
ScVal::I64(i) => {
if num::is_small_i64(*i) {
None
} else {
Some(ScValObjRef(value))
}
}
ScVal::U128(u) => {
if num::is_small_u128(u.into()) {
None
} else {
Some(ScValObjRef(value))
}
}
ScVal::I128(i) => {
if num::is_small_i128(i.into()) {
None
} else {
Some(ScValObjRef(value))
}
}
ScVal::U256(u) => {
if num::is_small_u256_parts(u) {
None
} else {
Some(ScValObjRef(value))
}
}
ScVal::I256(i) => {
if num::is_small_i256_parts(i) {
None
} else {
Some(ScValObjRef(value))
}
}
ScVal::Symbol(s) => {
if s.len() <= crate::symbol::MAX_SMALL_CHARS {
None
} else {
Some(ScValObjRef(value))
}
}
}
}
}