bert.d 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. import std.stdio;
  2. public{
  3. import std.bigint; // *10-15 times more slow than gmp but this works -- gmp-d conflicts with other deps ((
  4. import std.conv;
  5. /*
  6. // example std.bigint usage
  7. //BigInt num2 = 1;
  8. //auto num1 = 1;
  9. auto num1 = "1";
  10. BigInt num2 = BigInt(num1);
  11. num2 += 2;
  12. string num3 = num2.to!string;
  13. writefln("num2 = %s - %s", num2, typeof(num2).stringof);
  14. writefln("num3 = %s - %s", num3, typeof(num3).stringof);
  15. BigInt num = 0;
  16. for(ulong i = 1; i < 4_000_001; i++){
  17. num += i;
  18. }
  19. writefln("SUM(1, 4_000_000) = %s", num);
  20. num = 1;
  21. for(ubyte j = 1; j < 101; j++){
  22. num *= j;
  23. }
  24. writefln("PRODUCT(1, 100) = %s", num);
  25. */
  26. }
  27. private{
  28. import std.bitmanip;
  29. import std.string;
  30. import std.utf;
  31. import std.math;
  32. import std.traits;
  33. import std.algorithm;
  34. import std.range;
  35. import std.digest : toHexString;
  36. import std.array : appender;
  37. import std.format : format;
  38. }
  39. enum BERT_TAG : ubyte{
  40. VERSION = 131,
  41. SMALL_INT = 97,
  42. INT = 98,
  43. BIGINT = 110,
  44. //LARGE_BIG = 111,
  45. FLOAT = 70,
  46. ATOM = 118,
  47. TUPLE = 104, // SMALL_TUPLE
  48. LARGE_TUPLE = 105,
  49. NIL = 106,
  50. LIST = 108,
  51. BINARY = 109, // use BINARY as STRING
  52. MAP = 116
  53. }
  54. enum BertType{
  55. Int,
  56. BigInt,
  57. Float,
  58. Atom,
  59. Tuple,
  60. List,
  61. Binary,
  62. Map,
  63. Nil
  64. }
  65. struct BertValue{
  66. BertType type_;
  67. union{
  68. long intValue;
  69. BigInt bigintValue;
  70. double floatValue;
  71. string atomValue;
  72. BertValue[] tupleValue;
  73. BertValue[] listValue;
  74. ubyte[] binaryValue;
  75. BertValue[BertValue] mapValue;
  76. }
  77. ubyte[] encode() const{
  78. final switch(type_){
  79. case BertType.Int:
  80. return encodeInt(intValue);
  81. case BertType.BigInt:
  82. return encodeBigInt(bigintValue);
  83. case BertType.Float:
  84. return encodeFloat(floatValue);
  85. case BertType.Atom:
  86. return encodeAtom(atomValue);
  87. case BertType.Tuple:
  88. return encodeTuple(tupleValue.dup);
  89. case BertType.List:
  90. return encodeList(listValue.dup);
  91. case BertType.Binary:
  92. return encodeBinary(binaryValue.dup);
  93. case BertType.Map:
  94. return encodeMap(mapValue.dup);
  95. case BertType.Nil:
  96. return [cast(ubyte)BERT_TAG.NIL];
  97. }
  98. }
  99. string toString() const{
  100. final switch(type_){
  101. case BertType.Int:
  102. return to!string(intValue);
  103. case BertType.BigInt:
  104. return bigintValue.to!string;
  105. case BertType.Float:
  106. return to!string(floatValue);
  107. case BertType.Atom:
  108. return format("'%s'", atomValue);
  109. case BertType.Tuple:
  110. return "{" ~ tupleValue.map!(e => e.toString()).join(", ") ~ "}";
  111. case BertType.List:
  112. return "[" ~ listValue.map!(e => e.toString()).join(", ") ~ "]";
  113. case BertType.Binary:
  114. auto result = appender!string();
  115. result.put("<<");
  116. foreach(i, b; binaryValue){
  117. if(i > 0){ result.put(","); }
  118. //result.put(format("%02X", b)); // string bytes in hex = <<"blabla">> = <<62,6C,61,62,6C,61>>
  119. result.put(to!string(b)); // string bytes in dec (like in erlang) = <<"blabla">> = <<98,108,97,98,108,97>>
  120. }
  121. result.put(">>");
  122. return result.data;
  123. case BertType.Map:
  124. string[] pairs;
  125. foreach(key, value; mapValue){
  126. pairs ~= format("%s: %s", key.toString(), value.toString());
  127. }
  128. return "#{" ~ pairs.join(", ") ~ "}";
  129. case BertType.Nil:
  130. return "[]";
  131. }
  132. }
  133. }
  134. ubyte[] bertEncode(BertValue term){
  135. return [cast(ubyte)BERT_TAG.VERSION] ~ term.encode();
  136. }
  137. /*
  138. ubyte[] encodeInt(byte value){ // small_integer - int8
  139. return [cast(ubyte)BERT_TAG.SMALL_INT, cast(ubyte)value];
  140. }
  141. */
  142. ubyte[] encodeInt(ubyte value){ // small_integer - uint8
  143. return [cast(ubyte)BERT_TAG.SMALL_INT, value];
  144. }
  145. /*
  146. ubyte[] encodeInt(short value){ // integer - int16
  147. if(value >= 0 && value <= 255){
  148. return [cast(ubyte)BERT_TAG.SMALL_INT, cast(ubyte)value];
  149. }else{
  150. ubyte[4] bytes = nativeToBigEndian!int(cast(int)value);
  151. return [cast(ubyte)BERT_TAG.INT] ~ bytes[];
  152. }
  153. }
  154. */
  155. ubyte[] encodeInt(ushort value){ // integer - uint16
  156. if(value <= 255) {
  157. return [cast(ubyte)BERT_TAG.SMALL_INT, cast(ubyte)value];
  158. }else{
  159. ubyte[4] bytes = nativeToBigEndian!int(cast(int)value);
  160. return [cast(ubyte)BERT_TAG.INT] ~ bytes[];
  161. }
  162. }
  163. /*
  164. ubyte[] encodeInt(int value){ // integer - int32
  165. if(value >= 0 && value <= 255){
  166. return [cast(ubyte)BERT_TAG.SMALL_INT, cast(ubyte)value];
  167. }else if(value >= -2147483648 && value <= 2147483647){
  168. ubyte[4] bytes = nativeToBigEndian!int(value);
  169. return [cast(ubyte)BERT_TAG.INT] ~ bytes[];
  170. }else{
  171. return encodeBigInt( cast(ulong)value );
  172. }
  173. }
  174. */
  175. ubyte[] encodeInt(uint value){ // integer - uint32
  176. if(value <= 255){
  177. return [cast(ubyte)BERT_TAG.SMALL_INT, cast(ubyte)value];
  178. }else if(value <= 2147483647) {
  179. ubyte[4] bytes = nativeToBigEndian!int(cast(int)value);
  180. return [cast(ubyte)BERT_TAG.INT] ~ bytes[];
  181. }else{
  182. return encodeBigInt( cast(ulong)value );
  183. }
  184. }
  185. /*
  186. ubyte[] encodeInt(long value){ // integer - small_big_int - int64 ;; we do not use erlang large_big_int because small_big_int max value = 2^(8*255) - 1 ;; it is too enaught
  187. if(value >= 0 && value <= 255){
  188. return [cast(ubyte)BERT_TAG.SMALL_INT, cast(ubyte)value];
  189. }else if(value >= -2147483648 && value <= 2147483647){
  190. ubyte[4] bytes = nativeToBigEndian!int(cast(int)value);
  191. return [cast(ubyte)BERT_TAG.INT] ~ bytes[];
  192. }else{
  193. return encodeBigInt( cast(ulong)value );
  194. }
  195. }
  196. */
  197. ubyte[] encodeInt(ulong value){ // integer - small_big_int - uint64 ;; we do not use erlang large_big_int because small_big_int max value = 2^(8*255) - 1 ;; it is too enaught
  198. if(value <= 255){
  199. return [cast(ubyte)BERT_TAG.SMALL_INT, cast(ubyte)value];
  200. }else if(value <= 2147483647){
  201. ubyte[4] bytes = nativeToBigEndian!int(cast(int)value);
  202. return [cast(ubyte)BERT_TAG.INT] ~ bytes[];
  203. }else{
  204. return encodeBigInt(value);
  205. }
  206. }
  207. /*
  208. ubyte[] encodeBigInt(long value){
  209. bool isNegative = (value < 0);
  210. ulong absValue = isNegative ? (-value) : value;
  211. ubyte[8] temp;
  212. size_t len = 0;
  213. while(absValue > 0){
  214. temp[len++] = cast(ubyte)(absValue & 0xFF);
  215. absValue >>= 8;
  216. }
  217. ubyte[] result = [
  218. cast(ubyte)BERT_TAG.BIGINT,
  219. cast(ubyte)len,
  220. isNegative ? 1 : 0
  221. ];
  222. foreach_reverse(i; 0..len){
  223. result ~= temp[i];
  224. }
  225. return result;
  226. }
  227. */
  228. ubyte[] encodeBigInt(ulong value){
  229. ubyte[8] temp;
  230. size_t len = 0;
  231. while(value > 0){
  232. temp[len++] = cast(ubyte)(value & 0xFF);
  233. value >>= 8;
  234. }
  235. if(len == 0){
  236. return [ cast(ubyte)BERT_TAG.BIGINT, 1, 0, 0 ];
  237. }
  238. ubyte[] result = [
  239. cast(ubyte)BERT_TAG.BIGINT,
  240. cast(ubyte)len,
  241. 0
  242. ];
  243. foreach_reverse (i; 0..len){
  244. result ~= temp[i];
  245. }
  246. return result;
  247. }
  248. ubyte[] encodeBigInt(BigInt value){
  249. if(value == 0){
  250. return [cast(ubyte)BERT_TAG.BIGINT, 1, 0];
  251. }
  252. //bool isNegative = value < 0; // no sign
  253. //if(isNegative){
  254. // value = -value;
  255. //}
  256. ubyte[] digits;
  257. while(value > 0){
  258. digits ~= cast(ubyte)(value & 0xFF);
  259. value >>= 8;
  260. }
  261. /* // we do not use erlang large_big_int because small_big_int max value = 2^(8*255) - 1 ;; it is too enaught
  262. ubyte tag;
  263. if(digits.length <= 255) {
  264. tag = BERT_TAG.BIGINT;
  265. }else{
  266. tag = BERT_TAG.LARGE_BIGINT;
  267. }
  268. */
  269. ubyte[] result;
  270. //if(tag == BERT_TAG.BIGINT){
  271. result = [ cast(ubyte)BERT_TAG.BIGINT,
  272. cast(ubyte)digits.length,
  273. //cast(ubyte)(isNegative ? 1 : 0) // no sign
  274. cast(ubyte)(0) // no sign
  275. ];
  276. result ~= digits; // in little-endian
  277. return result;
  278. }
  279. ubyte[] encodeFloat(double value){
  280. ubyte[8] bytes = nativeToBigEndian!double(value);
  281. return [cast(ubyte)BERT_TAG.FLOAT] ~ bytes[];
  282. }
  283. ubyte[] encodeAtom(string name){
  284. if(name.length > 255){ throw new Exception("Atom too long"); }
  285. return [
  286. cast(ubyte)BERT_TAG.ATOM,
  287. cast(ubyte)(name.length >> 8),
  288. cast(ubyte)(name.length & 0xFF)
  289. ] ~ cast(ubyte[])name;
  290. }
  291. ubyte[] encodeTuple(BertValue[] elements){
  292. ubyte[] result;
  293. if(elements.length <= 255){
  294. result = [cast(ubyte)BERT_TAG.TUPLE, cast(ubyte)elements.length];
  295. }else{
  296. result = [cast(ubyte)BERT_TAG.LARGE_TUPLE] ~ nativeToBigEndian!uint(cast(uint)elements.length);
  297. }
  298. foreach(elem; elements){
  299. result ~= elem.encode();
  300. }
  301. return result;
  302. }
  303. ubyte[] encodeList(BertValue[] elements){
  304. ubyte[4] lenBytes = nativeToBigEndian!uint(cast(uint)elements.length);
  305. return [cast(ubyte)BERT_TAG.LIST] ~ lenBytes[] ~ elements.map!(e => e.encode()).join() ~ cast(ubyte)BERT_TAG.NIL;
  306. }
  307. ubyte[] encodeBinary(ubyte[] data){
  308. ubyte[4] lenBytes = nativeToBigEndian!uint(cast(uint)data.length);
  309. return [cast(ubyte)BERT_TAG.BINARY] ~ lenBytes[] ~ data;
  310. }
  311. ubyte[] encodeMap(const BertValue[BertValue] map){
  312. ubyte[4] lenBytes = nativeToBigEndian!uint(cast(uint)map.length);
  313. return [cast(ubyte)BERT_TAG.MAP] ~ lenBytes[] ~ map.byPair.map!(p => p.key.encode() ~ p.value.encode()).join();
  314. }
  315. /*
  316. BertValue bertInt(byte value){
  317. BertValue v;
  318. v.type_ = BertType.Int;
  319. v.intValue = value;
  320. return v;
  321. }
  322. */
  323. BertValue bertInt(ubyte value){
  324. BertValue v;
  325. v.type_ = BertType.Int;
  326. v.intValue = value;
  327. return v;
  328. }
  329. /*
  330. BertValue bertInt(short value){
  331. BertValue v;
  332. v.type_ = BertType.Int;
  333. v.intValue = value;
  334. return v;
  335. }
  336. */
  337. BertValue bertInt(ushort value){
  338. BertValue v;
  339. v.type_ = BertType.Int;
  340. v.intValue = value;
  341. return v;
  342. }
  343. /*
  344. BertValue bertInt(int value){
  345. BertValue v;
  346. v.type_ = BertType.Int;
  347. v.intValue = value;
  348. return v;
  349. }
  350. */
  351. BertValue bertInt(uint value){
  352. BertValue v;
  353. v.type_ = BertType.Int;
  354. v.intValue = value;
  355. return v;
  356. }
  357. /*
  358. BertValue bertInt(long value){
  359. BertValue v;
  360. v.type_ = BertType.Int;
  361. v.intValue = value;
  362. return v;
  363. }
  364. */
  365. BertValue bertInt(ulong value){
  366. BertValue v;
  367. v.type_ = BertType.Int;
  368. v.intValue = value;
  369. return v;
  370. }
  371. BertValue bertBigInt(BigInt value){
  372. BertValue v;
  373. v.type_ = BertType.BigInt;
  374. v.bigintValue = value;
  375. return v;
  376. }
  377. BertValue bertFloat(double value){
  378. BertValue v;
  379. v.type_ = BertType.Float;
  380. v.floatValue = value;
  381. return v;
  382. }
  383. BertValue bertAtom(string name){
  384. BertValue v;
  385. v.type_ = BertType.Atom;
  386. v.atomValue = name;
  387. return v;
  388. }
  389. BertValue bertBinary(ubyte[] data){
  390. BertValue v;
  391. v.type_ = BertType.Binary;
  392. v.binaryValue = data;
  393. return v;
  394. }
  395. BertValue bertList(BertValue[] elements){
  396. BertValue v;
  397. v.type_ = BertType.List;
  398. v.listValue = elements;
  399. return v;
  400. }
  401. BertValue bertTuple(BertValue[] elements){
  402. BertValue v;
  403. v.type_ = BertType.Tuple;
  404. v.tupleValue = elements;
  405. return v;
  406. }
  407. BertValue bertMap(BertValue[BertValue] map){
  408. BertValue v;
  409. v.type_ = BertType.Map;
  410. v.mapValue = map;
  411. return v;
  412. }
  413. BertValue bertNil(){
  414. BertValue v;
  415. v.type_ = BertType.Nil;
  416. return v;
  417. }
  418. struct BertDecoder{
  419. ubyte[] data;
  420. size_t pos;
  421. BertValue decode(){
  422. try{
  423. if(pos >= data.length){ throw new Exception("No data to decode"); }
  424. if(data[pos++] != BERT_TAG.VERSION){
  425. throw new Exception("Invalid BERT format: missing version byte");
  426. }
  427. return decodeValue();
  428. }catch (Exception e){
  429. writeln("Got error: ", e.msg);
  430. return bertNil();
  431. }
  432. }
  433. private BertValue decodeValue(){
  434. if(pos >= data.length){ throw new Exception("Unexpected end of data"); }
  435. ubyte tag = data[pos++];
  436. switch(tag){
  437. case BERT_TAG.SMALL_INT:
  438. if(pos >= data.length){ throw new Exception("Incomplete SMALL_INT"); }
  439. return bertInt( cast(ubyte)data[pos++] );
  440. case BERT_TAG.INT:
  441. if((pos + 4) > data.length){ throw new Exception("Incomplete INT"); }
  442. uint value = bigEndianToNative!uint(data[pos..pos+4][0..4]);
  443. pos += 4;
  444. if(value <= ubyte.max){ // maybe can to ubyte, ushort
  445. return bertInt( cast(ubyte)value );
  446. }else if(value <= ushort.max){
  447. return bertInt( cast(ushort)value );
  448. }else{ // uint
  449. return bertInt(value);
  450. }
  451. case BERT_TAG.FLOAT:
  452. if((pos + 8) > data.length){ throw new Exception("Incomplete FLOAT"); }
  453. double fvalue = bigEndianToNative!double(data[pos..pos+8][0..8]);
  454. pos += 8;
  455. return bertFloat(fvalue);
  456. case BERT_TAG.ATOM:
  457. if((pos + 2) > data.length){ throw new Exception("Incomplete ATOM length"); }
  458. ushort len = (cast(ushort)data[pos] << 8) | data[pos+1];
  459. pos += 2;
  460. if(pos + len > data.length){ throw new Exception("Incomplete ATOM data"); }
  461. string atom = cast(string)data[pos..pos+len];
  462. pos += len;
  463. return bertAtom(atom);
  464. case BERT_TAG.TUPLE:
  465. if(pos >= data.length){ throw new Exception("Incomplete TUPLE"); }
  466. ubyte arity = data[pos++];
  467. auto elements = new BertValue[arity];
  468. foreach(i; 0..arity){
  469. elements[i] = decodeValue();
  470. }
  471. return bertTuple(elements);
  472. case BERT_TAG.LIST:
  473. if((pos + 4) > data.length){ throw new Exception("Incomplete LIST length"); }
  474. uint len = bigEndianToNative!uint(data[pos..pos+4][0..4]);
  475. pos += 4;
  476. auto elements = new BertValue[len];
  477. foreach(i; 0..len){
  478. elements[i] = decodeValue();
  479. }
  480. if(pos >= data.length || data[pos++] != BERT_TAG.NIL){
  481. throw new Exception("Missing NIL terminator for LIST");
  482. }
  483. return bertList(elements);
  484. case BERT_TAG.BINARY:
  485. if((pos + 4) > data.length){ throw new Exception("Incomplete BINARY length"); }
  486. uint len = bigEndianToNative!uint(data[pos..pos+4][0..4]);
  487. pos += 4;
  488. if((pos + len) > data.length){ throw new Exception("Incomplete BINARY data"); }
  489. auto bin = bertBinary(data[pos..pos+len]);
  490. pos += len;
  491. return bin;
  492. case BERT_TAG.NIL:
  493. return bertNil();
  494. case BERT_TAG.BIGINT:
  495. //case BERT_TAG.LARGE_BIG:
  496. return decodeBigInt();
  497. case BERT_TAG.MAP:
  498. if((pos + 4) > data.length){ throw new Exception("Incomplete MAP size"); }
  499. uint size = bigEndianToNative!uint(data[pos..pos+4][0..4]);
  500. pos += 4;
  501. BertValue[BertValue] map;
  502. foreach(i; 0..size){
  503. auto key = decodeValue();
  504. auto value = decodeValue();
  505. map[key] = value;
  506. }
  507. return bertMap(map);
  508. default:
  509. throw new Exception(format("Unknown BERT tag: 0x%x", tag));
  510. }
  511. }
  512. //private BertValue decodeBigInt(ubyte tag){ // BIGINT, not use LARGE_BIG
  513. private BertValue decodeBigInt(){ // BIGINT, not use LARGE_BIG
  514. //uint n;
  515. //ubyte sign; // ignore sign - as unsigned
  516. //if(tag == BERT_TAG.BIGINT){
  517. if(pos >= data.length){ throw new Exception("Incomplete BIGINT"); }
  518. uint n = data[pos++];
  519. //}else{
  520. // if((pos + 4) > data.length){ throw new Exception("Incomplete LARGE_BIG size"); }
  521. // n = bigEndianToNative!uint(data[pos..pos+4][0..4]);
  522. // pos += 4;
  523. //}
  524. writeln("642 n = ", n);
  525. //writeln("n type = ", typeof(n).stringof);
  526. if(pos >= data.length){ throw new Exception("Incomplete BIG sign"); }
  527. //sign = data[pos++]; // ignore sign - as unsigned
  528. pos++; // skip sign
  529. if((pos + n) > data.length){ throw new Exception("Incomplete BIG data"); }
  530. if(n <= 8){ // maybe can to ubyte, ushort, uint, ulong
  531. if(n == 1){
  532. return bertInt( cast(ubyte)data[pos++] );
  533. }
  534. ulong value = 0;
  535. foreach(i; 0..n){
  536. value += cast(ulong)data[pos++] << (8 * i);
  537. }
  538. if(n == 2){
  539. return bertInt( cast(ushort)value );
  540. }else if( (n == 3) || (n == 4) ){
  541. return bertInt( cast(uint)value );
  542. }else{ // ( n == 5) || (n == 6) || (n == 7) || (n == 8)
  543. return bertInt(value);
  544. }
  545. /*
  546. if(n == 2){
  547. auto value = cast(ushort)littleEndianToNative!ushort(data[pos..pos+2][0..2]);
  548. pos += n;
  549. return bertInt(value);
  550. }else if(n == 3){
  551. ubyte[] temp = data[pos..pos+3][0..3];
  552. auto value = cast(uint)littleEndianToNative!uint( [ temp[0], temp[1], temp[2], cast(ubyte)0x00 ] );
  553. pos += n;
  554. return bertInt(value);
  555. }else if(n == 4){
  556. auto value = cast(uint)littleEndianToNative!uint(data[pos..pos+4][0..4]);
  557. pos += n;
  558. return bertInt( cast(uint)value );
  559. }else if(n == 5){
  560. ubyte[] temp = data[pos..pos+5][0..5];
  561. auto value = cast(ulong)littleEndianToNative!ulong( [ temp[0], temp[1], temp[2], temp[3], temp[4], cast(ubyte)0x00, cast(ubyte)0x00, cast(ubyte)0x00 ] );
  562. pos += n;
  563. return bertInt(value);
  564. }else if(n == 6){
  565. ubyte[] temp = data[pos..pos+6][0..6];
  566. auto value = cast(ulong)littleEndianToNative!ulong( [ temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], cast(ubyte)0x00, cast(ubyte)0x00 ] );
  567. pos += n;
  568. return bertInt(value);
  569. }else if(n == 7){
  570. ubyte[] temp = data[pos..pos+7][0..7];
  571. auto value = cast(ulong)littleEndianToNative!ulong( [ temp[0], temp[1], temp[2], temp[3], temp[4], temp[5], temp[6], cast(ubyte)0x00 ] );
  572. pos += n;
  573. return bertInt(value);
  574. }else{ // n == 8
  575. auto value = cast(ulong)littleEndianToNative!ulong(data[pos..pos+8][0..8]);
  576. pos += n;
  577. return bertInt(value);
  578. }
  579. */
  580. //return bertInt(sign ? (-cast(long)value) : cast(long)value);
  581. }else{ // just bigint
  582. BigInt value = 0;
  583. foreach(i; 0..n){
  584. value += BigInt(data[pos++]) << (8 * i);
  585. }
  586. return bertBigInt(value);
  587. }
  588. }
  589. }