Skip to content
Snippets Groups Projects
typeset.js 21.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
    typeset.js
    
    Jake Read at the Center for Bits and Atoms
    (c) Massachusetts Institute of Technology 2019
    
    This work may be reproduced, modified, distributed, performed, and
    displayed for any purpose, but must acknowledge the squidworks and cuttlefish projects.
    Copyright is retained and must be preserved. The work is provided as is;
    no warranty is provided, and users accept all liability.
    */
    
    
    Jake Read's avatar
    Jake Read committed
    // typeset: functional types -> bytes for js -> embedded sys
    
    Jake Read's avatar
    Jake Read committed
    // bless up @ modern js https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
    
    
    Jake Read's avatar
    Jake Read committed
    let tsdebug = false
    
    Jake Read's avatar
    Jake Read committed
    // oy,
    
    Jake Read's avatar
    Jake Read committed
    const checkKey = (type, arr, start) => {
    
    Jake Read's avatar
    Jake Read committed
      if (arr[start] !== type.key) {
        console.log('erroneous bytes')
        console.log(arr)
        throw new Error(`mismatched key on phy read: for ${type.name}, find ${arr[start]} instead of ${type.key} ... at ${start} index`)
      }
    
    Jake Read's avatar
    Jake Read committed
    }
    
    const checkBoolean = (value) => {
    
      if (typeof value !== 'boolean')
        throw new Error('cannot cast non-boolean to bool at phy')
    
    Jake Read's avatar
    Jake Read committed
    }
    
    const checkNumber = (value) => {
    
      if (typeof value !== 'number')
        throw new Error(`cannot cast non-number into physical world "${value}", ${typeof value}`)
    
    Jake Read's avatar
    Jake Read committed
    }
    
    const checkString = (value) => {
    
      if (typeof value !== 'string')
        throw new Error(`cannot cast non-string to string at phy! "${value}", "${typeof value}"`)
    
    Jake Read's avatar
    Jake Read committed
    }
    
    const checkArray = (thing) => {
    
      if (!Array.isArray(thing))
        throw new Error('this thing is not an array!')
    
    Jake Read's avatar
    Jake Read committed
    }
    
    const checkUnsigned = (value, bits) => {
    
      if (value > Math.pow(2, bits))
        throw new Error('value out of byte bounds')
    
    Jake Read's avatar
    Jake Read committed
    }
    
    const checkSigned = (value, bits) => {
    
    Jake Read's avatar
    Jake Read committed
      let comparator = Math.pow(2, bits - 1)
    
      if (value > comparator || value < -comparator)
        throw new Error('value out of byte bounds')
    
    Jake Read's avatar
    Jake Read committed
    }
    
    Jake Read's avatar
    Jake Read committed
    const findPhy = (type) => {
      let phy = TSET.find((cand) => {
        return cand.name === type
      })
    
      if (phy === undefined)
    
        // try this... catch err elsewhere
    
        throw new Error(`could not find phy for datatype: ${type}`)
    
    Jake Read's avatar
    Jake Read committed
      return phy
    }
    
    
    const bounds = (value, min, max) => {
      return Math.max(min, Math.min(value, max))
    }
    
    const intBounds = (pfloat, min, max) => {
      return Math.round(bounds(pfloat, min, max))
    }
    
    // TYPES:
    /*
    name: string identifier, how we 'specify' what an input / output / state is
    key: byte-code for the network. if this, write, and read, don't exist, link can't have one
    write: serialize into bytes
    read: deserialize
    copy: move about within js,
     copies are 'outgoing' ... so typeA.copy.typeB(value) turns the value from
     typeA -> typeB
     the standard is typeA.copy.typeA(value), this is just a memory shuffle
     for the sake of dereferencing: we can write our own types per item
    */
    
    // TODO: TYPES:
    /*
    we are still not really type-checking on calls to .put(), and should be...
    there is probably a slick, clean way to do this
    also: would really like to work with typedarrays where they are appropriate
    
    
    .. *could* imagine some hairbrain walk through these things: if we have, i.e., conversion
    from string -> number written, and from number -> uint8, we should be able to
    compose a tree of these on the fly ...
    
    */
    
    const TSET = [
      {
    
    Jake Read's avatar
    Jake Read committed
        name: 'boolean',
    
    Jake Read's avatar
    Jake Read committed
        write: function(value) {
    
    Jake Read's avatar
    Jake Read committed
          checkBoolean(value)
    
    Jake Read's avatar
    Jake Read committed
          let rtarr = [this.key]
    
    Jake Read's avatar
    Jake Read committed
          if (value) {
    
    Jake Read's avatar
    Jake Read committed
            rtarr.push(1)
    
    Jake Read's avatar
    Jake Read committed
          } else {
    
    Jake Read's avatar
    Jake Read committed
            rtarr.push(0)
          }
          return rtarr
        },
    
    Jake Read's avatar
    Jake Read committed
        read: function(arr, start) {
          checkKey(this, arr, start)
    
    Jake Read's avatar
    Jake Read committed
          if (arr[start + 1] === 1) {
    
    Jake Read's avatar
    Jake Read committed
          } else if (arr[start + 1] === 0) {
    
    Jake Read's avatar
    Jake Read committed
          } else {
    
            throw new Error(`non std boolean byte, ${arr[start + 1]}`)
    
    Jake Read's avatar
    Jake Read committed
          }
    
          return {item: item, increment: 2}
        },
        copy: {
          boolean: function(bool) {
            return bool // direct: a basic js type, so we just pass it on
          },
          number: function(bool) { // converts boolean -> numbers
            if (bool) {
              return 1
            } else {
              return 0
            }
    
    Jake Read's avatar
    Jake Read committed
        }
    
      }, { // booleanArray: 33,
    
    Jake Read's avatar
    Jake Read committed
        name: 'byte',
        key: 34,
        write: function(value) {
          checkNumber(value)
          checkUnsigned(value, 8)
          return [this.key, value]
        },
        read: function(arr, start) {
          checkKey(this, arr, start)
          return {
            item: arr[start + 1],
            increment: 2
          }
    
        },
        copy: {
          byte: function(byte) {
            return byte
          }
    
    Jake Read's avatar
    Jake Read committed
        }
    
      }, {
    
    Jake Read's avatar
    Jake Read committed
        name: 'byteArray',
        key: 35,
        write: function(value) {
          checkArray(value)
          let rtarr = writeLenBytes(value.length).concat(value)
          rtarr.unshift(this.key)
    
          if (tsdebug)
            console.log('byteArray sanity check:', value, 'written as:', rtarr)
    
    Jake Read's avatar
    Jake Read committed
          return rtarr
        },
        read: function(arr, start) {
          checkKey(this, arr, start)
          let lb = readLenBytes(arr, start + 1)
          let narr = new Array()
    
    Jake Read's avatar
    Jake Read committed
          for (let i = 0; i < lb.len; i++) {
    
    Jake Read's avatar
    Jake Read committed
            narr.push(arr[start + 1 + lb.numBytes + i])
          }
          return {
            item: narr,
            increment: lb.len + lb.numBytes + 1
          }
    
        copy: { // copy:  into another bytearray
    
          byteArray: function(arr) {
            // TODO would be making bytearrays into buffers, would speed this up ...
            let ret = new Array(arr.length)
            for (let item in arr) {
              ret[item] = arr[item]
            }
            return ret
    
          },
          reference: function(arr){
            let ret = new Array(arr.length)
            for (let item in arr) {
              ret[item] = arr[item]
            }
            return ret
    
    Jake Read's avatar
    Jake Read committed
        }
    
      }, { // char 36, string 37,
    
        name: 'string',
    
    Jake Read's avatar
    Jake Read committed
        key: 37,
        write: function(str) {
          checkString(str)
    
          let rtarr = new Array()
    
    Jake Read's avatar
    Jake Read committed
          for (let i = 0; i < str.length; i++) {
    
            rtarr.push(str.charCodeAt(i))
          }
          // length bytes are 7-bit 'msb for continue' numbers ...
    
    Jake Read's avatar
    Jake Read committed
          // the -1 because we are not counting the length of the key
    
          let lb = writeLenBytes(rtarr.length)
          rtarr = lb.concat(rtarr)
          rtarr.unshift(this.key)
          return rtarr
        },
        read: function(arr, start) {
    
    Jake Read's avatar
    Jake Read committed
          checkKey(this, arr, start)
    
          let lb = readLenBytes(arr, start + 1)
    
    Jake Read's avatar
    Jake Read committed
          //console.log('lenbytes', lb)
    
          let str = new String()
    
    Jake Read's avatar
    Jake Read committed
          for (let i = 0; i < lb.len; i++) {
    
    Jake Read's avatar
    Jake Read committed
            str += String.fromCharCode(arr[start + 1 + lb.numBytes + i])
          }
          return {
            item: str,
            increment: lb.len + lb.numBytes + 1
    
        },
        copy: {
          string: function(str) {
    
    Jake Read's avatar
    Jake Read committed
            return str
    
          },
          number: function(str) {
            return parseFloat(str)
          },
          boolean: function(str){
            if(str == true){
              return true
            } else {
              return false
            }
    
    Jake Read's avatar
    Jake Read committed
          },
          reference: function(str){
            return str
    
      }, {
    
        name: 'uint8',
    
    Jake Read's avatar
    Jake Read committed
        key: 38,
    
        write: function(value) {
    
    Jake Read's avatar
    Jake Read committed
          checkNumber(value)
          checkUnsigned(value, 8)
    
          if (value > 255 || value < 0)
            throw new Error('num too large to represent with cast type, will contencate')
            // dont' need to type-buffer this,
    
          let rtarr = [this.key, value]
          return rtarr
        },
    
    Jake Read's avatar
    Jake Read committed
        read: function(arr, start) {
    
          // assume we're reading out of an array
          // start[] should === key
    
          if (arr[start] !== this.key)
            throw new Error(`mismatched key on phy read: ${arr[start]}, ${this.key}`)
          if (arr[start + 1] > 255 || arr[start + 1] < 0)
            throw new Error('whaky read-in on uint8')
    
          return {
    
    Jake Read's avatar
    Jake Read committed
            item: arr[start + 1],
    
            increment: 2
          }
    
        },
        copy: {
          uint8: function(uint8){
            // by clamping at the copy, we can reduce complexity at read and write ?
            // and improve clarity elsewhere ...
            return bounds(uint8, 0, 255) // clamp number
          },
          uint16: function(uint8){
            // because we always copy-in before copying-out (to other types)
            // we don't have to clamp here again, that's nice.
            // but would to go down to a smaller value ...
            return uint8
          },
          uint32: function(uint8){
            // this could really get exhaustive,
            return uint8
    
          },
          number: function(uint8){
            return uint8
    
      }, { // uint8Array 39
    
    Jake Read's avatar
    Jake Read committed
        key: 40,
    
          if (typeof value !== 'number')
            throw new Error(`cannot cast non-number into physical world "${value}", ${typeof value}`)
          if (value > 65536 || value < 0)
            throw new Error('num too large to represent with cast type, will contencate')
    
          let tparr = new Uint16Array(1)
          tparr[0] = value
          let btarr = new Uint8Array(tparr.buffer)
          //place
    
          let rtarr = Array.from(btarr)
    
    Jake Read's avatar
    Jake Read committed
        read: function(arr, start) {
    
          // assume we're reading out of an array
          // start[] should === key
    
          if (arr[start] !== this.key)
            throw new Error(`mismatched key on phy read: ${arr[start]}, ${this.key}`)
    
          let rdarr = arr.slice(start + 1, start + 3)
    
          if (tsdebug)
            console.log('bytes on read of uint16 (little eadian)', btarr)
            // now make uint32 view on this ...
    
          let vlarr = new Uint16Array(btarr.buffer)
    
          if (tsdebug)
            console.log('vlarr', vlarr)
          return {item: vlarr[0], increment: 3}
        },
        copy: {
          uint16: function(uint16){
            return bounds(uint16, 0, 65535)
          },
          uint8: function(uint16){
            return bounds(uint16, 0, 255)
    
          },
          number: function(uint16){
            return uint16
    
      }, { // uint16 array 41
    
    Jake Read's avatar
    Jake Read committed
        name: 'uint32',
    
    Jake Read's avatar
    Jake Read committed
        key: 42,
    
    Jake Read's avatar
    Jake Read committed
        write: function(value) {
    
          if (typeof value !== 'number')
            throw new Error(`cannot cast non-number into physical world "${value}", ${typeof value}`)
          if (value > 4294967296)
            throw new Error('num too large to represent with cast type, will contencate')
    
    Jake Read's avatar
    Jake Read committed
          let tparr = new Uint32Array(1)
          tparr[0] = value
          let btarr = new Uint8Array(tparr.buffer)
    
          let rtarr = Array.from(btarr)
    
          rtarr.unshift(this.key)
    
          if (tsdebug)
            console.log("UINT32 WRITES ARR: ", rtarr, "FOR: ", value)
    
          return rtarr
    
    Jake Read's avatar
    Jake Read committed
        },
    
        read: function(arr, start) {
    
          // assume we're reading out of an array
          // start[] should === key
    
          if (arr[start] !== this.key) {
            console.log("erroneous bytes:", arr)
            console.log("error at byte:", start, "is", arr[start])
            console.log("expected key:", this.key)
            throw new Error(`mismatched key on phy read: ${arr[start]}, ${this.key}`)
          }
    
          let rdarr = arr.slice(start + 1, start + 5)
    
          let btarr = Uint8Array.from(rdarr)
    
          if (tsdebug)
            console.log('bts on read of uint32', btarr)
            // now make uint32 view on this ...
    
          let vlarr = new Uint32Array(btarr.buffer)
    
          if (tsdebug)
            console.log("UINT32 READ ARR: ", vlarr[0], "FROM: ", btarr)
          if (tsdebug)
            console.log('vlarr', vlarr)
          return {item: vlarr[0], increment: 5}
        },
        copy: {
          uint32: function(uint32){
            return bounds(uint32, 0, 4294967295)
    
          },
          number: function(uint32){
            return uint32
    
    Jake Read's avatar
    Jake Read committed
        }
    
    Jake Read's avatar
    Jake Read committed
      }, // uint32array 43,
      /*
      uint64 44, uint64array 45,
      int8 46, int8array 47,
      int16 48, int16array 49,
      int32 50, int32array 50,
    
    Jake Read's avatar
    Jake Read committed
      */
      {
        name: 'int32',
        key: 50,
        write: function(value) {
    
          if (typeof value !== 'number')
            throw new Error(`cannot cast non-number into physical world "${value}", ${typeof value}`)
    
    Jake Read's avatar
    Jake Read committed
          let tparr = new Int32Array(1)
          tparr[0] = value
          let btarr = new Uint8Array(tparr.buffer)
          //place
          let rtarr = Array.from(btarr)
          rtarr.unshift(this.key)
    
          if (tsdebug)
            console.log("INT32 WRITES ARR: ", rtarr, "FOR: ", value)
    
    Jake Read's avatar
    Jake Read committed
          return rtarr
        },
        read: function(arr, start) {
          // assume we're reading out of an array
          // start[] should === key
    
          if (arr[start] !== this.key)
            throw new Error(`mismatched key on phy read: ${arr[start]}, ${this.key}`)
    
    Jake Read's avatar
    Jake Read committed
          let rdarr = arr.slice(start + 1, start + 5)
          let btarr = Uint8Array.from(rdarr)
    
          if (tsdebug)
            console.log('bts on read of uint32', btarr)
            // now make uint32 view on this ...
    
    Jake Read's avatar
    Jake Read committed
          let vlarr = new Int32Array(btarr.buffer)
    
          if (tsdebug)
            console.log("UINT32 READ ARR: ", vlarr[0], "FROM: ", btarr)
          if (tsdebug)
            console.log('vlarr', vlarr)
          return {item: vlarr[0], increment: 5}
        },
        copy: {
          int32: function(int32){
            return bounds(int32, -2147483647, 2147483647)
    
          },
          number: function(int32){
    
            return int32
    
    Jake Read's avatar
    Jake Read committed
      int64 52, int64array 53,
      float32 54, float32array 55,
      float64 56, float64array 57 (these are === javascript 'numbers') ... how to alias ?
      */
    
    Jake Read's avatar
    Jake Read committed
      {
        name: 'number',
    
    Jake Read's avatar
    Jake Read committed
        key: 56,
        write: function(value) {
    
          if (typeof value !== 'number')
            throw new Error(`cannot cast non-number into physical world "${value}", ${typeof value}`)
    
    Jake Read's avatar
    Jake Read committed
          let tparr = new Float64Array(1)
          tparr[0] = value
          let btarr = new Uint8Array(tparr.buffer)
          // place
    
          let rtarr = Array.from(btarr)
    
    Jake Read's avatar
    Jake Read committed
          rtarr.unshift(this.key)
          return rtarr
        },
    
    Jake Read's avatar
    Jake Read committed
        read: function(arr, start) {
    
          if (arr[start] !== this.key)
            throw new Error(`mismatched key on phy read: ${arr[start]}, ${this.key}`)
    
          let rdarr = arr.slice(start + 1, start + 9)
    
    Jake Read's avatar
    Jake Read committed
          let btarr = Uint8Array.from(rdarr)
    
          if (tsdebug)
            console.log('bts on read of float64', btarr)
    
    Jake Read's avatar
    Jake Read committed
          let vlarr = new Float64Array(btarr.buffer)
    
          if (tsdebug)
            console.log('vlarr', vlarr)
          return {item: vlarr[0], increment: 9}
        },
        copy: {
          number: function(num){
            return num
          },
          boolean: function(num){
            if(num > 0){
              return true
            } else {
              return false
            }
          },
          uint8: function(num){
            return intBounds(num, 0, 255)
          },
          uint16: function(num){
            return intBounds(num, 0, 65535)
          },
          uint32: function(num){
            return intBounds(num, 0, 4294967295)
          },
          int32: function(num){
            return intBounds(num, -2147483647, 2147483647)
    
    Jake Read's avatar
    Jake Read committed
          }
        }
    
    Jake Read's avatar
    Jake Read committed
      },
    
    Jake Read's avatar
    Jake Read committed
      { // cuttlefish only, not a real pass
        name: 'reference',
        copy: {
          reference: function(ref){
            let type = typeof ref
            if(type === 'string' || type === 'number' || type === 'boolean'){
              console.error('cannot pass core types as a reference')
              return null
            } else {
              return ref
            }
          }
        }
      },
    
    Jake Read's avatar
    Jake Read committed
      {
        name: 'object',
        copy: {
          object: function(obj){
            return JSON.parse(JSON.stringify(obj))
          }
        }
      },
    
    Jake Read's avatar
    Jake Read committed
      { // cuttlefish only, so no key, read or write fn's
        // this is : https://developer.mozilla.org/en-US/docs/Web/API/ImageData
        name: 'ImageData',
        copy: {
          ImageData: function(imageData){
            return new ImageData(
              new Uint8ClampedArray(imageData.data),
              imageData.width,
              imageData.height
            ) //
    
    Jake Read's avatar
    Jake Read committed
          },
          reference: function(imageData){
            return imageData
    
    Jake Read's avatar
    Jake Read committed
          }
        }
    
      },
      {
        name: 'Float32Array',
        copy: {
          Float32Array: function(float32Array) {
            return float32Array.slice();
          }
        }
      },
      {
        name: 'array',
        copy: {
    
          array: (arr) => [...arr],
          reference: (arr) => {
    
    Jake Read's avatar
    Jake Read committed
            return arr
    
    Jake Read's avatar
    Jake Read committed
      },
      {
        name: 'MDmseg',
    
    Jake Read's avatar
    Jake Read committed
        key: 88,
        write: function(ms) {
          // ok, bless up, we have:
          /*
          p0: 3-arr
          p1: 3-arr
          t: num
          v0: num
          a: num
          // for simplicity, we should write one typedarray
          */
          let f32arr = Float32Array.from([
            ms.p0[0], ms.p0[1], ms.p0[2],
            ms.p1[0], ms.p1[1], ms.p1[2],
            ms.t, ms.v0, ms.a]
          )
          // ok,
          let btarr = new Uint8Array(f32arr.buffer)
          let rtarr = Array.from(btarr)
          rtarr.unshift(this.key)
          return rtarr
        },
        read: function(arr, start) {
          /*
          if (arr[start] !== this.key)
            throw new Error(`mismatched key on phy read: ${arr[start]}, ${this.key}`)
          let rdarr = arr.slice(start + 1, start + 9)
          let btarr = Uint8Array.from(rdarr)
          if (tsdebug)
            console.log('bts on read of float64', btarr)
          let vlarr = new Float64Array(btarr.buffer)
          if (tsdebug)
            console.log('vlarr', vlarr)
          return {item: vlarr[0], increment: 9}
          */
        },
    
    Jake Read's avatar
    Jake Read committed
        copy: {
          MDmseg: (mdmseg) => {
            return {
              p0: mdmseg.p0,
              p1: mdmseg.p1,
              t: mdmseg.t,
              v0: mdmseg.v0,
              a: mdmseg.a
            }
          },
          reference: (mdmseg) => {
            return mdmseg
          }
        }
    
    Jake Read's avatar
    Jake Read committed
      }
    
    Jake Read's avatar
    Jake Read committed
      // etc
    
    Jake Read's avatar
    Jake Read committed
    ] // end TSET
    
    let intTypes = [
    
      'uint8',
      'uint16',
      'uint32',
      'uint64',
      'int8',
      'int16',
      'int32',
      'int64'
    
    Jake Read's avatar
    Jake Read committed
    ]
    
    Jake Read's avatar
    Jake Read committed
    
    
    let floatTypes = ['number']
    
    Jake Read's avatar
    Jake Read committed
    const isIntType = (type) => {
    
    Jake Read's avatar
    Jake Read committed
      for (let t of intTypes) {
    
        if (type == t)
          return true
    
    Jake Read's avatar
    Jake Read committed
      }
      return false
    }
    
    
    const isFloatType = (type) => {
    
    Jake Read's avatar
    Jake Read committed
      for (let t of floatTypes) {
    
        if (type == t)
          return true
    
      }
      return false
    }
    
    const isNumType = (type) => {
    
      if (isIntType(type))
        return true
      if (isFloatType(type))
        return true
    
    const writeLenBytes = (len) => {
      // return array of len bytes for this number
      let bts = new Array()
    
    Jake Read's avatar
    Jake Read committed
      if (len > 65536) {
    
    Jake Read's avatar
    Jake Read committed
        throw new Error('cannot write length bytes for len > 2^16')
      } else {
    
        // this is little eadian ... right ?
    
    Jake Read's avatar
    Jake Read committed
        bts.push(len & 255);
    
        bts.push((len >> 8) & 255);
    
    Jake Read's avatar
    Jake Read committed
      }
      // here to check,
    
      //if(len > 255){
      //  console.log(`LEN > 255: writes len bytes `, bts[0], bts[1], 'for', len)
      //}
    
      return bts
    }
    
    Jake Read's avatar
    Jake Read committed
    
    
    const readLenBytes = (arr, start) => {
      // need 2 know how many to increment as well,
    
      let len = (arr[start + 1] << 8) | arr[start]
    
    Jake Read's avatar
    Jake Read committed
      // still interested in this,
    
      //if(len > 255){
      //  console.log(`LEN > 255: reads len bytes `, arr[start], arr[start+1], 'for len', len)
      //}
    
      return {len: len, numBytes: 2}
    
    Jake Read's avatar
    Jake Read committed
    // heavy mixin of functional programming
    const MSGS = {
    
    Jake Read's avatar
    Jake Read committed
      writeTo: function(bytes, thing, type, debug) {
    
    Jake Read's avatar
    Jake Read committed
        let phy = findPhy(type)
    
    Jake Read's avatar
    Jake Read committed
        // try some js type conversion,
        // course correction here: sometimes states that are numbers are saved as strings (json)
        // we can unf- this here,
        if (typeof thing === 'string' && isNumType(type)) {
    
    Jake Read's avatar
    Jake Read committed
          //console.warn('patching num')
    
    Jake Read's avatar
    Jake Read committed
          if (isIntType(type)) {
            thing = parseInt(thing)
          } else {
            thing = parseFloat(thing)
          }
    
    Jake Read's avatar
    Jake Read committed
          //console.log('new num val', thing)
    
    Jake Read's avatar
    Jake Read committed
        } else if (typeof thing === 'string' && type === 'boolean') {
          // ha! use (?) for 'truthiness'
    
    Jake Read's avatar
    Jake Read committed
          //console.warn('patching bool')
    
    Jake Read's avatar
    Jake Read committed
          if (thing == 'true') {
            thing = true
          } else {
            thing = false
          }
    
    Jake Read's avatar
    Jake Read committed
          //console.log('new bool val', thing)
    
    Jake Read's avatar
    Jake Read committed
        }
    
    Jake Read's avatar
    Jake Read committed
        let block = phy.write(thing)
    
        if (debug)
          console.log(`writing for type ${type} and thing '${thing}' the following block of bytes`, block)
          // write-in to msg like this
    
    Jake Read's avatar
    Jake Read committed
        // this *must be* slow AF, pls correct
    
    Jake Read's avatar
    Jake Read committed
        block.forEach((byte) => {
          bytes.push(byte)
        })
      },
    
    Jake Read's avatar
    Jake Read committed
      readFrom: function(bytes, place, type) {
    
    Jake Read's avatar
    Jake Read committed
        let phy = findPhy(type)
        // check that type exists at place, rip it oot and return it
    
    Jake Read's avatar
    Jake Read committed
        return phy.read(bytes, place)
    
    Jake Read's avatar
    Jake Read committed
      },
    
    Jake Read's avatar
    Jake Read committed
      readListFrom: function(bytes, place, type) {
    
    Jake Read's avatar
    Jake Read committed
        // using this where I expect a lit of values, i.e. the addLink(str,str,str,str) arguments,
        // plucks thru, continuing to pull values as long as the next in the serialized list is of
        // the right type
        let phy = findPhy(type)
        // the list of items,
        let list = new Array()
    
    Jake Read's avatar
    Jake Read committed
        while (place < bytes.length) {
    
    Jake Read's avatar
    Jake Read committed
          let res = phy.read(bytes, place)
          list.push(res.item)
          place += res.increment
    
          if (bytes[place] !== phy.key)
            break
            // this could throw us into infinite loops, so
          if (res.increment < 1)
            throw new Error('dangerous increment while reading list')
    
    Jake Read's avatar
    Jake Read committed
        }
    
        if (list.length < 1)
          throw new Error('reading list, found no items...')
        if (tsdebug)
          console.log('read list as', list)
    
    Jake Read's avatar
    Jake Read committed
        return list
      }
    }
    
    
    // typically: call, response expected
    // manager keys
    const MK = {
      // bzzt
    
    Jake Read's avatar
    Jake Read committed
      ERR: 254, // (str) message
    
      // heartbeats, wakeup
    
      HELLO: 231, // (eom)
    
      // request a top-level description
    
    Jake Read's avatar
    Jake Read committed
      QUERY: 251, // (eom)
    
    Jake Read's avatar
    Jake Read committed
      BRIEF: 250, // (str) name of interpreter, # hunks, # links (and then begin firing list back)
    
      // please show what is available
    
    Jake Read's avatar
    Jake Read committed
      REQLISTAVAIL: 249, // (eom)
      LISTOFAVAIL: 248, // (list)(str) names 'dirs/like/this' (includes programs ?) (this might be multiple packets?)
    
      // business ... we should be able to centralize all control w/i view.js if we can write these
    
    Jake Read's avatar
    Jake Read committed
      REQADDHUNK: 247, // (str) name
    
      REQNAMECHANGE: 246,
      HUNKALIVE: 245, // (hunkdescription): name, id, inputlist, outputlist, statelist
    
      HUNKREPLACE: 244,
      REQSTATECHANGE: 243,
      HUNKSTATECHANGE: 242,
      REQRMHUNK: 241, // (str) id
      HUNKREMOVED: 240, // (str) id
      REQADDLINK: 239, // (str) id, (str) outname, (str) id, (str) inname
      LINKALIVE: 238, // (str) id, (str) outname, (str) id, (str) inname
      REQRMLINK: 237, // (str) id, (str) outname, (str) id, (str) inname
      LINKREMOVED: 236, // (str) id, (str) outname, (str) id, (str) inname
    
    }
    
    // hunk description keys,
    const HK = {
      NAME: 253,
    
      INPUT: 249,
      OUTPUT: 247,
    
      CONNECTIONS: 246,
      CONNECTION: 245,
    
      STATE: 244
    
    Jake Read's avatar
    Jake Read committed
    
    
    Jake Read's avatar
    Jake Read committed
    // link keys,
    const LK = {
    
    Jake Read's avatar
    Jake Read committed
      ACK: 254,
      HELLO: 253 // ~ binary solo ~
    
    Jake Read's avatar
    Jake Read committed
    }
    
    
    Jake Read's avatar
    Jake Read committed
    // should write out as list of pairs ?
    // or write fn to do key(stringtype)
    
    
    Jake Read's avatar
    Jake Read committed
    export {
    
    Jake Read's avatar
    Jake Read committed
      TSET,
      MK, // manager keys
      HK, // hunk def keys
      LK, // link keys
    
    Jake Read's avatar
    Jake Read committed
      MSGS,
    
      isIntType,
      isFloatType,
      isNumType
    
    Jake Read's avatar
    Jake Read committed
    }