bert.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. // API
  2. function tuple(){ return { t: 104, v: Array.apply(null, arguments) }; }
  3. function list(){ return { t: 108, v: Array.apply(null, arguments) }; }
  4. function map(){ return { t: 116, v: Array.apply(null, arguments) }; }
  5. function atom(o){ return { t: 118, v: utf8_enc(o) }; }
  6. function string(o){ return { t: 107, v: utf8_enc(o) }; }
  7. function float(o){ return { t: 70, v: o }; }
  8. function number(o){
  9. var isInteger = (o % 1 === 0);
  10. if(isInteger && o >= 0 && o < 256){ return { t: 97, v: o }; }
  11. if(isInteger && o >= -2147483648 && o <= 2147483647){ return {t: 98, v: o}; }
  12. return {t: 110, v: o};
  13. }
  14. // BigInt to BERT, with https://github.com/peterolson/BigInteger.js
  15. function bignum(o){
  16. if(bigInt.isInstance(o) === false){ return {t: 999, v: [97, 0]}; } // o is not bigInt
  17. if(o.greaterOrEquals(0) && o.lesser(256)){
  18. // t: 97
  19. return {t: 999, v: [97, o.toJSNumber() ]};
  20. }
  21. if(o.greaterOrEquals(-2147483648) && o.lesserOrEquals(2147483647)){
  22. // t: 98
  23. return {t: 999, v: [98, o.shiftRight(24).toJSNumber(), o.shiftRight(16).and(255).toJSNumber(), o.shiftRight(8).and(255).toJSNumber(), o.and(255).toJSNumber() ]};
  24. }
  25. // t: 110
  26. if(o.isNegative()){
  27. var sign = 1;
  28. var s = bignum_to_bytes(o.abs());
  29. }else{
  30. var sign = 0;
  31. var s = bignum_to_bytes(o);
  32. }
  33. return {t: 999, v: [110, s.length, sign].concat(s) };
  34. }
  35. function bin(o){
  36. return { t: 109, v: o instanceof ArrayBuffer ? new Uint8Array(o) :
  37. o instanceof Uint8Array ? o : utf8_enc(o) };
  38. }
  39. // encoder
  40. function enc(o){ return fl([131, ein(o)]); }
  41. function ein(o){
  42. return Array.isArray(o) ? en_108({ t: 108, v: o }) :
  43. (o.t == 999 ? o.v : eval('en_' + o.t)(o) ); // t: 999 = bigInt, already encoded in bignum func
  44. }
  45. function en_undefined(o){ return [106]; }
  46. function unilen(o){
  47. return (o.v instanceof ArrayBuffer || o.v instanceof Uint8Array) ? o.v.byteLength :
  48. (new TextEncoder().encode(o.v)).byteLength;
  49. }
  50. function en_70(o){
  51. var x = Array(8).fill(0).flat();
  52. write_Float(x, o.v, 0, false, 52, 8);
  53. return [70].concat(x);
  54. }
  55. function en_97(o){ return [97, o.v]; }
  56. function en_98(o){ return [98, o.v >>> 24, (o.v >>> 16) & 255, (o.v >>> 8) & 255, o.v & 255]; }
  57. function en_99(o){
  58. var obj = o.v.toExponential(20),
  59. match = /([^e]+)(e[+-])(\d+)/.exec(obj),
  60. exponentialPart = match[3].length == 1 ? "0" + match[3] : match[3],
  61. num = Array.from(bin(match[1] + match[2] + exponentialPart).v);
  62. return [o.t].concat(num).concat(Array(31 - num.length).fill(0).flat());
  63. }
  64. function en_100(o){ return [100, o.v.length >>> 8, o.v.length & 255, ar(o)]; }
  65. function en_104(o){
  66. var l = o.v.length,
  67. r = [];
  68. for(var i = 0; i < l; i++) r[i] = ein(o.v[i]);
  69. return [104, l, r];
  70. }
  71. function en_106(o){ return [106]; }
  72. function en_107(o){ return [107, o.v.length >>> 8, o.v.length & 255, ar(o)]; }
  73. function en_108(o){
  74. var l = o.v.length,
  75. r = [];
  76. for(var i = 0; i < l; i++) r.push(ein(o.v[i]));
  77. return o.v.length == 0 ? [106] :
  78. [108, l >>> 24, (l >>> 16) & 255, (l >>> 8) & 255, l & 255, r, 106];
  79. }
  80. function en_109(o){
  81. var l = unilen(o);
  82. return [109, l >>> 24, (l >>> 16) & 255, (l >>> 8) & 255, l & 255, ar(o)];
  83. }
  84. function en_110(o){
  85. if(o.v < 0){
  86. var sign = 1;
  87. var s = int_to_bytes(-o.v);
  88. }else{
  89. var sign = 0;
  90. var s = int_to_bytes(o.v);
  91. }
  92. return [110, s.length, sign].concat(s);
  93. }
  94. function en_115(o){ return [115, o.v.length, ar(o)]; }
  95. function en_116(o){
  96. var l = o.v.length,
  97. x = [],
  98. r = [];
  99. for(var i = 0; i < l; i++) r.push([ein(o.v[i].k), ein(o.v[i].v)]);
  100. x = [116, l >>> 24, (l >>> 16) & 255, (l >>> 8) & 255, l & 255];
  101. return o.v.length == 0 ? x : [x, r];
  102. }
  103. function en_118(o){ return [118, ar(o).length >>> 8, ar(o).length & 255, ar(o)]; }
  104. function en_119(o){ return [119, ar(o).length, ar(o)]; }
  105. // decoder
  106. function nop(b){ return []; }
  107. function big(b){
  108. var sk = b == 1 ? sx.getUint8(ix++) : sx.getInt32((a = ix, ix += 4, a));
  109. var ret = 0,
  110. sig = sx.getUint8(ix++),
  111. count = sk;
  112. while(count-- > 0){
  113. ret = 256 * ret + sx.getUint8(ix + count);
  114. }
  115. ix += sk;
  116. return ret * (sig == 0 ? 1 : -1);
  117. }
  118. function int(b){
  119. return b == 1 ? sx.getUint8(ix++) : sx.getInt32((a = ix, ix += 4, a));
  120. }
  121. function dec(d){
  122. sx = new DataView(d);
  123. ix = 0;
  124. if(sx.getUint8(ix++) !== 131) throw ("BERT?");
  125. return din();
  126. }
  127. function str(b){
  128. var dv,
  129. sz = (b == 2 ? sx.getUint16(ix) : (b == 1 ? sx.getUint8(ix) : sx.getUint32(ix)));
  130. ix += b;
  131. var r = sx.buffer.slice(ix, ix += sz);
  132. return utf8_arr(r);
  133. }
  134. function run(b){
  135. var sz = (b == 1 ? sx.getUint8(ix) : sx.getUint32(ix)),
  136. r = [];
  137. ix += b;
  138. for(var i = 0; i < sz; i++) r.push(din());
  139. if(b == 4) ix++;
  140. return r;
  141. }
  142. function rut(b){
  143. var sz = (b == 1 ? sx.getUint8(ix) : sx.getUint32(ix)),
  144. r = [];
  145. ix += b;
  146. for(var i = 0; i < sz; i++) r.push(din());
  147. din();
  148. return r;
  149. }
  150. function dic(b){
  151. var sz = sx.getUint32(ix),
  152. r = [];
  153. ix += 4;
  154. for(var i = 0; i < sz; i++) r.push({k: din(), v: din()});
  155. return r;
  156. }
  157. function iee(x){
  158. return read_Float(new Uint8Array(sx.buffer.slice(ix, ix += 8)), 0, false, 52, 8);
  159. }
  160. function flo(x){
  161. return parseFloat(utf8_arr(sx.buffer.slice(ix, ix += 31)));
  162. }
  163. function arr(b){
  164. var dv,
  165. sz = sx.getUint16(ix);
  166. ix += b;
  167. return new Uint8Array(sx.buffer.slice(ix, ix += sz));
  168. }
  169. function ref(cr){
  170. var d,
  171. adj = sx.getUint8(ix++);
  172. adj += sx.getUint8(ix++);
  173. d = din();
  174. ix += cr + adj * 4;
  175. return d;
  176. }
  177. function din(){
  178. var x,
  179. c = sx.getUint8(ix++);
  180. switch(c){
  181. case 70: x = [iee, 0]; break;
  182. case 90: x = [ref, 4]; break;
  183. case 97: x = [int, 1]; break;
  184. case 98: x = [int, 4]; break;
  185. case 99: x = [flo, 0]; break;
  186. case 100: x = [str, 2]; break;
  187. case 104: x = [run, 1]; break;
  188. case 105: x = [run, 4]; break;
  189. case 107: x = [arr, 2]; break;
  190. case 108: x = [rut, 4]; break;
  191. case 109: x = [str, 4]; break;
  192. case 110: x = [big, 1]; break;
  193. case 111: x = [big, 4]; break;
  194. case 114: x = [ref, 1]; break;
  195. case 115: x = [str, 1]; break;
  196. case 116: x = [dic, 4]; break;
  197. case 118: x = [str, 2]; break;
  198. case 119: x = [str, 1]; break;
  199. default: x = [nop, 0];
  200. } return { t: c, v: x[0](x[1]) };
  201. }
  202. // helpers
  203. function int_to_bytes(Int){
  204. if(Int % 1 !== 0) return [0];
  205. var OriginalInt,
  206. Rem,
  207. s = [];
  208. OriginalInt = Int;
  209. while(Int !== 0){
  210. Rem = Int % 256;
  211. s.push(Rem);
  212. Int = Math.floor(Int / 256);
  213. }
  214. if(Int > 0){ throw ("Argument out of range: " + OriginalInt); }
  215. return s;
  216. }
  217. function bignum_to_bytes(big_Int){
  218. var v,
  219. big_Int,
  220. s = [];
  221. big_Int2 = big_Int;
  222. while(big_Int2.isZero() === false){
  223. v = big_Int2.divmod(256);
  224. s.push(v.remainder.toJSNumber());
  225. big_Int2 = v.quotient;
  226. }
  227. if(big_Int2.greater(0)){ throw ("Argument out of range::: " + big_Int.toString() ); }
  228. return s;
  229. }
  230. function uc(u1, u2){
  231. if(u1.byteLength == 0) return u2;
  232. if(u2.byteLength == 0) return u1;
  233. var a = new Uint8Array(u1.byteLength + u2.byteLength);
  234. a.set(u1, 0);
  235. a.set(u2, u1.byteLength);
  236. return a;
  237. }
  238. function ar(o){
  239. return o.v instanceof ArrayBuffer ? new Uint8Array(o.v) : o.v instanceof Uint8Array ? o.v :
  240. Array.isArray(o.v) ? new Uint8Array(o.v) : new Uint8Array(utf8_enc(o.v));
  241. }
  242. function fl(a){
  243. return a.reduce(function(f, t){
  244. return uc(f, t instanceof Uint8Array ? t :
  245. Array.isArray(t) ? fl(t) : new Uint8Array([t]));
  246. }, new Uint8Array());
  247. }
  248. // UTF-8 Support
  249. function utf8_dec(ab){ return (new TextDecoder()).decode(ab); }
  250. function utf8_enc(ab){ return (new TextEncoder("utf-8")).encode(ab); }
  251. function utf8_arr(ab){
  252. if(!(ab instanceof ArrayBuffer)) ab = new Uint8Array(utf8_enc(ab)).buffer;
  253. return utf8_dec(ab);
  254. }