#[cfg(all(feature = "async", target_os = "linux"))]
pub mod multitask;
use crate::error::{AllocError, JlrsError, JlrsResult};
#[cfg(all(feature = "async", target_os = "linux"))]
use crate::frame::AsyncFrame;
use crate::frame::{DynamicFrame, NullFrame, Output, StaticFrame};
#[cfg(all(feature = "async", target_os = "linux"))]
use crate::mode::Async;
use crate::mode::{Mode, Sync};
use crate::value::datatype::DataType;
use crate::value::string::JuliaString;
use crate::value::symbol::Symbol;
use crate::value::Value;
use jl_sys::{
jl_bool_type, jl_box_bool, jl_box_char, jl_box_float32, jl_box_float64, jl_box_int16,
jl_box_int32, jl_box_int64, jl_box_int8, jl_box_uint16, jl_box_uint32, jl_box_uint64,
jl_box_uint8, jl_box_voidpointer, jl_char_type, jl_datatype_t, jl_float32_type,
jl_float64_type, jl_int16_type, jl_int32_type, jl_int64_type, jl_int8_type, jl_pchar_to_string,
jl_string_data, jl_string_len, jl_uint16_type, jl_uint32_type, jl_uint64_type, jl_uint8_type,
jl_unbox_float32, jl_unbox_float64, jl_unbox_int16, jl_unbox_int32, jl_unbox_int64,
jl_unbox_int8, jl_unbox_uint16, jl_unbox_uint32, jl_unbox_uint64, jl_unbox_uint8,
jl_unbox_voidpointer, jl_value_t, jl_voidpointer_type,
};
use std::borrow::Cow;
use std::ffi::c_void;
macro_rules! p {
($trait:ident, $type:ty, $($bounds:tt)+) => {
unsafe impl<$($bounds)+> $trait for $type {}
};
($trait:ident, $type:ty) => {
unsafe impl $trait for $type {}
};
}
pub unsafe trait TemporarySymbol: private::TemporarySymbol {}
pub unsafe trait ValidLayout {
#[doc(hidden)]
unsafe fn valid_layout(ty: Value) -> bool;
}
pub unsafe trait Align {
const ALIGNMENT: usize;
}
pub unsafe trait BitsUnion {}
pub unsafe trait Flag {}
unsafe impl Flag for u8 {}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_valid_layout {
($type:ty, $($lt:lifetime),+) => {
unsafe impl<$($lt),+> $crate::traits::ValidLayout for $type {
unsafe fn valid_layout(v: $crate::value::Value) -> bool {
if let Ok(dt) = v.cast::<$crate::value::datatype::DataType>() {
dt.is::<$type>()
} else {
false
}
}
}
};
($t:ty) => {
unsafe impl $crate::traits::ValidLayout for $t {
unsafe fn valid_layout(v: $crate::value::Value) -> bool {
if let Ok(dt) = v.cast::<$crate::value::datatype::DataType>() {
dt.is::<$t>()
} else {
false
}
}
}
}
}
pub unsafe trait IntoJulia {
#[doc(hidden)]
unsafe fn into_julia(&self) -> *mut jl_value_t;
}
pub unsafe trait JuliaType {
#[doc(hidden)]
unsafe fn julia_type() -> *mut jl_datatype_t;
}
pub unsafe trait JuliaStruct: Copy {}
pub unsafe trait JuliaTypecheck {
#[doc(hidden)]
unsafe fn julia_typecheck(t: DataType) -> bool;
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_julia_typecheck {
($type:ty, $jl_type:expr, $($lt:lifetime),+) => {
unsafe impl<$($lt),+> crate::traits::JuliaTypecheck for $type {
unsafe fn julia_typecheck(t: $crate::value::datatype::DataType) -> bool {
t.ptr() == $jl_type
}
}
};
($type:ty, $jl_type:expr) => {
unsafe impl crate::traits::JuliaTypecheck for $type {
unsafe fn julia_typecheck(t: $crate::value::datatype::DataType) -> bool {
t.ptr() == $jl_type
}
}
};
($type:ty) => {
unsafe impl crate::traits::JuliaTypecheck for $type {
unsafe fn julia_typecheck(t: crate::value::datatype::DataType) -> bool {
t.ptr() == <$type as $crate::traits::JuliaType>::julia_type()
}
}
};
}
impl_julia_typecheck!(i8);
impl_julia_typecheck!(i16);
impl_julia_typecheck!(i32);
impl_julia_typecheck!(i64);
impl_julia_typecheck!(isize);
impl_julia_typecheck!(u8);
impl_julia_typecheck!(u16);
impl_julia_typecheck!(u32);
impl_julia_typecheck!(u64);
impl_julia_typecheck!(usize);
impl_julia_typecheck!(f32);
impl_julia_typecheck!(f64);
impl_julia_typecheck!(bool);
impl_julia_typecheck!(char);
impl_julia_typecheck!(*mut c_void);
pub unsafe trait Cast<'frame, 'data> {
type Output;
#[doc(hidden)]
fn cast(value: Value<'frame, 'data>) -> JlrsResult<Self::Output>;
#[doc(hidden)]
unsafe fn cast_unchecked(value: Value<'frame, 'data>) -> Self::Output;
}
pub trait Frame<'frame>: private::Frame<'frame> {
fn frame<'nested, T, F: FnOnce(&mut StaticFrame<'nested, Self::U>) -> JlrsResult<T>>(
&'nested mut self,
capacity: usize,
func: F,
) -> JlrsResult<T>;
fn dynamic_frame<'nested, T, F: FnOnce(&mut DynamicFrame<'nested, Self::U>) -> JlrsResult<T>>(
&'nested mut self,
func: F,
) -> JlrsResult<T>;
fn output(&mut self) -> JlrsResult<Output<'frame>>;
fn size(&self) -> usize;
#[doc(hidden)]
fn print_memory(&self);
}
p!(TemporarySymbol, String);
p!(TemporarySymbol, &dyn AsRef<str>);
p!(TemporarySymbol, &'a str, 'a);
p!(TemporarySymbol, Cow<'a, str>, 'a);
p!(TemporarySymbol, Symbol<'s>, 's);
p!(TemporarySymbol, JuliaString<'frame>, 'frame);
impl_valid_layout!(bool);
impl_valid_layout!(char);
impl_valid_layout!(i8);
impl_valid_layout!(i16);
impl_valid_layout!(i32);
impl_valid_layout!(i64);
impl_valid_layout!(isize);
impl_valid_layout!(u8);
impl_valid_layout!(u16);
impl_valid_layout!(u32);
impl_valid_layout!(u64);
impl_valid_layout!(usize);
impl_valid_layout!(f32);
impl_valid_layout!(f64);
macro_rules! impl_into_julia {
($type:ty, $boxer:ident) => {
unsafe impl IntoJulia for $type {
unsafe fn into_julia(&self) -> *mut jl_value_t {
$boxer(*self)
}
}
};
($type:ty, $as:ty, $boxer:ident) => {
unsafe impl IntoJulia for $type {
unsafe fn into_julia(&self) -> *mut jl_value_t {
$boxer(*self as $as)
}
}
};
}
impl_into_julia!(bool, i8, jl_box_bool);
impl_into_julia!(char, u32, jl_box_char);
impl_into_julia!(u8, jl_box_uint8);
impl_into_julia!(u16, jl_box_uint16);
impl_into_julia!(u32, jl_box_uint32);
impl_into_julia!(u64, jl_box_uint64);
impl_into_julia!(i8, jl_box_int8);
impl_into_julia!(i16, jl_box_int16);
impl_into_julia!(i32, jl_box_int32);
impl_into_julia!(i64, jl_box_int64);
impl_into_julia!(f32, jl_box_float32);
impl_into_julia!(f64, jl_box_float64);
impl_into_julia!(*mut c_void, jl_box_voidpointer);
#[cfg(not(target_pointer_width = "64"))]
unsafe impl IntoJulia for usize {
unsafe fn into_julia(&self) -> *mut jl_value_t {
jl_box_uint32(*self as u32)
}
}
#[cfg(target_pointer_width = "64")]
unsafe impl IntoJulia for usize {
unsafe fn into_julia(&self) -> *mut jl_value_t {
jl_box_uint64(*self as u64)
}
}
#[cfg(not(target_pointer_width = "64"))]
unsafe impl IntoJulia for isize {
unsafe fn into_julia(&self) -> *mut jl_value_t {
jl_box_int32(*self as i32)
}
}
#[cfg(target_pointer_width = "64")]
unsafe impl IntoJulia for isize {
unsafe fn into_julia(&self) -> *mut jl_value_t {
jl_box_int64(*self as i64)
}
}
unsafe impl<'a> IntoJulia for &'a str {
unsafe fn into_julia(&self) -> *mut jl_value_t {
let ptr = self.as_ptr().cast();
let len = self.len();
jl_pchar_to_string(ptr, len)
}
}
unsafe impl<'a> IntoJulia for Cow<'a, str> {
unsafe fn into_julia(&self) -> *mut jl_value_t {
let ptr = self.as_ptr().cast();
let len = self.len();
jl_pchar_to_string(ptr, len)
}
}
unsafe impl IntoJulia for String {
unsafe fn into_julia(&self) -> *mut jl_value_t {
let ptr = self.as_ptr().cast();
let len = self.len();
jl_pchar_to_string(ptr, len)
}
}
unsafe impl IntoJulia for &dyn AsRef<str> {
unsafe fn into_julia(&self) -> *mut jl_value_t {
let ptr = self.as_ref().as_ptr().cast();
let len = self.as_ref().len();
jl_pchar_to_string(ptr, len)
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_julia_type {
($type:ty, $jl_type:expr) => {
unsafe impl crate::traits::JuliaType for $type {
unsafe fn julia_type() -> *mut ::jl_sys::jl_datatype_t {
$jl_type
}
}
};
($type:ty, $jl_type:expr, $($bounds:tt)+) => {
unsafe impl<$($bounds)+> crate::traits::JuliaType for $type {
unsafe fn julia_type() -> *mut ::jl_sys::jl_datatype_t {
$jl_type
}
}
};
}
impl_julia_type!(u8, jl_uint8_type);
impl_julia_type!(u16, jl_uint16_type);
impl_julia_type!(u32, jl_uint32_type);
impl_julia_type!(u64, jl_uint64_type);
impl_julia_type!(i8, jl_int8_type);
impl_julia_type!(i16, jl_int16_type);
impl_julia_type!(i32, jl_int32_type);
impl_julia_type!(i64, jl_int64_type);
impl_julia_type!(f32, jl_float32_type);
impl_julia_type!(f64, jl_float64_type);
impl_julia_type!(bool, jl_bool_type);
impl_julia_type!(char, jl_char_type);
impl_julia_type!(*mut c_void, jl_voidpointer_type);
#[cfg(not(target_pointer_width = "64"))]
unsafe impl JuliaType for usize {
unsafe fn julia_type() -> *mut jl_datatype_t {
jl_uint32_type
}
}
#[cfg(target_pointer_width = "64")]
unsafe impl JuliaType for usize {
unsafe fn julia_type() -> *mut jl_datatype_t {
jl_uint64_type
}
}
#[cfg(not(target_pointer_width = "64"))]
unsafe impl JuliaType for isize {
unsafe fn julia_type() -> *mut jl_datatype_t {
jl_int32_type
}
}
#[cfg(target_pointer_width = "64")]
unsafe impl JuliaType for isize {
unsafe fn julia_type() -> *mut jl_datatype_t {
jl_int64_type
}
}
macro_rules! impl_primitive_cast {
($type:ty, $unboxer:ident) => {
unsafe impl<'frame, 'data> Cast<'frame, 'data> for $type {
type Output = Self;
fn cast(value: Value<'frame, 'data>) -> JlrsResult<Self::Output> {
if value.is::<$type>() {
return unsafe { Ok(Self::cast_unchecked(value)) };
}
Err(JlrsError::WrongType)?
}
unsafe fn cast_unchecked(value: Value<'frame, 'data>) -> Self::Output {
$unboxer(value.ptr().cast()) as _
}
}
};
}
impl_primitive_cast!(u8, jl_unbox_uint8);
impl_primitive_cast!(u16, jl_unbox_uint16);
impl_primitive_cast!(u32, jl_unbox_uint32);
impl_primitive_cast!(u64, jl_unbox_uint64);
impl_primitive_cast!(i8, jl_unbox_int8);
impl_primitive_cast!(i16, jl_unbox_int16);
impl_primitive_cast!(i32, jl_unbox_int32);
impl_primitive_cast!(i64, jl_unbox_int64);
impl_primitive_cast!(f32, jl_unbox_float32);
impl_primitive_cast!(f64, jl_unbox_float64);
impl_primitive_cast!(*mut c_void, jl_unbox_voidpointer);
#[cfg(not(target_pointer_width = "64"))]
impl_primitive_cast!(usize, jl_unbox_uint32);
#[cfg(not(target_pointer_width = "64"))]
impl_primitive_cast!(isize, jl_unbox_int32);
#[cfg(target_pointer_width = "64")]
impl_primitive_cast!(usize, jl_unbox_uint64);
#[cfg(target_pointer_width = "64")]
impl_primitive_cast!(isize, jl_unbox_int64);
unsafe impl<'frame, 'data> Cast<'frame, 'data> for bool {
type Output = Self;
fn cast(value: Value<'frame, 'data>) -> JlrsResult<Self::Output> {
if value.is::<bool>() {
unsafe { return Ok(Self::cast_unchecked(value)) }
}
Err(JlrsError::WrongType)?
}
unsafe fn cast_unchecked(value: Value<'frame, 'data>) -> Self::Output {
jl_unbox_int8(value.ptr()) != 0
}
}
unsafe impl<'frame, 'data> Cast<'frame, 'data> for char {
type Output = Self;
fn cast(value: Value<'frame, 'data>) -> JlrsResult<Self::Output> {
if value.is::<char>() {
unsafe {
return std::char::from_u32(jl_unbox_uint32(value.ptr()))
.ok_or(JlrsError::InvalidCharacter.into());
}
}
Err(JlrsError::WrongType)?
}
unsafe fn cast_unchecked(value: Value<'frame, 'data>) -> Self::Output {
std::char::from_u32_unchecked(jl_unbox_uint32(value.ptr()))
}
}
unsafe impl<'frame, 'data> Cast<'frame, 'data> for String {
type Output = Self;
fn cast(value: Value<'frame, 'data>) -> JlrsResult<Self::Output> {
if value.is::<String>() {
unsafe {
let len = jl_string_len(value.ptr());
if len == 0 {
return Ok(String::new());
}
let raw = jl_string_data(value.ptr());
let raw_slice = std::slice::from_raw_parts(raw, len);
return Ok(String::from_utf8(raw_slice.into()).map_err(JlrsError::other)?);
}
}
Err(JlrsError::WrongType)?
}
unsafe fn cast_unchecked(value: Value<'frame, 'data>) -> Self::Output {
let len = jl_string_len(value.ptr());
if len == 0 {
return String::new();
}
let raw = jl_string_data(value.ptr());
let raw_slice = std::slice::from_raw_parts(raw, len);
let owned_slice = Vec::from(raw_slice);
String::from_utf8_unchecked(owned_slice)
}
}
impl<'frame, M: Mode> Frame<'frame> for StaticFrame<'frame, M> {
fn frame<'nested, T, F: FnOnce(&mut StaticFrame<'nested, M>) -> JlrsResult<T>>(
&'nested mut self,
capacity: usize,
func: F,
) -> JlrsResult<T> {
let mut frame = unsafe { self.nested_frame(capacity).unwrap() };
func(&mut frame)
}
fn dynamic_frame<'nested, T, F: FnOnce(&mut DynamicFrame<'nested, M>) -> JlrsResult<T>>(
&'nested mut self,
func: F,
) -> JlrsResult<T> {
unsafe {
let mut view = self.memory.nest_dynamic();
let idx = view.new_frame()?;
let mut frame = DynamicFrame {
idx,
len: 0,
memory: view,
};
func(&mut frame)
}
}
fn output(&mut self) -> JlrsResult<Output<'frame>> {
if self.capacity == self.len {
return Err(AllocError::FrameOverflow(1, self.len).into());
}
let out = unsafe {
let out = self.memory.new_output(self.idx, self.len);
self.len += 1;
out
};
Ok(out)
}
fn size(&self) -> usize {
self.len
}
fn print_memory(&self) {
self.memory.print_memory()
}
}
impl<'frame, M: Mode> Frame<'frame> for DynamicFrame<'frame, M> {
fn dynamic_frame<'nested, T, F: FnOnce(&mut DynamicFrame<'nested, M>) -> JlrsResult<T>>(
&'nested mut self,
func: F,
) -> JlrsResult<T> {
let mut frame = unsafe { self.nested_frame().unwrap() };
func(&mut frame)
}
fn frame<'nested, T, F: FnOnce(&mut StaticFrame<'nested, M>) -> JlrsResult<T>>(
&'nested mut self,
capacity: usize,
func: F,
) -> JlrsResult<T> {
unsafe {
let mut view = self.memory.nest_static();
let idx = view.new_frame(capacity)?;
let mut frame = StaticFrame {
idx,
capacity,
len: 0,
memory: view,
};
func(&mut frame)
}
}
fn output(&mut self) -> JlrsResult<Output<'frame>> {
unsafe {
let out = self.memory.new_output(self.idx)?;
self.len += 1;
Ok(out)
}
}
fn size(&self) -> usize {
self.len
}
fn print_memory(&self) {
self.memory.print_memory()
}
}
impl<'frame> Frame<'frame> for NullFrame<'frame> {
fn frame<'nested, T, F: FnOnce(&mut StaticFrame<'nested, Sync>) -> JlrsResult<T>>(
&'nested mut self,
_: usize,
_: F,
) -> JlrsResult<T> {
Err(JlrsError::NullFrame)?
}
fn dynamic_frame<'nested, T, F: FnOnce(&mut DynamicFrame<'nested, Sync>) -> JlrsResult<T>>(
&'nested mut self,
_: F,
) -> JlrsResult<T> {
Err(JlrsError::NullFrame)?
}
fn output(&mut self) -> JlrsResult<Output<'frame>> {
Err(JlrsError::NullFrame)?
}
fn size(&self) -> usize {
0
}
fn print_memory(&self) {}
}
#[cfg(all(feature = "async", target_os = "linux"))]
impl<'frame> Frame<'frame> for AsyncFrame<'frame> {
fn frame<'nested, T, F: FnOnce(&mut StaticFrame<'nested, Async>) -> JlrsResult<T>>(
&'nested mut self,
capacity: usize,
func: F,
) -> JlrsResult<T> {
unsafe {
let mut view = self.memory.nest_static();
let idx = view.new_frame(capacity)?;
let mut frame = StaticFrame {
idx,
capacity,
len: 0,
memory: view,
};
func(&mut frame)
}
}
fn dynamic_frame<'nested, T, F: FnOnce(&mut DynamicFrame<'nested, Async>) -> JlrsResult<T>>(
&'nested mut self,
func: F,
) -> JlrsResult<T> {
let mut frame = unsafe { self.nested_frame().unwrap() };
func(&mut frame)
}
fn output(&mut self) -> JlrsResult<Output<'frame>> {
unsafe {
let out = self.memory.new_output(self.idx)?;
self.len += 1;
Ok(out)
}
}
fn size(&self) -> usize {
self.len
}
fn print_memory(&self) {
self.memory.print_memory()
}
}
pub(crate) mod private {
use crate::error::AllocError;
#[cfg(all(feature = "async", target_os = "linux"))]
use crate::frame::AsyncFrame;
use crate::frame::{DynamicFrame, FrameIdx, NullFrame, Output, StaticFrame};
#[cfg(all(feature = "async", target_os = "linux"))]
use crate::mode::Async;
use crate::mode::{Mode, Sync};
use crate::value::string::JuliaString;
use crate::value::symbol::Symbol;
use crate::value::{Value, Values};
use jl_sys::jl_value_t;
use jl_sys::{jl_symbol, jl_symbol_n};
use std::borrow::Cow;
pub struct Internal;
pub trait TemporarySymbol {
unsafe fn temporary_symbol<'symbol>(&self, _: Internal) -> Symbol<'symbol>;
}
pub trait Frame<'frame> {
type U: Mode;
unsafe fn protect(
&mut self,
value: *mut jl_value_t,
_: Internal,
) -> Result<Value<'frame, 'static>, AllocError>;
fn create_many<P: super::IntoJulia>(
&mut self,
values: &[P],
_: Internal,
) -> Result<Values<'frame>, AllocError>;
fn create_many_dyn(
&mut self,
values: &[&dyn super::IntoJulia],
_: Internal,
) -> Result<Values<'frame>, AllocError>;
fn assign_output<'output>(
&mut self,
output: Output<'output>,
value: *mut jl_value_t,
_: Internal,
) -> Value<'output, 'static>;
}
impl<'a> TemporarySymbol for &'a str {
unsafe fn temporary_symbol<'symbol>(&self, _: Internal) -> Symbol<'symbol> {
let symbol_ptr = self.as_ptr();
let symbol = jl_symbol_n(symbol_ptr.cast(), self.len());
Symbol::wrap(symbol)
}
}
impl<'a> TemporarySymbol for Cow<'a, str> {
unsafe fn temporary_symbol<'symbol>(&self, _: Internal) -> Symbol<'symbol> {
let symbol_ptr = self.as_ptr().cast();
let symbol = jl_symbol_n(symbol_ptr, self.len());
Symbol::wrap(symbol)
}
}
impl TemporarySymbol for String {
unsafe fn temporary_symbol<'symbol>(&self, _: Internal) -> Symbol<'symbol> {
let symbol_ptr = self.as_ptr().cast();
let symbol = jl_symbol_n(symbol_ptr, self.len());
Symbol::wrap(symbol)
}
}
impl TemporarySymbol for &dyn AsRef<str> {
unsafe fn temporary_symbol<'symbol>(&self, _: Internal) -> Symbol<'symbol> {
let symbol_ptr = self.as_ref().as_ptr().cast();
let symbol = jl_symbol_n(symbol_ptr, self.as_ref().len());
Symbol::wrap(symbol)
}
}
impl<'frame> TemporarySymbol for JuliaString<'frame> {
unsafe fn temporary_symbol<'symbol>(&self, _: Internal) -> Symbol<'symbol> {
let symbol_ptr = self.as_c_str();
let symbol = jl_symbol(symbol_ptr.as_ptr());
Symbol::wrap(symbol)
}
}
impl<'s> TemporarySymbol for Symbol<'s> {
unsafe fn temporary_symbol<'symbol>(&self, _: Internal) -> Symbol<'symbol> {
Symbol::wrap(self.ptr())
}
}
impl<'frame, M: Mode> Frame<'frame> for StaticFrame<'frame, M> {
type U = M;
unsafe fn protect(
&mut self,
value: *mut jl_value_t,
_: Internal,
) -> Result<Value<'frame, 'static>, AllocError> {
if self.capacity == self.len {
return Err(AllocError::FrameOverflow(1, self.len));
}
let out = {
let out = self.memory.protect(self.idx, self.len, value.cast());
self.len += 1;
out
};
Ok(out)
}
fn create_many<P: super::IntoJulia>(
&mut self,
values: &[P],
_: Internal,
) -> Result<Values<'frame>, AllocError> {
unsafe {
if self.capacity < self.len + values.len() {
return Err(AllocError::FrameOverflow(values.len(), self.capacity()));
}
let offset = self.len;
for value in values {
self.memory
.protect(self.idx, self.len, value.into_julia().cast());
self.len += 1;
}
Ok(self.memory.as_values(self.idx, offset, values.len()))
}
}
fn create_many_dyn(
&mut self,
values: &[&dyn super::IntoJulia],
_: Internal,
) -> Result<Values<'frame>, AllocError> {
unsafe {
if self.capacity < self.len + values.len() {
return Err(AllocError::FrameOverflow(values.len(), self.capacity()));
}
let offset = self.len;
for value in values {
self.memory
.protect(self.idx, self.len, value.into_julia().cast());
self.len += 1;
}
Ok(self.memory.as_values(self.idx, offset, values.len()))
}
}
fn assign_output<'output>(
&mut self,
output: Output<'output>,
value: *mut jl_value_t,
_: Internal,
) -> Value<'output, 'static> {
unsafe {
self.memory
.protect(FrameIdx::default(), output.offset, value.cast())
}
}
}
impl<'frame, M: Mode> Frame<'frame> for DynamicFrame<'frame, M> {
type U = M;
unsafe fn protect(
&mut self,
value: *mut jl_value_t,
_: Internal,
) -> Result<Value<'frame, 'static>, AllocError> {
let out = self.memory.protect(self.idx, value.cast())?;
self.len += 1;
Ok(out)
}
fn create_many<P: super::IntoJulia>(
&mut self,
values: &[P],
_: Internal,
) -> Result<Values<'frame>, AllocError> {
unsafe {
let offset = self.len;
for value in values {
match self.memory.protect(self.idx, value.into_julia().cast()) {
Ok(_) => (),
Err(AllocError::StackOverflow(_, n)) => {
return Err(AllocError::StackOverflow(values.len(), n))
}
_ => unreachable!(),
}
self.len += 1;
}
Ok(self.memory.as_values(self.idx, offset, values.len()))
}
}
fn create_many_dyn(
&mut self,
values: &[&dyn super::IntoJulia],
_: Internal,
) -> Result<Values<'frame>, AllocError> {
unsafe {
let offset = self.len;
for value in values {
self.memory.protect(self.idx, value.into_julia().cast())?;
self.len += 1;
}
Ok(self.memory.as_values(self.idx, offset, values.len()))
}
}
fn assign_output<'output>(
&mut self,
output: Output<'output>,
value: *mut jl_value_t,
_: Internal,
) -> Value<'output, 'static> {
unsafe { self.memory.protect_output(output, value.cast()) }
}
}
impl<'frame> Frame<'frame> for NullFrame<'frame> {
type U = Sync;
unsafe fn protect(
&mut self,
_: *mut jl_value_t,
_: Internal,
) -> Result<Value<'frame, 'static>, AllocError> {
Err(AllocError::FrameOverflow(1, 0))
}
fn create_many<P: super::IntoJulia>(
&mut self,
values: &[P],
_: Internal,
) -> Result<Values<'frame>, AllocError> {
Err(AllocError::FrameOverflow(values.len(), 0))
}
fn create_many_dyn(
&mut self,
values: &[&dyn super::IntoJulia],
_: Internal,
) -> Result<Values<'frame>, AllocError> {
Err(AllocError::FrameOverflow(values.len(), 0))
}
fn assign_output<'output>(
&mut self,
_: Output<'output>,
_: *mut jl_value_t,
_: Internal,
) -> Value<'output, 'static> {
unreachable!()
}
}
#[cfg(all(feature = "async", target_os = "linux"))]
impl<'frame> Frame<'frame> for AsyncFrame<'frame> {
type U = Async;
unsafe fn protect(
&mut self,
value: *mut jl_value_t,
_: Internal,
) -> Result<Value<'frame, 'static>, AllocError> {
let out = self.memory.protect(self.idx, value.cast())?;
self.len += 1;
Ok(out)
}
fn create_many<P: super::IntoJulia>(
&mut self,
values: &[P],
_: Internal,
) -> Result<Values<'frame>, AllocError> {
unsafe {
let offset = self.len;
for value in values {
match self.memory.protect(self.idx, value.into_julia().cast()) {
Ok(_) => (),
Err(AllocError::StackOverflow(_, n)) => {
return Err(AllocError::StackOverflow(values.len(), n))
}
_ => unreachable!(),
}
self.len += 1;
}
Ok(self.memory.as_values(self.idx, offset, values.len()))
}
}
fn create_many_dyn(
&mut self,
values: &[&dyn super::IntoJulia],
_: Internal,
) -> Result<Values<'frame>, AllocError> {
unsafe {
let offset = self.len;
for value in values {
self.memory.protect(self.idx, value.into_julia().cast())?;
self.len += 1;
}
Ok(self.memory.as_values(self.idx, offset, values.len()))
}
}
fn assign_output<'output>(
&mut self,
output: Output<'output>,
value: *mut jl_value_t,
_: Internal,
) -> Value<'output, 'static> {
unsafe { self.memory.protect_output(output, value.cast()) }
}
}
}