tvm_ffi/extra/
unchanged.rsuse std::marker::PhantomData;
use crate::any::{Any, AnyView, TryFromTemp};
use crate::error::{Error, Result, TYPE_ERROR};
use crate::tvm_ffi_sys::{TVMFFIAny, TVMFFITypeIndex};
use crate::type_traits::{AnyCompatible, ContainerElement};
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct Unchanged;
unsafe impl AnyCompatible for Unchanged {
unsafe fn copy_to_any_view(_src: &Self, data: &mut TVMFFIAny) {
*data = TVMFFIAny::new();
data.type_index = TVMFFITypeIndex::kTVMFFIUnchanged as i32;
}
unsafe fn move_to_any(src: Self, data: &mut TVMFFIAny) {
Self::copy_to_any_view(&src, data);
}
unsafe fn check_any_strict(data: &TVMFFIAny) -> bool {
data.type_index == TVMFFITypeIndex::kTVMFFIUnchanged as i32
}
unsafe fn copy_from_any_view_after_check(_data: &TVMFFIAny) -> Self {
Self
}
unsafe fn move_from_any_after_check(_data: &mut TVMFFIAny) -> Self {
Self
}
unsafe fn try_cast_from_any_view(data: &TVMFFIAny) -> std::result::Result<Self, ()> {
Self::check_any_strict(data).then_some(Self).ok_or(())
}
fn type_str() -> std::string::String {
"Unchanged".into()
}
fn type_schema() -> std::string::String {
crate::type_traits::type_schema("ffi.Unchanged", &[])
}
}
crate::impl_try_from_any!(Unchanged);
#[repr(transparent)]
pub struct UnchangedOr<T: ContainerElement = Any> {
data: Any,
_marker: PhantomData<T>,
}
impl<T: ContainerElement> UnchangedOr<T> {
#[inline]
pub fn unchanged() -> Self {
Self {
data: Unchanged.into(),
_marker: PhantomData,
}
}
#[inline]
pub fn changed(value: T) -> Self {
let mut raw = TVMFFIAny::new();
unsafe {
T::container_move_to_any(value, &mut raw);
Self {
data: Any::from_raw_ffi_any(raw),
_marker: PhantomData,
}
}
}
#[inline]
pub fn is_unchanged(&self) -> bool {
is_unchanged(&self.data)
}
#[inline]
pub fn unchanged_or_same_as(&self, original: &T) -> bool {
if self.is_unchanged() {
return true;
}
let mut raw = TVMFFIAny::new();
unsafe {
T::container_copy_to_any_view(original, &mut raw);
}
super::structural_common::same_shallow(raw, *self.data.as_raw_ffi_any())
}
#[inline]
pub fn into_option(self) -> Option<T> {
if self.is_unchanged() {
return None;
}
unsafe {
let mut raw = Any::into_raw_ffi_any(self.data);
Some(T::container_move_from_any_after_check(&mut raw))
}
}
#[inline]
pub fn value_or(self, original: T) -> T {
self.value_or_else(|| original)
}
#[inline]
pub fn value_or_else(self, original: impl FnOnce() -> T) -> T {
self.into_option().unwrap_or_else(original)
}
#[inline]
pub fn map<U: ContainerElement>(self, convert: impl FnOnce(T) -> U) -> UnchangedOr<U> {
match self.into_option() {
Some(value) => UnchangedOr::changed(convert(value)),
None => UnchangedOr::unchanged(),
}
}
#[inline]
pub fn try_map<U: ContainerElement, E>(
self,
convert: impl FnOnce(T) -> std::result::Result<U, E>,
) -> std::result::Result<UnchangedOr<U>, E> {
match self.into_option() {
Some(value) => convert(value).map(UnchangedOr::changed),
None => Ok(UnchangedOr::unchanged()),
}
}
#[inline]
pub fn try_cast<U: ContainerElement>(self) -> Result<UnchangedOr<U>> {
if unsafe { UnchangedOr::<U>::check_any_strict(self.data.as_raw_ffi_any()) } {
Ok(UnchangedOr {
data: self.data,
_marker: PhantomData,
})
} else {
Err(Error::new(
TYPE_ERROR,
&format!(
"structural mutation result does not match {}",
U::container_type_str()
),
"",
))
}
}
}
impl UnchangedOr<Any> {
#[inline]
pub(crate) fn from_carrier(data: Any) -> Result<Self> {
if data.type_index() == TVMFFITypeIndex::kTVMFFIError as i32 {
return match Error::try_from(data) {
Ok(error) | Err(error) => Err(error),
};
}
Ok(Self {
data,
_marker: PhantomData,
})
}
}
impl<T: ContainerElement> Clone for UnchangedOr<T> {
#[inline]
fn clone(&self) -> Self {
Self {
data: self.data.clone(),
_marker: PhantomData,
}
}
}
unsafe impl<T: ContainerElement> AnyCompatible for UnchangedOr<T> {
unsafe fn copy_to_any_view(src: &Self, data: &mut TVMFFIAny) {
*data = *src.data.as_raw_ffi_any();
}
unsafe fn move_to_any(src: Self, data: &mut TVMFFIAny) {
*data = Any::into_raw_ffi_any(src.data);
}
unsafe fn check_any_strict(data: &TVMFFIAny) -> bool {
if T::CONTAINER_IS_ANY {
data.type_index != TVMFFITypeIndex::kTVMFFIError as i32
} else {
Unchanged::check_any_strict(data) || T::container_check_any_strict(data)
}
}
unsafe fn match_constraints(data: &TVMFFIAny) -> bool {
Unchanged::check_any_strict(data) || T::container_match_constraints(data)
}
unsafe fn copy_from_any_view_after_check(data: &TVMFFIAny) -> Self {
if Unchanged::check_any_strict(data) {
return Self::unchanged();
}
Self::changed(T::container_copy_from_any_view_after_check(data))
}
unsafe fn move_from_any_after_check(data: &mut TVMFFIAny) -> Self {
Self {
data: Any::from_raw_ffi_any(std::mem::replace(data, TVMFFIAny::new())),
_marker: PhantomData,
}
}
unsafe fn try_cast_from_any_view(data: &TVMFFIAny) -> std::result::Result<Self, ()> {
if T::CONTAINER_IS_ANY && data.type_index == TVMFFITypeIndex::kTVMFFIError as i32 {
return Err(());
}
if Unchanged::check_any_strict(data) {
return Ok(Self::unchanged());
}
T::container_try_cast_from_any_view(data).map(Self::changed)
}
fn type_str() -> std::string::String {
format!("UnchangedOr<{}>", T::container_type_str())
}
fn type_schema() -> std::string::String {
crate::type_traits::type_schema("UnchangedOr", &[T::container_type_schema()])
}
}
impl<T: ContainerElement> TryFrom<Any> for UnchangedOr<T> {
type Error = Error;
#[inline]
fn try_from(value: Any) -> Result<Self> {
TryFromTemp::<Self>::try_from(value).map(TryFromTemp::into_value)
}
}
impl<'a, T: ContainerElement> TryFrom<AnyView<'a>> for UnchangedOr<T> {
type Error = Error;
#[inline]
fn try_from(value: AnyView<'a>) -> Result<Self> {
TryFromTemp::<Self>::try_from(value).map(TryFromTemp::into_value)
}
}
#[inline]
pub(crate) fn is_unchanged(value: &Any) -> bool {
value.type_index() == TVMFFITypeIndex::kTVMFFIUnchanged as i32
}