import assert from 'assert' ; import { AnyId , Value } from './core' ; import { TimeValue } from './time' ; declare module './core' { interface AnyId { seq ( ) : AnyId ; startWith ( n ) : AnyId ; max ( n ) : AnyId ; resetByTime ( ) : AnyId ; } } class SequenceValue extends Value { private lowerBound = 0 ; private upperBound = 2 ^ 32 ; private seq : number | undefined ; private _resetByTime = false ; private timeValue : TimeValue | undefined ; private time : Buffer | undefined ; private initialized = false ; startWith ( n ) { this . lowerBound = n ; } max ( n ) { this . upperBound = n ; } resetByTime ( ) { this . _resetByTime = true ; } value ( ) { if ( ! this . initialized ) { this . init ( ) ; } if ( ! this . seq || this . seq > this . upperBound || this . toBeReset ( ) ) { this . seq = this . lowerBound ; } return this . returnValue ( this . seq ++ ) ; } private init ( ) { if ( this . _resetByTime ) { this . timeValue = < TimeValue > this . owner . findValueByType ( TimeValue . name ) ; assert ( this . timeValue , 'resetByTime() requires time()' ) ; this . time = this . timeValue . value ( ) ; } this . initialized = true ; } private toBeReset ( ) { if ( this . _resetByTime ) { const now = this . timeValue ! . value ( ) ; if ( this . time ! . compare ( now ) !== 0 ) { this . time = now ; return true ; } } return false ; } } export class Sequence { seq ( this ) { this . addValue ( new SequenceValue ( this ) ) ; return this ; } startWith ( this , n ) { assert ( this . lastValue ( ) instanceof SequenceValue , 'startWith() must follow seq()' ) ; ( this . lastValue ( ) as SequenceValue ) . startWith ( n ) ; return this ; } max ( this , n ) { assert ( this . lastValue ( ) instanceof SequenceValue , 'max() must follow seq()' ) ; ( this . lastValue ( ) as SequenceValue ) . max ( n ) ; return this ; } resetByTime ( this ) { assert ( this . lastValue ( ) instanceof SequenceValue , 'resetByTime() must follow seq()' ) ; ( this . lastValue ( ) as SequenceValue ) . resetByTime ( ) ; return this ; } }