import { NameCounter } from '../name-counter' ; import { rgraphql , PackPrimitive , UnpackPrimitive } from 'rgraphql' ; export interface IVariableReference { id : number ; name : string ; varb : Variable ; clone ( ) : IVariableReference | undefined ; unsubscribe ( ) : void ; } export class Variable { public removed = false ; private referenceCounter = 0 ; private references : number [ ] = [ ] ; constructor ( public id , public name , public value ) { } public toProto ( ) { return { id : this . id , value : PackPrimitive ( this . value ) } ; } public get hasReferences ( ) : boolean { return this . references . length > 0 ; } public addReference ( ) { let refId = ++ this . referenceCounter ; this . references . push ( refId ) ; let unsubbed = false ; return { id : this . id , name : this . name , varb : this , clone : ( ) => { if ( unsubbed ) { return ; } return this . addReference ( ) ; } , unsubscribe : ( ) => { if ( unsubbed ) { return ; } unsubbed = true ; let idx = this . references . indexOf ( refId ) ; if ( idx === - 1 ) { return ; } this . references . splice ( idx , 1 ) ; } } ; } } export type AddVariableCallback = ( varb : Variable ) => void ; export class VariableStore { private variableIdCounter = 0 ; private variableNameCounter = new NameCounter ( ) ; private variables : { [ name ] : Variable ; } = { } ; constructor ( private cb ) { } public getVariable ( value ) { for ( let variableName in this . variables ) { if ( ! this . variables . hasOwnProperty ( variableName ) ) { continue ; } let variable = this . variables [ variableName ] ; if ( variable . value === value ) { return variable . addReference ( ) ; } } let nvar = new Variable ( this . variableIdCounter ++ , this . variableNameCounter . increment ( ) , value ) ; this . variables [ nvar . name ] = nvar ; this . cb ( nvar ) ; return nvar . addReference ( ) ; } public getVariableByName ( name ) { let variable = this . variables [ name ] ; if ( ! variable ) { return null ; } return variable . addReference ( ) ; } public forEach ( cb ) { for ( let variableName in this . variables ) { if ( ! this . variables . hasOwnProperty ( variableName ) ) { continue ; } cb ( this . variables [ variableName ] ) ; } } public garbageCollect ( ) { for ( let variableName of Object . keys ( this . variables ) ) { let variable = this . variables [ variableName ] ; if ( ! variable . hasReferences ) { variable . removed = true ; delete this . variables [ variableName ] ; } } } }