Newer
Older
// bless up @ modern js https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
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`)
}
if (typeof value !== 'boolean')
throw new Error('cannot cast non-boolean to bool at phy')
if (typeof value !== 'number')
throw new Error(`cannot cast non-number into physical world "${value}", ${typeof value}`)
if (typeof value !== 'string')
throw new Error(`cannot cast non-string to string at phy! "${value}", "${typeof value}"`)
if (!Array.isArray(thing))
throw new Error('this thing is not an array!')
if (value > Math.pow(2, bits))
throw new Error('value out of byte bounds')
if (value > comparator || value < -comparator)
throw new Error('value out of byte bounds')
const findPhy = (type) => {
let phy = TSET.find((cand) => {
return cand.name === type
})
throw new Error(`could not find phy for datatype: ${type}`)
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 ...
read: function(arr, start) {
checkKey(this, arr, start)
throw new Error(`non std boolean byte, ${arr[start + 1]}`)
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
}
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
}
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)
return rtarr
},
read: function(arr, start) {
checkKey(this, arr, start)
let lb = readLenBytes(arr, start + 1)
let narr = new Array()
narr.push(arr[start + 1 + lb.numBytes + i])
}
return {
item: narr,
increment: lb.len + lb.numBytes + 1
}
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
rtarr.push(str.charCodeAt(i))
}
// length bytes are 7-bit 'msb for continue' numbers ...
// 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) {
str += String.fromCharCode(arr[start + 1 + lb.numBytes + i])
}
return {
item: str,
increment: lb.len + lb.numBytes + 1
},
number: function(str) {
return parseFloat(str)
},
boolean: function(str){
if(str == true){
return true
} else {
return false
}
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
},
// 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')
},
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
name: 'uint16',
write: function(value) {
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
rtarr.unshift(this.key)
return rtarr
},
// 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)
let btarr = Uint8Array.from(rdarr)
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
}
}
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')
let tparr = new Uint32Array(1)
tparr[0] = value
let btarr = new Uint8Array(tparr.buffer)
if (tsdebug)
console.log("UINT32 WRITES ARR: ", rtarr, "FOR: ", value)
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
}, // uint32array 43,
/*
uint64 44, uint64array 45,
int8 46, int8array 47,
int16 48, int16array 49,
int32 50, int32array 50,
*/
{
name: 'int32',
key: 50,
write: function(value) {
if (typeof value !== 'number')
throw new Error(`cannot cast non-number into physical world "${value}", ${typeof value}`)
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)
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}`)
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 ...
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){
int64 52, int64array 53,
float32 54, float32array 55,
float64 56, float64array 57 (these are === javascript 'numbers') ... how to alias ?
*/
if (typeof value !== 'number')
throw new Error(`cannot cast non-number into physical world "${value}", ${typeof value}`)
let tparr = new Float64Array(1)
tparr[0] = value
let btarr = new Uint8Array(tparr.buffer)
// place
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)
if (tsdebug)
console.log('bts on read of float64', btarr)
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
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)
{ // 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
}
}
}
},
{
name: 'object',
copy: {
object: function(obj){
return JSON.parse(JSON.stringify(obj))
}
}
},
{ // 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
) //
},
{
name: 'Float32Array',
copy: {
Float32Array: function(float32Array) {
return float32Array.slice();
}
}
},
{
name: 'array',
copy: {

Jake Read
committed
array: (arr) => [...arr],
reference: (arr) => {

Jake Read
committed
}
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
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}
*/
},
copy: {
MDmseg: (mdmseg) => {
return {
p0: mdmseg.p0,
p1: mdmseg.p1,
t: mdmseg.t,
v0: mdmseg.v0,
a: mdmseg.a
}
},
reference: (mdmseg) => {
return mdmseg
}
}
'uint8',
'uint16',
'uint32',
'uint64',
'int8',
'int16',
'int32',
'int64'
const isFloatType = (type) => {
}
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()
throw new Error('cannot write length bytes for len > 2^16')
} else {
//if(len > 255){
// console.log(`LEN > 255: writes len bytes `, bts[0], bts[1], 'for', len)
//}
const readLenBytes = (arr, start) => {
// need 2 know how many to increment as well,
let len = (arr[start + 1] << 8) | arr[start]
//if(len > 255){
// console.log(`LEN > 255: reads len bytes `, arr[start], arr[start+1], 'for len', len)
//}
// heavy mixin of functional programming
const MSGS = {
// 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)) {
if (isIntType(type)) {
thing = parseInt(thing)
} else {
thing = parseFloat(thing)
}
} else if (typeof thing === 'string' && type === 'boolean') {
// ha! use (?) for 'truthiness'
if (thing == 'true') {
thing = true
} else {
thing = false
}
if (debug)
console.log(`writing for type ${type} and thing '${thing}' the following block of bytes`, block)
// write-in to msg like this
block.forEach((byte) => {
bytes.push(byte)
})
},
let phy = findPhy(type)
// check that type exists at place, rip it oot and return it
// 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()
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')
if (list.length < 1)
throw new Error('reading list, found no items...')
if (tsdebug)
console.log('read list as', list)
// typically: call, response expected
// manager keys
const MK = {
// bzzt
BRIEF: 250, // (str) name of interpreter, # hunks, # links (and then begin firing list back)
REQLISTAVAIL: 249, // (eom)
LISTOFAVAIL: 248, // (list)(str) names 'dirs/like/this' (includes programs ?) (this might be multiple packets?)

Jake Read
committed
// business ... we should be able to centralize all control w/i view.js if we can write these
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
MSGID: 235
}
// hunk description keys,
const HK = {
NAME: 253,
TYPE: 252,
IND: 251,
DESCR: 250,
// should write out as list of pairs ?
// or write fn to do key(stringtype)
TSET,
MK, // manager keys
HK, // hunk def keys
LK, // link keys
isIntType,
isFloatType,
isNumType