import { BaseDecorationOptions , Decoration } from './decoration' ; import { LuaType , PointerSize } from './types' ; import Global from './global' ; import Thread from './thread' ; export default abstract class LuaTypeExtension < T , K extends BaseDecorationOptions = BaseDecorationOptions > { public readonly name : string ; protected thread : Global ; public constructor ( thread , name ) { this . thread = thread ; this . name = name ; } public isType ( _thread , _index , type , name ? ) { return type === LuaType . Userdata && name === this . name ; } public abstract close ( ) ; public getValue ( thread , index , _userdata ? ) { const refUserdata = thread . lua . luaL_testudata ( thread . address , index , this . name ) ; if ( ! refUserdata ) { throw new Error ( `data does not have the expected metatable: ${ this . name }` ) ; } const referencePointer = thread . lua . module . getValue ( refUserdata , '*' ) ; return thread . lua . getRef ( referencePointer ) ; } public pushValue ( thread , decoratedValue , _userdata ? ) { const { target } = decoratedValue ; const pointer = thread . lua . ref ( target ) ; const userDataPointer = thread . lua . lua_newuserdatauv ( thread . address , PointerSize , 0 ) ; thread . lua . module . setValue ( userDataPointer , pointer , '*' ) ; if ( LuaType . Nil === thread . lua . luaL_getmetatable ( thread . address , this . name ) ) { thread . pop ( 2 ) ; throw new Error ( `metatable not found: ${ this . name }` ) ; } thread . lua . lua_setmetatable ( thread . address , - 2 ) ; return true ; } }