PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/otp.net/Otp/OtpInputStream.cs

https://github.com/babo/jungerl
C# | 965 lines | 523 code | 157 blank | 285 comment | 70 complexity | 6d35682f00cbb6c083fe82b5dedcc341 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, AGPL-1.0
  1. /*``The contents of this file are subject to the Erlang Public License,
  2. * Version 1.1, (the "License"); you may not use this file except in
  3. * compliance with the License. You should have received a copy of the
  4. * Erlang Public License along with this software. If not, it can be
  5. * retrieved via the world wide web at http://www.erlang.org/.
  6. *
  7. * Software distributed under the License is distributed on an "AS IS"
  8. * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  9. * the License for the specific language governing rights and limitations
  10. * under the License.
  11. *
  12. * The Initial Developer of the Original Code is Ericsson Utvecklings AB.
  13. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
  14. * AB. All Rights Reserved.''
  15. *
  16. * Converted from Java to C# by Vlad Dumitrescu (vlad_Dumitrescu@hotmail.com)
  17. */
  18. namespace Otp
  19. {
  20. using System;
  21. /*
  22. * Provides a stream for decoding Erlang terms from external format.
  23. *
  24. * <p> Note that this class is not synchronized, if you need
  25. * synchronization you must provide it yourself.
  26. **/
  27. public class OtpInputStream:System.IO.MemoryStream
  28. {
  29. /*
  30. * Create a stream from a buffer containing encoded Erlang terms.
  31. **/
  32. public OtpInputStream(byte[] buf):base(buf)
  33. {
  34. }
  35. /*
  36. * Create a stream from a buffer containing encoded
  37. * Erlang terms at the given offset and length.
  38. **/
  39. public OtpInputStream(byte[] buf, int offset, int length):base(buf, offset, length)
  40. {
  41. }
  42. /*
  43. * Get the current position in the stream.
  44. *
  45. * @return the current position in the stream.
  46. **/
  47. public virtual int getPos()
  48. {
  49. return (int) base.Position;
  50. }
  51. /*
  52. * Set the current position in the stream.
  53. *
  54. * @param pos the position to move to in the stream. If pos
  55. * indicates a position beyond the end of the stream, the position
  56. * is move to the end of the stream instead. If pos is negative, the
  57. * position is moved to the beginning of the stream instead.
  58. *
  59. * @return the previous position in the stream.
  60. **/
  61. public virtual int setPos(int pos)
  62. {
  63. int oldpos = (int) base.Position;
  64. if (pos > (int) base.Length)
  65. pos = (int) base.Length;
  66. else if (pos < 0)
  67. pos = 0;
  68. base.Position = (System.Int64) pos;
  69. return oldpos;
  70. }
  71. /*
  72. * Read an array of bytes from the stream. The method reads at most
  73. * buf.length bytes from the input stream.
  74. *
  75. * @return the number of bytes read.
  76. *
  77. * @exception OtpErlangDecodeException if the next byte cannot be
  78. * read.
  79. **/
  80. public virtual int readN(byte[] buf)
  81. {
  82. try
  83. {
  84. return base.Read(buf, 0, buf.Length);
  85. }
  86. catch (System.IO.IOException)
  87. {
  88. throw new Erlang.DecodeException("Cannot read from input stream");
  89. }
  90. }
  91. /*
  92. * Look ahead one position in the stream without consuming the byte
  93. * found there.
  94. *
  95. * @return the next byte in the stream, as an integer.
  96. *
  97. * @exception Erlang.DecodeException if the next byte cannot be
  98. * read.
  99. **/
  100. public virtual int peek()
  101. {
  102. int i;
  103. try
  104. {
  105. i = base.ReadByte();
  106. base.Seek(-1, System.IO.SeekOrigin.Current);
  107. if (i < 0)
  108. i += 256;
  109. return i;
  110. }
  111. catch (System.Exception)
  112. {
  113. throw new Erlang.DecodeException("Cannot read from input stream");
  114. }
  115. }
  116. /*
  117. * Read a one byte integer from the stream.
  118. *
  119. * @return the byte read, as an integer.
  120. *
  121. * @exception Erlang.DecodeException if the next byte cannot be
  122. * read.
  123. **/
  124. public virtual int read1()
  125. {
  126. int i;
  127. i = base.ReadByte();
  128. if (i < 0)
  129. {
  130. throw new Erlang.DecodeException("Cannot read from input stream");
  131. }
  132. return i;
  133. }
  134. /*
  135. * Read a two byte big endian integer from the stream.
  136. *
  137. * @return the bytes read, converted from big endian to an integer.
  138. *
  139. * @exception Erlang.DecodeException if the next byte cannot be
  140. * read.
  141. **/
  142. public virtual int read2BE()
  143. {
  144. byte[] b = new byte[2];
  145. try
  146. {
  147. base.Read(b, 0, b.Length);
  148. }
  149. catch (System.IO.IOException)
  150. {
  151. throw new Erlang.DecodeException("Cannot read from input stream");
  152. }
  153. return ((((int) b[0] << 8) & 0xff00) + (((int) b[1]) & 0xff));
  154. }
  155. /*
  156. * Read a four byte big endian integer from the stream.
  157. *
  158. * @return the bytes read, converted from big endian to an integer.
  159. *
  160. * @exception Erlang.DecodeException if the next byte cannot be
  161. * read.
  162. **/
  163. public virtual int read4BE()
  164. {
  165. byte[] b = new byte[4];
  166. try
  167. {
  168. base.Read(b, 0, b.Length);
  169. }
  170. catch (System.IO.IOException)
  171. {
  172. throw new Erlang.DecodeException("Cannot read from input stream");
  173. }
  174. return (int)((((int) b[0] << 24) & 0xff000000) + (((int) b[1] << 16) & 0xff0000) + (((int) b[2] << 8) & 0xff00) + (((int) b[3]) & 0xff));
  175. }
  176. /*
  177. * Read a two byte little endian integer from the stream.
  178. *
  179. * @return the bytes read, converted from little endian to an
  180. * integer.
  181. *
  182. * @exception Erlang.DecodeException if the next byte cannot be
  183. * read.
  184. **/
  185. public virtual int read2LE()
  186. {
  187. byte[] b = new byte[2];
  188. try
  189. {
  190. base.Read(b, 0, b.Length);
  191. }
  192. catch (System.IO.IOException)
  193. {
  194. throw new Erlang.DecodeException("Cannot read from input stream");
  195. }
  196. return ((((int) b[1] << 8) & 0xff00) + (((int) b[0]) & 0xff));
  197. }
  198. /*
  199. * Read a four byte little endian integer from the stream.
  200. *
  201. * @return the bytes read, converted from little endian to an
  202. * integer.
  203. *
  204. * @exception Erlang.DecodeException if the next byte cannot be
  205. * read.
  206. **/
  207. public virtual int read4LE()
  208. {
  209. byte[] b = new byte[4];
  210. try
  211. {
  212. base.Read(b, 0, b.Length);
  213. }
  214. catch (System.IO.IOException)
  215. {
  216. throw new Erlang.DecodeException("Cannot read from input stream");
  217. }
  218. return (int)((((int) b[3] << 24) & 0xff000000) + (((int) b[2] << 16) & 0xff0000) + (((int) b[1] << 8) & 0xff00) + (((int) b[0]) & 0xff));
  219. }
  220. /*
  221. * Read an Erlang atom from the stream and interpret the value as a
  222. * boolean.
  223. *
  224. * @return true if the atom at the current position in the stream
  225. * contains the value 'true' (ignoring case), false otherwise.
  226. *
  227. * @exception Erlang.DecodeException if the next term in the
  228. * stream is not an atom.
  229. **/
  230. public virtual bool read_boolean()
  231. {
  232. return System.Boolean.Parse(this.read_atom());
  233. }
  234. /*
  235. * Read an Erlang atom from the stream.
  236. *
  237. * @return a String containing the value of the atom.
  238. *
  239. * @exception Erlang.DecodeException if the next term in the
  240. * stream is not an atom.
  241. **/
  242. public virtual System.String read_atom()
  243. {
  244. int tag;
  245. int len;
  246. byte[] strbuf;
  247. System.String atom;
  248. tag = this.read1();
  249. if (tag == OtpExternal.versionTag)
  250. {
  251. tag = this.read1();
  252. }
  253. if (tag != OtpExternal.atomTag)
  254. {
  255. throw new Erlang.DecodeException("wrong tag encountered, expected " + OtpExternal.atomTag + ", got " + tag);
  256. }
  257. len = this.read2BE();
  258. strbuf = new byte[len];
  259. this.readN(strbuf);
  260. char[] tmpChar;
  261. tmpChar = new char[strbuf.Length];
  262. strbuf.CopyTo(tmpChar, 0);
  263. atom = new System.String(tmpChar);
  264. if (atom.Length > OtpExternal.maxAtomLength)
  265. {
  266. atom = atom.Substring(0, (OtpExternal.maxAtomLength) - (0));
  267. }
  268. return atom;
  269. }
  270. /*
  271. * Read an Erlang binary from the stream.
  272. *
  273. * @return a byte array containing the value of the binary.
  274. *
  275. * @exception Erlang.DecodeException if the next term in the
  276. * stream is not a binary.
  277. **/
  278. public virtual byte[] read_binary()
  279. {
  280. int tag;
  281. int len;
  282. byte[] bin;
  283. tag = this.read1();
  284. if (tag == OtpExternal.versionTag)
  285. {
  286. tag = this.read1();
  287. }
  288. if (tag != OtpExternal.binTag)
  289. {
  290. throw new Erlang.DecodeException("Wrong tag encountered, expected " + OtpExternal.binTag + ", got " + tag);
  291. }
  292. len = this.read4BE();
  293. bin = new byte[len];
  294. this.readN(bin);
  295. return bin;
  296. }
  297. /*
  298. * Read an Erlang float from the stream.
  299. *
  300. * @return the float value.
  301. *
  302. * @exception Erlang.DecodeException if the next term in the
  303. * stream is not a float.
  304. **/
  305. public virtual float read_float()
  306. {
  307. double d = this.read_double();
  308. float f = (float) d;
  309. if (System.Math.Abs(d - f) >= 1.0E-20)
  310. throw new Erlang.DecodeException("Value cannot be represented as float: " + d);
  311. return f;
  312. }
  313. /*
  314. * Read an Erlang float from the stream.
  315. *
  316. * @return the float value, as a double.
  317. *
  318. * @exception Erlang.DecodeException if the next term in the
  319. * stream is not a float.
  320. *
  321. **/
  322. public virtual double read_double()
  323. {
  324. return getFloatOrDouble();
  325. }
  326. private double getFloatOrDouble()
  327. {
  328. // parse the stream
  329. int tag = this.read1();
  330. if (tag == OtpExternal.versionTag)
  331. {
  332. tag = this.read1();
  333. }
  334. if (tag != OtpExternal.floatTag)
  335. {
  336. throw new Erlang.DecodeException("Wrong tag encountered, expected " + OtpExternal.floatTag + ", got " + tag);
  337. }
  338. // get the string
  339. byte[] strbuf = new byte[31];
  340. this.readN(strbuf);
  341. char[] tmpChar = new char[strbuf.Length];
  342. strbuf.CopyTo(tmpChar, 0);
  343. System.String str = new System.String(tmpChar);
  344. //System.Diagnostics.Debug.WriteLine("getFloatOrDouble: str = " + str);
  345. double parsedValue = 0.0;
  346. try
  347. {
  348. // Easier than the java version.
  349. parsedValue = System.Double.Parse(str);
  350. }
  351. catch
  352. {
  353. throw new Erlang.DecodeException("Error parsing float format: '" + str + "'");
  354. }
  355. return parsedValue;
  356. }
  357. /*
  358. * Read one byte from the stream.
  359. *
  360. * @return the byte read.
  361. *
  362. * @exception Erlang.DecodeException if the next byte cannot be
  363. * read.
  364. **/
  365. public virtual byte read_byte()
  366. {
  367. long l = this.read_long();
  368. byte i = (byte) l;
  369. if (l != i)
  370. {
  371. throw new Erlang.DecodeException("Value too large for byte: " + l);
  372. }
  373. return i;
  374. }
  375. /*
  376. * Read a character from the stream.
  377. *
  378. * @return the character value.
  379. *
  380. * @exception Erlang.DecodeException if the next term in the
  381. * stream is not an integer that can be represented as a char.
  382. **/
  383. public virtual char read_char()
  384. {
  385. long l = this.read_long();
  386. char i = (char) l;
  387. if (l != i)
  388. {
  389. throw new Erlang.DecodeException("Value too large for byte: " + l);
  390. }
  391. return i;
  392. }
  393. /*
  394. * Read an unsigned integer from the stream.
  395. *
  396. * @return the integer value.
  397. *
  398. * @exception Erlang.DecodeException if the next term in the
  399. * stream can not be represented as a positive integer.
  400. **/
  401. public virtual int read_uint()
  402. {
  403. long l = this.read_long();
  404. int i = (int) l;
  405. if (l != i)
  406. {
  407. throw new Erlang.DecodeException("Value too large for integer: " + l);
  408. }
  409. else if (l < 0)
  410. {
  411. throw new Erlang.DecodeException("Value not unsigned: " + l);
  412. }
  413. return i;
  414. }
  415. /*
  416. * Read an integer from the stream.
  417. *
  418. * @return the integer value.
  419. *
  420. * @exception Erlang.DecodeException if the next term in the
  421. * stream can not be represented as an integer.
  422. **/
  423. public virtual int read_int()
  424. {
  425. long l = this.read_long();
  426. int i = (int) l;
  427. if (l != i)
  428. {
  429. throw new Erlang.DecodeException("Value too large for byte: " + l);
  430. }
  431. return i;
  432. }
  433. /*
  434. * Read an unsigned short from the stream.
  435. *
  436. * @return the short value.
  437. *
  438. * @exception Erlang.DecodeException if the next term in the
  439. * stream can not be represented as a positive short.
  440. **/
  441. public virtual short read_ushort()
  442. {
  443. long l = this.read_long();
  444. short i = (short) l;
  445. if (l != i)
  446. {
  447. throw new Erlang.DecodeException("Value too large for byte: " + l);
  448. }
  449. else if (l < 0)
  450. {
  451. throw new Erlang.DecodeException("Value not unsigned: " + l);
  452. }
  453. return i;
  454. }
  455. /*
  456. * Read a short from the stream.
  457. *
  458. * @return the short value.
  459. *
  460. * @exception Erlang.DecodeException if the next term in the
  461. * stream can not be represented as a short.
  462. **/
  463. public virtual short read_short()
  464. {
  465. long l = this.read_long();
  466. short i = (short) l;
  467. if (l != i)
  468. {
  469. throw new Erlang.DecodeException("Value too large for byte: " + l);
  470. }
  471. return i;
  472. }
  473. /*
  474. * Read an unsigned long from the stream.
  475. *
  476. * @return the long value.
  477. *
  478. * @exception Erlang.DecodeException if the next term in the
  479. * stream can not be represented as a positive long.
  480. **/
  481. public virtual long read_ulong()
  482. {
  483. long l = this.read_long();
  484. if (l < 0)
  485. {
  486. throw new Erlang.DecodeException("Value not unsigned: " + l);
  487. }
  488. return l;
  489. }
  490. /*
  491. * Read a long from the stream.
  492. *
  493. * @return the long value.
  494. *
  495. * @exception Erlang.DecodeException if the next term in the
  496. * stream can not be represented as a long.
  497. **/
  498. public virtual long read_long()
  499. {
  500. int tag;
  501. int sign;
  502. int arity;
  503. long val;
  504. tag = this.read1();
  505. if (tag == OtpExternal.versionTag)
  506. {
  507. tag = this.read1();
  508. }
  509. switch (tag)
  510. {
  511. case OtpExternal.smallIntTag:
  512. val = this.read1();
  513. break;
  514. case OtpExternal.intTag:
  515. val = this.read4BE();
  516. break;
  517. case OtpExternal.smallBigTag:
  518. arity = this.read1();
  519. if (arity != 4)
  520. {
  521. throw new Erlang.DecodeException("Arity for smallBig must be 4, was " + arity);
  522. }
  523. sign = this.read1();
  524. // obs! little endian here
  525. val = this.read4LE();
  526. val = (sign == 0?val:- val); // should deal with overflow
  527. break;
  528. case OtpExternal.largeBigTag: default:
  529. throw new Erlang.DecodeException("Not valid integer tag: " + tag);
  530. }
  531. return val;
  532. }
  533. /*
  534. * Read a list header from the stream.
  535. *
  536. * @return the arity of the list.
  537. *
  538. * @exception Erlang.DecodeException if the next term in the
  539. * stream is not a list.
  540. **/
  541. public virtual int read_list_head()
  542. {
  543. int arity = 0;
  544. int tag = this.read1();
  545. if (tag == OtpExternal.versionTag)
  546. {
  547. tag = this.read1();
  548. }
  549. switch (tag)
  550. {
  551. case OtpExternal.nilTag:
  552. arity = 0;
  553. break;
  554. case OtpExternal.stringTag:
  555. arity = this.read2BE();
  556. break;
  557. case OtpExternal.listTag:
  558. arity = this.read4BE();
  559. break;
  560. default:
  561. throw new Erlang.DecodeException("Not valid list tag: " + tag);
  562. }
  563. return arity;
  564. }
  565. /*
  566. * Read a tuple header from the stream.
  567. *
  568. * @return the arity of the tuple.
  569. *
  570. * @exception Erlang.DecodeException if the next term in the
  571. * stream is not a tuple.
  572. **/
  573. public virtual int read_tuple_head()
  574. {
  575. int arity = 0;
  576. int tag = this.read1();
  577. if (tag == OtpExternal.versionTag)
  578. {
  579. tag = this.read1();
  580. }
  581. // decode the tuple header and get arity
  582. switch (tag)
  583. {
  584. case OtpExternal.smallTupleTag:
  585. arity = this.read1();
  586. break;
  587. case OtpExternal.largeTupleTag:
  588. arity = this.read4BE();
  589. break;
  590. default:
  591. throw new Erlang.DecodeException("Not valid tuple tag: " + tag);
  592. }
  593. return arity;
  594. }
  595. /*
  596. * Read an empty list from the stream.
  597. *
  598. * @return zero (the arity of the list).
  599. *
  600. * @exception Erlang.DecodeException if the next term in the
  601. * stream is not an empty list.
  602. **/
  603. public virtual int read_nil()
  604. {
  605. int arity = 0;
  606. int tag = this.read1();
  607. if (tag == OtpExternal.versionTag)
  608. {
  609. tag = this.read1();
  610. }
  611. switch (tag)
  612. {
  613. case OtpExternal.nilTag:
  614. arity = 0;
  615. break;
  616. default:
  617. throw new Erlang.DecodeException("Not valid nil tag: " + tag);
  618. }
  619. return arity;
  620. }
  621. /*
  622. * Read an Erlang PID from the stream.
  623. *
  624. * @return the value of the PID.
  625. *
  626. * @exception Erlang.DecodeException if the next term in the
  627. * stream is not an Erlang PID.
  628. **/
  629. public virtual Erlang.Pid read_pid()
  630. {
  631. System.String node;
  632. int id;
  633. int serial;
  634. int creation;
  635. int tag;
  636. tag = this.read1();
  637. if (tag == OtpExternal.versionTag)
  638. {
  639. tag = this.read1();
  640. }
  641. if (tag != OtpExternal.pidTag)
  642. {
  643. throw new Erlang.DecodeException("Wrong tag encountered, expected " + OtpExternal.pidTag + ", got " + tag);
  644. }
  645. node = this.read_atom();
  646. id = this.read4BE() & 0x7fff; // 15 bits
  647. serial = this.read4BE() & 0x07; // 3 bits
  648. creation = this.read1() & 0x03; // 2 bits
  649. return new Erlang.Pid(node, id, serial, creation);
  650. }
  651. /*
  652. * Read an Erlang port from the stream.
  653. *
  654. * @return the value of the port.
  655. *
  656. * @exception DecodeException if the next term in the
  657. * stream is not an Erlang port.
  658. **/
  659. public virtual Erlang.Port read_port()
  660. {
  661. System.String node;
  662. int id;
  663. int creation;
  664. int tag;
  665. tag = this.read1();
  666. if (tag == OtpExternal.versionTag)
  667. {
  668. tag = this.read1();
  669. }
  670. if (tag != OtpExternal.portTag)
  671. {
  672. throw new Erlang.DecodeException("Wrong tag encountered, expected " + OtpExternal.portTag + ", got " + tag);
  673. }
  674. node = this.read_atom();
  675. id = this.read4BE() & 0x3ffff; // 18 bits
  676. creation = this.read1() & 0x03; // 2 bits
  677. return new Erlang.Port(node, id, creation);
  678. }
  679. /*
  680. * Read an Erlang reference from the stream.
  681. *
  682. * @return the value of the reference
  683. *
  684. * @exception DecodeException if the next term in the
  685. * stream is not an Erlang reference.
  686. **/
  687. public virtual Erlang.Ref read_ref()
  688. {
  689. System.String node;
  690. int id;
  691. int creation;
  692. int tag;
  693. tag = this.read1();
  694. if (tag == OtpExternal.versionTag)
  695. {
  696. tag = this.read1();
  697. }
  698. switch (tag)
  699. {
  700. case OtpExternal.refTag:
  701. node = this.read_atom();
  702. id = this.read4BE() & 0x3ffff; // 18 bits
  703. creation = this.read1() & 0x03; // 2 bits
  704. return new Erlang.Ref(node, id, creation);
  705. case OtpExternal.newRefTag:
  706. int arity = this.read2BE();
  707. node = this.read_atom();
  708. creation = this.read1() & 0x03; // 2 bits
  709. int[] ids = new int[arity];
  710. for (int i = 0; i < arity; i++)
  711. {
  712. ids[i] = this.read4BE();
  713. }
  714. ids[0] &= 0x3ffff; // first id gets truncated to 18 bits
  715. return new Erlang.Ref(node, ids, creation);
  716. default:
  717. throw new Erlang.DecodeException("Wrong tag encountered, expected ref, got " + tag);
  718. }
  719. }
  720. /*
  721. * Read a string from the stream.
  722. *
  723. * @return the value of the string.
  724. *
  725. * @exception DecodeException if the next term in the
  726. * stream is not a string.
  727. **/
  728. public virtual System.String read_string()
  729. {
  730. int tag;
  731. int len;
  732. byte[] strbuf;
  733. char[] charbuf;
  734. tag = this.read1();
  735. if (tag == OtpExternal.versionTag)
  736. {
  737. tag = this.read1();
  738. }
  739. switch (tag)
  740. {
  741. case OtpExternal.stringTag:
  742. char[] tmpChar;
  743. len = this.read2BE();
  744. strbuf = new byte[len];
  745. this.readN(strbuf);
  746. tmpChar = new char[strbuf.Length];
  747. strbuf.CopyTo(tmpChar, 0);
  748. return new System.String(tmpChar);
  749. case OtpExternal.nilTag:
  750. return "";
  751. case OtpExternal.listTag:
  752. // List when unicode +
  753. len = this.read4BE();
  754. charbuf = new char[len];
  755. for (int i = 0; i < len; i++)
  756. charbuf[i] = this.read_char();
  757. this.read_nil();
  758. return new System.String(charbuf);
  759. default:
  760. throw new Erlang.DecodeException("Wrong tag encountered, expected " + OtpExternal.stringTag + " or " + OtpExternal.listTag + ", got " + tag);
  761. }
  762. }
  763. /*
  764. * Read an arbitrary Erlang term from the stream.
  765. *
  766. * @return the Erlang term.
  767. *
  768. * @exception DecodeException if the stream does not
  769. * contain a known Erlang type at the next position.
  770. **/
  771. public virtual Erlang.Object read_any()
  772. {
  773. // calls one of the above functions, depending on o
  774. int tag = this.peek();
  775. if (tag == OtpExternal.versionTag)
  776. {
  777. this.read1();
  778. tag = this.peek();
  779. }
  780. //System.Diagnostics.Debug.WriteLine("read_any: tag = " + tag);
  781. switch (tag)
  782. {
  783. case OtpExternal.smallIntTag: case OtpExternal.intTag: case OtpExternal.smallBigTag:
  784. return new Erlang.Long(this);
  785. case OtpExternal.atomTag:
  786. return new Erlang.Atom(this);
  787. case OtpExternal.floatTag:
  788. return new Erlang.Double(this);
  789. case OtpExternal.refTag: case OtpExternal.newRefTag:
  790. return new Erlang.Ref(this);
  791. case OtpExternal.portTag:
  792. return new Erlang.Port(this);
  793. case OtpExternal.pidTag:
  794. return new Erlang.Pid(this);
  795. case OtpExternal.stringTag:
  796. return new Erlang.String(this);
  797. case OtpExternal.listTag: case OtpExternal.nilTag:
  798. return new Erlang.List(this);
  799. case OtpExternal.smallTupleTag: case OtpExternal.largeTupleTag:
  800. return new Erlang.Tuple(this);
  801. case OtpExternal.binTag:
  802. return new Erlang.Binary(this);
  803. case OtpExternal.largeBigTag: default:
  804. throw new Erlang.DecodeException("Uknown data type: " + tag);
  805. }
  806. }
  807. }
  808. }