macro_rules! impl_construct_type_managed {
($ty:ident, 1, $jl_ty:expr) => {
unsafe impl crate::data::types::construct_type::ConstructType for $ty<'_> {
type Static = $ty<'static>;
const CACHEABLE: bool = false;
#[inline]
fn construct_type_uncached<'target, 'current, 'borrow, Tgt>(
target: Tgt,
) -> $crate::data::managed::value::ValueData<'target, 'static, Tgt>
where
Tgt: $crate::memory::target::Target<'target>,
{
unsafe {
target.data_from_ptr(
NonNull::new_unchecked($jl_ty.cast::<::jl_sys::jl_value_t>()),
$crate::private::Private,
)
}
}
#[inline]
fn base_type<'target, Tgt>(_target: &Tgt) -> Option<$crate::data::managed::value::Value<'target, 'static>>
where
Tgt: crate::memory::target::Target<'target>,
{
unsafe {
let ptr = NonNull::new_unchecked($jl_ty.cast::<::jl_sys::jl_value_t>());
Some(<$crate::data::managed::value::Value as $crate::data::managed::private::ManagedPriv>::wrap_non_null(
ptr,
$crate::private::Private,
))
}
}
}
};
($ty:ident, 2, $jl_ty:expr) => {
unsafe impl crate::data::types::construct_type::ConstructType for $ty<'_, '_> {
type Static = $ty<'static, 'static>;
const CACHEABLE: bool = false;
#[inline]
fn construct_type_uncached<'target, 'current, 'borrow, Tgt>(
target: Tgt,
) -> $crate::data::managed::value::ValueData<'target, 'static, Tgt>
where
Tgt: $crate::memory::target::Target<'target>,
{
unsafe {
target.data_from_ptr(
NonNull::new_unchecked($jl_ty.cast::<::jl_sys::jl_value_t>()),
$crate::private::Private,
)
}
}
#[inline]
fn base_type<'target, Tgt>(_target: &Tgt) -> Option<$crate::data::managed::value::Value<'target, 'static>>
where
Tgt: crate::memory::target::Target<'target>,
{
unsafe {
let ptr = NonNull::new_unchecked($jl_ty.cast::<::jl_sys::jl_value_t>());
Some(<$crate::data::managed::value::Value as $crate::data::managed::private::ManagedPriv>::wrap_non_null(
ptr,
$crate::private::Private,
))
}
}
}
};
}
macro_rules! impl_ccall_arg_managed {
($ty:ident, 1) => {
unsafe impl<'scope> $crate::convert::ccall_types::CCallArg for $ty<'scope> {
type CCallArgType = $crate::data::managed::value::Value<'scope, 'static>;
type FunctionArgType = $ty<'scope>;
}
unsafe impl $crate::convert::ccall_types::CCallReturn
for $crate::data::managed::Ref<'static, 'static, $ty<'static>>
{
type CCallReturnType = $crate::data::managed::value::Value<'static, 'static>;
type FunctionReturnType = $ty<'static>;
type ReturnAs = Self;
#[inline]
unsafe fn return_or_throw(self) -> Self::ReturnAs {
self
}
}
};
($ty:ident, 2) => {
unsafe impl<'scope, 'data> $crate::convert::ccall_types::CCallArg for $ty<'scope, 'data> {
type CCallArgType = $crate::data::managed::value::Value<'static, 'static>;
type FunctionArgType = $ty<'scope, 'data>;
}
unsafe impl $crate::convert::ccall_types::CCallReturn
for $crate::data::managed::Ref<'static, 'static, $ty<'static, 'static>>
{
type CCallReturnType = $crate::data::managed::value::Value<'static, 'static>;
type FunctionReturnType = $ty<'static, 'static>;
type ReturnAs = Self;
#[inline]
unsafe fn return_or_throw(self) -> Self::ReturnAs {
self
}
}
};
}
macro_rules! impl_into_typed {
($ty:ident) => {
impl<'scope, 'data> $crate::data::managed::value::typed::AsTyped<'scope, 'data>
for $ty<'scope>
{
#[inline]
fn as_typed(
self,
) -> $crate::error::JlrsResult<
$crate::data::managed::value::typed::TypedValue<'scope, 'data, Self>,
> {
unsafe {
Ok(
$crate::data::managed::value::typed::TypedValue::wrap_non_null(
self.unwrap_non_null($crate::private::Private).cast(),
$crate::private::Private,
),
)
}
}
}
};
}
macro_rules! impl_valid_layout {
($ref_type:ident, $type:ident, $type_obj:ident) => {
unsafe impl $crate::data::layout::valid_layout::ValidLayout for $ref_type<'_> {
fn valid_layout(ty: $crate::data::managed::value::Value) -> bool {
if ty.is::<$crate::data::managed::datatype::DataType>() {
let dt = unsafe { ty.cast_unchecked::<$crate::data::managed::datatype::DataType>() };
dt.is::<$type>()
} else {
false
}
}
fn type_object<'target, Tgt>(
_: &Tgt
) -> $crate::data::managed::value::Value<'target, 'static>
where
Tgt: $crate::memory::target::Target<'target>
{
unsafe {
<$crate::data::managed::value::Value as $crate::data::managed::private::ManagedPriv>::wrap_non_null(
std::ptr::NonNull::new_unchecked($type_obj.cast()),
$crate::private::Private
)
}
}
const IS_REF: bool = true;
}
unsafe impl $crate::data::layout::valid_layout::ValidField for Option<$ref_type<'_>> {
#[inline]
fn valid_field(ty: $crate::data::managed::value::Value) -> bool {
if ty.is::<$crate::data::managed::datatype::DataType>() {
let dt = unsafe { ty.cast_unchecked::<$crate::data::managed::datatype::DataType>() };
dt.is::<$type>()
} else {
false
}
}
}
unsafe impl $crate::data::layout::valid_layout::ValidLayout for $type<'_> {
#[inline]
fn valid_layout(ty: $crate::data::managed::value::Value) -> bool {
if ty.is::<$crate::data::managed::datatype::DataType>() {
let dt = unsafe { ty.cast_unchecked::<$crate::data::managed::datatype::DataType>() };
dt.is::<$type>()
} else {
false
}
}
fn type_object<'target, Tgt>(
_: &Tgt
) -> $crate::data::managed::value::Value<'target, 'static>
where
Tgt: $crate::memory::target::Target<'target>
{
unsafe {
<$crate::data::managed::value::Value as $crate::data::managed::private::ManagedPriv>::wrap_non_null(
std::ptr::NonNull::new_unchecked($type_obj.cast()),
$crate::private::Private
)
}
}
const IS_REF: bool = true;
}
unsafe impl $crate::data::layout::valid_layout::ValidField for Option<$type<'_>> {
#[inline]
fn valid_field(ty: $crate::data::managed::value::Value) -> bool {
if ty.is::<$crate::data::managed::datatype::DataType>() {
let dt = unsafe { ty.cast_unchecked::<$crate::data::managed::datatype::DataType>() };
dt.is::<$type>()
} else {
false
}
}
}
};
}
macro_rules! impl_debug {
($type:ty) => {
impl ::std::fmt::Debug for $type {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match <Self as $crate::data::managed::Managed>::display_string(*self) {
Ok(s) => f.write_str(&s),
Err(e) => f.write_fmt(format_args!("<Cannot display value: {}>", e)),
}
}
}
};
}
pub mod array;
pub mod ccall_ref;
pub mod datatype;
pub mod function;
#[cfg(feature = "internal-types")]
pub mod internal;
pub mod module;
pub mod parachute;
pub mod rust_result;
pub mod simple_vector;
pub mod string;
pub mod symbol;
pub mod task;
pub mod type_name;
pub mod type_var;
pub mod union;
pub mod union_all;
pub mod value;
use std::{
ffi::c_void,
fmt::{Debug, Formatter, Result as FmtResult},
marker::PhantomData,
ptr::NonNull,
};
use jl_sys::jl_stderr_obj;
use self::module::JlrsCore;
use crate::{
call::Call,
data::{
layout::valid_layout::{ValidField, ValidLayout},
managed::{module::Module, private::ManagedPriv as _, string::JuliaString, value::Value},
},
error::{JlrsError, JlrsResult, CANNOT_DISPLAY_VALUE},
memory::target::{unrooted::Unrooted, Target},
private::Private,
};
pub trait ManagedRef<'scope, 'data>:
private::ManagedRef<'scope, 'data> + Copy + Debug + ValidLayout
{
type Managed: Managed<'scope, 'data>;
}
impl<'scope, 'data, T> ManagedRef<'scope, 'data> for Ref<'scope, 'data, T>
where
T: Managed<'scope, 'data>,
Self: Copy + ValidLayout,
Option<Self>: ValidField,
{
type Managed = T;
}
pub trait Managed<'scope, 'data>: private::ManagedPriv<'scope, 'data> {
type TypeConstructor<'target, 'da>: Managed<'target, 'da>;
#[inline]
fn as_ref(self) -> Ref<'scope, 'data, Self> {
Ref::wrap(self.unwrap_non_null(Private))
}
#[inline]
fn as_value(self) -> Value<'scope, 'data> {
unsafe { Value::wrap_non_null(self.unwrap_non_null(Private).cast(), Private) }
}
#[inline]
fn root<'target, T>(self, target: T) -> T::Data<'data, Self::TypeConstructor<'target, 'data>>
where
T: Target<'target>,
{
unsafe { target.data_from_ptr(self.unwrap_non_null(Private).cast(), Private) }
}
#[inline]
fn unrooted_target(self) -> Unrooted<'scope> {
unsafe { Unrooted::new() }
}
fn display_string(self) -> JlrsResult<String> {
let global = self.unrooted_target();
let s = unsafe {
JlrsCore::value_string(&global)
.call1(&global, self.as_value())
.map_err(|e| e.as_value().error_string_or(CANNOT_DISPLAY_VALUE))
.map_err(|e| JlrsError::exception(format!("JlrsCore.valuestring failed: {}", e)))?
.as_value()
.cast::<JuliaString>()?
.as_str()?
.to_string()
};
Ok(s)
}
fn error_string(self) -> JlrsResult<String> {
let global = self.unrooted_target();
let s = unsafe {
JlrsCore::error_string(&global)
.call1(&global, self.as_value())
.map_err(|e| e.as_value().error_string_or(CANNOT_DISPLAY_VALUE))
.map_err(|e| JlrsError::exception(format!("JlrsCore.errorstring failed: {}", e)))?
.as_value()
.cast::<JuliaString>()?
.as_str()?
.to_string()
};
Ok(s)
}
#[doc(hidden)]
unsafe fn print_error(self) {
let unrooted = Unrooted::new();
let stderr = Value::wrap_non_null(NonNull::new_unchecked(jl_stderr_obj()), Private);
let showerror = Module::base(&unrooted)
.global(unrooted, "showerror")
.unwrap()
.as_value();
showerror.call2(unrooted, stderr, self.as_value()).ok();
}
fn display_string_or<S: Into<String>>(self, default: S) -> String {
self.display_string().unwrap_or(default.into())
}
fn error_string_or<S: Into<String>>(self, default: S) -> String {
self.error_string().unwrap_or(default.into())
}
#[inline]
fn leak(self) -> Ref<'static, 'data, Self::TypeConstructor<'static, 'data>> {
self.as_ref().leak()
}
}
pub type ManagedType<'target, 'scope, 'data, T> =
<<T as ManagedRef<'scope, 'data>>::Managed as Managed<'scope, 'data>>::TypeConstructor<
'target,
'data,
>;
impl<'scope, 'data, W> Managed<'scope, 'data> for W
where
W: private::ManagedPriv<'scope, 'data>,
{
type TypeConstructor<'target, 'da> = Self::TypeConstructorPriv<'target, 'da>;
}
#[repr(transparent)]
pub struct Ref<'scope, 'data, T: Managed<'scope, 'data>>(
NonNull<T::Wraps>,
PhantomData<&'scope ()>,
PhantomData<&'data ()>,
);
impl<'scope, 'data, T> Clone for Ref<'scope, 'data, T>
where
T: Managed<'scope, 'data>,
{
#[inline]
fn clone(&self) -> Self {
Ref(self.0, PhantomData, PhantomData)
}
}
impl<'scope, 'data, T> Copy for Ref<'scope, 'data, T> where T: Managed<'scope, 'data> {}
impl<'scope, 'data, T: Managed<'scope, 'data>> Debug for Ref<'scope, 'data, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "Ref<{}>", T::NAME)
}
}
impl<'scope, 'data, W: Managed<'scope, 'data>> Ref<'scope, 'data, W> {
#[inline]
pub unsafe fn root<'target, T>(
self,
target: T,
) -> T::Data<'data, W::TypeConstructor<'target, 'data>>
where
T: Target<'target>,
{
target.data_from_ptr(self.ptr().cast(), Private)
}
#[inline]
pub(crate) fn wrap(ptr: NonNull<W::Wraps>) -> Self {
Ref(ptr, PhantomData, PhantomData)
}
#[inline]
pub unsafe fn as_managed(self) -> W {
W::wrap_non_null(self.ptr(), Private)
}
#[inline]
pub unsafe fn as_value(self) -> Value<'scope, 'data> {
Value::wrap_non_null(self.data_ptr().cast(), Private)
}
#[inline]
pub unsafe fn assume_owned(self) -> Ref<'scope, 'static, W::TypeConstructor<'scope, 'static>> {
Ref::wrap(self.ptr().cast())
}
#[inline]
pub fn leak(self) -> Ref<'static, 'data, W::TypeConstructor<'static, 'data>> {
Ref::wrap(self.ptr().cast())
}
#[inline]
pub fn data_ptr(self) -> NonNull<c_void> {
self.ptr().cast()
}
#[inline]
pub(crate) fn ptr(self) -> NonNull<W::Wraps> {
self.0
}
}
#[inline]
pub fn leak<'scope, 'data, M: Managed<'scope, 'data>>(
data: M,
) -> Ref<'static, 'data, M::TypeConstructor<'static, 'data>> {
data.as_ref().leak()
}
#[inline]
pub unsafe fn assume_rooted<'scope, M: Managed<'scope, 'static>>(
data: Ref<'scope, 'static, M>,
) -> M {
data.as_managed()
}
#[inline]
pub unsafe fn erase_scope_lifetime<'scope, 'data, M: Managed<'scope, 'data>>(
data: M,
) -> M::TypeConstructor<'static, 'data> {
data.leak().as_managed()
}
pub(crate) mod private {
use std::{fmt::Debug, ptr::NonNull};
use crate::{
data::managed::{value::Value, Ref},
private::Private,
};
pub trait ManagedPriv<'scope, 'data>: Copy + Debug {
type Wraps;
type TypeConstructorPriv<'target, 'da>: ManagedPriv<'target, 'da>;
const NAME: &'static str;
unsafe fn wrap_non_null(inner: NonNull<Self::Wraps>, _: Private) -> Self;
#[inline]
unsafe fn from_value_unchecked(value: Value<'scope, 'data>, _: Private) -> Self {
Self::wrap_non_null(value.unwrap_non_null(Private).cast(), Private)
}
fn unwrap_non_null(self, _: Private) -> NonNull<Self::Wraps>;
#[inline]
fn unwrap(self, _: Private) -> *mut Self::Wraps {
self.unwrap_non_null(Private).as_ptr()
}
}
pub trait ManagedRef<'scope, 'data> {}
impl<'scope, 'data, T> ManagedRef<'scope, 'data> for Ref<'scope, 'data, T> where
T: ManagedPriv<'scope, 'data>
{
}
}