bert.js 7.8 KB

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