OverviewFilesCommitsIssuesDocsReleasesPeers

mirall-cli / node_modules / binary-stream-equals / index.js

102 lines · javascript ref:
const b4a = require('b4a')

module.exports = function (a, b) {
  return new Promise((resolve, reject) => binaryEquals(a, b, resolve, reject))
}

function binaryEquals (a, b, resolve, reject) {
  let aBuf = null
  let aEnded = false

  let bBuf = null
  let bEnded = false

  let closed = 0
  let done = false
  let error = null
  let equals = false

  a.on('readable', tick)
  a.on('end', onend)
  a.on('error', onerror)
  a.on('close', onclose)

  b.on('readable', tick)
  b.on('end', onend)
  b.on('error', onerror)
  b.on('close', onclose)

  function onerror (err) {
    error = err
    a.destroy()
    b.destroy()
  }

  function onclose () {
    if (++closed !== 2) return
    if (error !== null && done === false) reject(error)
    else resolve(equals)
  }

  function ondone (eq) {
    if (done) return
    done = true

    equals = eq

    a.destroy()
    b.destroy()
  }

  function onend () {
    if (this === a) aEnded = true
    else bEnded = true
    tick()
  }

  function tick () {
    while (done === false) {
      if (aBuf === null) aBuf = a.read()
      if (bBuf === null) bBuf = b.read()

      if (aBuf === null && bBuf === null && aEnded && bEnded) {
        ondone(true)
        return
      }

      if (aBuf !== null && (bBuf === null && bEnded)) {
        ondone(false)
        return
      }

      if (bBuf !== null && (aBuf === null && aEnded)) {
        ondone(false)
        return
      }

      if (aBuf === null || bBuf === null) return // read pending

      if (aBuf.byteLength === bBuf.byteLength) {
        if (b4a.equals(aBuf, bBuf)) {
          aBuf = bBuf = null
          continue
        }

        ondone(false)
        return
      }

      const min = Math.min(aBuf.byteLength, bBuf.byteLength)

      if (b4a.equals(aBuf.subarray(0, min), bBuf.subarray(0, min))) {
        aBuf = aBuf.byteLength === min ? null : aBuf.subarray(min)
        bBuf = bBuf.byteLength === min ? null : bBuf.subarray(min)
        continue
      }

      ondone(false)
      return
    }
  }
}