import initTrace from "debug" ; import { PTR_ADOPT_WRONG_MESSAGE , PTR_ALREADY_ADOPTED , PTR_INVALID_POINTER_TYPE } from "../../errors" ; import { format } from "../../util" ; import { ListElementSize } from "../list-element-size" ; import { ObjectSize , getWordLength } from "../object-size" ; import { Segment } from "../segment" ; import { Pointer , getTargetListLength , getTargetStructSize , getTargetPointerType , getTargetListElementSize , getTargetCompositeListSize , getCapabilityId , getContent , erasePointer , initPointer , erase , setStructPointer , setListPointer , setInterfacePointer , getListByteLength , } from "./pointer" ; import { PointerType } from "./pointer-type" ; const trace = initTrace ( "capnp:orphan" ) ; trace ( "load" ) ; export interface _Orphan { capId : number ; elementSize : ListElementSize ; length : number ; size : ObjectSize ; type : PointerType ; } export class extends Pointer template T export class Orphan < T extends Pointer > { /** If this member is not present then the orphan has already been adopted, or something went very wrong. */ _capnp ? : _Orphan ; byteOffset : number ; segment : Segment ; constructor ( src ) { const c = getContent ( src ) ; this . segment = c . segment ; this . byteOffset = c . byteOffset ; this . _capnp = { } as _Orphan ; this . _capnp . type = getTargetPointerType ( src ) ; switch ( this . _capnp . type ) { case PointerType . STRUCT : this . _capnp . size = getTargetStructSize ( src ) ; break ; case PointerType . LIST : this . _capnp . length = getTargetListLength ( src ) ; this . _capnp . elementSize = getTargetListElementSize ( src ) ; if ( this . _capnp . elementSize === ListElementSize . COMPOSITE ) { this . _capnp . size = getTargetCompositeListSize ( src ) ; } break ; case PointerType . OTHER : this . _capnp . capId = getCapabilityId ( src ) ; break ; default : throw new Error ( PTR_INVALID_POINTER_TYPE ) ; } erasePointer ( src ) ; } param { T } dst returns { void } _moveTo ( dst ) { if ( this . _capnp === undefined ) { throw new Error ( format ( PTR_ALREADY_ADOPTED , this ) ) ; } if ( this . segment . message !== dst . segment . message ) { throw new Error ( format ( PTR_ADOPT_WRONG_MESSAGE , this , dst ) ) ; } erase ( dst ) ; const res = initPointer ( this . segment , this . byteOffset , dst ) ; switch ( this . _capnp . type ) { case PointerType . STRUCT : setStructPointer ( res . offsetWords , this . _capnp . size , res . pointer ) ; break ; case PointerType . LIST : { let offsetWords = res . offsetWords ; if ( this . _capnp . elementSize === ListElementSize . COMPOSITE ) { offsetWords -- ; } setListPointer ( offsetWords , this . _capnp . elementSize , this . _capnp . length , res . pointer , this . _capnp . size ) ; break ; } case PointerType . OTHER : setInterfacePointer ( this . _capnp . capId , res . pointer ) ; break ; default : throw new Error ( PTR_INVALID_POINTER_TYPE ) ; } this . _capnp = undefined ; } dispose ( ) { if ( this . _capnp === undefined ) { trace ( "not disposing an already disposed orphan" , this ) ; return ; } switch ( this . _capnp . type ) { case PointerType . STRUCT : this . segment . fillZeroWords ( this . byteOffset , getWordLength ( this . _capnp . size ) ) ; break ; case PointerType . LIST : { const byteLength = getListByteLength ( this . _capnp . elementSize , this . _capnp . length , this . _capnp . size ) ; this . segment . fillZeroWords ( this . byteOffset , byteLength ) ; break ; } default : break ; } this . _capnp = undefined ; } toString ( ) { return format ( "Orphan_%d@%a,type:%s" , this . segment . id , this . byteOffset , this . _capnp && this . _capnp . type ) ; } }