import type { BaseN } from "@thi.ng/base-n" ; import { BASE62 } from "@thi.ng/base-n/62" ; import { assert } from "@thi.ng/errors/assert" ; import type { IRandom } from "@thi.ng/random" ; import { randomBytes , randomBytesFrom } from "@thi.ng/random/random-bytes" ; import { padLeft } from "@thi.ng/strings/pad-left" ; import type { IKSUID , KSUIDOpts } from "./api.js" ; /**
 * Abstract base class for both 32 & 64bit implementations. See  KSUID * and  KSUID64 .
  export abstract class AKSUID implements IKSUID { readonly size : number ; readonly encodedSize : number ; readonly base : BaseN ; readonly epoch : number ; protected rnd ? : IRandom ; protected pad : ( x : any ) => string ; protected constructor ( public readonly epochSize , opts ) { this . base = opts . base || BASE62 ; this . rnd = opts . rnd ; this . epoch = opts . epoch ! ; this . size = this . epochSize + opts . bytes ! ; this . encodedSize = this . base . size ( 2 ** ( this . size * 8 ) - 1 ) ; this . pad = padLeft ( this . encodedSize , this . base . base [ 0 ] ) ; } next ( ) { return this . format ( this . nextBinary ( ) ) ; } nextBinary ( ) { const buf = this . timeOnlyBinary ( ) ; return this . rnd ? randomBytesFrom ( this . rnd , buf , this . epochSize ) : randomBytes ( buf , this . epochSize ) ; } timeOnly ( epoch ? ) { return this . format ( this . timeOnlyBinary ( epoch ) ) ; } abstract timeOnlyBinary ( epoch ? ) ; format ( buf ) { this . ensureSize ( buf ) ; return this . pad ( this . base . encodeBytes ( buf ) ) ; } abstract parse ( id ) ; protected ensureSize ( buf ) { assert ( buf . length == this . size , `illegal KSUID size, expected ${ this . size } bytes` ) ; return buf ; } protected ensureTime ( t ) { assert ( t >= 0 , "configured base epoch must be in the past" ) ; return t ; } protected u32 ( buf , i = 0 ) { return ( ( ( buf [ i ] << 24 ) | ( buf [ i + 1 ] << 16 ) | ( buf [ i + 2 ] << 8 ) | buf [ i + 3 ] ) >>> 0 ) ; } }