OverviewFilesCommitsIssuesDocsReleasesPeers

mirall-cli / node_modules / compact-encoding-net / index.js

216 lines · javascript ref:
const c = require('compact-encoding')

const port = c.uint16

const address = (host, family) => {
  return {
    preencode(state, m) {
      host.preencode(state, m.host)
      port.preencode(state, m.port || 0)
    },
    encode(state, m) {
      host.encode(state, m.host)
      port.encode(state, m.port || 0)
    },
    decode(state) {
      return {
        host: host.decode(state),
        family,
        port: port.decode(state)
      }
    }
  }
}

const ipv4 = {
  preencode(state) {
    state.end += 4
  },
  encode(state, string) {
    string = string || '127.0.0.1'

    const start = state.start
    const end = start + 4

    let i = 0

    while (i < string.length) {
      let n = 0
      let c

      while (
        i < string.length &&
        (c = string.charCodeAt(i++)) !== /* . */ 0x2e
      ) {
        n = n * 10 + (c - /* 0 */ 0x30)
      }

      state.buffer[state.start++] = n
    }

    state.start = end
  },
  decode(state) {
    if (state.end - state.start < 4) throw new Error('Out of bounds')
    return (
      state.buffer[state.start++] +
      '.' +
      state.buffer[state.start++] +
      '.' +
      state.buffer[state.start++] +
      '.' +
      state.buffer[state.start++]
    )
  }
}

const ipv4Address = address(ipv4, 4)

const ipv6 = {
  preencode(state) {
    state.end += 16
  },
  encode(state, string) {
    string = string || '::1'

    const start = state.start
    const end = start + 16

    let i = 0
    let split = null

    while (i < string.length) {
      let n = 0
      let c

      while (
        i < string.length &&
        (c = string.charCodeAt(i++)) !== /* : */ 0x3a
      ) {
        if (c >= 0x30 && c <= 0x39) n = n * 0x10 + (c - /* 0 */ 0x30)
        else if (c >= 0x41 && c <= 0x46) n = n * 0x10 + (c - /* A */ 0x41 + 10)
        else if (c >= 0x61 && c <= 0x66) n = n * 0x10 + (c - /* a */ 0x61 + 10)
      }

      state.buffer[state.start++] = n >>> 8
      state.buffer[state.start++] = n

      if (i < string.length && string.charCodeAt(i) === /* : */ 0x3a) {
        i++
        split = state.start
      }
    }

    if (split !== null) {
      const offset = end - state.start
      state.buffer
        .copyWithin(split + offset, split)
        .fill(0, split, split + offset)
    }

    state.start = end
  },
  decode(state) {
    if (state.end - state.start < 16) throw new Error('Out of bounds')
    return (
      (
        state.buffer[state.start++] * 256 +
        state.buffer[state.start++]
      ).toString(16) +
      ':' +
      (
        state.buffer[state.start++] * 256 +
        state.buffer[state.start++]
      ).toString(16) +
      ':' +
      (
        state.buffer[state.start++] * 256 +
        state.buffer[state.start++]
      ).toString(16) +
      ':' +
      (
        state.buffer[state.start++] * 256 +
        state.buffer[state.start++]
      ).toString(16) +
      ':' +
      (
        state.buffer[state.start++] * 256 +
        state.buffer[state.start++]
      ).toString(16) +
      ':' +
      (
        state.buffer[state.start++] * 256 +
        state.buffer[state.start++]
      ).toString(16) +
      ':' +
      (
        state.buffer[state.start++] * 256 +
        state.buffer[state.start++]
      ).toString(16) +
      ':' +
      (
        state.buffer[state.start++] * 256 +
        state.buffer[state.start++]
      ).toString(16)
    )
  }
}

const ipv6Address = address(ipv6, 6)

const ip = {
  preencode(state, string) {
    string = string || '127.0.0.1'

    const family = string.includes(':') ? 6 : 4
    c.uint8.preencode(state, family)

    if (family === 4) ipv4.preencode(state)
    else ipv6.preencode(state)
  },
  encode(state, string) {
    string = string || '127.0.0.1'

    const family = string.includes(':') ? 6 : 4
    c.uint8.encode(state, family)

    if (family === 4) ipv4.encode(state, string)
    else ipv6.encode(state, string)
  },
  decode(state) {
    const family = c.uint8.decode(state)

    if (family === 4) return ipv4.decode(state)
    else return ipv6.decode(state)
  }
}

const ipAddress = {
  preencode(state, m) {
    ip.preencode(state, m.host)
    port.preencode(state, m.port || 0)
  },
  encode(state, m) {
    ip.encode(state, m.host)
    port.encode(state, m.port || 0)
  },
  decode(state) {
    const family = c.uint8.decode(state)
    return {
      host: family === 4 ? ipv4.decode(state) : ipv6.decode(state),
      family,
      port: port.decode(state)
    }
  }
}

module.exports = {
  port,
  ipv4,
  ipv4Address,
  ipv6,
  ipv6Address,
  ip,
  ipAddress
}