use lua_gc::{Marker, Trace};
use crate::gc::GcRef;
use crate::value::LuaValue;
use crate::table::LuaTable;
use crate::upval::{UpVal, UpValState};
use crate::string::LuaString;
use crate::proto::LuaProto;
use crate::closure::{LuaClosure, LuaLClosure, LuaCClosure};
use crate::userdata::LuaUserData;
use crate::value::LuaThread;
impl<T: Trace + 'static> Trace for GcRef<T> {
fn trace(&self, m: &mut Marker) {
m.mark(self.0);
}
}
impl Trace for LuaValue {
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 trace(&self, _m: &mut Marker) {}
}
impl Trace for UpVal {
fn trace(&self, m: &mut Marker) {
let state = self.state.try_borrow();
if let Ok(state) = state {
match &*state {
UpValState::Open { .. } => {}
UpValState::Closed(v) => v.trace(m),
}
return;
}
if let Some(v) = self.try_closed_value() {
v.trace(m);
}
}
}
impl Trace for LuaTable {
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;
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 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 trace(&self, m: &mut Marker) {
self.proto.trace(m);
for uv in self.upvals.iter() {
uv.get().trace(m);
}
}
}
impl Trace for LuaClosure {
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 trace(&self, m: &mut Marker) {
for v in self.upvalues.borrow().iter() {
v.trace(m);
}
}
}
impl Trace for LuaUserData {
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 trace(&self, _m: &mut Marker) {}
}