{"version":3,"file":"index.cjs","sources":["../src/utils.ts","../src/encoder.ts","../src/reconciler.ts","../src/set.ts"],"sourcesContent":["export function arrayEquals(arr1: Uint8Array | number[], arr2: Uint8Array | number[]) {\n  for (let i = 0; i < arr1.length; i++) {\n    if (arr1[i] != arr2[i]) return false\n  }\n\n  return true\n}\n\nexport function arrayCompare(arr1: Uint8Array | number[], arr2: Uint8Array | number[]) {\n  for (let i = 0; i < arr1.length; i++) {\n    if (arr1[i] < arr2[i]) return -1\n    if (arr1[i] > arr2[i]) return 1\n  }\n\n  return 0\n}\n\nexport function arrayZero(arr: Uint8Array | number[]): boolean {\n  for (let i = 0; i < arr.length; i++) {\n    if (arr[i] != 0) return false\n  }\n  return true\n}\n","import {Hash} from 'sha256-uint8array'\n\nimport {arrayCompare} from './utils'\n\n/** The ID if a descriptor. */\nexport type ID = string\n\n/**\n * A descriptor with an `id` and `type`.\n *\n * @public\n */\nexport type Encoded<T extends string, U extends EncodableObject = EncodableObject> = U & {\n  id: ID\n  type: T\n}\n\n/**\n * The subset of values which we can encode.\n *\n * @public\n */\nexport type EncodableValue = EncodableObject | Array<EncodableValue> | boolean | string | null\n\n/**\n * A JavaScript object which can be encoded as a descriptor.\n * @public\n */\nexport type EncodableObject = {[key: string]: EncodableValue | undefined}\n\n// Not sure why, but ESLint thinks that this shadows an existing identifier.\n// eslint-disable-next-line no-shadow\nenum Tag {\n  NULL = 0x6e,\n  TRUE = 0x74,\n  FALSE = 0x66,\n  STRING = 0x73,\n  ARRAY_START = 0x61,\n  ARRAY_END = 0x41,\n  OBJECT_START = 0x6f,\n  OBJECT_END = 0x4f,\n}\n\nconst MULTIHASH_SHA256 = '\\x12\\x20'\n\nclass IDEncoder {\n  hash: Hash = new Hash()\n  buffer: ArrayBuffer = new ArrayBuffer(4)\n  rewriteMap: Map<EncodableValue, EncodableValue>\n  uint8 = new Uint8Array(this.buffer)\n  uint8_byte = new Uint8Array(this.buffer, 0, 1)\n  int32 = new Int32Array(this.buffer)\n\n  constructor(rewriteMap: Map<EncodableValue, EncodableValue>) {\n    this.rewriteMap = rewriteMap\n  }\n\n  encodeByte(byte: number) {\n    this.uint8_byte[0] = byte\n    this.hash.update(this.uint8_byte)\n  }\n\n  encodeString(val: string) {\n    this.hash.update(val, 'utf8')\n  }\n\n  encodeInt32(val: number) {\n    this.int32[0] = val\n    if (this.int32[0] !== val) throw new Error('Only 32-bit numbers can be encoded as descriptors')\n    this.hash.update(this.uint8)\n  }\n\n  /**\n   * Encodes a value.\n   *\n   * Since values can be rewritten during encoding this returns the actual value that was encoded.\n   * This may be the exact same object that was passed in.\n   */\n  encodeValue(val: EncodableValue): EncodableValue {\n    const rewritten = this.rewriteMap.get(val)\n    if (rewritten) {\n      const result = this.encodeValue(rewritten)\n      // If this turned out to be a different value, then we can update the rewriteMap.\n      // This will only trigger on recursive rewrites.\n      if (result !== rewritten) this.rewriteMap.set(val, result)\n      return result\n    }\n\n    if (val === null) {\n      this.encodeByte(Tag.NULL)\n      return val\n    } else if (val === true) {\n      this.encodeByte(Tag.TRUE)\n      return val\n    } else if (val === false) {\n      this.encodeByte(Tag.FALSE)\n      return val\n    } else if (typeof val === 'string') {\n      this.encodeByte(Tag.STRING)\n      this.encodeString(val)\n      return val\n    } else if (Array.isArray(val)) {\n      // We set this array once we've discovered that something was rewritten.\n      let result: Array<EncodableValue> | undefined\n\n      this.encodeByte(Tag.ARRAY_START)\n      let idx = 0\n      for (const elem of val) {\n        const other = this.encodeValue(elem)\n        if (result) {\n          result.push(other)\n        } else if (other !== elem) {\n          result = val.slice(0, idx)\n          result.push(other)\n        }\n\n        idx++\n      }\n      this.encodeByte(Tag.ARRAY_END)\n      return result || val\n    } else {\n      const digests = []\n      let result: EncodableObject | undefined\n\n      let idx = 0\n      const entries = Object.entries(val)\n\n      for (const [key, field] of entries) {\n        if (field === undefined) {\n          idx++\n          continue\n        }\n\n        const fieldEncoder = new IDEncoder(this.rewriteMap)\n        fieldEncoder.encodeString(key)\n        const fieldValue = fieldEncoder.encodeValue(field)\n        digests.push(fieldEncoder.getDigest())\n\n        if (result) {\n          result[key] = fieldValue\n        } else if (fieldValue !== field) {\n          // This is the first time we've detected a new value.\n          result = {}\n          for (const [prevKey, prevField] of entries.slice(0, idx)) {\n            result[prevKey] = prevField\n          }\n          result[key] = fieldValue\n        }\n\n        idx++\n      }\n\n      digests.sort((a, b) => arrayCompare(a, b))\n\n      this.encodeByte(Tag.OBJECT_START)\n      for (const digest of digests) {\n        this.hash.update(digest)\n      }\n      this.encodeByte(Tag.OBJECT_END)\n\n      return result || val\n    }\n  }\n\n  encodeObjectWithType<Type extends string, Props extends EncodableObject>(\n    type: Type,\n    val: Props,\n  ): Props & {type: Type} {\n    const result: EncodableObject & {type: Type} = {type}\n\n    const digests = []\n\n    for (const [key, field] of Object.entries(val)) {\n      if (field === undefined) {\n        continue\n      }\n\n      const fieldEncoder = new IDEncoder(this.rewriteMap)\n      fieldEncoder.encodeString(key)\n      result[key] = fieldEncoder.encodeValue(field)\n      digests.push(fieldEncoder.getDigest())\n    }\n\n    const typeEncoder = new IDEncoder(this.rewriteMap)\n    typeEncoder.encodeString('type')\n    typeEncoder.encodeValue(type)\n    digests.push(typeEncoder.getDigest())\n\n    digests.sort((a, b) => arrayCompare(a, b))\n\n    this.encodeByte(Tag.OBJECT_START)\n    for (const digest of digests) {\n      this.hash.update(digest)\n    }\n    this.encodeByte(Tag.OBJECT_END)\n    return result as Props & {type: Type}\n  }\n\n  getDigest() {\n    return this.hash.digest()\n  }\n}\n\n/**\n * Encodes binary data into the base64url format as specified by multibase:\n * https://github.com/multiformats/multibase.\n *\n * @public\n */\nexport function encodeBase64(data: Uint8Array, prefix: string = ''): string {\n  let binary = prefix\n  for (let i = 0; i < data.length; i++) {\n    binary += String.fromCharCode(data[i])\n  }\n  return 'u' + globalThis.btoa(binary).replaceAll('+', '-').replaceAll('/', '_').replaceAll('=', '')\n}\n\n/**\n * Encodes a SHA256 hash (which should be 32 bytes long) as specified by multihash:\n * https://github.com/multiformats/multihash.\n *\n * @public\n */\nexport function encodeBase64Sha256(data: Uint8Array): string {\n  return encodeBase64(data, MULTIHASH_SHA256)\n}\n\n/**\n * Decodes a base64 value encoded using multibase.\n *\n * @public\n */\nexport function decodeBase64(input: string, into: Uint8Array): void {\n  if (input[0] !== 'u') throw new Error('Invalid base64')\n\n  const binary = globalThis.atob(input.slice(1).replaceAll('-', '+').replaceAll('_', '/'))\n  for (let i = 0; i < binary.length; i++) {\n    into[i] = binary.charCodeAt(i)\n  }\n}\n\nconst EMPTY_REWRITE_MAP = new Map<EncodableObject, EncodableObject>()\n\n/**\n * Encodes an object with the given type.\n *\n * @public\n */\nexport function encode<Type extends string, Props extends EncodableObject>(\n  type: Type,\n  props: Props,\n  options?: {\n    /**\n     * This is invoked with the raw SHA256 hash, which will also be placed in\n     * `id` in encoded form.\n     **/\n    withDigest?: (digest: Uint8Array) => void\n    /**\n     * A map of objects that will be rewritten.\n     * Any of the keys that are seen will be replaced with the value.\n     */\n    rewriteMap?: Map<EncodableValue, EncodableValue>\n  },\n): Encoded<Type, Props> {\n  const idEncoder = new IDEncoder(options?.rewriteMap || EMPTY_REWRITE_MAP)\n  const tweakedProps = idEncoder.encodeObjectWithType<Type, Props>(type, props)\n  const digest = idEncoder.getDigest()\n  if (options?.withDigest) options.withDigest(digest)\n  const id = encodeBase64(digest, MULTIHASH_SHA256)\n  return {id, ...tweakedProps}\n}\n","import {arrayCompare, arrayEquals, arrayZero} from './utils'\n\nconst NUM_HASH = 3\n\n/**\n * A sketch of a set of n-byte objects (als sometimes called \"invertible Bloom\n * filter\"). It supports the following operation:\n *\n * - `construct`: Create a sketch with a given number of buckets (i.e.\n *   capacity).\n * - `toggle`: Add/remove (depending on whether it already existed) a value into\n *   the sketch.\n * - `toggleAll`: Add/remove all the values from _another_ sketch.\n * - `decode`: Attempt to recover the values inside the set. This should succeed\n *   with a high probability if the set currently contains ~80% of the number of\n *   buckets it was constructed with.\n *\n * The typical use case is to use this to construct two different sketches, each\n * could contain hundreds or thousands entries, and then by invoking `toggleAll`\n * between these sketches it's possible to decode the symmetric difference\n * between the sets.\n *\n * This is an implementation of https://doi.org/10.4230/LIPIcs.ICALP.2024.20.\n *\n * @internal\n */\nexport class SetSketch {\n  arr: Uint8Array\n  byteSize: number\n  numBuckets: number\n\n  constructor(byteSize: number, numBuckets: number) {\n    if (numBuckets >= 31) throw new Error('numBuckets must be less than 31')\n\n    this.byteSize = byteSize\n    this.numBuckets = numBuckets\n    this.arr = new Uint8Array(this.byteSize * this.numBuckets)\n  }\n\n  toggle(val: Uint8Array | number[], yieldBucket?: (bucket: number) => void): void {\n    for (let k = 0; k < NUM_HASH; k++) {\n      const bucket = val[k] % this.numBuckets\n      if (yieldBucket) yieldBucket(bucket)\n\n      const offset = bucket * this.byteSize\n      for (let idx = 0; idx < this.byteSize; idx++) {\n        this.arr[offset + idx] ^= val[idx]\n      }\n    }\n  }\n\n  toggleAll(other: SetSketch): void {\n    for (let i = 0; i < this.arr.length; i++) {\n      this.arr[i] ^= other.arr[i]\n    }\n  }\n\n  copy(): SetSketch {\n    const result = new SetSketch(this.byteSize, this.numBuckets)\n    for (let idx = 0; idx < this.arr.length; idx++) {\n      result.arr[idx] = this.arr[idx]\n    }\n    return result\n  }\n\n  decode(): BufferSet | null {\n    const max = this.numBuckets * 2\n    const set = new BufferSet(this.byteSize, max)\n    const queue = new BitQueue(this.numBuckets)\n\n    let t = 0\n\n    while (!queue.isEmpty()) {\n      const bucket = queue.pop()\n      if (this.looksPure(bucket)) {\n        if (t >= max) {\n          // It's possible for the algorithm to be stuck in a loop so we guard this here.\n          return null\n        }\n\n        const offset = bucket * this.byteSize\n\n        // OPT: Maybe we could avoid copying here.\n        const slice = this.arr.slice(offset, offset + this.byteSize)\n\n        set.toggle(slice)\n        this.toggle(slice, (otherBuckets) => {\n          if (otherBuckets !== bucket) {\n            queue.set(otherBuckets)\n          }\n        })\n\n        t++\n      }\n    }\n\n    if (!arrayZero(this.arr)) return null\n\n    return set\n  }\n\n  looksPure(bucket: number): boolean {\n    const offset = bucket * this.byteSize\n    const val = this.arr.subarray(offset, offset + this.byteSize)\n    if (arrayZero(val)) return false\n\n    let hashedToBucketCount = 0\n\n    for (let k = 0; k < NUM_HASH; k++) {\n      const hashedBucket = val[k] % this.numBuckets\n      if (hashedBucket === bucket) hashedToBucketCount++\n    }\n\n    return hashedToBucketCount % 2 == 1\n  }\n}\n\n/**\n * Represents a set of Uint8Array's which are all of the same size.\n * The primary interface is the `toggle` method which either adds or removes\n * a value to the set.\n *\n * @beta\n */\nexport class BufferSet {\n  arr: Uint8Array\n  byteSize: number\n  length: number\n  capacity: number\n\n  constructor(byteSize: number, capacity: number) {\n    this.arr = new Uint8Array(byteSize * capacity)\n    this.byteSize = byteSize\n    this.length = 0\n    this.capacity = capacity\n  }\n\n  toggle(val: Uint8Array | number[]): void {\n    for (let i = 0; i < this.length; i++) {\n      const start = i * this.byteSize\n      const slice = this.arr.subarray(start, start + this.byteSize)\n      if (arrayEquals(val, slice)) {\n        if (i != this.length - 1) {\n          // Move the last entry into this slot.\n          const lastEntryByteIdx = (this.length - 1) * this.byteSize\n          for (let j = 0; j < this.byteSize; j++) {\n            slice[j] = this.arr[lastEntryByteIdx + j]\n          }\n        }\n\n        this.length--\n        return\n      }\n    }\n\n    if (this.length === this.capacity) throw new Error('BufferSet is full')\n\n    const byteIdx = this.length * this.byteSize\n    for (let i = 0; i < this.byteSize; i++) {\n      this.arr[byteIdx + i] = val[i]\n    }\n    this.length++\n  }\n\n  forEach(fn: (val: Uint8Array) => void): void {\n    for (let i = 0; i < this.length; i++) {\n      const start = i * this.byteSize\n      fn(this.arr.subarray(start, start + this.byteSize))\n    }\n  }\n\n  /**\n   * Returns a normalized JSON representation.\n   *\n   * This is not optimized and should mainly be used for debugging.\n   */\n  toJSON(): number[][] {\n    const result: number[][] = []\n    this.forEach((entry) => {\n      result.push(Array.from(entry))\n    })\n\n    result.sort((a, b) => arrayCompare(a, b))\n    return result\n  }\n}\n\n/**\n * A queue which can store numbers in the range of [0, 32).The `set` method is\n * idempontent and will only add a value to the queue if it's not set there\n * already.\n *\n * It uses a single bitset to efficiently keep track of which values have\n * already been set.\n *\n * The construct defaults to putting all the numbers onto the queue.\n */\nclass BitQueue {\n  bitset: number\n  queue: number[]\n\n  constructor(size: number) {\n    // Set all bits to 1\n    this.bitset = (1 << size) - 1\n    this.queue = Array.from({length: size}, (_, i) => i)\n  }\n\n  set(idx: number) {\n    const mask = 1 << idx\n    if (this.bitset & mask) {\n      // Already set. Nothing to do.\n      return\n    }\n\n    this.queue.push(idx)\n    this.bitset |= mask\n  }\n\n  isEmpty() {\n    return this.bitset === 0\n  }\n\n  pop(): number {\n    const idx = this.queue.shift()!\n    const mask = 1 << idx\n    this.bitset &= ~mask\n    return idx\n  }\n}\n","import {type EncodableObject, encode, type Encoded, type ID} from './encoder'\nimport {SetSketch} from './reconciler'\nimport type {SynchronizationRequest, SynchronizationResult} from './sync'\n\n/**\n * A set descriptor. This follows the very specific form with a property called\n * `keys` containing other descriptor IDs.\n *\n * @public\n */\nexport type EncodedSet<Type extends string> = Encoded<Type, {keys: ID[]}>\n\n/**\n * SetSynchronization contains information about a set so that it can be\n * synchronized.\n *\n * @public\n */\nexport interface SetSynchronization<Type extends string> {\n  /** @internal */\n  set: EncodedSet<Type>\n\n  /** @internal */\n  digest: Uint8Array\n\n  /** @internal */\n  objectValues: Record<string, Encoded<string, EncodableObject>>\n\n  /** @internal */\n  setValues: Record<string, SetSynchronization<string>>\n  /** @internal */\n  sketch: SetSketch\n}\n\nexport type SetBuilderOptions = {\n  /**\n   * See {@link encode}\n   */\n  rewriteMap?: Map<EncodableObject, EncodableObject>\n}\n\n/**\n * SetBuilder is a class which helps you construct a set for efficient synchronization.\n *\n * @public\n */\nexport class SetBuilder {\n  private objectValues: Record<string, Encoded<string, EncodableObject>> = {}\n  private setValues: Record<string, SetSynchronization<string>> = {}\n  private keys: string[] = []\n  private sketch: SetSketch = new SetSketch(32, 8)\n  private rewriteMap: Map<EncodableObject, EncodableObject> | undefined\n\n  constructor({rewriteMap}: SetBuilderOptions = {}) {\n    this.rewriteMap = rewriteMap\n  }\n\n  /**\n   * Add an object to the set.\n   */\n  addObject<Type extends string>(type: Type, obj: EncodableObject): void {\n    const value = encode(type, obj, {\n      withDigest: (digest) => {\n        this.sketch.toggle(digest)\n      },\n      rewriteMap: this.rewriteMap,\n    })\n    this.objectValues[value.id] = value\n    this.keys.push(value.id)\n  }\n\n  /**\n   * Add another set to the set.\n   */\n  addSet<Type extends string>(sync: SetSynchronization<Type>): void {\n    this.setValues[sync.set.id] = sync\n    this.sketch.toggle(sync.digest)\n    this.keys.push(sync.set.id)\n  }\n\n  build<Type extends string>(type: Type): SetSynchronization<Type> {\n    this.keys.sort()\n\n    let digest: Uint8Array\n\n    const set = encode(\n      type,\n      {keys: this.keys},\n      {\n        withDigest: (d) => {\n          digest = d\n        },\n      },\n    )\n\n    return {\n      set,\n      digest: digest!,\n      objectValues: this.objectValues,\n      setValues: this.setValues,\n      sketch: this.sketch,\n    }\n  }\n}\n\n/**\n * The main logic for synchronizing a set to a server.\n *\n * Initially this function should be invoked with `prevResult` set to `null`.\n * This returns a SynchronizationRequest which should then be sent to a server.\n * Once the server returns a result this function should be invoked with this\n * as a parameter. This proccess should be continued until this function return\n * `null`.\n *\n * @param sync The set to synchronize.\n * @param prevResult The result from the previous synchronization.\n * @returns `null` when the synchronization is complete, or a request which should be sent.\n * @public\n */\nexport function processSetSynchronization<Type extends string>(\n  sync: SetSynchronization<Type>,\n  prevResult: SynchronizationResult | null,\n): SynchronizationRequest | null {\n  const id = sync.set.id\n  if (!prevResult) return {id}\n\n  if (prevResult.type === 'complete') return null\n\n  const descriptors: Array<Encoded<string, EncodableObject>> = []\n\n  for (const missingId of prevResult.missingIds) {\n    const descriptor = findDescriptor(sync, missingId)\n    if (!descriptor) throw new Error(`Synchronization server is requested an unknonwn descriptor`)\n    descriptors.push(descriptor)\n  }\n\n  return {id, descriptors}\n}\n\nfunction findDescriptor<Type extends string>(\n  sync: SetSynchronization<Type>,\n  id: ID,\n): Encoded<string, EncodableObject> | null {\n  if (sync.set.id === id) return sync.set\n\n  const desc = sync.objectValues[id]\n  if (desc) return desc\n\n  for (const child of Object.values(sync.setValues)) {\n    const childDesc = findDescriptor(child, id)\n    if (childDesc) return childDesc\n  }\n\n  return null\n}\n"],"names":["Hash"],"mappings":"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"}