1#![no_std]
148#![cfg_attr(docsrs, feature(doc_cfg))]
149
150pub use self::function::*;
151pub use self::gc::Ref;
152pub use self::module::*;
153pub use self::number::*;
154pub use self::parser::*;
155pub use self::registry::*;
156pub use self::string::*;
157pub use self::table::*;
158pub use self::thread::*;
159pub use self::ty::*;
160pub use self::userdata::*;
161
162use self::collections::{BTreeMap, CollectionValue};
163use self::context::{Arg, Args, Context, Ret};
164use self::gc::{Gc, Object};
165use self::ldebug::{funcinfo, luaG_getfuncline};
166use self::ldo::luaD_protectedparser;
167use self::llex::{TK_WHILE, luaX_tokens};
168use self::lstate::lua_Debug;
169use self::ltm::{
170 TM_ADD, TM_BAND, TM_BNOT, TM_BOR, TM_BXOR, TM_CALL, TM_CLOSE, TM_CONCAT, TM_DIV, TM_EQ, TM_GC,
171 TM_IDIV, TM_INDEX, TM_LE, TM_LEN, TM_LT, TM_MOD, TM_MODE, TM_MUL, TM_NEWINDEX, TM_POW, TM_SHL,
172 TM_SHR, TM_SUB, TM_UNM, luaT_gettm,
173};
174use self::lzio::Zio;
175use self::value::{UnsafeValue, UntaggedValue};
176use alloc::boxed::Box;
177use alloc::rc::Rc;
178use alloc::string::String;
179use alloc::vec::Vec;
180use core::any::{Any, TypeId, type_name};
181use core::cell::{Cell, UnsafeCell};
182use core::convert::identity;
183use core::error::Error;
184use core::fmt::{Display, Formatter};
185use core::marker::PhantomPinned;
186use core::mem::MaybeUninit;
187use core::ops::{Deref, DerefMut};
188use core::pin::Pin;
189use core::ptr::null;
190use core::task::RawWakerVTable;
191use thiserror::Error;
192
193pub mod builtin;
194pub mod collections;
195pub mod context;
196
197mod function;
198mod gc;
199mod hasher;
200mod lapi;
201mod lauxlib;
202mod lcode;
203mod lctype;
204mod ldebug;
205mod ldo;
206mod lfunc;
207mod llex;
208mod lmem;
209mod lobject;
210mod lparser;
211mod lstate;
212mod lstring;
213mod ltm;
214mod lzio;
215mod module;
216mod number;
217mod parser;
218mod registry;
219mod string;
220mod table;
221mod thread;
222mod ty;
223mod userdata;
224mod value;
225mod vm;
226
227extern crate alloc;
228#[cfg(feature = "std")]
229extern crate std;
230
231#[macro_export]
233macro_rules! fp {
234 ($f:path) => {
235 $crate::Fp::new($f)
236 };
237 ($f:path as yield) => {
238 $crate::YieldFp::new($f)
239 };
240 ($f:path as async) => {
241 $crate::async_fp!($f)
242 };
243}
244
245#[cfg(feature = "std")]
246#[doc(hidden)]
247#[macro_export]
248macro_rules! async_fp {
249 ($f:path) => {
250 $crate::AsyncFp::new(|cx| ::std::boxed::Box::pin($f(cx)))
251 };
252}
253
254#[cfg(not(feature = "std"))]
255#[doc(hidden)]
256#[macro_export]
257macro_rules! async_fp {
258 ($f:path) => {
259 $crate::AsyncFp::new(|cx| ::alloc::boxed::Box::pin($f(cx)))
260 };
261}
262
263pub use tsuki_macros::FromStr;
281
282pub use tsuki_macros::class;
321
322#[repr(C)] pub struct Lua<A> {
325 gc: Gc<A>,
326 strt: StringTable<A>,
327 l_registry: UnsafeCell<UnsafeValue<A>>,
328 nilvalue: UnsafeCell<UnsafeValue<A>>,
329 dummy_node: Node<A>,
330 seed: u32,
331 modules_locked: Cell<bool>,
332 associated_data: A,
333 phantom: PhantomPinned,
334}
335
336impl<A> Lua<A> {
337 #[cfg(feature = "rand")]
344 #[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
345 pub fn new(associated_data: A) -> Pin<Rc<Self>> {
346 Self::with_seed(associated_data, rand::random())
347 }
348
349 pub fn with_seed(associated_data: A, seed: u32) -> Pin<Rc<Self>> {
361 let g = Rc::pin(Lua {
362 gc: unsafe { Gc::new() }, strt: StringTable::new(),
364 l_registry: UnsafeCell::new(Nil.into()),
365 nilvalue: UnsafeCell::new(Nil.into()),
366 dummy_node: Node {
367 tt_: 0 | 1 << 4,
368 key_tt: 0 | 0 << 4,
369 value_: UntaggedValue { i: 0 },
370 next: 0,
371 key_val: UntaggedValue { i: 0 },
372 },
373 seed,
374 modules_locked: Cell::new(false),
375 associated_data,
376 phantom: PhantomPinned,
377 });
378
379 let reg = unsafe { Table::new(g.deref()) };
381
382 unsafe { g.gc.set_root(reg.cast()) };
383 unsafe { g.l_registry.get().write(UnsafeValue::from_obj(reg.cast())) };
384 unsafe { luaH_resize(reg, 6, 0) };
385
386 let reg = unsafe { (*reg).array.get() };
388 let glb = unsafe { Table::new(g.deref()) };
389
390 unsafe { reg.add(0).write(false.into()) };
391 unsafe { reg.add(1).write(UnsafeValue::from_obj(glb.cast())) };
392
393 let mts = unsafe { Table::new(g.deref()) };
395
396 unsafe { luaH_resize(mts, 9, 0) };
397
398 for i in 0..9 {
399 let e = unsafe { (*mts).array.get().add(i) };
400
401 unsafe { (*e).tt_ = 1 | 0 << 4 };
402 unsafe { (*e).value_.gc = null() };
403 }
404
405 unsafe { reg.add(2).write(UnsafeValue::from_obj(mts.cast())) };
406
407 let events = unsafe { Table::new(g.deref()) };
409 let entries = &[
410 (TM_INDEX, "__index"),
411 (TM_NEWINDEX, "__newindex"),
412 (TM_GC, "__gc"),
413 (TM_MODE, "__mode"),
414 (TM_LEN, "__len"),
415 (TM_EQ, "__eq"),
416 (TM_ADD, "__add"),
417 (TM_SUB, "__sub"),
418 (TM_MUL, "__mul"),
419 (TM_MOD, "__mod"),
420 (TM_POW, "__pow"),
421 (TM_DIV, "__div"),
422 (TM_IDIV, "__idiv"),
423 (TM_BAND, "__band"),
424 (TM_BOR, "__bor"),
425 (TM_BXOR, "__bxor"),
426 (TM_SHL, "__shl"),
427 (TM_SHR, "__shr"),
428 (TM_UNM, "__unm"),
429 (TM_BNOT, "__bnot"),
430 (TM_LT, "__lt"),
431 (TM_LE, "__le"),
432 (TM_CONCAT, "__concat"),
433 (TM_CALL, "__call"),
434 (TM_CLOSE, "__close"),
435 ];
436
437 unsafe { luaH_resize(events, entries.len().try_into().unwrap(), 0) };
438
439 for &(k, v) in entries {
440 let v = unsafe { Str::from_str(g.deref(), v).unwrap_or_else(identity) };
441 let v = unsafe { UnsafeValue::from_obj(v.cast()) };
442
443 unsafe { (*events).set_unchecked(k, v).unwrap_unchecked() };
444 }
445
446 unsafe { reg.add(3).write(UnsafeValue::from_obj(events.cast())) };
447
448 let tokens = unsafe { Table::new(g.deref()) };
450 let n = TK_WHILE - (255 + 1) + 1;
451
452 unsafe { luaH_resize(tokens, 0, n.try_into().unwrap()) };
453
454 for i in 0..n {
455 let k = unsafe { Str::from_str(g.deref(), luaX_tokens[i as usize]) }
456 .unwrap_or_else(identity);
457 let k = unsafe { UnsafeValue::from_obj(k.cast()) };
458
459 unsafe { (*tokens).set_unchecked(k, i + 1).unwrap_unchecked() };
460 }
461
462 unsafe { reg.add(4).write(UnsafeValue::from_obj(tokens.cast())) };
463
464 let mods = unsafe { Table::new(g.deref()) };
466
467 unsafe { reg.add(5).write(UnsafeValue::from_obj(mods.cast())) };
468
469 g
470 }
471
472 #[inline(always)]
474 pub fn associated_data(&self) -> &A {
475 &self.associated_data
476 }
477
478 pub fn use_module<'a, M>(
491 &'a self,
492 name: Option<&str>,
493 global: bool,
494 module: M,
495 ) -> Result<(), Box<dyn Error>>
496 where
497 M: Module<A>,
498 M::Inst<'a>: Into<UnsafeValue<A>>,
499 {
500 let lock = match ModulesLock::new(&self.modules_locked) {
502 Some(v) => v,
503 None => return Err(Box::new(RecursiveCall::new(Self::use_module::<M>))),
504 };
505
506 let name = name.unwrap_or(M::NAME);
508 let n = unsafe { Str::from_str(self, name).unwrap_or_else(identity) };
509 let n = unsafe { UnsafeValue::from_obj(n.cast()) };
510 let t = self.modules();
511 let s = unsafe { t.get_raw_unchecked(n) };
512
513 if unsafe { ((*s).tt_ & 0xf) != 0 } {
514 return Err(Box::new(ModuleExists));
515 }
516
517 let n = unsafe { Ref::new(n.value_.gc.cast::<Str<A>>()) };
519 let m = module.open(self)?.into();
520
521 if (m.tt_ & 0xf) == 0 {
522 return Ok(());
523 } else if unsafe { (m.tt_ & 1 << 6) != 0 && (*m.value_.gc).global != self } {
524 panic!("the module instance was created from different Lua instance");
525 }
526
527 unsafe { t.set_slot_unchecked(s, n.deref(), m).unwrap_unchecked() };
529
530 if global {
531 unsafe { self.global().set_unchecked(n, m).unwrap_unchecked() };
532 }
533
534 drop(lock);
535
536 Ok(())
537 }
538
539 pub fn set_str_metatable(&self, mt: &Table<A>) {
545 if mt.hdr.global != self {
546 panic!("attempt to set string metatable created from a different Lua");
547 }
548
549 if unsafe { mt.flags.get() & 1 << TM_GC == 0 && !luaT_gettm(mt, TM_GC).is_null() } {
551 panic!("__gc metamethod is not supported");
552 }
553
554 unsafe { self.metatables().set_unchecked(4, mt).unwrap_unchecked() };
555 }
556
557 pub fn register_metatable<T: Any>(&self, mt: &Table<A>) {
568 if mt.hdr.global != self {
569 panic!("attempt to register a metatable created from a different Lua");
570 }
571
572 if unsafe { mt.flags.get() & 1 << TM_GC == 0 && !luaT_gettm(mt, TM_GC).is_null() } {
574 panic!("__gc metamethod is not supported");
575 }
576
577 let k = unsafe { RustId::new(self, TypeId::of::<T>()) };
579 let k = unsafe { UnsafeValue::from_obj(k.cast()) };
580
581 unsafe { self.metatables().set_unchecked(k, mt).unwrap_unchecked() };
582
583 self.gc.step();
584 }
585
586 pub fn register_class<T: Class<A>>(&self) {
596 let mt = T::create_metatable(self);
598 let mt = mt.deref();
599
600 if mt.hdr.global != self {
601 panic!(
602 "{} returns a table that was created from a different Lua",
603 type_name::<T>()
604 );
605 } else if unsafe { mt.flags.get() & 1 << TM_GC == 0 && !luaT_gettm(mt, TM_GC).is_null() } {
606 panic!("{} returns a table that contains __gc", type_name::<T>());
607 }
608
609 let k = unsafe { RustId::new(self, TypeId::of::<T>()) };
611 let k = unsafe { UnsafeValue::from_obj(k.cast()) };
612
613 unsafe { self.metatables().set_unchecked(k, mt).unwrap_unchecked() };
614
615 self.gc.step();
616 }
617
618 pub fn set_registry<'a, K>(&self, v: <K::Value<'a> as RegValue<A>>::In<'a>)
623 where
624 K: RegKey<A>,
625 K::Value<'a>: RegValue<A>,
626 {
627 let v = K::Value::into_unsafe(v);
628
629 if unsafe { (v.tt_ & 1 << 6) != 0 && (*v.value_.gc).global != self } {
630 panic!("attempt to set registry value created from different Lua instance");
631 }
632
633 let r = unsafe { (*self.l_registry.get()).value_.gc.cast::<Table<A>>() };
635 let k = unsafe { RustId::new(self, TypeId::of::<K>()) };
636 let k = unsafe { UnsafeValue::from_obj(k.cast()) };
637
638 unsafe { (*r).set_unchecked(k, v).unwrap_unchecked() };
640 }
641
642 pub fn registry<'a, K>(&'a self) -> Option<<K::Value<'a> as RegValue<A>>::Out<'a>>
645 where
646 K: RegKey<A>,
647 K::Value<'a>: RegValue<A>,
648 {
649 let id = TypeId::of::<K>();
650 let reg = unsafe { &*(*self.l_registry.get()).value_.gc.cast::<Table<A>>() };
651 let s = unsafe { luaH_getid(reg, &id) };
652
653 match unsafe { (*s).tt_ & 0xf } {
654 0 => None,
655 _ => Some(unsafe { K::Value::from_unsafe(s) }),
656 }
657 }
658
659 #[inline(always)]
661 pub fn global(&self) -> &Table<A> {
662 let reg = unsafe { (*self.l_registry.get()).value_.gc.cast::<Table<A>>() };
663 let tab = unsafe { (*reg).array.get().add(1) };
664 let tab = unsafe { (*tab).value_.gc.cast::<Table<A>>() };
665
666 unsafe { &*tab }
667 }
668
669 #[inline(always)]
671 pub fn create_str<T>(&self, v: T) -> Ref<'_, Str<A>>
672 where
673 T: AsRef<str> + AsRef<[u8]> + Into<Vec<u8>>,
674 {
675 let s = unsafe { Str::from_str(self, v) };
676 let v = unsafe { Ref::new(s.unwrap_or_else(identity)) };
677
678 if s.is_ok() {
679 self.gc.step();
680 }
681
682 v
683 }
684
685 #[inline(always)]
687 pub fn create_bytes<T>(&self, v: T) -> Ref<'_, Str<A>>
688 where
689 T: AsRef<[u8]> + Into<Vec<u8>>,
690 {
691 let s = unsafe { Str::from_bytes(self, v) };
692 let v = unsafe { Ref::new(s.unwrap_or_else(identity)) };
693
694 if s.is_ok() {
695 self.gc.step();
696 }
697
698 v
699 }
700
701 #[inline(always)]
703 pub fn create_table(&self) -> Ref<'_, Table<A>> {
704 let v = unsafe { Ref::new(Table::new(self)) };
705
706 self.gc.step();
707
708 v
709 }
710
711 #[inline(always)]
717 pub fn create_ud<T: Any>(&self, v: T) -> Ref<'_, UserData<A, T>> {
718 let v = unsafe { Ref::new(UserData::new(self, v).cast()) };
719
720 self.gc.step();
721
722 v
723 }
724
725 pub fn create_thread(&self) -> Ref<'_, Thread<A>> {
727 let v = unsafe { Ref::new(Thread::new(self)) };
728
729 self.gc.step();
730
731 v
732 }
733
734 pub fn create_btree_map<K, V>(&self) -> Ref<'_, BTreeMap<A, K, V>>
739 where
740 K: Ord + 'static,
741 V: CollectionValue<A> + 'static,
742 {
743 let v = unsafe { Ref::new(BTreeMap::new(self)) };
744
745 self.gc.step();
746
747 v
748 }
749
750 #[cfg(feature = "serde")]
754 #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
755 pub fn deserialize_value<'de, D: serde::Deserializer<'de>>(
756 &self,
757 deserializer: D,
758 ) -> Result<Value<'_, A>, D::Error> {
759 deserializer.deserialize_any(self::value::serde::ValueVisitor::new(self))
760 }
761
762 pub fn load(
764 &self,
765 name: impl Into<String>,
766 chunk: impl AsRef<[u8]>,
767 ) -> Result<Ref<'_, LuaFn<A>>, ParseError> {
768 let chunk = chunk.as_ref();
769 let z = Zio {
770 n: chunk.len(),
771 p: chunk.as_ptr().cast(),
772 };
773
774 let f = unsafe { luaD_protectedparser(self, z, name.into().into())? };
776
777 if !(*f).upvals.is_empty() {
778 let gt = unsafe {
779 (*((*self.l_registry.get()).value_.gc.cast::<Table<A>>()))
780 .array
781 .get()
782 .offset(2 - 1)
783 };
784
785 let io1 = unsafe { (*(*f).upvals[0].get()).v.get() };
786
787 unsafe { (*io1).value_ = (*gt).value_ };
788 unsafe { (*io1).tt_ = (*gt).tt_ };
789
790 if unsafe { (*gt).tt_ & 1 << 6 != 0 } {
791 if unsafe {
792 (*(*f).upvals[0].get()).hdr.marked.get() & 1 << 5 != 0
793 && (*(*gt).value_.gc).marked.get() & (1 << 3 | 1 << 4) != 0
794 } {
795 unsafe {
796 self.gc
797 .barrier((*f).upvals[0].get().cast(), (*gt).value_.gc)
798 };
799 }
800 }
801 }
802
803 Ok(f)
804 }
805
806 unsafe fn metatable(&self, o: *const UnsafeValue<A>) -> *const Table<A> {
807 match unsafe { (*o).tt_ & 0xf } {
808 5 => unsafe { (*(*o).value_.gc.cast::<Table<A>>()).metatable.get() },
809 7 => unsafe { (*(*o).value_.gc.cast::<UserData<A, ()>>()).mt },
810 v => unsafe { self.metatables().get_raw_int_key(v.into()).value_.gc.cast() },
811 }
812 }
813
814 #[inline(always)]
815 fn metatables(&self) -> &Table<A> {
816 let reg = unsafe { (*self.l_registry.get()).value_.gc.cast::<Table<A>>() };
817 let tab = unsafe { (*reg).array.get().add(2) };
818 let tab = unsafe { (*tab).value_.gc.cast::<Table<A>>() };
819
820 unsafe { &*tab }
821 }
822
823 #[inline(always)]
824 fn events(&self) -> &Table<A> {
825 let reg = unsafe { (*self.l_registry.get()).value_.gc.cast::<Table<A>>() };
826 let tab = unsafe { (*reg).array.get().add(3) };
827 let tab = unsafe { (*tab).value_.gc.cast::<Table<A>>() };
828
829 unsafe { &*tab }
830 }
831
832 #[inline(always)]
833 fn tokens(&self) -> &Table<A> {
834 let reg = unsafe { (*self.l_registry.get()).value_.gc.cast::<Table<A>>() };
835 let tab = unsafe { (*reg).array.get().add(4) };
836 let tab = unsafe { (*tab).value_.gc.cast::<Table<A>>() };
837
838 unsafe { &*tab }
839 }
840
841 #[inline(always)]
842 fn modules(&self) -> &Table<A> {
843 let reg = unsafe { (*self.l_registry.get()).value_.gc.cast::<Table<A>>() };
844 let tab = unsafe { (*reg).array.get().add(5) };
845 let tab = unsafe { (*tab).value_.gc.cast::<Table<A>>() };
846
847 unsafe { &*tab }
848 }
849}
850
851struct ModulesLock<'a>(&'a Cell<bool>);
853
854impl<'a> ModulesLock<'a> {
855 #[inline(always)]
856 fn new(locked: &'a Cell<bool>) -> Option<Self> {
857 if locked.get() {
858 return None;
859 }
860
861 locked.set(true);
862
863 Some(Self(locked))
864 }
865}
866
867impl<'a> Drop for ModulesLock<'a> {
868 #[inline(always)]
869 fn drop(&mut self) {
870 self.0.set(false);
871 }
872}
873
874#[repr(u64, align(8))] pub enum Value<'a, A> {
877 Nil = 0 | 0 << 4,
879 False = 1 | 0 << 4,
881 True = 1 | 1 << 4,
883 Fp(Fp<A>) = 2 | 0 << 4,
885 YieldFp(YieldFp<A>) = 2 | 1 << 4,
887 AsyncFp(AsyncFp<A>) = 2 | 2 << 4,
889 Int(i64) = 3 | 0 << 4,
891 Float(Float) = 3 | 1 << 4,
893 Str(Ref<'a, Str<A>>) = 4 | 0 << 4 | 1 << 6,
895 Table(Ref<'a, Table<A>>) = 5 | 0 << 4 | 1 << 6,
897 LuaFn(Ref<'a, LuaFn<A>>) = 6 | 0 << 4 | 1 << 6,
899 UserData(Ref<'a, UserData<A, dyn Any>>) = 7 | 0 << 4 | 1 << 6,
901 Thread(Ref<'a, Thread<A>>) = 8 | 0 << 4 | 1 << 6,
903}
904
905const _: () = assert!(align_of::<Fp<()>>() <= 8);
907const _: () = assert!(align_of::<YieldFp<()>>() <= 8);
908const _: () = assert!(align_of::<AsyncFp<()>>() <= 8);
909const _: () = assert!(align_of::<i64>() <= 8);
910const _: () = assert!(align_of::<Float>() <= 8);
911const _: () = assert!(align_of::<Ref<Str<()>>>() <= 8);
912
913impl<'a, A> Value<'a, A> {
914 #[inline]
918 pub fn from_arg(v: &Arg<'_, 'a, A>) -> Option<Self> {
919 let v = v.get_raw_or_null();
920
921 match v.is_null() {
922 true => None,
923 false => Some(unsafe { Self::from_unsafe(v) }),
924 }
925 }
926
927 #[inline(always)]
929 pub const fn is_nil(&self) -> bool {
930 matches!(self, Self::Nil)
931 }
932
933 #[inline(always)]
935 pub fn ty(&self) -> Type {
936 let t = unsafe { (self as *const Self as *const u64).read() };
938
939 unsafe { core::mem::transmute((t & 0xf) as u8) }
941 }
942
943 #[inline(always)]
947 pub const fn to_bool(&self) -> bool {
948 !matches!(self, Self::Nil | Self::False)
949 }
950
951 #[inline(never)]
952 unsafe fn from_unsafe(v: *const UnsafeValue<A>) -> Self {
953 let mut r = MaybeUninit::<Self>::uninit();
954 let p = r.as_mut_ptr().cast::<u64>();
955 let t = unsafe { (*v).tt_ };
956
957 match t & 0xf {
958 0 => unsafe { p.write(0 | 0 << 4) },
959 1 | 2 | 3 => unsafe {
960 p.write(t.into());
961 p.add(1).cast::<UntaggedValue<A>>().write((*v).value_);
962 },
963 4 | 5 | 6 | 7 | 8 => unsafe {
964 let v = (*v).value_.gc;
965
966 p.write(t.into());
967 p.add(1).cast::<*const Object<A>>().write(v);
968
969 core::mem::forget(Ref::new_inline(v));
970 },
971 _ => unreachable!(),
972 }
973
974 unsafe { r.assume_init() }
975 }
976}
977
978impl<'a, A> Clone for Value<'a, A> {
979 #[inline(always)]
980 fn clone(&self) -> Self {
981 let v = self as *const Self as *const u64;
983 let t = unsafe { v.read() as u8 };
984 let v = unsafe { v.add(1).cast::<UntaggedValue<A>>() };
985
986 if t & 1 << 6 != 0 {
987 unsafe { Ref::increment_strong_count((*v).gc) };
988 }
989
990 let mut r = MaybeUninit::<Self>::uninit();
992 let p = r.as_mut_ptr().cast::<u64>();
993
994 unsafe { p.write(t.into()) };
995 unsafe { p.add(1).cast::<UntaggedValue<A>>().write(*v) };
996
997 unsafe { r.assume_init() }
998 }
999}
1000
1001pub struct Nil;
1003
1004#[repr(transparent)]
1006pub struct Fp<A>(fn(Context<A, Args>) -> Result<Context<A, Ret>, Box<dyn Error>>);
1007
1008impl<A> Fp<A> {
1009 #[inline(always)]
1013 pub const fn new(v: fn(Context<A, Args>) -> Result<Context<A, Ret>, Box<dyn Error>>) -> Self {
1014 Self(v)
1015 }
1016}
1017
1018impl<A> Clone for Fp<A> {
1019 #[inline(always)]
1020 fn clone(&self) -> Self {
1021 *self
1022 }
1023}
1024
1025impl<A> Copy for Fp<A> {}
1026
1027#[repr(transparent)]
1029pub struct YieldFp<A>(fn(Context<A, Args>) -> Result<Context<A, Ret>, Box<dyn Error>>);
1030
1031impl<A> YieldFp<A> {
1032 #[inline(always)]
1036 pub const fn new(v: fn(Context<A, Args>) -> Result<Context<A, Ret>, Box<dyn Error>>) -> Self {
1037 Self(v)
1038 }
1039}
1040
1041impl<A> Clone for YieldFp<A> {
1042 fn clone(&self) -> Self {
1043 *self
1044 }
1045}
1046
1047impl<A> Copy for YieldFp<A> {}
1048
1049#[repr(transparent)]
1059pub struct AsyncFp<A>(
1060 fn(
1061 Context<A, Args>,
1062 ) -> Pin<Box<dyn Future<Output = Result<Context<A, Ret>, Box<dyn Error>>> + '_>>,
1063);
1064
1065impl<A> AsyncFp<A> {
1066 #[inline(always)]
1070 pub const fn new(
1071 v: fn(
1072 Context<A, Args>,
1073 )
1074 -> Pin<Box<dyn Future<Output = Result<Context<A, Ret>, Box<dyn Error>>> + '_>>,
1075 ) -> Self {
1076 Self(v)
1077 }
1078}
1079
1080impl<A> Clone for AsyncFp<A> {
1081 #[inline(always)]
1082 fn clone(&self) -> Self {
1083 *self
1084 }
1085}
1086
1087impl<A> Copy for AsyncFp<A> {}
1088
1089pub struct Dynamic;
1091
1092#[repr(u8)]
1094#[derive(Clone, Copy, PartialEq, Eq)]
1095enum Ops {
1096 Add,
1097 Sub,
1098 Mul,
1099 Mod,
1100 Pow,
1101 NumDiv,
1102 IntDiv,
1103 And,
1104 Or,
1105 Xor,
1106 Shl,
1107 Shr,
1108 Neg,
1109 Not,
1110}
1111
1112impl Ops {
1113 const fn from_u8(v: u8) -> Option<Self> {
1114 match v {
1115 v if v == Self::Add as u8 => Some(Self::Add),
1116 v if v == Self::Sub as u8 => Some(Self::Sub),
1117 v if v == Self::Mul as u8 => Some(Self::Mul),
1118 v if v == Self::Mod as u8 => Some(Self::Mod),
1119 v if v == Self::Pow as u8 => Some(Self::Pow),
1120 v if v == Self::NumDiv as u8 => Some(Self::NumDiv),
1121 v if v == Self::IntDiv as u8 => Some(Self::IntDiv),
1122 v if v == Self::And as u8 => Some(Self::And),
1123 v if v == Self::Or as u8 => Some(Self::Or),
1124 v if v == Self::Xor as u8 => Some(Self::Xor),
1125 v if v == Self::Shl as u8 => Some(Self::Shl),
1126 v if v == Self::Shr as u8 => Some(Self::Shr),
1127 v if v == Self::Neg as u8 => Some(Self::Neg),
1128 v if v == Self::Not as u8 => Some(Self::Not),
1129 _ => None,
1130 }
1131 }
1132}
1133
1134#[derive(Default)]
1136struct Buffer(Vec<u8>);
1137
1138impl Deref for Buffer {
1139 type Target = Vec<u8>;
1140
1141 #[inline(always)]
1142 fn deref(&self) -> &Self::Target {
1143 &self.0
1144 }
1145}
1146
1147impl DerefMut for Buffer {
1148 #[inline(always)]
1149 fn deref_mut(&mut self) -> &mut Self::Target {
1150 &mut self.0
1151 }
1152}
1153
1154impl AsRef<[u8]> for Buffer {
1155 #[inline(always)]
1156 fn as_ref(&self) -> &[u8] {
1157 &self.0
1158 }
1159}
1160
1161impl core::fmt::Write for Buffer {
1162 #[inline]
1163 fn write_str(&mut self, s: &str) -> core::fmt::Result {
1164 self.0.extend_from_slice(s.as_bytes());
1165 Ok(())
1166 }
1167}
1168
1169impl From<Buffer> for Vec<u8> {
1170 #[inline(always)]
1171 fn from(value: Buffer) -> Self {
1172 value.0
1173 }
1174}
1175
1176#[derive(Debug)]
1178pub struct CallError {
1179 chunk: Option<(Rc<String>, u32)>,
1180 reason: Box<dyn Error>,
1181}
1182
1183impl CallError {
1184 unsafe fn new<A>(th: *const Thread<A>, mut reason: Box<dyn Error>) -> Box<Self> {
1185 reason = match reason.downcast() {
1187 Ok(v) => return v,
1188 Err(e) => e,
1189 };
1190
1191 let mut ci = unsafe { (*th).ci.get() };
1193 let mut chunk = None;
1194
1195 while unsafe { ci != (*th).base_ci.get() } {
1196 let mut ar = lua_Debug::default();
1197
1198 let func = unsafe { (*th).stack.get().add((*ci).func) };
1199 let cl = if unsafe {
1200 (*func).tt_ == 6 | 0 << 4 | 1 << 6 || (*func).tt_ == 6 | 2 << 4 | 1 << 6
1201 } {
1202 unsafe { (*func).value_.gc }
1203 } else {
1204 null()
1205 };
1206
1207 unsafe { funcinfo(&mut ar, cl) };
1208
1209 ar.currentline = if unsafe { !ci.is_null() && (*ci).callstatus & 1 << 1 == 0 } {
1210 unsafe {
1211 luaG_getfuncline(
1212 (*(*func).value_.gc.cast::<LuaFn<A>>()).p.get(),
1213 ((*ci).pc - 1) as _,
1214 )
1215 }
1216 } else {
1217 -1
1218 };
1219
1220 if let Some(v) = ar.chunk {
1221 chunk = Some((v, u32::try_from(ar.currentline).unwrap()));
1222 break;
1223 }
1224
1225 ci = unsafe { (*ci).previous };
1226 }
1227
1228 Box::new(Self { chunk, reason })
1229 }
1230
1231 pub fn location(&self) -> Option<(&str, u32)> {
1233 self.chunk.as_ref().map(|(n, l)| (n.as_str(), *l))
1234 }
1235
1236 pub fn reason(&self) -> &(dyn Error + 'static) {
1238 self.reason.deref()
1239 }
1240}
1241
1242impl Error for CallError {
1243 fn source(&self) -> Option<&(dyn Error + 'static)> {
1244 self.reason.source()
1245 }
1246}
1247
1248impl Display for CallError {
1249 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
1250 self.reason.fmt(f)
1251 }
1252}
1253
1254#[derive(Debug, Error)]
1256pub enum ArithError {
1257 #[error("attempt to perform 'n%0'")]
1259 ModZero,
1260
1261 #[error("attempt to divide by zero")]
1263 DivZero,
1264}
1265
1266#[derive(Debug, Error)]
1268#[error("stack overflow")]
1269pub struct StackOverflow;
1270
1271#[derive(Debug, Error)]
1273#[error("module with the same name already exists")]
1274pub struct ModuleExists;
1275
1276#[derive(Debug, Error)]
1279#[error("a call to '{0}' cannot be recursive")]
1280pub struct RecursiveCall(&'static str);
1281
1282impl RecursiveCall {
1283 fn new<F>(_: F) -> Self {
1284 Self(core::any::type_name::<F>())
1285 }
1286}
1287
1288static NON_YIELDABLE_WAKER: RawWakerVTable = RawWakerVTable::new(
1289 |_| unimplemented!(),
1290 |_| unimplemented!(),
1291 |_| unimplemented!(),
1292 |_| {},
1293);
1294
1295static YIELDABLE_WAKER: RawWakerVTable = RawWakerVTable::new(
1296 |_| unimplemented!(),
1297 |_| unimplemented!(),
1298 |_| unimplemented!(),
1299 |_| {},
1300);