use crate::closure::{LuaCClosure, LuaClosure, LuaLClosure};
use crate::gc::GcRef;
use crate::proto::LuaProto;
use crate::string::LuaString;
use crate::table::LuaTable;
use crate::upval::UpVal;
use crate::userdata::LuaUserData;
use crate::value::LuaThread;
use crate::value::LuaValue;
use lua_gc::{Marker, Trace};
impl<T: Trace + 'static> Trace for GcRef<T> {
fn trace(&self, m: &mut Marker) {
m.mark(self.0);
}
}
impl Trace for LuaValue {
fn type_name(&self) -> &'static str {
std::any::type_name::<Self>()
}
fn trace(&self, m: &mut Marker) {
match self {
LuaValue::Nil
| LuaValue::Bool(_)
| LuaValue::Int(_)
| LuaValue::Float(_)
| LuaValue::LightUserData(_) => {}
LuaValue::Str(s) => s.trace(m),
LuaValue::Table(t) => t.trace(m),
LuaValue::Function(c) => c.trace(m),
LuaValue::UserData(u) => {
u.trace(m);
}
LuaValue::Thread(t) => {
t.trace(m);
}
}
}
}
impl Trace for LuaString {
fn type_name(&self) -> &'static str {
std::any::type_name::<Self>()
}
fn trace(&self, _m: &mut Marker) {}
}
impl Trace for UpVal {
fn type_name(&self) -> &'static str {
std::any::type_name::<Self>()
}
fn trace(&self, m: &mut Marker) {
if self.try_open_payload().is_some() {
return;
}
if let Some(v) = self.try_closed_value() {
v.trace(m);
}
}
}
impl Trace for LuaTable {
fn type_name(&self) -> &'static str {
std::any::type_name::<Self>()
}
fn trace(&self, m: &mut Marker) {
const WEAK_KEYS: u8 = 1;
const WEAK_VALUES: u8 = 1 << 1;
let mode = self.weak_mode();
let trace_keys = (mode & WEAK_KEYS) == 0;
let trace_values = (mode & WEAK_VALUES) == 0 && trace_keys;
if trace_keys && trace_values {
self.trace_entries_with_clearkey(|v| v.trace(m));
} else {
self.for_each_entry(|k, v| {
if trace_keys {
k.trace(m);
}
if trace_values {
v.trace(m);
}
});
}
if let Some(mt) = self.metatable() {
mt.trace(m);
}
}
}
impl Trace for LuaProto {
fn type_name(&self) -> &'static str {
std::any::type_name::<Self>()
}
fn trace(&self, m: &mut Marker) {
for v in self.k.iter() {
v.trace(m);
}
for p in self.p.iter() {
p.trace(m);
}
if let Some(src) = &self.source {
src.trace(m);
}
for uv in self.upvalues.iter() {
if let Some(name) = &uv.name {
name.trace(m);
}
}
for lv in self.locvars.iter() {
lv.varname.trace(m);
}
if let Some(c) = self.cache.borrow().as_ref() {
c.trace(m);
}
}
}
impl Trace for LuaLClosure {
fn type_name(&self) -> &'static str {
std::any::type_name::<Self>()
}
fn trace(&self, m: &mut Marker) {
self.proto.trace(m);
for uv in self.upvals.iter() {
uv.get().trace(m);
}
}
}
impl Trace for LuaClosure {
fn type_name(&self) -> &'static str {
std::any::type_name::<Self>()
}
fn trace(&self, m: &mut Marker) {
match self {
LuaClosure::Lua(l) => l.trace(m),
LuaClosure::C(c) => c.trace(m),
LuaClosure::LightC(_) => {}
}
}
}
impl Trace for LuaCClosure {
fn type_name(&self) -> &'static str {
std::any::type_name::<Self>()
}
fn trace(&self, m: &mut Marker) {
for v in self.upvalues.borrow().iter() {
v.trace(m);
}
}
}
impl Trace for LuaUserData {
fn type_name(&self) -> &'static str {
std::any::type_name::<Self>()
}
fn trace(&self, m: &mut Marker) {
if let Some(mt) = self.metatable() {
mt.trace(m);
}
for v in self.uv.borrow().iter() {
v.trace(m);
}
}
}
impl Trace for LuaThread {
fn type_name(&self) -> &'static str {
std::any::type_name::<Self>()
}
fn trace(&self, _m: &mut Marker) {}
}