use core::{
cmp::Ordering,
fmt::{self, Display, Write},
};
use alloc::{
string::{String, ToString},
vec::Vec,
};
#[cfg(feature = "std")]
use std::error;
use evil_janet::{Janet as CJanet, JanetType as CJanetType};
pub mod array;
pub mod buffer;
pub mod fiber;
pub mod function;
pub mod io;
#[path = "types/abstract.rs"]
pub mod janet_abstract;
pub mod pointer;
pub mod string;
pub mod structs;
pub mod symbol;
pub mod table;
pub mod tuple;
mod random;
pub use array::JanetArray;
pub use buffer::JanetBuffer;
pub use fiber::JanetFiber;
pub use function::{JanetCFunction, JanetFunction};
pub use janet_abstract::{IsJanetAbstract, JanetAbstract};
pub use pointer::JanetPointer;
pub use random::JanetRng;
pub use string::JanetString;
pub use structs::JanetStruct;
pub use symbol::{JanetKeyword, JanetSymbol};
pub use table::JanetTable;
pub use tuple::JanetTuple;
use crate::env::JanetEnvironment;
pub trait DeepEq<Rhs = Self> {
fn deep_eq(&self, other: &Rhs) -> bool;
}
#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
pub struct JanetConversionError;
#[cfg(feature = "std")]
#[cfg_attr(_doc, doc(cfg(feature = "std")))]
impl error::Error for JanetConversionError {}
impl Display for JanetConversionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad("Error converting Janet to concrete type")
}
}
#[allow(clippy::derive_ord_xor_partial_ord)]
#[allow(clippy::derive_hash_xor_eq)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct Janet {
pub(crate) inner: CJanet,
}
impl Janet {
#[inline]
pub fn nil() -> Self {
Self {
inner: unsafe { evil_janet::janet_wrap_nil() },
}
}
#[inline]
pub fn boolean(value: bool) -> Self {
Self {
inner: unsafe { evil_janet::janet_wrap_boolean(value.into()) },
}
}
#[inline]
pub fn number(value: f64) -> Self {
Self {
inner: unsafe { evil_janet::janet_wrap_number(value) },
}
}
#[inline]
pub fn integer(value: i32) -> Self {
Self {
inner: unsafe { evil_janet::janet_wrap_integer(value) },
}
}
#[inline]
pub fn int64(value: i64) -> Self {
Self::j_abstract(JanetAbstract::new(value))
}
#[inline]
pub fn uint64(value: u64) -> Self {
Self::j_abstract(JanetAbstract::new(value))
}
#[inline]
pub fn array(value: JanetArray<'_>) -> Self {
Self {
inner: unsafe { evil_janet::janet_wrap_array(value.raw) },
}
}
#[inline]
pub fn buffer(value: JanetBuffer<'_>) -> Self {
Self {
inner: unsafe { evil_janet::janet_wrap_buffer(value.raw) },
}
}
#[inline]
pub fn table(value: JanetTable<'_>) -> Self {
Self {
inner: unsafe { evil_janet::janet_wrap_table(value.raw) },
}
}
#[inline]
pub fn tuple(value: JanetTuple<'_>) -> Self {
Self {
inner: unsafe { evil_janet::janet_wrap_tuple(value.raw) },
}
}
#[inline]
pub fn string(value: JanetString<'_>) -> Self {
Self {
inner: unsafe { evil_janet::janet_wrap_string(value.raw) },
}
}
#[inline]
pub fn structs(value: JanetStruct<'_>) -> Self {
Self {
inner: unsafe { evil_janet::janet_wrap_struct(value.raw) },
}
}
#[inline]
pub fn symbol(value: JanetSymbol<'_>) -> Self {
Self {
inner: unsafe { evil_janet::janet_wrap_symbol(value.raw) },
}
}
#[inline]
pub fn keyword(value: JanetKeyword<'_>) -> Self {
Self {
inner: unsafe { evil_janet::janet_wrap_keyword(value.raw) },
}
}
#[inline]
pub fn fiber(value: JanetFiber<'_>) -> Self {
Self {
inner: unsafe { evil_janet::janet_wrap_fiber(value.raw) },
}
}
#[inline]
pub fn function(value: JanetFunction<'_>) -> Self {
Self {
inner: unsafe { evil_janet::janet_wrap_function(value.raw) },
}
}
#[inline]
pub fn c_function(value: JanetCFunction) -> Self {
Self {
inner: unsafe { evil_janet::janet_wrap_cfunction(value) },
}
}
#[inline]
pub fn pointer(value: JanetPointer) -> Self {
Self {
inner: unsafe { evil_janet::janet_wrap_pointer(value.as_ptr()) },
}
}
#[inline]
pub fn j_abstract(value: JanetAbstract) -> Self {
Self {
inner: unsafe { evil_janet::janet_wrap_abstract(value.raw) },
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn dynamic(key: impl AsRef<[u8]>) -> Option<Self> {
Self::_dynamic(key.as_ref())
}
fn _dynamic(key: &[u8]) -> Option<Self> {
let mut key: JanetBuffer = key.into();
key.push('\0');
let janet = Self::from(unsafe { evil_janet::janet_dyn(key.as_ptr() as *const _) });
if janet.is_nil() { None } else { Some(janet) }
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn from_core<'a>(symbol: impl Into<JanetSymbol<'a>>) -> Option<Self> {
let env = JanetEnvironment::default();
env.resolve(symbol)
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn wrap(value: impl Into<Self>) -> Self {
value.into()
}
#[inline]
pub fn unwrap<'data>(self) -> TaggedJanet<'data> {
self.into()
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn unwrap_or<T: TryFrom<Self>>(self, default: T) -> T {
T::try_from(self).unwrap_or(default)
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn unwrap_or_else<T, F>(self, op: F) -> T
where
T: TryFrom<Self>,
F: FnOnce(T::Error) -> T,
{
T::try_from(self).unwrap_or_else(op)
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn unwrap_or_default<T>(self) -> T
where T: TryFrom<Self> + Default {
T::try_from(self).unwrap_or_default()
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn try_unwrap<T: TryFrom<Self>>(self) -> Result<T, T::Error> {
T::try_from(self)
}
#[inline]
pub fn is_nil(&self) -> bool {
matches!(self.kind(), JanetType::Nil)
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn len(&self) -> Option<i32> {
match self.unwrap() {
TaggedJanet::Array(x) => Some(x.len()),
TaggedJanet::Buffer(x) => Some(x.len()),
TaggedJanet::Keyword(x) => Some(x.len()),
TaggedJanet::String(x) => Some(x.len()),
TaggedJanet::Struct(x) => Some(x.len()),
TaggedJanet::Symbol(x) => Some(x.len()),
TaggedJanet::Table(x) => Some(x.len()),
TaggedJanet::Tuple(x) => Some(x.len()),
TaggedJanet::Abstract(_) => {
self.get_method("length")
.and_then(|method: Self| match method.unwrap() {
TaggedJanet::CFunction(fun) => fun,
_ => None,
})
.map(|f| {
unsafe { f(1, [self.inner].as_mut_ptr()) }.into()
})
.and_then(|len: Self| match len.unwrap() {
TaggedJanet::Number(x) => {
if x >= i32::MIN as f64
&& x <= i32::MAX as f64
&& (x - x as i32 as f64).abs() < f64::EPSILON
{
Some(x as i32)
} else {
None
}
},
_ => None,
})
},
_ => None,
}
}
#[inline]
pub fn is_empty(&self) -> bool {
matches!(self.len(), Some(0))
}
#[inline]
pub fn is_truthy(&self) -> bool {
unsafe { evil_janet::janet_truthy(self.inner) == 0 }
}
#[inline]
pub fn get_method(&self, method_name: &str) -> Option<Self> {
let method_name: Self = JanetKeyword::from(method_name).into();
let method: Self = unsafe { evil_janet::janet_get(self.inner, method_name.inner) }.into();
if method.is_nil() {
return None;
}
Some(method)
}
#[inline]
pub fn has_method(&self, method_name: &str) -> bool {
self.get_method(method_name).is_some()
}
#[inline]
pub fn kind(&self) -> JanetType {
unsafe { evil_janet::janet_type(self.inner) }.into()
}
#[inline]
pub const fn raw_data(&self) -> CJanet {
self.inner
}
}
impl fmt::Debug for Janet {
#[cfg_attr(feature = "inline-more", inline)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("Janet").field(&self.unwrap()).finish()
}
}
macro_rules! struct_table_display {
($id:ident, $f:expr) => {
let len = $id.len();
if len > 10 {
let keys: JanetTuple = $id.keys().collect();
for i in 0..3 {
let key = unsafe { keys.get_unchecked(i) };
let value = unsafe { $id.get_unchecked(key) };
Display::fmt(key, $f)?;
$f.write_str(" : ")?;
Display::fmt(value, $f)?;
$f.write_str(", ")?;
}
$f.write_str("..., ")?;
for i in len - 4..len - 2 {
let key = unsafe { keys.get_unchecked(i) };
let value = unsafe { $id.get_unchecked(key) };
Display::fmt(key, $f)?;
$f.write_str(" : ")?;
Display::fmt(value, $f)?;
$f.write_str(", ")?;
}
let key = unsafe { keys.get_unchecked(len - 1) };
let value = unsafe { $id.get_unchecked(key) };
Display::fmt(key, $f)?;
$f.write_str(" : ")?;
Display::fmt(value, $f)?;
} else {
let mut count = $id.len();
for (key, value) in $id.iter() {
Display::fmt(key, $f)?;
$f.write_str(" : ")?;
Display::fmt(value, $f)?;
if count != 1 {
$f.write_str(", ")?;
}
count -= 1;
}
}
};
}
macro_rules! array_tuple_display {
($id:ident, $f:expr) => {
let mut len = $id.len();
if len > 10 {
let len = len;
for i in 0..5 {
let it = unsafe { $id.get_unchecked(i) };
Display::fmt(it, $f)?;
$f.write_str(", ")?;
}
$f.write_str("..., ")?;
for i in len - 5..len - 1 {
let it = unsafe { $id.get_unchecked(i) };
Display::fmt(it, $f)?;
$f.write_str(", ")?;
}
let it = unsafe { $id.get_unchecked(len) };
Display::fmt(it, $f)?;
} else {
for it in $id.iter() {
Display::fmt(it, $f)?;
if len != 1 {
$f.write_str(", ")?;
}
len -= 1;
}
}
};
}
impl Display for Janet {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.unwrap(), f)
}
}
#[cfg(feature = "std")]
#[cfg_attr(_doc, doc(cfg(feature = "std")))]
impl error::Error for Janet {}
impl PartialEq<&Self> for Janet {
#[inline]
fn eq(&self, other: &&Self) -> bool {
self.eq(*other)
}
}
impl PartialOrd<&Self> for Janet {
#[inline]
fn partial_cmp(&self, other: &&Self) -> Option<Ordering> {
self.partial_cmp(*other)
}
}
impl PartialEq<Janet> for &Janet {
#[inline]
fn eq(&self, other: &Janet) -> bool {
(*self).eq(other)
}
}
impl PartialOrd<Janet> for &Janet {
#[inline]
fn partial_cmp(&self, other: &Janet) -> Option<Ordering> {
(*self).partial_cmp(other)
}
}
impl DeepEq for Janet {
#[inline]
fn deep_eq(&self, other: &Self) -> bool {
match (self.unwrap(), other.unwrap()) {
(TaggedJanet::Array(s), TaggedJanet::Array(ref o)) => s.deep_eq(o),
(TaggedJanet::Array(s), TaggedJanet::Tuple(ref o)) => s.deep_eq(o),
(TaggedJanet::Tuple(s), TaggedJanet::Array(ref o)) => s.deep_eq(o),
(TaggedJanet::Buffer(s), TaggedJanet::Buffer(ref o)) => s.deep_eq(o),
(TaggedJanet::Buffer(s), TaggedJanet::String(ref o)) => s.deep_eq(o),
(TaggedJanet::String(s), TaggedJanet::Buffer(ref o)) => s.deep_eq(o),
(TaggedJanet::Struct(s), TaggedJanet::Struct(ref o)) => s.deep_eq(o),
(TaggedJanet::Struct(s), TaggedJanet::Table(ref o)) => s.deep_eq(o),
(TaggedJanet::Table(s), TaggedJanet::Struct(ref o)) => s.deep_eq(o),
(TaggedJanet::Table(s), TaggedJanet::Table(ref o)) => s.deep_eq(o),
_ => self.eq(other),
}
}
}
impl From<CJanet> for Janet {
#[inline]
fn from(val: CJanet) -> Self {
Self { inner: val }
}
}
impl From<&CJanet> for Janet {
#[inline]
fn from(val: &CJanet) -> Self {
Self { inner: *val }
}
}
impl From<&Self> for Janet {
#[inline]
fn from(val: &Self) -> Self {
*val
}
}
impl From<i32> for Janet {
#[inline]
fn from(val: i32) -> Self {
Self::integer(val)
}
}
impl From<&i32> for Janet {
#[inline]
fn from(val: &i32) -> Self {
Self::integer(*val)
}
}
impl TryFrom<Janet> for i32 {
type Error = JanetConversionError;
#[inline]
fn try_from(value: Janet) -> Result<Self, Self::Error> {
if matches!(value.kind(), JanetType::Number) {
Ok(unsafe { evil_janet::janet_unwrap_integer(value.inner) })
} else {
Err(JanetConversionError)
}
}
}
impl From<i64> for Janet {
#[inline]
fn from(val: i64) -> Self {
Self::int64(val)
}
}
impl From<&i64> for Janet {
#[inline]
fn from(val: &i64) -> Self {
Self::int64(*val)
}
}
impl TryFrom<Janet> for i64 {
type Error = JanetConversionError;
#[inline]
fn try_from(value: Janet) -> Result<Self, Self::Error> {
if let TaggedJanet::Abstract(x) = value.unwrap() {
if x.is::<Self>() {
Ok(unsafe { *x.cast() })
} else {
Err(JanetConversionError)
}
} else {
Err(JanetConversionError)
}
}
}
impl From<u64> for Janet {
#[inline]
fn from(val: u64) -> Self {
Self::uint64(val)
}
}
impl From<&u64> for Janet {
#[inline]
fn from(val: &u64) -> Self {
Self::uint64(*val)
}
}
impl TryFrom<Janet> for u64 {
type Error = JanetConversionError;
#[inline]
fn try_from(value: Janet) -> Result<Self, Self::Error> {
if let TaggedJanet::Abstract(x) = value.unwrap() {
if x.is::<Self>() {
Ok(unsafe { *x.cast() })
} else {
Err(JanetConversionError)
}
} else {
Err(JanetConversionError)
}
}
}
impl From<&str> for Janet {
#[inline]
fn from(val: &str) -> Self {
if let Some(val) = val.strip_prefix(':') {
let s = JanetKeyword::new(val);
Self::keyword(s)
} else {
let s = JanetString::new(val);
Self::string(s)
}
}
}
impl From<char> for Janet {
#[inline]
fn from(val: char) -> Self {
let s = JanetString::from(val);
Self::string(s)
}
}
impl From<&char> for Janet {
#[inline]
fn from(val: &char) -> Self {
let s = JanetString::from(val);
Self::string(s)
}
}
impl From<JanetCFunction> for Janet {
#[inline]
fn from(val: JanetCFunction) -> Self {
Self::c_function(val)
}
}
impl From<Janet> for CJanet {
#[inline]
fn from(val: Janet) -> Self {
val.inner
}
}
impl From<&Janet> for CJanet {
#[inline]
fn from(val: &Janet) -> Self {
val.inner
}
}
impl PartialEq<CJanet> for Janet {
#[inline]
fn eq(&self, other: &CJanet) -> bool {
self.inner.eq(other)
}
}
impl PartialEq<Janet> for CJanet {
#[inline]
fn eq(&self, other: &Janet) -> bool {
self.eq(&other.inner)
}
}
impl PartialOrd<CJanet> for Janet {
#[inline]
fn partial_cmp(&self, other: &CJanet) -> Option<Ordering> {
self.inner.partial_cmp(other)
}
}
impl PartialOrd<Janet> for CJanet {
#[inline]
fn partial_cmp(&self, other: &Janet) -> Option<Ordering> {
self.partial_cmp(&other.inner)
}
}
impl PartialEq<&CJanet> for Janet {
#[inline]
fn eq(&self, other: &&CJanet) -> bool {
self.inner.eq(*other)
}
}
impl PartialEq<&Janet> for CJanet {
#[inline]
fn eq(&self, other: &&Janet) -> bool {
self.eq(&(*other).inner)
}
}
impl PartialOrd<&CJanet> for Janet {
#[inline]
fn partial_cmp(&self, other: &&CJanet) -> Option<Ordering> {
self.inner.partial_cmp(*other)
}
}
impl PartialOrd<&Janet> for CJanet {
#[inline]
fn partial_cmp(&self, other: &&Janet) -> Option<Ordering> {
self.partial_cmp(&(*other).inner)
}
}
macro_rules! from_for_janet {
($ty:ty, $fn_name:ident) => {
impl From<$ty> for Janet {
#[inline]
fn from(val: $ty) -> Self {
Self::$fn_name(val)
}
}
};
(clone $ty:ty, $fn_name:ident) => {
impl From<$ty> for Janet {
#[inline]
fn from(val: $ty) -> Self {
Self::$fn_name(val.clone())
}
}
};
(deref $ty:ty, $fn_name:ident) => {
impl From<$ty> for Janet {
#[inline]
fn from(val: $ty) -> Self {
Self::$fn_name(*val)
}
}
};
}
macro_rules! try_from_janet {
($ty:ty, $kind:path) => {
impl TryFrom<Janet> for $ty {
type Error = JanetConversionError;
#[inline]
fn try_from(value: Janet) -> Result<Self, Self::Error> {
if let $kind(x) = value.unwrap() {
Ok(x)
} else {
Err(JanetConversionError)
}
}
}
};
}
from_for_janet!(JanetPointer, pointer);
from_for_janet!(deref & JanetPointer, pointer);
try_from_janet!(JanetPointer, TaggedJanet::Pointer);
from_for_janet!(JanetAbstract, j_abstract);
try_from_janet!(JanetAbstract, TaggedJanet::Abstract);
from_for_janet!(JanetTable<'_>, table);
from_for_janet!(clone &JanetTable<'_>, table);
try_from_janet!(JanetTable<'_>, TaggedJanet::Table);
from_for_janet!(JanetArray<'_>, array);
from_for_janet!(clone &JanetArray<'_>, array);
try_from_janet!(JanetArray<'_>, TaggedJanet::Array);
from_for_janet!(JanetBuffer<'_>, buffer);
from_for_janet!(clone &JanetBuffer<'_>, buffer);
try_from_janet!(JanetBuffer<'_>, TaggedJanet::Buffer);
from_for_janet!(JanetTuple<'_>, tuple);
from_for_janet!(clone &JanetTuple<'_>, tuple);
try_from_janet!(JanetTuple<'_>, TaggedJanet::Tuple);
from_for_janet!(JanetString<'_>, string);
from_for_janet!(clone &JanetString<'_>, string);
try_from_janet!(JanetString<'_>, TaggedJanet::String);
from_for_janet!(JanetStruct<'_>, structs);
from_for_janet!(clone &JanetStruct<'_>, structs);
try_from_janet!(JanetStruct<'_>, TaggedJanet::Struct);
from_for_janet!(JanetSymbol<'_>, symbol);
from_for_janet!(clone &JanetSymbol<'_>, symbol);
try_from_janet!(JanetSymbol<'_>, TaggedJanet::Symbol);
from_for_janet!(JanetKeyword<'_>, keyword);
from_for_janet!(clone &JanetKeyword<'_>, keyword);
try_from_janet!(JanetKeyword<'_>, TaggedJanet::Keyword);
from_for_janet!(JanetFunction<'_>, function);
from_for_janet!(clone &JanetFunction<'_>, function);
try_from_janet!(JanetFunction<'_>, TaggedJanet::Function);
from_for_janet!(JanetFiber<'_>, fiber);
from_for_janet!(clone &JanetFiber<'_>, fiber);
try_from_janet!(JanetFiber<'_>, TaggedJanet::Fiber);
try_from_janet!(JanetCFunction, TaggedJanet::CFunction);
from_for_janet!(bool, boolean);
from_for_janet!(deref & bool, boolean);
try_from_janet!(bool, TaggedJanet::Boolean);
from_for_janet!(f64, number);
from_for_janet!(deref & f64, number);
try_from_janet!(f64, TaggedJanet::Number);
macro_rules! janet_unwrap_unchecked {
(abstracts $janet:expr) => {
unsafe { JanetAbstract::from_raw(evil_janet::janet_unwrap_abstract($janet.into())) }
};
(array $janet:expr) => {
unsafe { JanetArray::from_raw(evil_janet::janet_unwrap_array($janet.into())) }
};
(boolean $janet:expr) => {
unsafe { evil_janet::janet_unwrap_boolean($janet.inner) } != 0
};
(buffer $janet:expr) => {
unsafe { JanetBuffer::from_raw(evil_janet::janet_unwrap_buffer($janet.into())) }
};
(cfunc $janet:expr) => {
unsafe { evil_janet::janet_unwrap_cfunction($janet.into()) }
};
(fiber $janet:expr) => {
unsafe { JanetFiber::from_raw(evil_janet::janet_unwrap_fiber($janet.into())) }
};
(function $janet:expr) => {
unsafe { JanetFunction::from_raw(evil_janet::janet_unwrap_function($janet.into())) }
};
(keyword $janet:expr) => {
unsafe { JanetKeyword::from_raw(evil_janet::janet_unwrap_keyword($janet.into())) }
};
(number $janet:expr) => {
unsafe { evil_janet::janet_unwrap_number($janet.into()) }
};
(pointer $janet:expr) => {
unsafe { JanetPointer::new(evil_janet::janet_unwrap_pointer($janet.into())) }
};
(string $janet:expr) => {
unsafe { JanetString::from_raw(evil_janet::janet_unwrap_string($janet.into())) }
};
(structs $janet:expr) => {
unsafe { JanetStruct::from_raw(evil_janet::janet_unwrap_struct($janet.into())) }
};
(symbol $janet:expr) => {
unsafe { JanetSymbol::from_raw(evil_janet::janet_unwrap_symbol($janet.into())) }
};
(table $janet:expr) => {
unsafe { JanetTable::from_raw(evil_janet::janet_unwrap_table($janet.into())) }
};
(tuple $janet:expr) => {
unsafe { JanetTuple::from_raw(evil_janet::janet_unwrap_tuple($janet.into())) }
};
}
#[derive(Debug)]
pub enum TaggedJanet<'data> {
Abstract(JanetAbstract),
Array(JanetArray<'data>),
Boolean(bool),
Buffer(JanetBuffer<'data>),
CFunction(JanetCFunction),
Fiber(JanetFiber<'data>),
Function(JanetFunction<'data>),
Keyword(JanetKeyword<'data>),
Nil,
Number(f64),
Pointer(JanetPointer),
String(JanetString<'data>),
Struct(JanetStruct<'data>),
Symbol(JanetSymbol<'data>),
Table(JanetTable<'data>),
Tuple(JanetTuple<'data>),
}
impl Display for TaggedJanet<'_> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TaggedJanet::Boolean(b) => Display::fmt(b, f),
TaggedJanet::Buffer(s) => Display::fmt(s, f),
TaggedJanet::Number(n) => Display::fmt(n, f),
TaggedJanet::String(s) => Display::fmt(s, f),
TaggedJanet::Abstract(a) => {
if let Ok(int) = a.get::<i64>() {
return Display::fmt(int, f);
}
if let Ok(int) = a.get::<u64>() {
return Display::fmt(int, f);
}
if let Some(tostring) = a.type_info().tostring {
let buff = JanetBuffer::with_capacity(30);
unsafe { tostring(a.raw, buff.raw) }
return Display::fmt(&buff, f);
}
f.write_str("<Abstract>")
},
TaggedJanet::Array(arr) => {
f.write_str("@[")?;
array_tuple_display!(arr, f);
f.write_char(']')
},
TaggedJanet::CFunction(_) => f.write_str("<C function>"),
TaggedJanet::Fiber(fiber) => {
f.write_str("<Fiber ")?;
fmt::Debug::fmt(&fiber.as_raw(), f)?;
f.write_char('>')
},
TaggedJanet::Function(_) => f.write_str("<Function>"),
TaggedJanet::Keyword(key) => Display::fmt(key, f),
TaggedJanet::Nil => f.write_str("nil"),
TaggedJanet::Pointer(ptr) => {
f.write_char('<')?;
fmt::Pointer::fmt(&ptr, f)?;
f.write_char('>')
},
TaggedJanet::Struct(st) => {
f.write_char('{')?;
struct_table_display!(st, f);
f.write_char('}')
},
TaggedJanet::Symbol(sym) => Display::fmt(sym, f),
TaggedJanet::Table(table) => {
if let Some(proto) = table.prototype() {
if let Some(name) = proto.get(JanetKeyword::new("_name")) {
match name.unwrap() {
TaggedJanet::Buffer(s) => {
f.write_char('@')?;
Display::fmt(&s, f)?;
},
TaggedJanet::String(s) => {
f.write_char('@')?;
Display::fmt(&s, f)?;
},
TaggedJanet::Symbol(s) => {
f.write_char('@')?;
Display::fmt(&s, f)?;
},
_ => f.write_char('@')?,
}
} else {
f.write_char('@')?;
}
} else {
f.write_char('@')?;
}
f.write_char('{')?;
struct_table_display!(table, f);
f.write_char('}')
},
TaggedJanet::Tuple(tup) => {
f.write_char('[')?;
array_tuple_display!(tup, f);
f.write_char(']')
},
}
}
}
impl From<Janet> for TaggedJanet<'_> {
#[inline]
fn from(val: Janet) -> Self {
match val.kind() {
JanetType::Abstract => Self::Abstract(janet_unwrap_unchecked!(abstracts val)),
JanetType::Array => Self::Array(janet_unwrap_unchecked!(array val)),
JanetType::Boolean => Self::Boolean(janet_unwrap_unchecked!(boolean val)),
JanetType::Buffer => Self::Buffer(janet_unwrap_unchecked!(buffer val)),
JanetType::CFunction => Self::CFunction(janet_unwrap_unchecked!(cfunc val)),
JanetType::Fiber => Self::Fiber(janet_unwrap_unchecked!(fiber val)),
JanetType::Function => Self::Function(janet_unwrap_unchecked!(function val)),
JanetType::Keyword => Self::Keyword(janet_unwrap_unchecked!(keyword val)),
JanetType::Nil => Self::Nil,
JanetType::Number => Self::Number(janet_unwrap_unchecked!(number val)),
JanetType::Pointer => Self::Pointer(janet_unwrap_unchecked!(pointer val)),
JanetType::String => Self::String(janet_unwrap_unchecked!(string val)),
JanetType::Struct => Self::Struct(janet_unwrap_unchecked!(structs val)),
JanetType::Symbol => Self::Symbol(janet_unwrap_unchecked!(symbol val)),
JanetType::Table => Self::Table(janet_unwrap_unchecked!(table val)),
JanetType::Tuple => Self::Tuple(janet_unwrap_unchecked!(tuple val)),
}
}
}
impl TaggedJanet<'_> {
#[inline]
pub const fn kind(&self) -> JanetType {
match self {
TaggedJanet::Abstract(_) => JanetType::Abstract,
TaggedJanet::Array(_) => JanetType::Array,
TaggedJanet::Boolean(_) => JanetType::Boolean,
TaggedJanet::Buffer(_) => JanetType::Buffer,
TaggedJanet::CFunction(_) => JanetType::CFunction,
TaggedJanet::Fiber(_) => JanetType::Fiber,
TaggedJanet::Function(_) => JanetType::Function,
TaggedJanet::Keyword(_) => JanetType::Keyword,
TaggedJanet::Nil => JanetType::Nil,
TaggedJanet::Number(_) => JanetType::Number,
TaggedJanet::Pointer(_) => JanetType::Pointer,
TaggedJanet::String(_) => JanetType::String,
TaggedJanet::Struct(_) => JanetType::Struct,
TaggedJanet::Symbol(_) => JanetType::Symbol,
TaggedJanet::Table(_) => JanetType::Table,
TaggedJanet::Tuple(_) => JanetType::Tuple,
}
}
}
impl From<TaggedJanet<'_>> for Janet {
#[inline]
fn from(val: TaggedJanet) -> Self {
match val {
TaggedJanet::Abstract(inner) => inner.into(),
TaggedJanet::Array(inner) => inner.into(),
TaggedJanet::Boolean(inner) => inner.into(),
TaggedJanet::Buffer(inner) => inner.into(),
TaggedJanet::CFunction(inner) => inner.into(),
TaggedJanet::Fiber(inner) => inner.into(),
TaggedJanet::Function(inner) => inner.into(),
TaggedJanet::Keyword(inner) => inner.into(),
TaggedJanet::Nil => Janet::nil(),
TaggedJanet::Number(inner) => inner.into(),
TaggedJanet::Pointer(inner) => inner.into(),
TaggedJanet::String(inner) => inner.into(),
TaggedJanet::Struct(inner) => inner.into(),
TaggedJanet::Symbol(inner) => inner.into(),
TaggedJanet::Table(inner) => inner.into(),
TaggedJanet::Tuple(inner) => inner.into(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[repr(u32)]
pub enum JanetType {
Abstract = evil_janet::JanetType_JANET_ABSTRACT,
Array = evil_janet::JanetType_JANET_ARRAY,
Boolean = evil_janet::JanetType_JANET_BOOLEAN,
Buffer = evil_janet::JanetType_JANET_BUFFER,
CFunction = evil_janet::JanetType_JANET_CFUNCTION,
Fiber = evil_janet::JanetType_JANET_FIBER,
Function = evil_janet::JanetType_JANET_FUNCTION,
Keyword = evil_janet::JanetType_JANET_KEYWORD,
Nil = evil_janet::JanetType_JANET_NIL,
Number = evil_janet::JanetType_JANET_NUMBER,
Pointer = evil_janet::JanetType_JANET_POINTER,
String = evil_janet::JanetType_JANET_STRING,
Struct = evil_janet::JanetType_JANET_STRUCT,
Symbol = evil_janet::JanetType_JANET_SYMBOL,
Table = evil_janet::JanetType_JANET_TABLE,
Tuple = evil_janet::JanetType_JANET_TUPLE,
}
impl From<CJanetType> for JanetType {
#[allow(non_upper_case_globals)]
#[inline]
fn from(raw: CJanetType) -> Self {
match raw {
evil_janet::JanetType_JANET_ABSTRACT => Self::Abstract,
evil_janet::JanetType_JANET_ARRAY => Self::Array,
evil_janet::JanetType_JANET_BOOLEAN => Self::Boolean,
evil_janet::JanetType_JANET_BUFFER => Self::Buffer,
evil_janet::JanetType_JANET_CFUNCTION => Self::CFunction,
evil_janet::JanetType_JANET_FIBER => Self::Fiber,
evil_janet::JanetType_JANET_FUNCTION => Self::Function,
evil_janet::JanetType_JANET_KEYWORD => Self::Keyword,
evil_janet::JanetType_JANET_NIL => Self::Nil,
evil_janet::JanetType_JANET_NUMBER => Self::Number,
evil_janet::JanetType_JANET_POINTER => Self::Pointer,
evil_janet::JanetType_JANET_STRING => Self::String,
evil_janet::JanetType_JANET_STRUCT => Self::Struct,
evil_janet::JanetType_JANET_SYMBOL => Self::Symbol,
evil_janet::JanetType_JANET_TABLE => Self::Table,
evil_janet::JanetType_JANET_TUPLE => Self::Tuple,
_ => unreachable!(),
}
}
}
impl Display for JanetType {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Abstract => Display::fmt("abstract", f),
Self::Array => Display::fmt("array", f),
Self::Boolean => Display::fmt("boolean", f),
Self::Buffer => Display::fmt("buffer", f),
Self::CFunction => Display::fmt("cfunction", f),
Self::Fiber => Display::fmt("fiber", f),
Self::Function => Display::fmt("function", f),
Self::Keyword => Display::fmt("keyword", f),
Self::Nil => Display::fmt("nil", f),
Self::Number => Display::fmt("number", f),
Self::Pointer => Display::fmt("pointer", f),
Self::String => Display::fmt("string", f),
Self::Struct => Display::fmt("struct", f),
Self::Symbol => Display::fmt("symbol", f),
Self::Table => Display::fmt("table", f),
Self::Tuple => Display::fmt("tuple", f),
}
}
}
impl From<JanetType> for CJanetType {
#[inline]
fn from(val: JanetType) -> Self {
val as u32
}
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[repr(u32)]
pub enum JanetSignal {
Ok = evil_janet::JanetSignal_JANET_SIGNAL_OK,
Error = evil_janet::JanetSignal_JANET_SIGNAL_ERROR,
Debug = evil_janet::JanetSignal_JANET_SIGNAL_DEBUG,
Yield = evil_janet::JanetSignal_JANET_SIGNAL_YIELD,
User0 = evil_janet::JanetSignal_JANET_SIGNAL_USER0,
User1 = evil_janet::JanetSignal_JANET_SIGNAL_USER1,
User2 = evil_janet::JanetSignal_JANET_SIGNAL_USER2,
User3 = evil_janet::JanetSignal_JANET_SIGNAL_USER3,
User4 = evil_janet::JanetSignal_JANET_SIGNAL_USER4,
User5 = evil_janet::JanetSignal_JANET_SIGNAL_USER5,
User6 = evil_janet::JanetSignal_JANET_SIGNAL_USER6,
User7 = evil_janet::JanetSignal_JANET_SIGNAL_USER7,
User8 = evil_janet::JanetSignal_JANET_SIGNAL_USER8,
User9 = evil_janet::JanetSignal_JANET_SIGNAL_USER9,
}
impl From<u32> for JanetSignal {
fn from(val: u32) -> Self {
match val {
evil_janet::JanetSignal_JANET_SIGNAL_OK => Self::Ok,
evil_janet::JanetSignal_JANET_SIGNAL_ERROR => Self::Error,
evil_janet::JanetSignal_JANET_SIGNAL_DEBUG => Self::Debug,
evil_janet::JanetSignal_JANET_SIGNAL_YIELD => Self::Yield,
evil_janet::JanetSignal_JANET_SIGNAL_USER0 => Self::User0,
evil_janet::JanetSignal_JANET_SIGNAL_USER1 => Self::User1,
evil_janet::JanetSignal_JANET_SIGNAL_USER2 => Self::User2,
evil_janet::JanetSignal_JANET_SIGNAL_USER3 => Self::User3,
evil_janet::JanetSignal_JANET_SIGNAL_USER4 => Self::User4,
evil_janet::JanetSignal_JANET_SIGNAL_USER5 => Self::User5,
evil_janet::JanetSignal_JANET_SIGNAL_USER6 => Self::User6,
evil_janet::JanetSignal_JANET_SIGNAL_USER7 => Self::User7,
evil_janet::JanetSignal_JANET_SIGNAL_USER8 => Self::User8,
evil_janet::JanetSignal_JANET_SIGNAL_USER9 => Self::User9,
_ => unreachable!(),
}
}
}
impl From<JanetSignal> for u32 {
fn from(val: JanetSignal) -> Self {
val as _
}
}
pub trait JanetExtend<T> {
fn extend(&mut self, collection: T);
}
macro_rules! impl_string_like {
($($ty:ty)+) => {
$(
impl From<&[u8]> for $ty {
#[inline]
fn from(bytes: &[u8]) -> Self { Self::new(bytes) }
}
impl From<alloc::vec::Vec<u8>> for $ty {
#[inline]
fn from(vec: Vec<u8>) -> Self {
Self::new(vec)
}
}
impl From<&str> for $ty {
#[inline]
fn from(rust_str: &str) -> Self { Self::new(rust_str) }
}
impl From<alloc::string::String> for $ty {
#[inline]
fn from(s: String) -> Self {
Self::new(s)
}
}
impl PartialEq for $ty {
#[inline]
fn eq(&self, other: &Self) -> bool { unsafe { evil_janet::janet_string_equal(self.raw, other.raw) != 0 } }
}
impl Eq for $ty {}
impl PartialOrd for $ty {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
let cmp_res = unsafe { evil_janet::janet_string_compare(self.raw, other.raw) };
Some(match cmp_res {
0 => Ordering::Equal,
_ if cmp_res < 0 => Ordering::Less,
_ if cmp_res > 0 => Ordering::Greater,
_ => return None,
})
}
}
impl Ord for $ty {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
match self.partial_cmp(other) {
Some(ord) => ord,
None => {
unreachable!()
},
}
}
}
)+
};
}
macro_rules! impl_part {
($t1:ty, $t2:ty) => {
impl PartialEq<$t1> for $t2 {
#[inline]
fn eq(&self, other: &$t1) -> bool {
unsafe { evil_janet::janet_string_equal(self.raw, other.raw) != 0 }
}
}
impl PartialEq<$t2> for $t1 {
#[inline]
fn eq(&self, other: &$t2) -> bool {
unsafe { evil_janet::janet_string_equal(self.raw, other.raw) != 0 }
}
}
impl PartialOrd<$t1> for $t2 {
#[inline]
fn partial_cmp(&self, other: &$t1) -> Option<Ordering> {
let cmp_res = unsafe { evil_janet::janet_string_compare(self.raw, other.raw) };
Some(match cmp_res {
0 => Ordering::Equal,
_ if cmp_res < 0 => Ordering::Less,
_ if cmp_res > 0 => Ordering::Greater,
_ => return None,
})
}
}
impl PartialOrd<$t2> for $t1 {
#[inline]
fn partial_cmp(&self, other: &$t2) -> Option<Ordering> {
let cmp_res = unsafe { evil_janet::janet_string_compare(self.raw, other.raw) };
Some(match cmp_res {
0 => Ordering::Equal,
_ if cmp_res < 0 => Ordering::Less,
_ if cmp_res > 0 => Ordering::Greater,
_ => return None,
})
}
}
};
}
macro_rules! string_impl_partial_eq {
($lhs:ty, $rhs:ty) => {
impl<'a, 'b> PartialEq<$rhs> for $lhs {
#[inline]
fn eq(&self, other: &$rhs) -> bool {
let other: &[u8] = other.as_ref();
PartialEq::eq(self.as_bytes(), other)
}
}
impl<'a, 'b> PartialEq<$lhs> for $rhs {
#[inline]
fn eq(&self, other: &$lhs) -> bool {
let this: &[u8] = self.as_ref();
PartialEq::eq(this, other.as_bytes())
}
}
};
(#[cfg($attr:meta)]; $lhs:ty, $rhs:ty) => {
#[cfg($attr)]
#[cfg_attr(_doc, doc(cfg($attr)))]
impl<'a, 'b> PartialEq<$rhs> for $lhs {
#[inline]
fn eq(&self, other: &$rhs) -> bool {
let other: &[u8] = other.as_ref();
PartialEq::eq(self.as_bytes(), other)
}
}
#[cfg($attr)]
#[cfg_attr(_doc, doc(cfg($attr)))]
impl<'a, 'b> PartialEq<$lhs> for $rhs {
#[inline]
fn eq(&self, other: &$lhs) -> bool {
let this: &[u8] = self.as_ref();
PartialEq::eq(this, other.as_bytes())
}
}
};
}
macro_rules! string_impl_partial_ord {
($lhs:ty, $rhs:ty) => {
impl<'a, 'b> PartialOrd<$rhs> for $lhs {
#[inline]
fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
let other: &[u8] = other.as_ref();
PartialOrd::partial_cmp(self.as_bytes(), other)
}
}
impl<'a, 'b> PartialOrd<$lhs> for $rhs {
#[inline]
fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
let this: &[u8] = self.as_ref();
PartialOrd::partial_cmp(this, other.as_bytes())
}
}
};
(#[cfg($attr:meta)]; $lhs:ty, $rhs:ty) => {
#[cfg($attr)]
#[cfg_attr(_doc, doc(cfg($attr)))]
impl<'a, 'b> PartialOrd<$rhs> for $lhs {
#[inline]
fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
let other: &[u8] = other.as_ref();
PartialOrd::partial_cmp(self.as_bytes(), other)
}
}
#[cfg($attr)]
#[cfg_attr(_doc, doc(cfg($attr)))]
impl<'a, 'b> PartialOrd<$lhs> for $rhs {
#[inline]
fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
let this: &[u8] = self.as_ref();
PartialOrd::partial_cmp(this, other.as_bytes())
}
}
};
}
impl_string_like!(JanetString<'_> JanetKeyword<'_> JanetSymbol<'_>);
impl_part!(JanetString<'_>, JanetKeyword<'_>);
impl_part!(JanetString<'_>, JanetSymbol<'_>);
impl_part!(JanetKeyword<'_>, JanetSymbol<'_>);
string_impl_partial_eq!(JanetString<'_>, Vec<u8>);
string_impl_partial_eq!(JanetString<'_>, [u8]);
string_impl_partial_eq!(JanetString<'_>, &'a [u8]);
string_impl_partial_eq!(JanetString<'_>, String);
string_impl_partial_eq!(JanetString<'_>, str);
string_impl_partial_eq!(JanetString<'_>, &'a str);
string_impl_partial_eq!(JanetString<'_>, bstr::BStr);
string_impl_partial_eq!(JanetString<'_>, &'a bstr::BStr);
string_impl_partial_eq!(#[cfg(feature = "std")]; JanetString<'_>, bstr::BString);
string_impl_partial_eq!(#[cfg(feature = "std")]; JanetString<'_>, &'a bstr::BString);
string_impl_partial_ord!(JanetString<'_>, Vec<u8>);
string_impl_partial_ord!(JanetString<'_>, [u8]);
string_impl_partial_ord!(JanetString<'_>, &'a [u8]);
string_impl_partial_ord!(JanetString<'_>, String);
string_impl_partial_ord!(JanetString<'_>, str);
string_impl_partial_ord!(JanetString<'_>, &'a str);
string_impl_partial_ord!(JanetString<'_>, bstr::BStr);
string_impl_partial_ord!(JanetString<'_>, &'a bstr::BStr);
string_impl_partial_ord!(#[cfg(feature = "std")]; JanetString<'_>, bstr::BString);
string_impl_partial_ord!(#[cfg(feature = "std")]; JanetString<'_>, &'a bstr::BString);
string_impl_partial_eq!(JanetBuffer<'_>, Vec<u8>);
string_impl_partial_eq!(JanetBuffer<'_>, [u8]);
string_impl_partial_eq!(JanetBuffer<'_>, &'a [u8]);
string_impl_partial_eq!(JanetBuffer<'_>, String);
string_impl_partial_eq!(JanetBuffer<'_>, str);
string_impl_partial_eq!(JanetBuffer<'_>, &'a str);
string_impl_partial_eq!(JanetBuffer<'_>, bstr::BStr);
string_impl_partial_eq!(JanetBuffer<'_>, &'a bstr::BStr);
string_impl_partial_eq!(#[cfg(feature = "std")]; JanetBuffer<'_>, bstr::BString);
string_impl_partial_eq!(#[cfg(feature = "std")]; JanetBuffer<'_>, &'a bstr::BString);
string_impl_partial_ord!(JanetBuffer<'_>, Vec<u8>);
string_impl_partial_ord!(JanetBuffer<'_>, [u8]);
string_impl_partial_ord!(JanetBuffer<'_>, &'a [u8]);
string_impl_partial_ord!(JanetBuffer<'_>, String);
string_impl_partial_ord!(JanetBuffer<'_>, str);
string_impl_partial_ord!(JanetBuffer<'_>, &'a str);
string_impl_partial_ord!(JanetBuffer<'_>, bstr::BStr);
string_impl_partial_ord!(JanetBuffer<'_>, &'a bstr::BStr);
string_impl_partial_ord!(#[cfg(feature = "std")]; JanetBuffer<'_>, bstr::BString);
string_impl_partial_ord!(#[cfg(feature = "std")]; JanetBuffer<'_>, &'a bstr::BString);
string_impl_partial_eq!(JanetSymbol<'_>, Vec<u8>);
string_impl_partial_eq!(JanetSymbol<'_>, [u8]);
string_impl_partial_eq!(JanetSymbol<'_>, &'a [u8]);
string_impl_partial_eq!(JanetSymbol<'_>, String);
string_impl_partial_eq!(JanetSymbol<'_>, str);
string_impl_partial_eq!(JanetSymbol<'_>, &'a str);
string_impl_partial_eq!(JanetSymbol<'_>, bstr::BStr);
string_impl_partial_eq!(JanetSymbol<'_>, &'a bstr::BStr);
string_impl_partial_eq!(#[cfg(feature = "std")]; JanetSymbol<'_>, bstr::BString);
string_impl_partial_eq!(#[cfg(feature = "std")]; JanetSymbol<'_>, &'a bstr::BString);
string_impl_partial_ord!(JanetSymbol<'_>, Vec<u8>);
string_impl_partial_ord!(JanetSymbol<'_>, [u8]);
string_impl_partial_ord!(JanetSymbol<'_>, &'a [u8]);
string_impl_partial_ord!(JanetSymbol<'_>, String);
string_impl_partial_ord!(JanetSymbol<'_>, str);
string_impl_partial_ord!(JanetSymbol<'_>, &'a str);
string_impl_partial_ord!(JanetSymbol<'_>, bstr::BStr);
string_impl_partial_ord!(JanetSymbol<'_>, &'a bstr::BStr);
string_impl_partial_ord!(#[cfg(feature = "std")]; JanetSymbol<'_>, bstr::BString);
string_impl_partial_ord!(#[cfg(feature = "std")]; JanetSymbol<'_>, &'a bstr::BString);
string_impl_partial_eq!(JanetKeyword<'_>, Vec<u8>);
string_impl_partial_eq!(JanetKeyword<'_>, [u8]);
string_impl_partial_eq!(JanetKeyword<'_>, &'a [u8]);
string_impl_partial_eq!(JanetKeyword<'_>, String);
string_impl_partial_eq!(JanetKeyword<'_>, str);
string_impl_partial_eq!(JanetKeyword<'_>, &'a str);
string_impl_partial_eq!(JanetKeyword<'_>, bstr::BStr);
string_impl_partial_eq!(JanetKeyword<'_>, &'a bstr::BStr);
string_impl_partial_eq!(#[cfg(feature = "std")]; JanetKeyword<'_>, bstr::BString);
string_impl_partial_eq!(#[cfg(feature = "std")]; JanetKeyword<'_>, &'a bstr::BString);
string_impl_partial_ord!(JanetKeyword<'_>, Vec<u8>);
string_impl_partial_ord!(JanetKeyword<'_>, [u8]);
string_impl_partial_ord!(JanetKeyword<'_>, &'a [u8]);
string_impl_partial_ord!(JanetKeyword<'_>, String);
string_impl_partial_ord!(JanetKeyword<'_>, str);
string_impl_partial_ord!(JanetKeyword<'_>, &'a str);
string_impl_partial_ord!(JanetKeyword<'_>, bstr::BStr);
string_impl_partial_ord!(JanetKeyword<'_>, &'a bstr::BStr);
string_impl_partial_ord!(#[cfg(feature = "std")]; JanetKeyword<'_>, bstr::BString);
string_impl_partial_ord!(#[cfg(feature = "std")]; JanetKeyword<'_>, &'a bstr::BString);
pub trait JanetArgs {
fn get_unwraped<T: TryFrom<Janet>>(&self, index: usize) -> Result<T, T::Error>;
fn get_or<T: TryFrom<Janet>>(&self, index: usize, default: T) -> T;
fn get_opt<T: TryFrom<Janet> + JanetTypeName>(&self, index: usize, default: T) -> T;
fn get_panic<T: TryFrom<Janet> + JanetTypeName>(&self, index: usize) -> T;
}
impl JanetArgs for [Janet] {
fn get_unwraped<T: TryFrom<Janet>>(&self, index: usize) -> Result<T, T::Error> {
T::try_from(*self.get(index).unwrap_or(&Janet::nil()))
}
fn get_or<T: TryFrom<Janet>>(&self, index: usize, default: T) -> T {
self.get(index)
.and_then(|val| T::try_from(*val).ok())
.unwrap_or(default)
}
fn get_panic<T: TryFrom<Janet> + JanetTypeName>(&self, index: usize) -> T {
match self.get(index) {
Some(&val) => T::try_from(val).unwrap_or_else(|_| {
crate::jpanic!(
"bad slot #{}, expected {}, got {}",
index,
T::name(),
val.kind()
)
}),
None => crate::jpanic!("bad slot #{}, there is no value in this slot", index),
}
}
fn get_opt<T: TryFrom<Janet> + JanetTypeName>(&self, index: usize, default: T) -> T {
let val = self.get(index).copied().unwrap_or_else(Janet::nil);
if val.is_nil() {
return default;
}
match T::try_from(val) {
Ok(x) => x,
Err(_) => crate::jpanic!(
"bad slot #{}, expected {}, got {}",
index,
T::name(),
val.kind()
),
}
}
}
pub trait JanetTypeName {
fn name() -> String;
}
macro_rules! type_name {
($($t:ty : $helper:ident),+ $(,)?) => {
$(
impl JanetTypeName for $t {
fn name() -> String {
JanetType::$helper.to_string()
}
}
)+
};
($($t:ty : $helper:literal),+ $(,)?) => {
$(
impl JanetTypeName for $t {
fn name() -> String {
$helper.to_string()
}
}
)+
};
}
type_name!(
bool: Boolean,
f64: Number,
JanetString<'_>: String,
JanetSymbol<'_>: Symbol,
JanetKeyword<'_>: Keyword,
JanetBuffer<'_>: Buffer,
JanetTuple<'_>: Tuple,
JanetArray<'_>: Array,
JanetStruct<'_>: Struct,
JanetTable<'_>: Table,
JanetPointer: Pointer,
JanetAbstract: Abstract,
JanetFunction<'_>: Function,
JanetCFunction: CFunction,
JanetFiber<'_>: Fiber,
);
type_name!(i64: "s64", u64: "u64", io::JanetFile: "file", JanetRng: "rng");
#[cfg(all(test, any(feature = "amalgation", feature = "link-system")))]
mod tests {
use super::*;
#[cfg(feature = "std")]
use core::hash::{Hash, Hasher};
#[cfg_attr(feature = "std", test)]
#[cfg(feature = "std")]
fn janet_eq_hash() -> Result<(), crate::client::Error> {
let _client = crate::client::JanetClient::init()?;
let mut hasher1 = std::collections::hash_map::DefaultHasher::new();
let mut hasher2 = std::collections::hash_map::DefaultHasher::new();
let (j1, j2) = (Janet::from(10), Janet::from(10));
j1.hash(&mut hasher1);
j2.hash(&mut hasher2);
assert_eq!(j1, j2);
assert_eq!(hasher1.finish(), hasher2.finish());
assert_eq!(j1 == j2, hasher1.finish() == hasher2.finish());
let mut hasher1 = std::collections::hash_map::DefaultHasher::new();
let mut hasher2 = std::collections::hash_map::DefaultHasher::new();
let (j1, j2) = (Janet::from(10), Janet::from("hey"));
j1.hash(&mut hasher1);
j2.hash(&mut hasher2);
assert_ne!(j1, j2);
assert_ne!(hasher1.finish(), hasher2.finish());
assert_eq!(j1 == j2, hasher1.finish() == hasher2.finish());
Ok(())
}
#[test]
fn dynamic() -> Result<(), crate::client::Error> {
let _client = crate::client::JanetClient::init()?;
unsafe { evil_janet::janet_setdyn("test\0".as_ptr() as *const _, Janet::from(10).into()) };
assert_eq!(Some(Janet::number(10.0)), Janet::dynamic("test"));
Ok(())
}
}