[
  {
    "path": ".github/workflows/codeql.yml",
    "content": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# You may wish to alter this file to override the set of languages analyzed,\n# or to provide custom queries or build logic.\n#\n# ******** NOTE ********\n# We have attempted to detect the languages in your repository. Please check\n# the `language` matrix defined below to confirm you have the correct set of\n# supported CodeQL languages.\n#\nname: \"CodeQL\"\n\non:\n  push:\n    branches: [ \"master\" ]\n  pull_request:\n    # The branches below must be a subset of the branches above\n    branches: [ \"master\" ]\n  schedule:\n    - cron: '45 14 * * 3'\n\njobs:\n  analyze:\n    name: Analyze\n    runs-on: ubuntu-latest\n    permissions:\n      actions: read\n      contents: read\n      security-events: write\n\n    strategy:\n      fail-fast: false\n      matrix:\n        language: [ 'javascript' ]\n        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]\n        # Use only 'java' to analyze code written in Java, Kotlin or both\n        # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both\n        # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support\n\n    steps:\n    - name: Checkout repository\n      uses: actions/checkout@v3\n\n    # Initializes the CodeQL tools for scanning.\n    - name: Initialize CodeQL\n      uses: github/codeql-action/init@v2\n      with:\n        languages: ${{ matrix.language }}\n        # If you wish to specify custom queries, you can do so here or in a config file.\n        # By default, queries listed here will override any specified in a config file.\n        # Prefix the list here with \"+\" to use these queries and those in the config file.\n\n        # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs\n        # queries: security-extended,security-and-quality\n\n\n    # Autobuild attempts to build any compiled languages  (C/C++, C#, Go, or Java).\n    # If this step fails, then you should remove it and run the build manually (see below)\n    - name: Autobuild\n      uses: github/codeql-action/autobuild@v2\n\n    # ℹ️ Command-line programs to run using the OS shell.\n    # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun\n\n    #   If the Autobuild fails above, remove it and uncomment the following three lines.\n    #   modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.\n\n    # - run: |\n    #   echo \"Run, Build Application using script\"\n    #   ./location_of_script_within_repo/buildscript.sh\n\n    - name: Perform CodeQL Analysis\n      uses: github/codeql-action/analyze@v2\n      with:\n        category: \"/language:${{matrix.language}}\"\n"
  },
  {
    "path": ".github/workflows/nodejs.yml",
    "content": "name: CI\n\non:\n  push:\n    branches: [ master, 1.x ]\n\n  pull_request:\n    branches: [ master, 1.x ]\n\n  workflow_dispatch: {}\n\njobs:\n  Job:\n    name: Node.js\n    uses: artusjs/github-actions/.github/workflows/node-test.yml@v1\n    with:\n      os: 'ubuntu-latest'\n      version: '14, 16, 18'\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\n\non:\n  push:\n    branches: [ master ]\n\n  workflow_dispatch: {}\n\njobs:\n  release:\n    name: Node.js\n    uses: artusjs/github-actions/.github/workflows/node-release.yml@v1\n    secrets:\n      NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n      GIT_TOKEN: ${{ secrets.GIT_TOKEN }}\n    with:\n      checkTest: false\n"
  },
  {
    "path": ".gitignore",
    "content": "lib-cov\n*.seed\n*.log\n*.csv\n*.out\n*.pid\n*.gz\n\npids\nlogs\nresults\n\nnpm-debug.log\nnode_modules\n\n.DS_Store\ncoverage.html\ncoverage/\n.idea/"
  },
  {
    "path": ".jshintignore",
    "content": "node_modules/\ncoverage/\n.tmp/\n.git/\n"
  },
  {
    "path": ".jshintrc",
    "content": "{\n    // JSHint Default Configuration File (as on JSHint website)\n    // See http://jshint.com/docs/ for more details\n\n    \"maxerr\"        : 50,       // {int} Maximum error before stopping\n\n    // Enforcing\n    \"bitwise\"       : false,    // true: Prohibit bitwise operators (&, |, ^, etc.)\n    \"camelcase\"     : false,    // true: Identifiers must be in camelCase\n    \"curly\"         : true,     // true: Require {} for every new block or scope\n    \"eqeqeq\"        : true,     // true: Require triple equals (===) for comparison\n    \"forin\"         : false,    // true: Require filtering for..in loops with obj.hasOwnProperty()\n    \"immed\"         : false,    // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`\n    \"indent\"        : false,    // {int} Number of spaces to use for indentation\n    \"latedef\"       : false,    // true: Require variables/functions to be defined before being used\n    \"newcap\"        : false,    // true: Require capitalization of all constructor functions e.g. `new F()`\n    \"noarg\"         : true,     // true: Prohibit use of `arguments.caller` and `arguments.callee`\n    \"noempty\"       : true,     // true: Prohibit use of empty blocks\n    \"nonew\"         : false,    // true: Prohibit use of constructors for side-effects (without assignment)\n    \"plusplus\"      : false,    // true: Prohibit use of `++` & `--`\n    \"quotmark\"      : false,    // Quotation mark consistency:\n                                //   false    : do nothing (default)\n                                //   true     : ensure whatever is used is consistent\n                                //   \"single\" : require single quotes\n                                //   \"double\" : require double quotes\n    \"undef\"         : true,     // true: Require all non-global variables to be declared (prevents global leaks)\n    \"unused\"        : false,    // true: Require all defined variables be used\n    \"strict\"        : \"global\",     // true: Requires all functions run in ES5 Strict Mode\n    \"trailing\"      : false,    // true: Prohibit trailing whitespaces\n    \"maxparams\"     : false,    // {int} Max number of formal params allowed per function\n    \"maxdepth\"      : false,    // {int} Max depth of nested blocks (within functions)\n    \"maxstatements\" : false,    // {int} Max number statements per function\n    \"maxcomplexity\" : false,    // {int} Max cyclomatic complexity per function\n    \"maxlen\"        : false,    // {int} Max number of characters per line\n\n    // Relaxing\n    \"asi\"           : false,     // true: Tolerate Automatic Semicolon Insertion (no semicolons)\n    \"boss\"          : true,      // true: Tolerate assignments where comparisons would be expected\n    \"debug\"         : false,     // true: Allow debugger statements e.g. browser breakpoints.\n    \"eqnull\"        : false,     // true: Tolerate use of `== null`\n    \"es5\"           : false,     // true: Allow ES5 syntax (ex: getters and setters)\n    \"esnext\"        : true,      // true: Allow ES.next (ES6) syntax (ex: `const`)\n    \"moz\"           : false,     // true: Allow Mozilla specific syntax (extends and overrides esnext features)\n                                 // (ex: `for each`, multiple try/catch, function expression…)\n    \"evil\"          : false,     // true: Tolerate use of `eval` and `new Function()`\n    \"expr\"          : true,      // true: Tolerate `ExpressionStatement` as Programs\n    \"funcscope\"     : false,     // true: Tolerate defining variables inside control statements\"\n    \"iterator\"      : false,     // true: Tolerate using the `__iterator__` property\n    \"lastsemic\"     : false,     // true: Tolerate omitting a semicolon for the last statement of a 1-line block\n    \"laxbreak\"      : true,      // true: Tolerate possibly unsafe line breakings\n    \"laxcomma\"      : false,     // true: Tolerate comma-first style coding\n    \"loopfunc\"      : true,     // true: Tolerate functions being defined in loops\n    \"multistr\"      : true,      // true: Tolerate multi-line strings\n    \"proto\"         : false,     // true: Tolerate using the `__proto__` property\n    \"scripturl\"     : false,     // true: Tolerate script-targeted URLs\n    \"smarttabs\"     : false,     // true: Tolerate mixed tabs/spaces when used for alignment\n    \"shadow\"        : true,      // true: Allows re-define variables later in code e.g. `var x=1; x=2;`\n    \"sub\"           : false,     // true: Tolerate using `[]` notation when it can still be expressed in dot notation\n    \"supernew\"      : false,     // true: Tolerate `new function () { ... };` and `new Object;`\n    \"validthis\"     : true,      // true: Tolerate using this in a non-constructor function\n\n    // Environments\n    \"browser\"       : true,     // Web Browser (window, document, etc)\n    \"couch\"         : false,    // CouchDB\n    \"devel\"         : true,     // Development/debugging (alert, confirm, etc)\n    \"dojo\"          : false,    // Dojo Toolkit\n    \"jquery\"        : false,    // jQuery\n    \"mootools\"      : false,    // MooTools\n    \"node\"          : true,     // Node.js\n    \"nonstandard\"   : false,    // Widely adopted globals (escape, unescape, etc)\n    \"prototypejs\"   : false,    // Prototype and Scriptaculous\n    \"rhino\"         : false,    // Rhino\n    \"worker\"        : false,    // Web Workers\n    \"wsh\"           : false,    // Windows Scripting Host\n    \"yui\"           : false,    // Yahoo User Interface\n    \"noyield\"       : true,     // allow generators without a yield\n\n    // Legacy\n    \"nomen\"         : false,    // true: Prohibit dangling `_` in variables\n    \"onevar\"        : false,    // true: Allow only one `var` statement per function\n    \"passfail\"      : false,    // true: Stop on first error\n    \"white\"         : false,    // true: Check against strict whitespace and indentation rules\n\n    // Custom Globals\n    \"globals\"       : {         // additional predefined global variables\n      // mocha\n      \"describe\": true,\n      \"it\": true,\n      \"before\": true,\n      \"afterEach\": true,\n      \"beforeEach\": true,\n      \"after\": true\n    }\n}\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\n## [2.11.0](https://github.com/node-modules/hessian.js/compare/v2.10.1...v2.11.0) (2023-04-16)\n\n\n### Features\n\n* remove debug and use byte@2 ([#137](https://github.com/node-modules/hessian.js/issues/137)) ([1eb3b3e](https://github.com/node-modules/hessian.js/commit/1eb3b3ed5193deaa176231322d03daab99e49aff))\n\n\n---\n\n\n2.10.1 / 2021-11-15\n==================\n\n**fixes**\n  * [[`543b2bc`](https://github.com/node-modules/hessian.js.git/commit/543b2bc482828ae5e6cb804cf958c9f22dfb24d6)] - fix: 🐛 ref should use custom handler (#126) (Hongcai Deng <<admin@dhchouse.com>>)\n\n**others**\n  * [[`33dcabf`](https://github.com/node-modules/hessian.js.git/commit/33dcabf7a585705c6e88b9f49782120bf5e29475)] - test: github action only test on macOS and Linux (#129) (fengmk2 <<fengmk2@gmail.com>>)\n  * [[`895fa83`](https://github.com/node-modules/hessian.js.git/commit/895fa8367c428cb6b2a42dd6ded311ed9eb1b475)] - test: 💍 fix ref should use custom handler circular bug (#128) (Hongcai Deng <<admin@dhchouse.com>>)\n  * [[`5c633be`](https://github.com/node-modules/hessian.js.git/commit/5c633be4ae130d55f263133b6607ce1238273b52)] - test: run test on github action (#127) (fengmk2 <<fengmk2@gmail.com>>)\n  * [[`0b14874`](https://github.com/node-modules/hessian.js.git/commit/0b148740d78e312d2ec6da4e37b0ade35a3c15ae)] - chore: add contributors (#117) (fengmk2 <<fengmk2@gmail.com>>)\n  * [[`9012536`](https://github.com/node-modules/hessian.js.git/commit/9012536fc49fe7d57eeafb390ab11fcff027d12a)] - chore: add node 12 & 14 into travis list (#125) (Jackson Tian <<shyvo1987@gmail.com>>)\n\n2.10.0 / 2020-05-15\n==================\n\n**features**\n  * [[`461a715`](http://github.com/node-modules/hessian.js/commit/461a71551503d6f6430f9b078ffd2be4f7624de4)] - feat: support encode & decode custom map type (#122) (zōng yǔ <<gxcsoccer@users.noreply.github.com>>)\n\n2.9.0 / 2019-05-15\n==================\n\n**features**\n  * [[`ee57e93`](http://github.com/node-modules/hessian.js/commit/ee57e93e580dd4a595cf1098a4f35febfbc6a990)] - feat: support custom decode handler (#119) (zōng yǔ <<gxcsoccer@users.noreply.github.com>>)\n\n**fixes**\n  * [[`3f0b392`](http://github.com/node-modules/hessian.js/commit/3f0b392c58a9b5e65915eca55bc209439ba1e3db)] - fix: should reset _classRefFields (#87) (fengmk2 <<fengmk2@gmail.com>>)\n\n**others**\n  * [[`f71da69`](http://github.com/node-modules/hessian.js/commit/f71da690266f1fb65e6a569ee417996001ded8f1)] - test: fix throws test on node 10 (#110) (fengmk2 <<fengmk2@gmail.com>>)\n\n2.8.1 / 2018-01-18\n==================\n\n**fixes**\n  * [[`b231db0`](http://github.com/dead-horse/hessian.js/commit/b231db01af9379936bd810762a1a0bb1f37cd59c)] - fix: compose cache key with class and fields length (#102) (Yiyu He <<dead_horse@qq.com>>)\n\n2.8.0 / 2018-01-10\n==================\n\n**features**\n  * [[`ce5a7f8`](http://github.com/node-modules/hessian.js/commit/ce5a7f81fb65285f04619d3131872b2325dd92b0)] - feat: support convert java.util.Locale to com.caucho.hessian.io.LocaleHandle (#99) (zōng yǔ <<gxcsoccer@users.noreply.github.com>>)\n\n2.7.0 / 2017-12-26\n==================\n\n**features**\n  * [[`ceaef7b`](http://github.com/dead-horse/hessian.js/commit/ceaef7b169772ad8edb07a5839d830c4789eee1e)] - feat: hessian2 optimize codec (#97) (Hongcai Deng <<admin@dhchouse.com>>)\n\n2.6.0 / 2017-11-16\n==================\n\n**features**\n  * [[`1403a44`](http://github.com/dead-horse/hessian.js/commit/1403a445db7982f35c2b557f13411a9ced4b83e1)] - feat: use byte.getRawStringByStringLength to read utf8 string (#94) (Yiyu He <<dead_horse@qq.com>>)\n\n**fixes**\n  * [[`a7a3f92`](http://github.com/dead-horse/hessian.js/commit/a7a3f9276bc2d5f2bd48006850694b494285c3a4)] - fix: support writeLong parameter is a Long object (#96) (zōng yǔ <<gxcsoccer@users.noreply.github.com>>)\n\n2.5.0 / 2017-11-01\n==================\n\n**features**\n  * [[`4d3b48e`](http://github.com/dead-horse/hessian.js/commit/4d3b48e6e5ed06dca54f2c1dffeb092628b80fbd)] - feat: support cache class for v2/decode (#90) (Yiyu He <<dead_horse@qq.com>>)\n\n2.4.0 / 2017-08-02\n==================\n\n**features**\n  * [[`ab45730`](http://github.com/node-modules/hessian.js/commit/ab457306e0ab6ac28eaa0e93b3478bcb1fbf5108)] - feat: upgrade is-type-of to 1.1.0 (#81) (fengmk2 <<fengmk2@gmail.com>>)\n\n2.3.1 / 2017-07-25\n==================\n\n  * fix: skip regExp & Function property (#77)\n\n2.3.0 / 2017-07-25\n==================\n\n  * feat: map key is object should try to use `name` propery (#78)\n\n2.2.2 / 2017-07-13\n==================\n\n  * fix: package.json to reduce vulnerabilities (#75)\n\n2.2.1 / 2016-08-25\n==================\n\n  * fix: downward compatibility (#71)\n\n2.2.0 / 2016-08-24\n==================\n\n  * feat: support java.util.HashMap to es6 Map (#70)\n\n2.1.9 / 2016-08-24\n==================\n\n  * fix(writeDate): overflow 32-bit signed integer issue\n\n2.1.8 / 2016-04-03\n==================\n\n  * deps: upgrade all deps\n\n2.1.7 / 2016-04-01\n==================\n\n  * fix: remove es6\n  * chore: add examples for test\n  * fix: v2 list encode\n\n2.1.6 / 2016-03-10\n==================\n\n  * lint: remove deprecated rule \"globastrict\", replace with rule \"strict:global\"\n  * fix: donnot use the api of module long introduced in new version, module byte depends on the old version.\n  * fix: output Number.MAX_SAFE_INTEGER as string rather than number. fix #56\n\n2.1.5 / 2016-02-03\n==================\n\n  * fix: fix encode/decode date bug\n\n2.1.4 / 2015-10-12\n==================\n\n  * fix: HashMap & Map is same type\n\n2.1.3 / 2015-10-01\n==================\n\n * test: use npm scripts instead of Makefile\n * test: add undefined test\n * fix: array encode can be null\n\n2.1.2 / 2015-09-10\n==================\n\n * fix: skip innerClass ref field like this$\\d\n\n2.1.1 / 2015-09-06\n==================\n\n  * fix(writeLong) hessian2.0 write long bug\n\n2.1.0 / 2015-08-27\n==================\n\n * test(testcase) fix testcase\n * chore(README) modify README\n * feat(generic) support generic map\n\n2.0.0 / 2015-07-05\n==================\n\n * feat(hessian 2.0) implement hessian 2.0\n\n1.0.4 / 2015-04-09\n==================\n\n * test: add more node version on travis ci\n * test: add encode {$class: \"java.lang.Long\", $: null} => null test case\n * fix(encode) fix object property null issue\n\n1.0.3 / 2015-03-11\n==================\n\n  * fix(decode): toString is not stable.\n  * chore(test): skip large string with v0.11.15\n  * fix(writeObject): should assertType obj.$ when writeObject and add more messge\n  * ignore 0xd800 and 0xdbff char test cases\n\n1.0.2 / 2015-01-29\n==================\n\n * feat(null): writeNull when obj.$ is null\n\n1.0.1 / 2014-08-27\n==================\n\n  * Merge pull request #30 from node-modules/java.lang.Error\n  * support decode java.lang.*Error as js Error\n\n1.0.0 / 2014-08-27\n==================\n\n  * bump byte\n\n0.5.2 / 2014-08-20\n==================\n\n  * Merge pull request #29 from node-modules/exception-bug-fix\n  * only test on node 0.10.28\n  * change badge and add travis coverage\n  * fix exception convert bug\n  * support `java.util.concurrent.atomic.AtomicLong` fix #27\n\n0.5.1 / 2014-06-25\n==================\n\n  * default list and map withType\n\n0.5.0 / 2014-06-25\n==================\n\n  * Merge pull request #26 from node-modules/full-with-type\n  * withType return all type info for v1\n  * add bencmark result link\n\n0.4.2 / 2014-05-15\n==================\n\n  * Merge pull request #24 from node-modules/support-Long\n  * support encode Long instance\n\n0.4.1 / 2014-05-15\n==================\n\n  * Merge pull request #23 from node-modules/cache-class-name\n  * cache class name\n\n0.4.0 / 2014-05-13\n==================\n\n * reuse encoder and add base benchmark\n * fix read object missing with type\n\n0.3.1 / 2014-05-08\n==================\n\n * handle xxxx.HSFException\n * Decode java exception object to js Error object. close #18\n * hessian 2.0 should read hessian 1.0 date format\n * add utf8 test cases\n\n0.3.0 / 2014-04-28\n==================\n\n * hessian 2.0 can decode hessian 1.0 list\n * hessian 2.0 can read hessian 1.0 hashmap\n * hessian 2.0 can decode hessian 1.0 int format\n * hessian 2.0 can decode hessian 1.0 long format\n * fix hessian 2.0 long decode and encode\n * add hessian 1.0 enum, list, map bin test\n * encode string as java hessian 1.0 impl\n * add number bin test\n\n0.2.1 / 2014-04-24\n==================\n\n * fix writeObject 2.0, now Enum as a normal java Object\n * improve enum write in hessian 2.0\n\n0.2.0 / 2014-04-23\n==================\n\n * hessian 2.0 refator\n * refactor readArray\n * encode and decode enum\n * refactor writeObject, writeRef, writeDate\n * refactor hessian writeObject with real java codes\n\n0.1.11 / 2014-04-22\n==================\n\n  * bump byte\n\n0.1.10 / 2014-04-22\n==================\n\n  * fix write array error\n\n0.1.9 / 2014-04-22\n==================\n\n  * fix btypebuffer\n\n0.1.8 / 2014-04-22\n==================\n\n  * support java.lang.Object\n\n0.1.7 / 2014-04-06\n==================\n\n  * support response with int key\n\n0.1.6 / 2014-04-04\n==================\n\n  * fix type?\n\n0.1.5 / 2014-04-04\n==================\n\n  * fix encode array bug\n\n0.1.4 / 2014-04-03\n==================\n\n  * fix no length read array in v1\n  * use is-type-of\n\n0.1.3 / 2014-04-01\n==================\n\n  * fix test in 0.11\n\n0.1.2 / 2014-03-20\n==================\n\n  * remove exports.java, just let people use js-to-java module\n\n0.1.1 / 2014-03-13\n==================\n\n  * Merge pull request #11 from dead-horse/use-is-type-of\n  * use is-type-of to do type check\n  * use badge replace install code\n\n0.1.0 / 2014-02-14\n==================\n\n  * Merge pull request #9 from fengmk2/hessian-v2\n  * encode hessian 2.0 list\n  * encode hessian 2.0 map\n  * add readRefId() to share code logic between v1.0 and v2.0\n  * change decoder switch and if else to hash map code detect\n  * add hessian 2.0 decoder\n  * Support hessian 2.0 encoder.\n  * Support hessian 2.0 decode. #8\n  * fix test\n\n0.0.3 / 2014-02-12\n==================\n\n  * add decoder.position method\n  * update dependencies\n  * fix encode long, read end of buffer\n  * add npm badge\n\n0.0.2 / 2014-01-30\n==================\n\n  * update readme\n  * Merge pull request #6 from fengmk2/compact-types\n  * fix hasOwnProperty was override: `{hasOwnProperty: 1}`\n  * add type list examples: int[] = {0, 1, 2}\n  * Support decode sparse array, @see http://hessian.caucho.com/doc/hessian-1.0-spec.xtp#map fixed #5\n  * support anonymous variable-length list = {0, \"foobar\"}\n  * add binary, date, double, int, list, long, string test cases on hessian 1.0.2\n  * add java base types and each type mapping one test file.\n  * update readme\n  * Merge pull request #1 from fengmk2/more-tests\n  * add readArray error test case\n  * Add more tests and remove assert use TypeError instead.\n  * change name to hessian.js\n  * remove utility\n  * fix typo\n  * add AUTHORS\n\n0.0.1 / 2014-01-27\n==================\n\n  * update readme\n  * add npmignore\n  * complete all the unit test\n  * use get instead of read in readString\n  * add todo\n  * add mocha-lcov-reporter\n  * add fixture.dat\n  * add fixture.dat\n  * add travis\n  * add test\n  * add test for simple type\n  * update readme\n  * add v1 decoder\n  * add readme\n  * fully support simple and complex js object to hessian\n  * v1 encoder simple type done\n  * update byte\n  * use byte to handle the buffer things\n  * Initial commit\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) node-modules and other contributors.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "hessian.js\n=========\n\n[![NPM version][npm-image]][npm-url]\n[![build status][github-action-image]][github-action-url]\n[![Test coverage][codecov-image]][codecov-url]\n[![npm download][download-image]][download-url]\n\n[npm-image]: https://img.shields.io/npm/v/hessian.js.svg?style=flat-square\n[npm-url]: https://npmx.dev/package/hessian.js\n[github-action-image]: https://github.com/node-modules/hessian.js/actions/workflows/nodejs.yml/badge.svg\n[github-action-url]: https://github.com/node-modules/hessian.js/actions/workflows/nodejs.yml\n[codecov-image]: https://codecov.io/github/node-modules/hessian.js/coverage.svg?branch=master\n[codecov-url]: https://codecov.io/github/node-modules/hessian.js?branch=master\n[download-image]: https://img.shields.io/npm/dm/hessian.js.svg?style=flat-square\n[download-url]: https://npmx.dev/package/hessian.js\n\nHessian Serialization [1.0](http://hessian.caucho.com/doc/hessian-1.0-spec.xtp) and\n[2.0](http://hessian.caucho.com/doc/hessian-serialization.html) (base on version [4.0.7](http://mvnrepository.com/artifact/com.caucho/hessian/4.0.7)) written by pure JavaScript.\nSupport all kind of types in Java, with [high performance](benchmark/README.md).\n\n## Install\n\n```bash\n$ npm install hessian.js\n```\n\n## Support Types\n\n8 primitive types:\n\n1. raw binary data\n2. boolean\n3. 64-bit millisecond date\n4. 64-bit double\n5. 32-bit int\n6. 64-bit long\n7. null\n8. UTF8-encoded string\n\n3 recursive types:\n\n1. `list` for lists and arrays\n2. `map` for maps and dictionaries\n3. `object` for objects\n\none special contruct:\n\n1. ref for shared and circular object references\n\nHessian 2.0 has 3 internal reference maps:\n\n* An object/list reference map.\n* An class definition reference map.\n* A type (class name) reference map.\n\n## Encoder\n\nTips: you can use with [js-to-java](https://github.com/node-modules/js-to-java) to help you write java class in js.\n\n### Simple javascript type\n\n```js\nvar hessian = require('hessian.js');\nvar java = require('js-to-java');\nvar encoder = new hessian.Encoder();\n\nencoder.write(1); // int\nencoder.write(1.1); // double\nencoder.write(1e100); // double\nencoder.write(Math.pow(2, 18)); // long\nencoder.write(true); // boolean\nencoder.write(null); // null\nencoder.write('test'); // string\n\n// java base types\nencoder.write(java.long(3001010320)); // 3001010320L\nencoder.write(java.double(100)); // double\nencoder.write(java.array.int([0, 1, 2])); // int[] = {0, 1, 2}\n\nvar object = {};\nobject.prop1 = [1, 2, 3];\nobject.prop2 = 'string';\nobject.prop3 = {key: 'value'};\nobject.prop4 = object;  // circular\nencoder.write(object); // object\n```\n\n### Complex java type\n\n```js\nvar hessian = require('hessian.js');\nvar encoder = new hessian.Encoder();\n\nvar long = {\n  $class: 'java.lang.Long',\n  $: 1\n}\nencoder.write(long); // long type\n\nvar testObject = {\n  $class: 'com.hessian.TestObject',\n  $: {\n    a: 1,\n    b: 'test',\n    c: {$class: 'java.lang.Long', $: 123}\n  }\n};\nencoder.write(testObject);\n```\n\n### Java Generic Map\n\n```js\n// java code:\n// Map<Long, Integer> map = new HashMap<Long, Integer>();\n// map.put(123L, 123456);\n// map.put(123456L, 123);\n\nvar hessian = require('hessian.js');\nvar encoder = new hessian.Encoder();\n\n// using es6 Map\nvar map = new Map();\nmap.set({ '$class': 'java.lang.Long', '$': 123 }, 123456);\nmap.set({ '$class': 'java.lang.Long', '$': 123456 }, 123);\n\nencoder.write(map); // or encoder.write({ '$class': 'java.util.HashMap', '$': map })\n```\n\n### Consistent Java type\n\nIf a type of Class contains a plurality of data, you must ensure that the number of attributes, and each instance of the order is the same!\n\n```\n// Wrong\n\n[\n  {$class: 'com.X', $: {a: 1, b: 2}},\n  {$class: 'com.X', $: {b: 22, a: 11}},\n  {$class: 'com.X', $: {a: 1, b: 2, c: 3}}]\n\n// Right\n\n[\n  {$class: 'com.X', $: {a: 1, b: 2, c: 0}},\n  {$class: 'com.X', $: {a: 11, b: 22, c: 0}},\n  {$class: 'com.X', $: {a: 1, b: 2, c: 3}},\n]\n\n```\n\n\n## Decoder\n\n```js\nvar hessian = require('hessian.js');\nvar decoder = new hessian.Decoder(buf);\n\ndecoder.read(); //return what it is\ndecoder.readNull();\ndecoder.readBool();\ndecoder.readInt();\ndecoder.readLong();\ndecoder.readDouble();\ndecoder.readDate();\ndecoder.readObect();\ndecoder.readMap();\ndecoder.readArray();\ndecoder.readList();\ndecoder.readRef();\n```\n\n## Simple Usage\n\nhessian 1.0:\n\n```js\nvar hessian = require('hessian.js');\n\nvar testObject = {\n  a: 1,\n  b: 'string',\n  c: true,\n  d: 1.1,\n  e: Math.pow(2, 40),\n  f: [1, 2, 3, '4', true, 5],\n  g: {a: 1, b: true, c: 'string'}\n};\n\nvar buf;\ntry {\n  buf = hessian.encode(testObject);\n} catch (err) {\n  console.log('encode error: ', err.message);\n  process.exit(1);\n}\n\ntry {\n  var res = hessian.decode(buf);\n  // res.should.eql(testObject);\n} catch (err) {\n  console.log('decode error: ', err.message);\n}\n```\n\nhessian 2.0:\n\n```js\nvar hessian = require('hessian.js');\n\nvar testObject = {\n  a: 1,\n  b: 'string',\n  c: true,\n  d: 1.1,\n  e: Math.pow(2, 40),\n  f: [1, 2, 3, '4', true, 5],\n  g: {a: 1, b: true, c: 'string'}\n};\n\nvar buf;\ntry {\n  buf = hessian.encode(testObject, '2.0');\n} catch (err) {\n  console.log('encode error: ', err.message);\n  process.exit(1);\n}\n\ntry {\n  var res = hessian.decode(buf, '2.0');\n  // res.should.eql(testObject);\n} catch (err) {\n  console.log('decode error: ', err.message);\n}\n```\n\n## TODO\n\n1. more unit test, include test with other language.\n2. benchmark test.\n3. ~~hessian 2.0 decode~~\n3. ~~hessian 2.0 encode~~\n\n## What's different between hassian 1.0 and 2.0?\n\n* `R` meaning `ref` on 1.0, but `x52 ('R')` represents any non-final string chunk on 2.0\n\n## Hessian 2.0 Serialization Grammar\n\n```\n           # starting production\ntop        ::= value\n\n           # 8-bit binary data split into 64k chunks\nbinary     ::= x41 b1 b0 <binary-data> binary # non-final chunk\n           ::= 'B' b1 b0 <binary-data>        # final chunk\n           ::= [x20-x2f] <binary-data>        # binary data of\n                                                 #  length 0-15\n           ::= [x34-x37] <binary-data>        # binary data of\n                                                 #  length 0-1023\n\n           # boolean true/false\nboolean    ::= 'T'\n           ::= 'F'\n\n           # definition for an object (compact map)\nclass-def  ::= 'C' string int string*\n\n           # time in UTC encoded as 64-bit long milliseconds since\n           #  epoch\ndate       ::= x4a b7 b6 b5 b4 b3 b2 b1 b0\n           ::= x4b b3 b2 b1 b0       # minutes since epoch\n\n           # 64-bit IEEE double\ndouble     ::= 'D' b7 b6 b5 b4 b3 b2 b1 b0\n           ::= x5b                   # 0.0\n           ::= x5c                   # 1.0\n           ::= x5d b0                # byte cast to double\n                                     #  (-128.0 to 127.0)\n           ::= x5e b1 b0             # short cast to double\n           ::= x5f b3 b2 b1 b0       # 32-bit float cast to double\n\n           # 32-bit signed integer\nint        ::= 'I' b3 b2 b1 b0\n           ::= [x80-xbf]             # -x10 to x3f\n           ::= [xc0-xcf] b0          # -x800 to x7ff\n           ::= [xd0-xd7] b1 b0       # -x40000 to x3ffff\n\n           # list/vector\nlist       ::= x55 type value* 'Z'   # variable-length list\n           ::= 'V' type int value*   # fixed-length list\n           ::= x57 value* 'Z'        # variable-length untyped list\n           ::= x58 int value*        # fixed-length untyped list\n           ::= [x70-77] type value*  # fixed-length typed list\n           ::= [x78-7f] value*       # fixed-length untyped list\n\n           # 64-bit signed long integer\nlong       ::= 'L' b7 b6 b5 b4 b3 b2 b1 b0\n           ::= [xd8-xef]             # -x08 to x0f\n           ::= [xf0-xff] b0          # -x800 to x7ff\n           ::= [x38-x3f] b1 b0       # -x40000 to x3ffff\n           ::= x59 b3 b2 b1 b0       # 32-bit integer cast to long\n\n           # map/object\nmap        ::= 'M' type (value value)* 'Z'  # key, value map pairs\n           ::= 'H' (value value)* 'Z'       # untyped key, value\n\n           # null value\nnull       ::= 'N'\n\n           # Object instance\nobject     ::= 'O' int value*\n           ::= [x60-x6f] value*\n\n           # value reference (e.g. circular trees and graphs)\nref        ::= x51 int            # reference to nth map/list/object\n\n           # UTF-8 encoded character string split into 64k chunks\nstring     ::= x52 b1 b0 <utf8-data> string  # non-final chunk\n           ::= 'S' b1 b0 <utf8-data>         # string of length\n                                             #  0-65535\n           ::= [x00-x1f] <utf8-data>         # string of length\n                                             #  0-31\n           ::= [x30-x34] <utf8-data>         # string of length\n                                             #  0-1023\n\n           # map/list types for OO languages\ntype       ::= string                        # type name\n           ::= int                           # type reference\n\n           # main production\nvalue      ::= null\n           ::= binary\n           ::= boolean\n           ::= class-def value\n           ::= date\n           ::= double\n           ::= int\n           ::= list\n           ::= long\n           ::= map\n           ::= object\n           ::= ref\n           ::= string\n```\n\n## Hessian 2.0 Bytecode map\n\nHessian 2.0 is organized as a bytecode protocol.\nA Hessian reader is essentially a switch statement on the initial octet.\n\n```\nx00 - x1f    # utf-8 string length 0-32\nx20 - x2f    # binary data length 0-16\nx30 - x33    # utf-8 string length 0-1023\nx34 - x37    # binary data length 0-1023\nx38 - x3f    # three-octet compact long (-x40000 to x3ffff)\nx40          # reserved (expansion/escape)\nx41          # 8-bit binary data non-final chunk ('A')\nx42          # 8-bit binary data final chunk ('B')\nx43          # object type definition ('C')\nx44          # 64-bit IEEE encoded double ('D')\nx45          # reserved\nx46          # boolean false ('F')\nx47          # reserved\nx48          # untyped map ('H')\nx49          # 32-bit signed integer ('I')\nx4a          # 64-bit UTC millisecond date\nx4b          # 32-bit UTC minute date\nx4c          # 64-bit signed long integer ('L')\nx4d          # map with type ('M')\nx4e          # null ('N')\nx4f          # object instance ('O')\nx50          # reserved\nx51          # reference to map/list/object - integer ('Q')\nx52          # utf-8 string non-final chunk ('R')\nx53          # utf-8 string final chunk ('S')\nx54          # boolean true ('T')\nx55          # variable-length list/vector ('U')\nx56          # fixed-length list/vector ('V')\nx57          # variable-length untyped list/vector ('W')\nx58          # fixed-length untyped list/vector ('X')\nx59          # long encoded as 32-bit int ('Y')\nx5a          # list/map terminator ('Z')\nx5b          # double 0.0\nx5c          # double 1.0\nx5d          # double represented as byte (-128.0 to 127.0)\nx5e          # double represented as short (-32768.0 to 327676.0)\nx5f          # double represented as float\nx60 - x6f    # object with direct type (` ... n, o)\nx70 - x77    # fixed list with direct length (p, q, r, s, t, u, v, w)\nx78 - x7f    # fixed untyped list with direct length (x, y, z, {, |, }, ~, .....)\nx80 - xbf    # one-octet compact int (-x10 to x3f, x90 is 0)\nxc0 - xcf    # two-octet compact int (-x800 to x7ff)\nxd0 - xd7    # three-octet compact int (-x40000 to x3ffff)\nxd8 - xef    # one-octet compact long (-x8 to xf, xe0 is 0)\nxf0 - xff    # two-octet compact long (-x800 to x7ff, xf8 is 0)\n```\n\n## About Hessian 2.0 Optimized Decoder\nHessian 2.0 introduced [ref](http://hessian.caucho.com/doc/hessian-serialization.html##ref) to avoid sending duplicated class definition in the same context. Actully, the `context` can promote to `connection` level in some RPC framework. For example, [EADS](https://www.aliyun.com/product/edas), Requests using the same connection will not change their class definition.\n\n## Licences\n\n[MIT](LICENSE)\n<!-- GITCONTRIBUTOR_START -->\n\n## Contributors\n\n|[<img src=\"https://avatars.githubusercontent.com/u/985607?v=4\" width=\"100px;\"/><br/><sub><b>dead-horse</b></sub>](https://github.com/dead-horse)<br/>|[<img src=\"https://avatars.githubusercontent.com/u/156269?v=4\" width=\"100px;\"/><br/><sub><b>fengmk2</b></sub>](https://github.com/fengmk2)<br/>|[<img src=\"https://avatars.githubusercontent.com/u/1207064?v=4\" width=\"100px;\"/><br/><sub><b>gxcsoccer</b></sub>](https://github.com/gxcsoccer)<br/>|[<img src=\"https://avatars.githubusercontent.com/u/1433247?v=4\" width=\"100px;\"/><br/><sub><b>denghongcai</b></sub>](https://github.com/denghongcai)<br/>|[<img src=\"https://avatars.githubusercontent.com/u/340282?v=4\" width=\"100px;\"/><br/><sub><b>fool2fish</b></sub>](https://github.com/fool2fish)<br/>|[<img src=\"https://avatars.githubusercontent.com/u/1400114?v=4\" width=\"100px;\"/><br/><sub><b>coolme200</b></sub>](https://github.com/coolme200)<br/>|\n| :---: | :---: | :---: | :---: | :---: | :---: |\n[<img src=\"https://avatars.githubusercontent.com/u/327019?v=4\" width=\"100px;\"/><br/><sub><b>JacksonTian</b></sub>](https://github.com/JacksonTian)<br/>|[<img src=\"https://avatars.githubusercontent.com/u/1681459?v=4\" width=\"100px;\"/><br/><sub><b>xusiyuan841028</b></sub>](https://github.com/xusiyuan841028)<br/>|[<img src=\"https://avatars.githubusercontent.com/u/19733683?v=4\" width=\"100px;\"/><br/><sub><b>snyk-bot</b></sub>](https://github.com/snyk-bot)<br/>\n\nThis project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Sun Apr 16 2023 15:34:56 GMT+0800`.\n\n<!-- GITCONTRIBUTOR_END -->\n"
  },
  {
    "path": "benchmark/README.md",
    "content": "benchmark result\n----------\n\n```\nnode benchmark/encode.js\n\n  Hessian Encode Benchmark\n  node version: v0.11.12, date: Tue May 27 2014 11:30:03 GMT+0800 (CST)\n  Starting...\n  16 tests completed.\n\n  hessian1 encode: number         x 1,669,884 ops/sec ±1.38% (93 runs sampled)\n  hessian2 encode: number         x 1,893,674 ops/sec ±0.74% (96 runs sampled)\n  hessian1 encode: date           x   834,286 ops/sec ±1.40% (91 runs sampled)\n  hessian2 encode: date           x   789,740 ops/sec ±1.06% (95 runs sampled)\n  hessian1 encode: long           x   646,034 ops/sec ±0.89% (95 runs sampled)\n  hessian2 encode: long           x   643,354 ops/sec ±1.60% (88 runs sampled)\n  hessian1 encode: string         x   955,180 ops/sec ±1.19% (96 runs sampled)\n  hessian2 encode: string         x 1,006,919 ops/sec ±1.22% (93 runs sampled)\n  hessian1 encode: [1, 2, 3]      x   536,860 ops/sec ±0.85% (94 runs sampled)\n  hessian2 encode: [1, 2, 3]      x   615,294 ops/sec ±0.93% (95 runs sampled)\n  hessian1 encode array           x   377,167 ops/sec ±0.85% (95 runs sampled)\n  hessian2 encode array           x   403,383 ops/sec ±0.94% (91 runs sampled)\n  hessian1 encode: simple object  x   146,367 ops/sec ±1.67% (93 runs sampled)\n  hessian2 encode: simple object  x   147,188 ops/sec ±1.81% (94 runs sampled)\n  hessian1 encode: complex object x    95,309 ops/sec ±1.40% (91 runs sampled)\n  hessian2 encode: complex object x    95,851 ops/sec ±1.20% (96 runs sampled)\n\n\n  Hessian Decode Benchmark\n  node version: v0.11.12, date: Tue May 27 2014 11:31:30 GMT+0800 (CST)\n  Starting...\n  16 tests completed.\n\n  hessian1 decode: number         x 5,915,496 ops/sec ±0.73% (98 runs sampled)\n  hessian2 decode: number         x 5,838,371 ops/sec ±2.66% (90 runs sampled)\n  hessian1 decode: date           x 2,958,136 ops/sec ±1.87% (91 runs sampled)\n  hessian2 decode: date           x 2,721,653 ops/sec ±0.81% (97 runs sampled)\n  hessian1 decode: long           x 4,076,127 ops/sec ±0.83% (93 runs sampled)\n  hessian2 decode: long           x 5,400,659 ops/sec ±1.26% (93 runs sampled)\n  hessian1 decode: string         x 1,067,996 ops/sec ±2.20% (91 runs sampled)\n  hessian2 decode: string         x 1,133,082 ops/sec ±1.04% (93 runs sampled)\n  hessian1 decode: [1, 2, 3]      x 1,201,908 ops/sec ±1.26% (91 runs sampled)\n  hessian2 decode: [1, 2, 3]      x 1,915,498 ops/sec ±1.66% (95 runs sampled)\n  hessian1 decode array           x   505,896 ops/sec ±1.13% (93 runs sampled)\n  hessian2 decode array           x   616,792 ops/sec ±0.79% (98 runs sampled)\n  hessian1 decode: simple object  x   194,474 ops/sec ±0.87% (97 runs sampled)\n  hessian2 decode: simple object  x   177,599 ops/sec ±0.97% (96 runs sampled)\n  hessian1 decode: complex object x   139,387 ops/sec ±0.83% (97 runs sampled)\n  hessian2 decode: complex object x   139,213 ops/sec ±0.58% (99 runs sampled)\n  ```\n"
  },
  {
    "path": "benchmark/cache.js",
    "content": "'use strict';\n\nvar Benchmark = require('benchmark');\nvar benchmarks = require('beautify-benchmark');\nvar path = require('path');\nvar fs = require('fs');\nvar assert = require('assert');\nvar hessian = require('../');\n\n\nvar buf = fs.readFileSync(path.join(__dirname, 'buf.txt'));\nvar cache = new Map();\n\nassert.deepEqual(hessian.decode(buf, '2.0', { classCache: cache }), hessian.decode(buf, '2.0'));\nassert.deepEqual(hessian.decode(buf, '2.0', { classCache: cache }), hessian.decode(buf, '2.0'));\nvar suite = new Benchmark.Suite();\n\nsuite\n\n.add('with cache', function() {\n  hessian.decode(buf, '2.0', { classCache: cache });\n})\n.add('without cache', function() {\n  hessian.decode(buf, '2.0');\n})\n\n.on('cycle', function(event) {\n  benchmarks.add(event.target);\n})\n.on('start', function(event) {\n  console.log('\\n  Cache Benchmark\\n  node version: %s, date: %s\\n  Starting...',\n    process.version, Date());\n})\n.on('complete', function done() {\n  benchmarks.log();\n})\n.run({ 'async': false });\n\n// Cache Benchmark\n// node version: v8.9.0, date: Thu Nov 16 2017 13:30:47 GMT+0800 (CST)\n// Starting...\n// 2 tests completed.\n//\n// with cache    x 19,947 ops/sec ±3.81% (80 runs sampled)\n// without cache x  8,360 ops/sec ±1.38% (87 runs sampled)\n"
  },
  {
    "path": "benchmark/decode.js",
    "content": "'use strict';\n\nvar ByteBuffer = require('byte');\nvar Benchmark = require('benchmark');\nvar benchmarks = require('beautify-benchmark');\nvar java = require('js-to-java');\nvar hessian = require('../');\n\nvar suite = new Benchmark.Suite();\n\nvar simpleObject = {\n  $class: 'com.hessiantest.org.MockRequest',\n  $: {\n    id: 123,\n    name: 'getData',\n    args: [1, \"name\", \"xxx1231231231231xxx123\"]\n  }\n};\n\nvar simpleObjectBuf1 = hessian.encode(simpleObject, '1.0');\nvar simpleObjectBuf2 = hessian.encode(simpleObject, '2.0');\n\nvar complexObject = {\n  $class: 'com.hessiantest.org.MockRequest',\n  $: {\n    id: 123,\n    name: 'getData',\n    args: [1, \"name\", \"xxx1231231231231xxx123\"],\n    conn: {\n      $class: 'com.hessiantest.org.MockRequestConnection',\n      $: {\n        ctx: java.long(1024)\n      }\n    }\n  }\n};\n\nvar complexObjectBuf1 = hessian.encode(complexObject, '1.0');\nvar complexObjectBuf2 = hessian.encode(complexObject, '2.0');\n\nvar number1Buf1 = hessian.encode(1, '1.0');\nvar number1Buf2 = hessian.encode(1, '2.0');\n\nvar dateBuf1 = hessian.encode(new Date(), '1.0');\nvar dateBuf2 = hessian.encode(new Date(), '2.0');\n\nvar longBuf1 = hessian.encode(java.long(300), '1.0');\nvar longBuf2 = hessian.encode(java.long(300), '2.0');\n\nvar stringBuf1 = hessian.encode('xxx1231231231231xxx123', '1.0');\nvar stringBuf2 = hessian.encode('xxx1231231231231xxx123', '2.0');\n\nvar arrBuf1 = hessian.encode([1, 2, 3], '1.0');\nvar arrBuf2 = hessian.encode([1, 2, 3], '2.0');\n\nvar arrObjectBuf1 = hessian.encode([1, \"name\", \"xxx1231231231231xxx123\"], '1.0');\nvar arrObjectBuf2 = hessian.encode([1, \"name\", \"xxx1231231231231xxx123\"], '2.0');\n\nsuite\n\n.add('hessian1 decode: number', function() {\n  hessian.decode(number1Buf1, '1.0');\n})\n.add('hessian2 decode: number', function() {\n  hessian.decode(number1Buf2, '2.0');\n})\n\n.add('hessian1 decode: date', function() {\n  hessian.decode(dateBuf1, '1.0');\n})\n.add('hessian2 decode: date', function() {\n  hessian.decode(dateBuf2, '2.0');\n})\n\n.add('hessian1 decode: long', function() {\n  hessian.decode(longBuf1, '1.0');\n})\n.add('hessian2 decode: long', function() {\n  hessian.decode(longBuf2, '2.0');\n})\n\n.add('hessian1 decode: string', function() {\n  hessian.decode(stringBuf1, '1.0');\n})\n.add('hessian2 decode: string', function() {\n  hessian.decode(stringBuf2, '2.0');\n})\n\n.add('hessian1 decode: [1, 2, 3]', function() {\n  hessian.decode(arrBuf1, '1.0');\n})\n.add('hessian2 decode: [1, 2, 3]', function() {\n  hessian.decode(arrBuf2, '2.0');\n})\n.add('hessian1 decode array', function() {\n  hessian.decode(arrObjectBuf1, '1.0');\n})\n.add('hessian2 decode array', function() {\n  hessian.decode(arrObjectBuf2, '2.0');\n})\n\n.add('hessian1 decode: simple object', function() {\n  hessian.decode(simpleObjectBuf1, '1.0');\n})\n.add('hessian2 decode: simple object', function() {\n  hessian.decode(simpleObjectBuf2, '2.0');\n})\n\n.add('hessian1 decode: complex object', function() {\n  hessian.decode(complexObjectBuf1, '1.0');\n})\n.add('hessian2 decode: complex object', function() {\n  hessian.decode(complexObjectBuf2, '2.0');\n})\n.add('hessian1 decode with type: number', function() {\n  hessian.decode(number1Buf1, '1.0', true);\n})\n.add('hessian2 decode with type: number', function() {\n  hessian.decode(number1Buf2, '2.0', true);\n})\n\n.add('hessian1 decode with type: date', function() {\n  hessian.decode(dateBuf1, '1.0', true);\n})\n.add('hessian2 decode with type: date', function() {\n  hessian.decode(dateBuf2, '2.0', true);\n})\n\n.add('hessian1 decode with type: long', function() {\n  hessian.decode(longBuf1, '1.0', true);\n})\n.add('hessian2 decode with type: long', function() {\n  hessian.decode(longBuf2, '2.0', true);\n})\n\n.add('hessian1 decode with type: string', function() {\n  hessian.decode(stringBuf1, '1.0', true);\n})\n.add('hessian2 decode with type: string', function() {\n  hessian.decode(stringBuf2, '2.0', true);\n})\n\n.add('hessian1 decode with type: [1, 2, 3]', function() {\n  hessian.decode(arrBuf1, '1.0', true);\n})\n.add('hessian2 decode with type: [1, 2, 3]', function() {\n  hessian.decode(arrBuf2, '2.0', true);\n})\n.add('hessian1 decode with type array', function() {\n  hessian.decode(arrObjectBuf1, '1.0', true);\n})\n.add('hessian2 decode with type array', function() {\n  hessian.decode(arrObjectBuf2, '2.0', true);\n})\n\n.add('hessian1 decode with type: simple object', function() {\n  hessian.decode(simpleObjectBuf1, '1.0', true);\n})\n.add('hessian2 decode with type: simple object', function() {\n  hessian.decode(simpleObjectBuf2, '2.0', true);\n})\n\n.add('hessian1 decode with type: complex object', function() {\n  hessian.decode(complexObjectBuf1, '1.0', true);\n})\n.add('hessian2 decode with type: complex object', function() {\n  hessian.decode(complexObjectBuf2, '2.0', true);\n})\n\n.on('cycle', function(event) {\n  benchmarks.add(event.target);\n})\n.on('start', function(event) {\n  console.log('\\n  Hessian Decode Benchmark\\n  node version: %s, date: %s\\n  Starting...',\n    process.version, Date());\n})\n.on('complete', function done() {\n  benchmarks.log();\n})\n.run({ 'async': false });\n\n// Hessian Decode Benchmark\n// node version: v8.9.0, date: Thu Nov 16 2017 13:31:15 GMT+0800 (CST)\n// Starting...\n// 32 tests completed.\n//\n// hessian1 decode: number                   x 6,546,954 ops/sec ±1.41% (87 runs sampled)\n// hessian2 decode: number                   x 6,247,164 ops/sec ±2.10% (84 runs sampled)\n// hessian1 decode: date                     x 2,378,658 ops/sec ±2.29% (86 runs sampled)\n// hessian2 decode: date                     x 2,378,814 ops/sec ±1.71% (84 runs sampled)\n// hessian1 decode: long                     x 3,669,483 ops/sec ±1.88% (85 runs sampled)\n// hessian2 decode: long                     x 6,125,751 ops/sec ±1.13% (81 runs sampled)\n// hessian1 decode: string                   x 2,123,485 ops/sec ±1.26% (88 runs sampled)\n// hessian2 decode: string                   x 1,968,578 ops/sec ±1.53% (86 runs sampled)\n// hessian1 decode: [1, 2, 3]                x 1,292,327 ops/sec ±3.02% (83 runs sampled)\n// hessian2 decode: [1, 2, 3]                x 1,463,036 ops/sec ±2.95% (82 runs sampled)\n// hessian1 decode array                     x   764,305 ops/sec ±1.10% (85 runs sampled)\n// hessian2 decode array                     x   819,871 ops/sec ±4.13% (85 runs sampled)\n// hessian1 decode: simple object            x   225,427 ops/sec ±1.02% (87 runs sampled)\n// hessian2 decode: simple object            x   206,072 ops/sec ±1.41% (85 runs sampled)\n// hessian1 decode: complex object           x   139,136 ops/sec ±2.46% (86 runs sampled)\n// hessian2 decode: complex object           x   132,702 ops/sec ±3.12% (80 runs sampled)\n// hessian1 decode with type: number         x 4,971,071 ops/sec ±1.97% (83 runs sampled)\n// hessian2 decode with type: number         x 6,165,893 ops/sec ±1.59% (86 runs sampled)\n// hessian1 decode with type: date           x 2,205,802 ops/sec ±1.86% (85 runs sampled)\n// hessian2 decode with type: date           x 2,290,528 ops/sec ±2.34% (86 runs sampled)\n// hessian1 decode with type: long           x 3,340,413 ops/sec ±1.27% (86 runs sampled)\n// hessian2 decode with type: long           x 6,072,529 ops/sec ±0.94% (89 runs sampled)\n// hessian1 decode with type: string         x 1,986,114 ops/sec ±1.30% (86 runs sampled)\n// hessian2 decode with type: string         x 2,074,055 ops/sec ±0.97% (88 runs sampled)\n// hessian1 decode with type: [1, 2, 3]      x 1,026,832 ops/sec ±1.26% (86 runs sampled)\n// hessian2 decode with type: [1, 2, 3]      x 1,565,525 ops/sec ±1.06% (87 runs sampled)\n// hessian1 decode with type array           x   632,280 ops/sec ±4.27% (80 runs sampled)\n// hessian2 decode with type array           x   876,049 ops/sec ±2.26% (86 runs sampled)\n// hessian1 decode with type: simple object  x   189,740 ops/sec ±3.36% (82 runs sampled)\n// hessian2 decode with type: simple object  x   238,079 ops/sec ±1.85% (84 runs sampled)\n// hessian1 decode with type: complex object x   130,701 ops/sec ±2.27% (87 runs sampled)\n// hessian2 decode with type: complex object x   160,600 ops/sec ±1.63% (87 runs sampled)\n"
  },
  {
    "path": "benchmark/encode.js",
    "content": "'use strict';\n\nvar ByteBuffer = require('byte');\nvar Benchmark = require('benchmark');\nvar benchmarks = require('beautify-benchmark');\nvar java = require('js-to-java');\nvar hessian = require('../');\n\nvar suite = new Benchmark.Suite();\n\nvar simpleObject = {\n  $class: 'com.hessiantest.org.MockRequest',\n  $: {\n    id: 123,\n    name: 'getData',\n    args: [1, \"name\", \"xxx1231231231231xxx123\"]\n  }\n};\n\nvar complexObject = {\n  $class: 'com.hessiantest.org.MockRequest',\n  $: {\n    id: 123,\n    name: 'getData',\n    args: [1, \"name\", \"xxx1231231231231xxx123\"],\n    conn: {\n      $class: 'com.hessiantest.org.MockRequestConnection',\n      $: {\n        ctx: java.long(1024)\n      }\n    }\n  }\n};\n\nsuite\n\n.add('hessian1 encode: number', function() {\n  hessian.encode(1, '1.0');\n})\n.add('hessian2 encode: number', function() {\n  hessian.encode(1, '2.0');\n})\n\n.add('hessian1 encode: date', function() {\n  hessian.encode(new Date(), '1.0');\n})\n.add('hessian2 encode: date', function() {\n  hessian.encode(new Date(), '2.0');\n})\n\n.add('hessian1 encode: long', function() {\n  hessian.encode(java.long(300), '1.0');\n})\n.add('hessian2 encode: long', function() {\n  hessian.encode(java.long(300), '2.0');\n})\n\n.add('hessian1 encode: string', function() {\n  hessian.encode('xxx1231231231231xxx123', '1.0');\n})\n.add('hessian2 encode: string', function() {\n  hessian.encode('xxx1231231231231xxx123', '2.0');\n})\n\n.add('hessian1 encode: [1, 2, 3]', function() {\n  hessian.encode([1, 2, 3], '1.0');\n})\n.add('hessian2 encode: [1, 2, 3]', function() {\n  hessian.encode([1, 2, 3], '2.0');\n})\n.add('hessian1 encode array', function() {\n  hessian.encode([1, \"name\", \"xxx1231231231231xxx123\"], '1.0');\n})\n.add('hessian2 encode array', function() {\n  hessian.encode([1, \"name\", \"xxx1231231231231xxx123\"], '2.0');\n})\n\n.add('hessian1 encode: simple object', function() {\n  hessian.encode(simpleObject, '1.0');\n})\n.add('hessian2 encode: simple object', function() {\n  hessian.encode(simpleObject, '2.0');\n})\n\n.add('hessian1 encode: complex object', function() {\n  hessian.encode(complexObject, '1.0');\n})\n.add('hessian2 encode: complex object', function() {\n  hessian.encode(complexObject, '2.0');\n})\n\n.on('cycle', function(event) {\n  benchmarks.add(event.target);\n})\n.on('start', function(event) {\n  console.log('\\n  Hessian Encode Benchmark\\n  node version: %s, date: %s\\n  Starting...',\n    process.version, Date());\n})\n.on('complete', function done() {\n  benchmarks.log();\n})\n.run({ 'async': false });\n\n// node version: v0.11.12, date: Tue May 13 2014 10:30:18 GMT+0800 (CST)\n// Starting...\n// 16 tests completed.\n//\n// hessian1 encode: number         x 1,262,878 ops/sec ±10.80% (74 runs sampled)\n// hessian2 encode: number         x 1,816,722 ops/sec ±2.34% (92 runs sampled)\n// hessian1 encode: date           x   766,202 ops/sec ±3.90% (90 runs sampled)\n// hessian2 encode: date           x   673,284 ops/sec ±4.78% (83 runs sampled)\n// hessian1 encode: long           x   650,132 ops/sec ±1.48% (96 runs sampled)\n// hessian2 encode: long           x   636,692 ops/sec ±3.49% (88 runs sampled)\n// hessian1 encode: string         x   804,401 ops/sec ±6.48% (79 runs sampled)\n// hessian2 encode: string         x   967,111 ops/sec ±3.15% (88 runs sampled)\n// hessian1 encode: [1, 2, 3]      x   525,540 ops/sec ±2.36% (92 runs sampled)\n// hessian2 encode: [1, 2, 3]      x   623,072 ops/sec ±2.27% (97 runs sampled)\n// hessian1 encode array           x   318,811 ops/sec ±8.70% (82 runs sampled)\n// hessian2 encode array           x   396,659 ops/sec ±3.12% (92 runs sampled)\n// hessian1 encode: simple object  x   101,458 ops/sec ±9.30% (67 runs sampled)\n// hessian2 encode: simple object  x   132,938 ops/sec ±3.23% (89 runs sampled)\n// hessian1 encode: complex object x    90,243 ops/sec ±2.08% (93 runs sampled)\n// hessian2 encode: complex object x    80,702 ops/sec ±5.94% (86 runs sampled)\n\n// node version: v0.11.12, date: Wed May 14 2014 18:47:59 GMT+0800 (CST)\n// Starting...\n// 16 tests completed.\n//\n// hessian1 encode: number         x 1,601,925 ops/sec ±2.57% (89 runs sampled)\n// hessian2 encode: number         x 1,800,237 ops/sec ±1.90% (93 runs sampled)\n// hessian1 encode: date           x   773,461 ops/sec ±2.22% (88 runs sampled)\n// hessian2 encode: date           x   703,063 ops/sec ±4.90% (86 runs sampled)\n// hessian1 encode: long           x   555,507 ops/sec ±4.36% (87 runs sampled)\n// hessian2 encode: long           x   598,983 ops/sec ±3.26% (86 runs sampled)\n// hessian1 encode: string         x   911,037 ops/sec ±2.50% (95 runs sampled)\n// hessian2 encode: string         x 1,013,393 ops/sec ±1.75% (92 runs sampled)\n// hessian1 encode: [1, 2, 3]      x   520,715 ops/sec ±1.55% (91 runs sampled)\n// hessian2 encode: [1, 2, 3]      x   552,279 ops/sec ±3.97% (86 runs sampled)\n// hessian1 encode array           x   377,503 ops/sec ±1.40% (94 runs sampled)\n// hessian2 encode array           x   403,264 ops/sec ±3.10% (93 runs sampled)\n// hessian1 encode: simple object  x   132,363 ops/sec ±5.80% (83 runs sampled)\n// hessian2 encode: simple object  x   138,711 ops/sec ±3.52% (89 runs sampled)\n// hessian1 encode: complex object x    94,401 ops/sec ±1.15% (90 runs sampled)\n// hessian2 encode: complex object x    90,484 ops/sec ±1.33% (97 runs sampled)\n\n// node version: v0.11.12, date: Thu May 15 2014 18:13:05 GMT+0800 (CST)\n// Starting...\n// 16 tests completed.\n//\n// hessian1 encode: number         x 1,553,553 ops/sec ±3.58% (92 runs sampled)\n// hessian2 encode: number         x 1,895,587 ops/sec ±0.63% (97 runs sampled)\n// hessian1 encode: date           x   599,048 ops/sec ±0.58% (98 runs sampled)\n// hessian2 encode: date           x   562,479 ops/sec ±1.76% (93 runs sampled)\n// hessian1 encode: long           x   498,383 ops/sec ±0.69% (98 runs sampled)\n// hessian2 encode: long           x   672,058 ops/sec ±1.20% (96 runs sampled)\n// hessian1 encode: string         x   980,671 ops/sec ±2.19% (97 runs sampled)\n// hessian2 encode: string         x 1,041,627 ops/sec ±0.70% (93 runs sampled)\n// hessian1 encode: [1, 2, 3]      x   538,953 ops/sec ±2.54% (92 runs sampled)\n// hessian2 encode: [1, 2, 3]      x   631,285 ops/sec ±0.36% (99 runs sampled)\n// hessian1 encode array           x   389,785 ops/sec ±0.51% (98 runs sampled)\n// hessian2 encode array           x   408,655 ops/sec ±2.37% (97 runs sampled)\n// hessian1 encode: simple object  x   161,088 ops/sec ±0.84% (97 runs sampled)\n// hessian2 encode: simple object  x   155,580 ops/sec ±0.82% (98 runs sampled)\n// hessian1 encode: complex object x   103,974 ops/sec ±1.34% (96 runs sampled)\n// hessian2 encode: complex object x   100,160 ops/sec ±1.18% (101 runs sampled)\n"
  },
  {
    "path": "benchmark/reg.js",
    "content": "'use strict';\n\nvar Benchmark = require('benchmark');\nvar benchmarks = require('beautify-benchmark');\n\nvar suite = new Benchmark.Suite();\n\n\nvar INNER_CLASS_PROPERTY_REG = /^this\\$\\d+$/;\nvar INNER_CLASS_LABEL = '$$ignore_inner_property$$';\n\nvar name1 = 'foobar';\nvar name2 = 'this$123';\nvar name3 = INNER_CLASS_LABEL;\n\nsuite\n\n.add('dynamic', function() {\n  /^this\\$\\d+/.test(name1);\n  /^this\\$\\d+/.test(name2);\n})\n.add('static', function() {\n  INNER_CLASS_PROPERTY_REG.test(name1);\n  INNER_CLASS_PROPERTY_REG.test(name2);\n})\n.add('equal', function() {\n  name1 === INNER_CLASS_LABEL;\n  name3 === INNER_CLASS_LABEL;\n})\n\n.on('cycle', function(event) {\n  benchmarks.add(event.target);\n})\n.on('start', function(event) {\n  console.log('\\n  Reg Benchmark\\n  node version: %s, date: %s\\n  Starting...',\n    process.version, Date());\n})\n.on('complete', function done() {\n  benchmarks.log();\n})\n.run({ 'async': false });\n\n// node version: v8.5.0, date: Sat Oct 21 2017 08:00:33 GMT+0800 (CST)\n// Starting...\n// 3 tests completed.\n//\n// dynamic x   8,355,274 ops/sec ±1.00% (85 runs sampled)\n// static  x  10,547,340 ops/sec ±0.90% (89 runs sampled)\n// equal   x 488,054,083 ops/sec ±0.67% (88 runs sampled)\n"
  },
  {
    "path": "benchmark/string.js",
    "content": "'use strict';\n\nconst Benchmark = require('benchmark');\nconst benchmarks = require('beautify-benchmark');\nconst assert = require('assert');\n\nconst ByteBuffer = require('byte');\nconst io = ByteBuffer.allocate(1024 * 1024);\n\nconst str = '1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234';\nio.putRawString(str);\nconst buf = io.array();\n\n// io.position(0);\n// console.log(io.getRawStringByStringLength(1024));\n// console.log(buf.toString());\n\nio.position(0);\nassert(io.getRawStringByStringLength(1024) === buf.toString());\n\nfunction getUTF(buf) {\n  const data = [];\n  const length = buf.length;\n  for (let i = 0; i < length; i++) {\n    const ch = buf[i];\n    if (ch < 0x80) {\n      data.push(ch);\n    } else if ((ch & 0xe0) === 0xc0) {\n      const ch1 = buf[++i];\n      const v = ((ch & 0x1f) << 6) + (ch1 & 0x3f);\n      data.push(v);\n    } else if ((ch & 0xf0) === 0xe0) {\n      const ch1 = buf[++i];\n      const ch2 = buf[++i];\n      const v = ((ch & 0x0f) << 12) + ((ch1 & 0x3f) << 6) + (ch2 & 0x3f);\n      data.push(v);\n    } else {\n      throw new Error('string is not valid UTF-8 encode');\n    }\n  }\n  return String.fromCharCode.apply(String, data);\n}\n\nassert(getUTF(buf) === buf.toString());\n\n\nfunction getUTF2(buf) {\n  const length = buf.length;\n  const data = [];\n  let start = 0;\n  const numInts = length >> 2;\n  for (let i = 0; i < numInts; i++) {\n    const num = buf.readInt32BE(i * 4);\n    if ((num & 0x80808080) !== 0) {\n      throw new Error();\n    }\n  }\n  const offset = start + length;\n  return buf.toString('utf8', 0, offset);\n\n  // while (i < length) {\n  //   const num = buf.readInt32BE(i);\n  //   if ((num & 0x80808080) === 0) {\n  //     data.push(buf[i]);\n  //     data.push(buf[i + 1]);\n  //     data.push(buf[i + 2]);\n  //     data.push(buf[i + 3]);\n  //     i += 4;\n  //   } else {\n  //     assert(false);\n  //   }\n  // }\n  // return String.fromCharCode.apply(String, data);\n}\n\nassert(getUTF2(buf) === buf.toString());\nio.position(0);\nassert(io.getRawStringFast(1024) === buf.toString());\n\nconst suite = new Benchmark.Suite();\nsuite\n  .add('io.getRawStringByStringLength', function() {\n    io._offset = 0;\n    io.getRawStringByStringLength(1024);\n  })\n  .add('io.getRawStringFast', function() {\n    io._offset = 0;\n    io.getRawStringFast(1024);\n  })\n  .add('buf.toString', function() {\n    buf.toString();\n  })\n  .add('getUTF', function() {\n    getUTF(buf);\n  })\n  .add('getUTF2', function() {\n    getUTF2(buf);\n  })\n  .on('cycle', function(event) {\n    benchmarks.add(event.target);\n  })\n  .on('start', function(event) {\n    console.log('\\n  Cache Benchmark\\n  node version: %s, date: %s\\n  Starting...',\n      process.version, Date());\n  })\n  .on('complete', function done() {\n    benchmarks.log();\n  })\n  .run({ 'async': false });\n\n// Cache Benchmark\n// node version: v8.9.0, date: Thu Nov 16 2017 13:26:18 GMT+0800 (CST)\n// Starting...\n// 2 tests completed.\n//\n// with cache    x 21,724 ops/sec ±2.01% (82 runs sampled)\n// without cache x  8,523 ops/sec ±1.17% (89 runs sampled)\n"
  },
  {
    "path": "index.js",
    "content": "'use strict';\n\nvar EncoderV1 = exports.EncoderV1 = exports.Encoder = require('./lib/v1/encoder');\nvar DecoderV1 = exports.DecoderV1 = exports.Decoder = require('./lib/v1/decoder');\n\nvar EncoderV2 = exports.EncoderV2 = require('./lib/v2/encoder');\nvar DecoderV2 = exports.DecoderV2 = require('./lib/v2/decoder');\n\nexports.encoderV1 = new EncoderV1({size: 1024 * 1024});\nexports.encoderV2 = new EncoderV2({size: 1024 * 1024});\n\nexports.decode = function decode(buf, version, options) {\n  var classCache;\n  var withType;\n\n  if (version && typeof version !== 'string') {\n    // buf, withType, version\n    var t = version;\n    version = options;\n    options = t;\n  }\n\n  if (typeof options === 'boolean') {\n    withType = options;\n  }\n  if (typeof options === 'object') {\n    withType = options.withType;\n    classCache = options.classCache;\n  }\n  withType = !!withType;\n\n  if (version === '2.0') {\n    return new DecoderV2(buf, classCache).read(withType);\n  }\n  return new DecoderV1(buf, classCache).read(withType);\n};\n\nexports.encode = function encode(obj, version) {\n  var encoder;\n  if (version === '2.0') {\n    encoder = exports.encoderV2;\n  } else {\n    encoder = exports.encoderV1;\n  }\n\n  encoder.reset();\n  return encoder.write(obj).get();\n};\n\nvar custom = require('./lib/custom_handler');\n\nexports.registerDecodeHandler = custom.registerDecodeHandler;\nexports.deregisterDecodeHandler= custom.deregisterDecodeHandler;\n"
  },
  {
    "path": "lib/convert/index.js",
    "content": "'use strict';\n\nmodule.exports = {\n  'java.util.Locale': require('./java.util.locale'),\n};\n"
  },
  {
    "path": "lib/convert/java.util.locale.js",
    "content": "'use strict';\n\nmodule.exports = function(obj) {\n  return {\n    $class: 'com.caucho.hessian.io.LocaleHandle',\n    $: { value: obj.$ },\n  };\n};\n"
  },
  {
    "path": "lib/custom_handler.js",
    "content": "'use strict';\n\nvar assert = require('assert');\n\nvar handlers = {};\n\nfunction deregisterDecodeHandler(className) {\n\tdelete handlers[className];\n}\n\nfunction registerDecodeHandler(className, handler) {\n  assert(typeof handler === 'function', 'handler should be a function');\n  handlers[className] = handler;\n}\n\nfunction handle(result, withType) {\n  var className = result.$class;\n  var handler = handlers[className];\n\n  if (handler) {\n    result = handler(result);\n  }\n  return withType ? result : result.$;\n}\n\nexports.handle = handle;\nexports.registerDecodeHandler = registerDecodeHandler;\nexports.deregisterDecodeHandler = deregisterDecodeHandler;\n"
  },
  {
    "path": "lib/object.js",
    "content": "'use strict';\n\nvar util = require('util');\n\nexports.DEFAULT_CLASSNAME = {\n  boolean: 'boolean',\n  int: 'int',\n  long: 'long',\n  double: 'double',\n  date: 'java.util.Date',\n  string: 'java.lang.String',\n  byteArray: '[B',\n  list: 'java.util.ArrayList',\n  // iList: 'java.util.List',\n  map: 'java.util.HashMap',\n  iMap: 'java.util.Map',\n  exception: 'java.lang.RuntimeException'\n};\n\nexports.Object = 'java.lang.Object';\n\nvar SERIALIZER_MAP = exports.SERIALIZER_MAP = {};\n\n[\n  'boolean',\n  'java.lang.Boolean',\n  'bool',\n].forEach(function (t) {\n  SERIALIZER_MAP[t] = 'Bool';\n});\n\n[\n  'double',\n  'java.lang.Double',\n  'float',\n  'java.lang.Float',\n].forEach(function (t) {\n  SERIALIZER_MAP[t] = 'Double';\n});\n\n[\n  'java.lang.Long',\n  'long',\n].forEach(function (t) {\n  SERIALIZER_MAP[t] = 'Long';\n});\n\n[\n  'short',\n  'java.lang.Short',\n  'int',\n  'java.lang.Integer',\n  'byte',\n  'java.lang.Byte',\n].forEach(function (t) {\n  SERIALIZER_MAP[t] = 'Int';\n});\n\n[\n  'java.lang.String',\n  'String',\n  'string',\n  'char',\n  'char[]',\n  'java.lang.Character',\n].forEach(function (t) {\n  SERIALIZER_MAP[t] = 'String';\n});\n\n[\n  'java.util.Date'\n].forEach(function (t) {\n  SERIALIZER_MAP[t] = 'Date';\n});\n\n// http://www.devthought.com/2011/12/22/a-string-is-not-an-error/\nfunction JavaExceptionError(obj, withType) {\n  Error.call(this);\n  Error.captureStackTrace(this, JavaExceptionError);\n\n  // $: { detailMessage: 'this is a java IOException instance',\n  // cause: [Circular],\n  // stackTrace:\n  //  [ { declaringClass: 'hessian.Main',\n  //      methodName: 'main',\n  //      fileName: 'Main.java',\n  //      lineNumber: 1282 } ] }\n  var undeclaredThrowable = obj.$.undeclaredThrowable;\n  if (undeclaredThrowable && withType) {\n    undeclaredThrowable = undeclaredThrowable.$;\n  }\n  var detailMessage = obj.$.detailMessage;\n  if (detailMessage && withType) {\n    detailMessage = detailMessage.$;\n  }\n\n  var cause = obj.$.cause;\n  if (cause && cause.$ && withType) {\n    cause = cause.$;\n  }\n\n  if (undeclaredThrowable && undeclaredThrowable instanceof Error) {\n    if (!obj.$.detailMessage) {\n      return undeclaredThrowable;\n    }\n    this.name = undeclaredThrowable.name;\n    if (withType) {\n      this.message = obj.$.detailMessage.$ + '; ' + undeclaredThrowable.message;\n    } else {\n      this.message = obj.$.detailMessage + '; ' + undeclaredThrowable.message;\n    }\n  } else if (!detailMessage && cause && cause !== obj.$) {\n    return cause;\n  } else {\n    if (withType) {\n      this.message = obj.$.detailMessage && obj.$.detailMessage.$ || obj.$class;\n      if (obj.$.reasonAndSolution) {\n        this.message += '; reasonAndSolution: ' + obj.$.reasonAndSolution.$;\n      }\n    } else {\n      this.message = obj.$.detailMessage || obj.$class;\n      if (obj.$.reasonAndSolution) {\n        this.message += '; reasonAndSolution: ' + obj.$.reasonAndSolution;\n      }\n    }\n    this.name = obj.$class;\n  }\n\n  this.cause = obj.$.cause;\n\n  var stack = this.name + ': ' + this.message;\n  if (withType) {\n    var stackTraces = obj.$.stackTrace && obj.$.stackTrace.$ || [];\n    for (var i = 0; i < stackTraces.length; i++) {\n      var trace = stackTraces[i].$;\n      stack += '\\n    at ' + (trace.declaringClass && trace.declaringClass.$)\n        + '.' + (trace.methodName && trace.methodName.$)\n        + ' (' + (trace.fileName && trace.fileName.$)\n        + ':' + (trace.lineNumber && trace.lineNumber.$) + ')';\n    }\n  } else {\n    var stackTraces = obj.$.stackTrace || [];\n    for (var i = 0; i < stackTraces.length; i++) {\n      var trace = stackTraces[i];\n      stack += '\\n    at ' + trace.declaringClass + '.' + trace.methodName\n        + ' (' + trace.fileName + ':' + trace.lineNumber + ')';\n    }\n  }\n\n  this.stack = stack;\n}\n\nutil.inherits(JavaExceptionError, Error);\n\nexports.JavaExceptionError = JavaExceptionError;\n"
  },
  {
    "path": "lib/utils.js",
    "content": "'use strict';\n\nvar debug = require('util').debuglog('hessian.js:utils');\nvar Long = require('long');\nvar object = require('./object');\n\nvar MAX_SAFE_INT = Long.fromNumber(Math.pow(2, 53) - 1);\nvar MIN_SAFE_INT = Long.fromNumber(1 - Math.pow(2, 53));\n\nvar MAX_BYTE_TRUNK_SIZE = exports.MAX_BYTE_TRUNK_SIZE = 0x8000;\nvar MAX_CHAR_TRUNK_SIZE = exports.MAX_CHAR_TRUNK_SIZE = 0x8000;\n\n// Map feature detect\nexports.supportES6Map = typeof Map === 'function' && typeof Map.prototype.forEach === 'function';\n\nexports.getSerializer = function (type) {\n  // get from SERIALIZER_MAP\n  if (object.SERIALIZER_MAP[type]) {\n    return 'write' + object.SERIALIZER_MAP[type];\n  }\n  // array: [int\n  if (type[0] === '[') {\n    return 'writeArray';\n  }\n  // object\n  return 'writeObject';\n};\n\nexports.isJavaObject = function (type) {\n  return type === object.Object;\n};\n\nexports.handleLong = function (val) {\n  if (val.greaterThan(MAX_SAFE_INT) || val.lessThan(MIN_SAFE_INT)) {\n    val = val.toString();\n    debug('[hessian.js Warning] Read a not safe long(%s), translate it to string', val);\n    return val;\n  }\n  return val.toNumber();\n};\n\nvar _hasOwnProperty = Object.prototype.hasOwnProperty;\n/* jshint -W001 */\nexports.hasOwnProperty = function hasOwnProperty(obj, property) {\n  return _hasOwnProperty.call(obj, property);\n};\n\nexports.addByteCodes = function addByteCodes(map, codes, method) {\n  for (var i = 0; i < codes.length; i++) {\n    var code = codes[i];\n    if (Array.isArray(code)) {\n      var startCode = code[0];\n      var endCode = code[1];\n      for (var c = startCode; c <= endCode; c++) {\n        map[c] = method;\n      }\n    } else {\n      map[code] = method;\n    }\n  }\n};\n"
  },
  {
    "path": "lib/v1/decoder.js",
    "content": "'use strict';\n\nvar debug = require('util').debuglog('hessian:v1:decoder');\nvar ByteBuffer = require('byte');\nvar is = require('is-type-of');\nvar utils = require('../utils');\nvar object = require('../object');\nvar handle = require('../custom_handler').handle;\nvar JavaExceptionError = object.JavaExceptionError;\nvar supportES6Map = require('../utils').supportES6Map;\n\nvar BYTE_CODES = {};\n\nfunction Decoder(buf) {\n  this.byteBuffer = buf ? ByteBuffer.wrap(buf) : null;\n  this.refMap = {};\n  this.refId = 0;\n  this.BYTE_CODES = BYTE_CODES;\n}\n\n/**\n * prototype of Decoder\n */\n\nvar proto = Decoder.prototype;\n\nproto.throwError = function (method, code) {\n  throw new TypeError('hessian ' + method + ' error, unexpect code: 0x' + code.toString(16));\n};\n\nproto._addRef = function (obj) {\n  this.refMap[this.refId++] = obj;\n};\n\n/**\n * init from a buffer\n * @param {Buffer} buf\n * @api public\n */\nproto.init = function (buf) {\n  this.byteBuffer = ByteBuffer.wrap(buf);\n  return this;\n};\n\n/**\n * clean the decoder\n * @api public\n */\nproto.clean = function () {\n  this.byteBuffer = new ByteBuffer();\n  this.refMap = {};\n  this.refId = 0;\n  return this;\n};\n\n/**\n * check if the label match the method\n * @api private\n */\nproto._checkLabel = function (method, label) {\n  var l = this.byteBuffer.getChar();\n  var labelIsOk = l === label || label.indexOf(l) >= 0;\n  if (!labelIsOk) {\n    throw new TypeError('hessian ' + method + ' only accept label `' + label +\n      '` but got unexpect label `' + l + '`');\n  }\n  return l;\n};\n\nproto.handleType = function(type, val, withType) {\n  return withType ? {$class: object.DEFAULT_CLASSNAME[type], $: val} : val;\n};\n\n/**\n * read a null from buffer\n *\n * v1.0\n * ```\n * null ::= N(x4e)\n * ```\n *\n * @return {Null}\n * @api public\n */\nproto.readNull = function () {\n  this._checkLabel('readNull', 'N');\n  return null;\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x4e,\n], 'readNull');\n\n/**\n * read a boolean from buffer\n *\n * v1.0\n * ```\n * boolean ::= T(x54)\n *         ::= F(x46)\n * ```\n *\n * @return {Boolean}\n * @api public\n */\nproto.readBool = function (withType) {\n  var label = this._checkLabel('readBool', ['T', 'F']);\n  var val = label === 'T';\n  return this.handleType('boolean', val, withType);\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x54,\n  0x46,\n], 'readBool');\n\n/**\n * read a int from buffer\n *\n * v1.0\n * ```\n * int ::= I(x49) b32 b24 b16 b8\n * ```\n *\n * @return {Number}\n * @api public\n */\nproto.readInt = function (withType) {\n  this._checkLabel('readInt', 'I');\n  var val = this.byteBuffer.getInt();\n  return this.handleType('int', val, withType);\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x49\n], 'readInt');\n\n/**\n * read a long from buffer\n *\n * v1.0\n * ```\n * long ::= L(x4c) b64 b56 b48 b40 b32 b24 b16 b8\n * ```\n *\n * @return {Number}\n * @api public\n */\nproto.readLong = function (withType) {\n  this._checkLabel('readLong', 'L');\n  var val = utils.handleLong(this.byteBuffer.getLong());\n  return this.handleType('long', val, withType);\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x4c\n], 'readLong');\n\n/**\n * read a double from buffer\n *\n * v1.0\n * ```\n * double ::= D(x44) b64 b56 b48 b40 b32 b24 b16 b8\n * ```\n *\n * @return {Number}\n * @api public\n */\nproto.readDouble = function (withType) {\n  this._checkLabel('readDouble', 'D');\n  var val = this.byteBuffer.getDouble();\n  return this.handleType('double', val, withType);\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x44\n], 'readDouble');\n\n/**\n * read a date from buffer\n *\n * v1.0\n * ```\n * date ::= d(x64) b64 b56 b48 b40 b32 b24 b16 b8\n * ```\n * Date represented by a 64-bit long of milliseconds since Jan 1 1970 00:00H, UTC.\n *\n * @return {Date}\n * @api public\n */\nproto.readDate = function (withType) {\n  this._checkLabel('readDate', 'd');\n  var date = utils.handleLong(this.byteBuffer.getLong());\n  debug('read a date with milliEpoch: %d', date);\n  var val = new Date(date);\n  return this.handleType('date', val, withType);\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x64\n], 'readDate');\n\n/**\n * read bytes from buffer\n *\n * v1.0\n * ```\n * binary ::= (b(x62) b16 b8 binary-data)* B(x42) b16 b8 binary-data\n * ```\n * Binary data is encoded in chunks.\n * 'B' represents the final chunk and\n * 'b' represents any initial chunk. Each chunk has a 16-bit length value.\n *\n * @return {Buffer}\n * @api public\n */\nproto.readBytes = function () {\n  var label = this._checkLabel('readBytes', ['b', 'B']);\n  var bufs = [];\n  var length = 0;\n  // get all trunk start with 'b'\n  while (label === 'b') {\n    length = this.byteBuffer.getUInt16();\n    bufs.push(this.byteBuffer.read(length));\n    label = this._checkLabel('readBytes', ['b', 'B']);\n  }\n  // get the last trunk start with 'B'\n  length = this.byteBuffer.getUInt16();\n  bufs.push(this.byteBuffer.read(length));\n\n  return Buffer.concat(bufs);\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x62,\n  0x42\n], 'readBytes');\n\nproto._readUTF8String = function (len) {\n  if (!is.number(len)) {\n    len = this.byteBuffer.getUInt16();\n  }\n  if (len === 0) {\n    return '';\n  }\n  return this.byteBuffer.getRawStringByStringLength(len);\n};\n\n/**\n * read a string from buffer\n *\n * The length is the number of characters, which may be different than the number of bytes.\n *\n * v1.0\n * ```\n * string ::= (s(x73) b16 b8 utf-8-data)* S(x53) b16 b8 utf-8-data\n * ```\n *\n * @return {String}\n * @api public\n */\nproto.readString = function (withType) {\n  var str = '';\n  var code = this.byteBuffer.get();\n  // get all trunk start with 's'\n  while (code === 0x73) {\n    str += this._readUTF8String();\n    code = this.byteBuffer.get();\n  }\n\n  if (code === 0x53) {\n    // x53 ('S') represents the final chunk\n    debug('read last trunk of string');\n    str += this._readUTF8String();\n  } else {\n    // error format\n    throw new TypeError('hessian readString error, unexpect string code: 0x' + code.toString(16));\n  }\n  return this.handleType('string', str, withType);\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x73,\n  0x53\n], 'readString');\n\n/**\n * v1.0\n * ```\n * t(x74) b16 b8 type-string\n * ```\n *\n * @param {Boolean} skip skip type, if true, will return empty string\n * @return {String} type string\n */\nproto.readType = function (skip) {\n  this._checkLabel('readType', 't');\n  var typeLength = this.byteBuffer.getUInt16();\n  if (skip) {\n    this.byteBuffer.skip(typeLength);\n    debug('ignore type, skip %d bytes', typeLength);\n    return '';\n  } else {\n    var type = this.byteBuffer.readRawString(typeLength);\n    debug('get type: %s', type);\n    return type;\n  }\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x74,\n], 'readType');\n\nproto.readLength = function () {\n  this._checkLabel('readLength', 'l'); // x6c\n  var len = this.byteBuffer.getUInt();\n  debug('read length: %s', len);\n  return len;\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x6c,\n], 'readLength');\n\n/**\n * A sparse array, hessian v1.0\n * http://hessian.caucho.com/doc/hessian-1.0-spec.xtp#map\n */\nproto._readSparseObject = function (withType) {\n  var obj = {};\n  var label = this.byteBuffer.getChar(this.byteBuffer.position());\n  while (label !== 'z') {\n    debug('sparse array label: %s', label);\n    var key = this.read(withType);\n    var val = this.read(withType);\n    obj[key] = val;\n    label = this.byteBuffer.getChar(this.byteBuffer.position());\n  }\n  // skip 'z' char\n  this.byteBuffer.position(this.byteBuffer.position() + 1);\n\n  // default type info\n  if (withType) {\n    return {\n      $class: object.DEFAULT_CLASSNAME.map,\n      $: obj\n    };\n  }\n\n  return obj;\n};\n\n/**\n * read an object from buffer\n *\n * v1.0\n * ```\n * map ::= M(x4d) t b16 b8 type-string (object, object)* z\n * ```\n *\n * @param {Boolean} withType if need retain the type info\n * @return {Object}\n * @api public\n */\nproto.readObject = function (withType) {\n  this._checkLabel('readObject', 'M');\n  debug('start read an object');\n  var typeLabel = this.byteBuffer.getChar(this.byteBuffer.position());\n  if (typeLabel !== 't') {\n    debug('read sparse object, start label: %s', typeLabel);\n    return this._readSparseObject(withType);\n  }\n\n  var type = this.readType(false) || object.DEFAULT_CLASSNAME.map;\n  // if object is 'java.util.HashMap', type will be ''\n\n  var result = {\n    $class: type,\n    $: {}\n  };\n  var isMap = (type.indexOf(object.DEFAULT_CLASSNAME.map) === 0 ||\n    type.indexOf(object.DEFAULT_CLASSNAME.iMap) === 0) && supportES6Map;\n\n  if (isMap) {\n    Object.defineProperty(result.$, '$map', {\n      value: new Map(),\n      enumerable: false,\n    });\n  }\n\n  this._addRef(result);\n\n  // get\n  var label = this.byteBuffer.getChar();\n  var key;\n\n  while (label !== 'z') {\n    this.byteBuffer.position(this.byteBuffer.position() - 1);\n    key = this.read();\n\n    var value = this.read(withType);\n    label = this.byteBuffer.getChar();\n    // property name will auto transfer to a String type.\n    debug('read object prop: %j with type: %s', key, withType);\n    if (!/^this\\$\\d+$/.test(key)) {\n      var k = is.object(key) && key.name ? key.name : key;\n      result.$[k] = value;\n    }\n    if (isMap) {\n      result.$.$map.set(key, value);\n    }\n  }\n  debug('read object finish');\n\n  // java.lang.NoClassDefFoundError\n  if (/Exception$/.test(type) || /^java\\.lang\\.\\w+Error$/.test(type)) {\n    result.$ = new JavaExceptionError(result, withType);\n  }\n\n  return handle(result, withType);\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x4d,\n], 'readObject');\n\n/**\n * read an map from buffer\n *\n * v1.0\n * ```\n * map ::= M t b16 b8 type-string (object, object)* z\n * ```\n *\n * @param {Boolean} withType if need retain the type info\n * @return {Object}\n * @api public\n */\nproto.readMap = proto.readObject;\n\n/**\n * anonymous variable-length list = {0, \"foobar\"}\n * http://hessian.caucho.com/doc/hessian-1.0-spec.xtp#list\n */\nproto._readNoLengthArray = function (withType, type) {\n  var arr = [];\n  var label = this.byteBuffer.getChar(this.byteBuffer.position());\n  while (label !== 'z') {\n    debug('no length array item#%d label: %s', arr.length, label);\n    arr.push(this.read(withType));\n    label = this.byteBuffer.getChar(this.byteBuffer.position());\n  }\n  // skip 'z' char\n  this.byteBuffer.position(this.byteBuffer.position() + 1);\n\n  arr = withType\n  ? { $class: type, $: arr }\n  : arr;\n  return arr;\n};\n\n/**\n * read an array from buffer\n *\n * v1.0\n * ```\n * list ::= V(x56) type? length? object* z\n * ```\n *\n * @param {Boolean} withType if need retain the type info\n * @return {Array}\n * @api public\n */\nproto.readArray = function (withType) {\n  debug('start read an array');\n  this._checkLabel('readArray', 'V');\n  var type = '';\n\n  var typeLabel = this.byteBuffer.getChar(this.byteBuffer.position());\n  if (typeLabel === 't') {\n    type = this.readType(!withType);\n  }\n  type = type || object.DEFAULT_CLASSNAME.list;\n\n  var lengthLabel = this.byteBuffer.getChar(this.byteBuffer.position());\n  if (lengthLabel !== 'l') {\n    debug('read no length array, start label: %s', typeLabel);\n    return this._readNoLengthArray(withType, type);\n  }\n\n  // if object is 'java.util.ArrayList', type will be ''\n\n  var realResult = [];\n  var result = realResult;\n\n  if (withType) {\n    result = {\n      $class: type,\n      $: realResult\n    };\n  }\n\n  this._addRef(result);\n\n  var len = this.readLength();\n  while (len--) {\n    realResult.push(this.read(withType));\n  }\n  var endLabel = this.byteBuffer.getChar();\n  if (endLabel !== 'z') {\n    throw new TypeError('hessian readArray error, unexpect end label: ' + endLabel);\n  }\n  debug('read array finished with a length of %d', realResult.length);\n  return result;\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x56,\n], 'readArray');\n\nproto.readList = proto.readArray;\n\n/**\n * Get a object by ref id\n *\n * @return {Object}\n */\nproto.readRef = function (withType) {\n  var rid = this.readRefId();\n  var obj = this.refMap[rid];\n  if (!withType && obj && utils.hasOwnProperty(obj, '$')) {\n    return handle(obj, withType);\n  }\n  return obj;\n};\n\n/**\n * v1.0\n * ```\n * ref ::= R(x52) b32 b24 b16 b8\n * ```\n *\n * @return {Number}\n */\nproto.readRefId = function (withType) {\n  this._checkLabel('readRef', 'R');\n  return this.byteBuffer.getInt();\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x52,\n], 'readRef');\n\n/**\n * read any thing\n *\n * @param {Boolean} withType if need retain the type info\n * @api public\n */\nproto.read = function (withType) {\n  var pos = this.byteBuffer.position();\n  var code = this.byteBuffer.get(pos);\n  var method = this.BYTE_CODES[code];\n  if (debug.enabled) {\n    debug('read position: %s, code: 0x%s, method: %s', pos, code.toString(16), method);\n  }\n\n  if (!method) {\n    throw new Error('hessian read got an unexpect code: 0x' + code.toString(16));\n  }\n\n  return this[method](withType);\n};\n\n/**\n * set or get decoder byteBuffer position\n */\nproto.position = function (num) {\n  if (is.number(num)) {\n    this.byteBuffer.position(num);\n    return this;\n  }\n\n  return this.byteBuffer.position();\n};\n\nmodule.exports = Decoder;\n"
  },
  {
    "path": "lib/v1/encoder.js",
    "content": "'use strict';\n\nvar debug = require('util').debuglog('hessian:v1:encoder');\nvar utility = require('utility');\nvar ByteBuffer = require('byte');\nvar utils = require('../utils');\nvar javaObject = require('../object');\nvar is = require('is-type-of');\nvar converts = require('../convert');\nvar supportES6Map = require('../utils').supportES6Map;\n\nfunction Encoder(options) {\n  options = options || {};\n  //array of buffer\n  this.byteBuffer = new ByteBuffer({\n    size: options.size\n  });\n  this.objects = [];\n  this.mapTypes = utility.assign({\n    'java.util.HashMap': true,\n    'java.util.Map': true,\n    'com.alibaba.fastjson.JSONObject': true,\n  }, options.mapTypes);\n}\n\nvar proto = Encoder.prototype;\n\nproto.isMap = function (type) {\n  return utility.has(this.mapTypes, type) && this.mapTypes[type];\n};\n\nproto._assertType = function (method, expectType, val, desc) {\n  var valType = typeof val;\n  if (!is[expectType](val)) {\n    var msg = 'hessian ' + method +\n      ' expect input type is `' + expectType + '`, but got `' + valType + '`' + ' : ' + JSON.stringify(val) + ' ' + (desc || '');\n    throw new TypeError(msg);\n  }\n};\n\n/**\n * get the encode buffer\n * @return {Buffer}\n */\nproto.get = function () {\n  return this.byteBuffer.array();\n};\n\n/**\n * clean the buf\n */\nproto.reset = proto.clean = function () {\n  this.byteBuffer.reset();\n  this.objects = [];\n  return this;\n};\n\n/**\n * encode null\n * : N\n */\nproto.writeNull = function () {\n  this.byteBuffer.putChar('N');\n  return this;\n};\n\n/**\n * encode bool\n * : T\n * : F\n */\nproto.writeBool = function (val) {\n  this.byteBuffer.putChar(val ? 'T' : 'F');\n  return this;\n};\n\n/**\n * encode int\n * : I 0x00 0x00 0x00 0x10\n */\nproto.writeInt = function (val) {\n  this._assertType('writeInt', 'int32', val);\n  this.byteBuffer\n    .putChar('I')\n    .putInt(val);\n  return this;\n};\n\n/**\n * encode long\n * warning: we won't check if the long value is out of bound, be careful!\n * : L 0x00 0x00 0x00 0x00 0x10 0x32 0x33 0x12\n */\nproto.writeLong = function (val) {\n  this.byteBuffer\n    .putChar('L')\n    .putLong(val);\n  return this;\n};\n\n/**\n * encode double\n * : D 0x00 0x00 0x00 0x00 0x10 0x32 0x33 0x12\n */\nproto.writeDouble = function (val) {\n  this._assertType('writeDouble', 'number', val);\n  this.byteBuffer\n    .putChar('D')\n    .putDouble(val);\n  return this;\n};\n\n/**\n * encode date\n * 1.0: http://hessian.caucho.com/doc/hessian-1.0-spec.xtp#date\n * : d 0x00 0x00 0x00 0x00 0x10 0x32 0x33 0x12\n */\nproto.writeDate = function (milliEpoch) {\n  if (milliEpoch instanceof Date) {\n    milliEpoch = milliEpoch.getTime();\n  }\n  this._assertType('writeDate', 'number', milliEpoch);\n\n  this.byteBuffer\n    .putChar('d')\n    .putLong(milliEpoch);\n  return this;\n};\n\n/**\n * encode buffer\n * : b 0x80 0x00 [...]\n *   B 0x00 0x03 [0x01 0x02 0x03]\n */\nproto.writeBytes = function (buf) {\n  this._assertType('writeBytes', 'buffer', buf);\n  var offset = 0;\n  while (buf.length - offset > utils.MAX_BYTE_TRUNK_SIZE) {\n    this.byteBuffer\n      .putChar('b')\n      .putUInt16(utils.MAX_BYTE_TRUNK_SIZE)\n      .put(buf.slice(offset, offset + utils.MAX_BYTE_TRUNK_SIZE));\n\n    offset += utils.MAX_BYTE_TRUNK_SIZE;\n  }\n\n  this.byteBuffer\n    .putChar('B')\n    .putUInt16(buf.length - offset)\n    .put(buf.slice(offset));\n  return this;\n};\n\n/**\n * encode string\n * : s 0x80 0x00 [...]\n *   S 0x00 0x03 [0x01 0x02 0x03]\n */\nproto.writeString = function (str) {\n  this._assertType('writeString', 'string', str);\n  var offset = 0;\n\n  var length = str.length;\n  var strOffset = 0;\n  while (length > 0x8000) {\n    var sublen = 0x8000;\n    // chunk can't end in high surrogate\n    var tail = str.charCodeAt(strOffset + sublen - 1);\n\n    if (0xd800 <= tail && tail <= 0xdbff) {\n      debug('writeString got tail: 0x%s', tail.toString(16));\n      sublen--;\n    }\n\n    this.byteBuffer\n      .put(0x73) // 's'\n      .putUInt16(sublen)\n      .putRawString(str.slice(strOffset, strOffset + sublen));\n\n    length -= sublen;\n    strOffset += sublen;\n    debug('writeString strOffset: %s, length: %s, sublen: %s', strOffset, length, sublen);\n  }\n\n  debug('writeString left length: %s', length);\n  this.byteBuffer\n    .put(0x53) // 'S'\n    .putUInt16(length)\n    .putRawString(str.slice(strOffset));\n\n  return this;\n};\n\nvar _typecache = {};\n\n/**\n * encode type\n * v1.0\n * ```\n * type ::= 0x74(t) type-string-length(putUInt16) type-string(putRawString)\n * ```\n */\nproto.writeType = function (type) {\n  type = type || '';\n  if (_typecache[type]) {\n    this.byteBuffer.put(_typecache[type]);\n    return this;\n  }\n\n  var start = this.byteBuffer.position();\n\n  this.byteBuffer\n    .put(0x74)\n    .putUInt16(type.length)\n    .putRawString(type);\n\n  var end = this.byteBuffer.position();\n  _typecache[type] = this.byteBuffer.copy(start, end);\n\n  return this;\n};\n\n/**\n * encode ref\n * v1.0\n * ```\n * ref ::= R(0x52) int(putInt)\n * ```\n */\nproto.writeRef = function (refId) {\n  this.byteBuffer\n    .putChar('R')\n    .putInt(refId);\n\n  return this;\n};\n\nproto._checkRef = function (obj) {\n  var refIndex = this.objects.indexOf(obj);\n  if (refIndex >= 0) {\n    // already have this object\n    // just write ref\n    debug('writeObject with a refIndex: %d', refIndex);\n    this.writeRef(refIndex);\n    return true;\n  }\n  // a new comming object\n  this.objects.push(obj);\n  return false;\n};\n\n/**\n * A sparse array\n *\n * @param {Object} obj simple obj\n * @return {this}\n */\nproto._writeHashMap = function (obj, type) {\n  debug('_writeHashMap() %j, fields: %j', obj);\n\n  // Real code in java impl:\n  // http://grepcode.com/file/repo1.maven.org/maven2/com.caucho/hessian/3.1.3/com/caucho/hessian/io/Hessian2Output.java#Hessian2Output.writeMapBegin%28java.lang.String%29\n  // M(0x4d) type(writeType) (<key> <value>) z(0x7a)\n  this.byteBuffer.put(0x4d);\n  // hashmap's type is null\n  this.writeType(type);\n\n  if (supportES6Map && obj instanceof Map) {\n    obj.forEach(function (value, key) {\n      this.write(key);\n      this.write(value);\n    }, this);\n  } else {\n    // hash map must sort keys\n    var keys = Object.keys(obj).sort();\n    for (var i = 0; i < keys.length; i++) {\n      var k = keys[i];\n      this.writeString(k);\n      this.write(obj[k]);\n    }\n  }\n  this.byteBuffer.put(0x7a);\n  return this;\n};\n\n// M(0x4d) type(writeType) (<key> <value>) z(0x7a)\nproto._writeObject = function (obj) {\n  this._assertType('writeObject / writeMap', 'object', obj.$, obj.$class);\n  this.byteBuffer.put(0x4d);\n  this.writeType(obj.$class);\n\n  var val = obj.$;\n  var keys = Object.keys(val);\n  for (var i = 0, len = keys.length; i < len; i++) {\n    var key = keys[i];\n    this.writeString(key);\n    this.write(val[key]);\n  }\n  this.byteBuffer.put(0x7a);\n  return this;\n};\n\n/**\n * encode object\n *   support circular\n *   support all kind of java object\n * : {a: 1}\n * : {$class: 'java.lang.Map', $: {a: 1}}\n */\nproto.writeObject = function (obj) {\n  if (is.nullOrUndefined(obj) ||\n    // : { a: { '$class': 'xxx', '$': null } }\n    (is.string(obj.$class) && is.nullOrUndefined(obj.$))) {\n    debug('writeObject with a null');\n    return this.writeNull();\n  }\n  this._assertType('writeObject / writeMap', 'object', obj);\n\n  if (this._checkRef(obj)) {\n    // if is ref, will write by _checkRef\n    return this;\n  }\n\n  var className = '';\n  var realObj;\n  if (!obj.$class || !obj.$) {\n    // : {a: 1}\n    realObj = obj;\n  } else {\n    // : {$class: 'java.util.HashMap', $: {a: 1}}\n    className = obj.$class === javaObject.DEFAULT_CLASSNAME.map || obj.$class === javaObject.DEFAULT_CLASSNAME.iMap ? '' : obj.$class;\n    realObj = obj.$;\n  }\n\n  if (!className || this.isMap(className)) {\n    return this._writeHashMap(realObj, className);\n  }\n\n  debug('writeObject with complex object, className: %s', className);\n  var convertor = converts[obj.$class];\n  obj = convertor ? convertor(obj) : obj;\n  return this._writeObject(obj);\n};\n\nproto.writeMap = proto.writeObject;\n\nproto._writeListBegin = function (length, type) {\n  this.byteBuffer.putChar('V');\n\n  if (type) {\n    this.writeType(type);\n  }\n\n  this.byteBuffer.put(0x6c); // 'l'\n  this.byteBuffer.putInt(length);\n  return true;\n};\n\n/**\n * encode array\n *\n * v1.0\n * ```\n * list ::= V(x56) [type(writeType)] l(0x6c) long-length(putInt) values 'z'\n * ```\n *\n * v2.0\n * ```\n * list ::= V(x56) type(writeType) n(0x6e) short-length(put) values 'z'\n *      ::= V(x56) type(writeType) l(0x6c) long-length(putInt) values 'z'\n *      ::= v(x76) ref(writeInt) fix-length(writeInt) values\n * ```\n *\n * An ordered list, like an array.\n * The two list productions are a fixed-length list and a variable length list.\n * Both lists have a type.\n * The type string may be an arbitrary UTF-8 string understood by the service.\n *\n * fixed length list:\n * Hessian 2.0 allows a compact form of the list for successive lists of\n * the same type where the length is known beforehand.\n * The type and length are encoded by integers,\n * where the type is a reference to an earlier specified type.\n *\n * @param {Array} arr\n * @return {this}\n */\n\nproto.writeArray = function (arr) {\n  if (this._checkRef(arr)) {\n    // if is ref, will write by _checkRef\n    return this;\n  }\n\n  var isSimpleArray = is.array(arr);\n  var className = ''; // empty string meaning: `javaObject.DEFAULT_CLASSNAME.list`\n  var realArray = arr;\n  if (!isSimpleArray) {\n    if (is.object(arr) && is.nullOrUndefined(arr.$)) {\n      return this.writeNull();\n    }\n    var isComplexArray = is.object(arr) &&\n      is.string(arr.$class) && is.array(arr.$);\n    if (!isComplexArray) {\n      throw new TypeError('hessian writeArray input type invalid');\n    }\n\n    debug('write array with a complex array with className: %s', className);\n\n    className = arr.$class === javaObject.DEFAULT_CLASSNAME.list ? '' : arr.$class;\n    realArray = arr.$;\n  }\n\n  var hasEnd = this._writeListBegin(realArray.length, className);\n\n  for (var i = 0; i < realArray.length; i++) {\n    this.write(realArray[i]);\n  }\n\n  if (hasEnd) {\n    this.byteBuffer.putChar('z');\n  }\n  return this;\n};\n\nproto.writeList = proto.writeArray;\n\n/**\n * write any type\n * @param {Object|Number|String|Boolean|Array} val\n * : 1 => int\n * : 1.1 => double\n * :\n */\nproto.write = function (val) {\n  var type = typeof val;\n  if (is.nullOrUndefined(val) || is.NaN(val) || is.function(val) || is.regExp(val)) {\n    return this.writeNull();\n  }\n  switch (type) {\n  case 'string':\n    return this.writeString(val);\n  case 'boolean':\n    return this.writeBool(val);\n  case 'number':\n    // must check long value first\n    if (is.long(val)) {\n      debug('write number %d as long', val);\n      return this.writeLong(val);\n    }\n\n    if (is.int(val)) {\n      debug('write number %d as int', val);\n      return this.writeInt(val);\n    }\n\n    // double\n    debug('write number %d as double', val);\n    return this.writeDouble(val);\n  }\n\n  if (is.long(val) || is.Long(val)) {\n    debug('write long: high: %s, low: %s', val.high, val.low);\n    return this.writeLong(val);\n  }\n\n  if (is.date(val)) {\n    debug('write Date: %s', val);\n    return this.writeDate(val);\n  }\n\n  if (is.buffer(val)) {\n    debug('write Buffer with a length of %d', val.length);\n    return this.writeBytes(val);\n  }\n\n  if (is.array(val)) {\n    debug('write simple array with a length of %d', val.length);\n    return this.writeArray(val);\n  }\n\n  // Object\n  // {a: 1, b: 'test'}\n  // {a: 0, b: null}\n  if (!is.string(val.$class) || !utils.hasOwnProperty(val, '$')) {\n    debug('write simple object');\n    return this.writeObject(val);\n  }\n\n  if (is.array(val.$)) {\n    debug('detect val.$ is array');\n    return this.writeArray(val);\n  }\n\n  var method = utils.getSerializer(val.$class);\n  debug('write detect %s use serializer %s', val.$class, method);\n\n  // {$class: 'long', $: 123}\n  if (method !== 'writeObject' && method !== 'writeArray') {\n    if (is.nullOrUndefined(val.$)) {\n      return this.writeNull();\n    }\n    return this[method](val.$);\n  }\n\n  // java.lang.Object\n  if (utils.isJavaObject(val.$class)) {\n    if (is.date(val.$) || !is.object(val.$)) {\n      return this.write(val.$);\n    }\n  }\n\n  // {$class: 'java.util.Map', $: {a: 1}}\n  return this[method](val);\n};\n\nmodule.exports = Encoder;\n"
  },
  {
    "path": "lib/v2/decoder.js",
    "content": "'use strict';\n\nvar debug = require('util').debuglog('hessian:v2:decoder');\nvar util = require('util');\nvar is = require('is-type-of');\nvar DecoderV1 = require('../v1/decoder');\nvar utils = require('../utils');\nvar handle = require('../custom_handler').handle;\nvar JavaExceptionError = require('../object').JavaExceptionError;\nvar supportES6Map = require('../utils').supportES6Map;\n\nvar BYTE_CODES = {};\n\nfunction Decoder(buf, classCache) {\n  DecoderV1.call(this, buf);\n  this.BYTE_CODES = BYTE_CODES;\n  this.classes = []; // {name: classname, fields: []}\n  this.types = [];\n\n  this._isLastChunk = false;\n  this.classCache = classCache;\n}\n\nutil.inherits(Decoder, DecoderV1);\n\nvar proto = Decoder.prototype;\n\nproto.clean = function () {\n  DecoderV1.prototype.clean.call(this);\n  this.types = [];\n  this.classes = [];\n  return this;\n};\n\n// readBool()\nutils.addByteCodes(BYTE_CODES, [\n  0x46,\n  0x54,\n], 'readBool');\n\n// readNull()\nutils.addByteCodes(BYTE_CODES, [\n  0x4e,\n], 'readNull');\n\n/**\n * read a int from buffer\n *\n * v2.0\n * ```\n * int ::= I(x49) b3 b2 b1 b0\n *     ::= [x80-xbf]\n *     ::= [xc0-xcf] b0\n *     ::= [xd0-xd7] b1 b0\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##int\n * ```\n *\n * A 32-bit signed integer. An integer is represented by the octet x49 ('I')\n * followed by the 4 octets of the integer in big-endian order.\n * ```\n * value = (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;\n * ```\n *\n * single octet integers:\n * Integers between -16 and 47 can be encoded by a single octet in the range x80 to xbf.\n * ```\n * value = code - 0x90\n * ```\n *\n * two octet integers:\n * Integers between -2048 and 2047 can be encoded in two octets with the leading byte in the range xc0 to xcf.\n * ```\n * value = ((code - 0xc8) << 8) + b0;\n * ```\n *\n * three octet integers:\n * Integers between -262144 and 262143 can be encoded in three bytes with the leading byte in the range xd0 to xd7.\n * ```\n * value = ((code - 0xd4) << 16) + (b1 << 8) + b0;\n * ```\n *\n * @return {Number}\n * @api public\n */\nproto.readInt = function () {\n  var code = this.byteBuffer.get();\n  // Compact int\n  if (code >= 0x80 && code <= 0xbf) {\n    // Integers between -16 and 47 can be encoded by a single octet in the range x80 to xbf.\n    // value = code - 0x90\n    return code - 0x90;\n  }\n  if (code >= 0xc0 && code <= 0xcf) {\n    // Integers between -2048 and 2047 can be encoded in two octets with the leading byte in the range xc0 to xcf.\n    // value = ((code - 0xc8) << 8) + b0;\n    return ((code - 0xc8) << 8) + this.byteBuffer.get();\n  }\n  if (code >= 0xd0 && code <= 0xd7) {\n    // Integers between -262144 and 262143 can be encoded in three bytes with the leading byte in the range xd0 to xd7.\n    // value = ((code - 0xd4) << 16) + (b1 << 8) + b0;\n    var b1 = this.byteBuffer.get();\n    var b0 = this.byteBuffer.get();\n    return ((code - 0xd4) << 16) + (b1 << 8) + b0;\n  }\n  if (code === 0x49) {\n    return this.byteBuffer.getInt();\n  }\n\n  this.throwError('readInt', code);\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  [0x80, 0xbf],\n  [0xc0, 0xcf],\n  [0xd0, 0xd7],\n  0x49\n], 'readInt');\n\n/**\n * read a long from buffer\n *\n * v2.0\n * ```\n * long ::= L(x4c) b7 b6 b5 b4 b3 b2 b1 b0\n *      ::= [xd8-xef]\n *      ::= [xf0-xff] b0\n *      ::= [x38-x3f] b1 b0\n *      ::= x4c b3 b2 b1 b0\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##long\n * ```\n * A 64-bit signed integer. An long is represented by the octet x4c ('L' )\n * followed by the 8-bytes of the integer in big-endian order.\n *\n * single octet longs:\n * Longs between -8 and 15 are represented by a single octet in the range xd8 to xef.\n * ```\n * value = (code - 0xe0)\n * ```\n *\n * two octet longs:\n * Longs between -2048 and 2047 are encoded in two octets with the leading byte in the range xf0 to xff.\n * ```\n * value = ((code - 0xf8) << 8) + b0\n * ```\n *\n * three octet longs:\n * Longs between -262144 and 262143 are encoded in three octets with the leading byte in the range x38 to x3f.\n * ```\n * value = ((code - 0x3c) << 16) + (b1 << 8) + b0\n * ```\n *\n * four octet longs:\n * Longs between which fit into 32-bits are encoded in five octets with the leading byte x59.\n * ```\n * value = (b3 << 24) + (b2 << 16) + (b1 << 8) + b0\n * ```\n *\n * @return {Number}\n * @api public\n */\nproto.readLong = function () {\n  var code = this.byteBuffer.get();\n  // Compact long\n  if (code >= 0xd8 && code <= 0xef) {\n    // Longs between -8 and 15 are represented by a single octet in the range xd8 to xef.\n    // value = (code - 0xe0)\n    return code - 0xe0;\n  }\n  if (code >= 0xf0 && code <= 0xff) {\n    // Longs between -2048 and 2047 are encoded in two octets with the leading byte in the range xf0 to xff.\n    // value = ((code - 0xf8) << 8) + b0\n    return ((code - 0xf8) << 8) + this.byteBuffer.get();\n  }\n  if (code >= 0x38 && code <= 0x3f) {\n    // Longs between -262144 and 262143 are encoded in three octets with the leading byte in the range x38 to x3f.\n    // value = ((code - 0x3c) << 16) + (b1 << 8) + b0\n    var b1 = this.byteBuffer.get();\n    var b0 = this.byteBuffer.get();\n    return ((code - 0x3c) << 16) + (b1 << 8) + b0;\n  }\n  if (code === 0x59) {\n    // 32-bit integer cast to long\n    return this.byteBuffer.getInt32();\n  }\n  if (code === 0x4c) {\n    return utils.handleLong(this.byteBuffer.getLong());\n  }\n\n  this.throwError('readLong', code);\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  [0xd8, 0xef],\n  [0xf0, 0xff],\n  [0x38, 0x3f],\n  0x59,\n  0x4c\n], 'readLong');\n\n/**\n * read a double from buffer\n *\n * v2.0\n * ```\n * double ::= D(x44) b7 b6 b5 b4 b3 b2 b1 b0\n *        ::= x5b\n *        ::= x5c\n *        ::= x5d(byte) b0\n *        ::= x5e(short) b1 b0\n *        ::= x5f(float) b3 b2 b1 b0\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##double\n * ```\n * The double 0.0 can be represented by the octet x5b\n * The double 1.0 can be represented by the octet x5c\n *\n * double octet:\n * Doubles between -128.0 and 127.0 with no fractional component\n * can be represented in two octets by casting the byte value to a double.\n * ```\n * value = (double) b0\n * ```\n *\n * double short:\n * Doubles between -32768.0 (-0x8000) and 32767.0(0x8000 - 1) with no fractional component\n * can be represented in three octets by casting the short value to a double.\n * ```\n * value = (double) (256 * b1 + b0)\n * ```\n *\n * double float:\n * Doubles which are equivalent to their 32-bit float representation\n * can be represented as the 4-octet float and then cast to double.\n *\n * @return {Number}\n * @api public\n */\nproto.readDouble = function () {\n  var code = this.byteBuffer.get();\n  if (code === 0x44) {\n    return this.byteBuffer.getDouble();\n  }\n\n  // Compact double\n  if (code === 0x5b) {\n    return 0.0;\n  }\n  if (code === 0x5c) {\n    return 1.0;\n  }\n  if (code === 0x5d) {\n    return this.byteBuffer.getInt8();\n  }\n  if (code === 0x5e) {\n    return this.byteBuffer.getInt16();\n  }\n  if (code === 0x5f) {\n    return this.byteBuffer.getInt32() * 0.001;\n  }\n  this.throwError('readDouble', code);\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x44,\n  0x5b,\n  0x5c,\n  0x5d,\n  0x5e,\n  0x5f\n], 'readDouble');\n\n/**\n * read a date from buffer,\n *\n * v2.0\n * ```\n * date ::= x4a(J) b7 b6 b5 b4 b3 b2 b1 b0 // Date represented by a 64-bit long of milliseconds since Jan 1 1970 00:00H, UTC.\n *      ::= x4b(K) b4 b3 b2 b1 b0          // The second form contains a 32-bit int of minutes since Jan 1 1970 00:00H, UTC.\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##date\n * ```\n *\n * @return {Date}\n * @api public\n */\nproto.readDate = function () {\n  var code = this.byteBuffer.get();\n  if (code === 0x4a) {\n    return new Date(utils.handleLong(this.byteBuffer.getLong()));\n  }\n  if (code === 0x4b) {\n    return new Date(this.byteBuffer.getInt32() * 60000);\n  }\n\n  this.throwError('readDate', code);\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x4a,\n  0x4b,\n], 'readDate');\n\n/**\n * read bytes from buffer\n *\n * v2.0\n * ```\n * binary ::= x41(A) b1 b0 <binary-data> binary\n *        ::= x42(B) b1 b0 <binary-data>\n *        ::= [x20-x2f] <binary-data>\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##binary\n * ```\n * The octet x42 ('B') encodes the final chunk and\n * x41 ('A') represents any non-final chunk.\n * Each chunk has a 16-bit length value.\n *\n * len = 256 * b1 + b0\n *\n * Binary data with length less than 15 may be encoded by a single octet length [x20-x2f].\n *\n * len = code - 0x20\n *\n * @return {Buffer}\n * @api public\n */\nproto.readBytes = function () {\n  var code = this.byteBuffer.get();\n  if (code >= 0x20 && code <= 0x2f) {\n    // short binary\n    var len = code - 0x20;\n    return this.byteBuffer.read(len);\n  }\n\n  var bufs = [];\n  var length = 0;\n  // get non-final trunk start with 'A'\n  while (code === 0x41) {\n    length = this.byteBuffer.getUInt16();\n    bufs.push(this.byteBuffer.read(length));\n    code = this.byteBuffer.get();\n  }\n\n  if (code === 0x42) {\n    // get the last trunk start with 'B'\n    length = this.byteBuffer.getUInt16();\n    bufs.push(this.byteBuffer.read(length));\n  } else if (code >= 0x20 && code <= 0x2f) {\n    length = code - 0x20;\n    bufs.push(this.byteBuffer.read(length));\n  } else if (code >= 0x34 && code <= 0x37) {\n    length = (code - 0x34) * 256 + this.byteBuffer.get();\n    bufs.push(this.byteBuffer.read(length));\n  } else {\n    this.throwError('readBytes', code);\n  }\n\n  return Buffer.concat(bufs);\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x41,\n  0x42,\n  [0x34, 0x37],\n  [0x20, 0x2f],\n], 'readBytes');\n\n/**\n * read a string from buffer\n *\n * The length is the number of characters, which may be different than the number of bytes.\n *\n * v2.0\n * ```\n * string ::= R(x52) b1 b0 <utf8-data> string  # non-final chunk\n *        ::= S(x53) b1 b0 <utf8-data>         # string of length 0-65535\n *        ::= [x00-x1f] <utf8-data>            # string of length 0-31\n *        ::= [x30-x33] b0 <utf8-data>         # string of length 0-1023\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##string\n * ```\n * A 16-bit unicode character string encoded in UTF-8. Strings are encoded in chunks.\n * x53 ('S') represents the final chunk and x52 ('R') represents any non-final chunk.\n * Each chunk has a 16-bit unsigned integer length value.\n *\n * The length is the number of 16-bit characters, which may be different than the number of bytes.\n * String chunks may not split surrogate pairs.\n *\n * short strings:\n * Strings with length less than 32 may be encoded with a single octet length [x00-x1f].\n * ```\n * [x00-x1f] <utf8-data>\n * ```\n *\n * @return {String}\n * @api public\n */\nproto.readString = function () {\n  var str = '';\n  var code = this.byteBuffer.get();\n  debug('readString() code: %s', code);\n\n  var length;\n  switch(code) {\n    // 0-byte string\n    case 0x00: case 0x01: case 0x02: case 0x03:\n    case 0x04: case 0x05: case 0x06: case 0x07:\n    case 0x08: case 0x09: case 0x0a: case 0x0b:\n    case 0x0c: case 0x0d: case 0x0e: case 0x0f:\n\n    case 0x10: case 0x11: case 0x12: case 0x13:\n    case 0x14: case 0x15: case 0x16: case 0x17:\n    case 0x18: case 0x19: case 0x1a: case 0x1b:\n    case 0x1c: case 0x1d: case 0x1e: case 0x1f:\n      this._isLastChunk = true;\n      length = code - 0x00;\n      debug('read short strings');\n      str += this._readUTF8String(length);\n      break;\n\n    case 0x30: case 0x31: case 0x32: case 0x33:\n      this._isLastChunk = true;\n      length = (code - 0x30) * 256 + this.byteBuffer.get();\n      str += this._readUTF8String(length);\n      break;\n\n    case 0x53:\n      this._isLastChunk = true;\n      // x53 ('S') represents the final chunk\n      debug('read last trunk of string');\n      str += this._readUTF8String();\n      break;\n\n    case 0x52:\n      this._isLastChunk = false;\n      // x52 ('R') represents any non-final chunk.\n      str += this._readUTF8String();\n\n      while (!this._isLastChunk) {\n        str += this.readString();\n      }\n      break;\n\n    default:\n      this.throwError('readString', code);\n      break;\n  }\n  return str;\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x52,\n  0x53,\n  [0x00, 0x1f],\n  [0x30, 0x33],\n], 'readString');\n\n/**\n * @return {String} type string\n *\n * v2.0\n * ```\n * ref ::= (0x51) int(putInt)\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##ref\n * ```\n */\nproto.readType = function () {\n  var pos = this.byteBuffer.position();\n  var code = this.byteBuffer.get(pos);\n\n  var type = '';\n  switch (code) {\n    case 0x00: case 0x01: case 0x02: case 0x03:\n    case 0x04: case 0x05: case 0x06: case 0x07:\n    case 0x08: case 0x09: case 0x0a: case 0x0b:\n    case 0x0c: case 0x0d: case 0x0e: case 0x0f:\n\n    case 0x10: case 0x11: case 0x12: case 0x13:\n    case 0x14: case 0x15: case 0x16: case 0x17:\n    case 0x18: case 0x19: case 0x1a: case 0x1b:\n    case 0x1c: case 0x1d: case 0x1e: case 0x1f:\n\n    case 0x30: case 0x31: case 0x32: case 0x33:\n    case 0x52: case 0x53:\n      type = this.readString();\n      this.types.push(type);\n      debug('got type#%d: %s', this.types.length, type);\n      break;\n\n    default:\n      var ref = this.readInt();\n      type = this.types[ref];\n      debug('got ref:%d type#%d: %s', ref, this.types.length, type);\n      break;\n  }\n  return type;\n};\n\n// properties match with this$\\d+ means inner properties\n// it is useless for node and is circular structure\nvar INNER_CLASS_PROPERTY_REG = /^this\\$\\d+$/;\nvar INNER_CLASS_LABEL = '$$ignore_inner_property$$';\n\nproto._readObjectDefinition = function () {\n  var classname = this.readString();\n  var fieldsLength = this.readInt();\n  // compose cache key with class name and fields length\n  // more safely\n  var cachekey = classname + '##' + fieldsLength;\n\n  // get class definition from cache\n  var cacheClz = this.classCache && this.classCache.get(cachekey);\n  if (cacheClz) {\n    this.byteBuffer.skip(cacheClz.length);\n    this.classes.push(cacheClz);\n    return cacheClz;\n  }\n\n  var pos = this.byteBuffer.position();\n  var fields = [];\n  for (var i = 0; i < fieldsLength; i++) {\n    var name = this.readString();\n    if (INNER_CLASS_PROPERTY_REG.test(name)) {\n      name = INNER_CLASS_LABEL;\n    }\n    fields.push(name);\n  }\n  debug('_readObjectDefinition got %s fields: %j', classname, fields);\n  var clz = {\n    name: classname,\n    fields: fields,\n    length: this.byteBuffer.position() - pos,\n  };\n\n  this.classes.push(clz);\n  // set class definition into cache\n  if (this.classCache) {\n    this.classCache.set(cachekey, clz);\n  }\n  return clz;\n};\n\n/**\n * Read an object from buffer\n *\n * v2.0\n * ```\n * class-def  ::= 'C(x43)' string int string*\n *\n * object     ::= 'O(x4f)' int value*\n *            ::= [x60-x6f] value*\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##object\n * ```\n *\n * class definition:\n * Hessian 2.0 has a compact object form where the field names are only serialized once.\n * Following objects only need to serialize their values.\n *\n * The object definition includes a mandatory type string,\n * the number of fields, and the field names.\n * The object definition is stored in the object definition map\n * and will be referenced by object instances with an integer reference.\n *\n * object instantiation:\n * Hessian 2.0 has a compact object form where the field names are only serialized once.\n * Following objects only need to serialize their values.\n *\n * The object instantiation creates a new object based on a previous definition.\n * The integer value refers to the object definition.\n *\n * @param {Boolean} withType if need retain the type info\n * @return {Object}\n * @api public\n */\nproto.readObject = function (withType) {\n  var code = this.byteBuffer.get();\n  var ref;\n  if (code === 0x43) {\n    // C(x43) type fields-length(writeInt) fields-names(writeString) o ref fields-values(write)\n    this._readObjectDefinition();\n    return this.readObject(withType);\n  } else if (code === 0x4f) {\n    ref = this.readInt();\n  } else if (code >= 0x60 && code <= 0x6f) {\n    ref = code - 0x60;\n  } else {\n    this.throwError('readObject', code);\n  }\n\n  var cls = this.classes[ref];\n  debug('readObject %s, ref: %s', cls.name, ref);\n\n  var result = {\n    $class: cls.name,\n    $: {}\n  };\n  this._addRef(result);\n\n  var fields = cls.fields;\n  for (var i = 0; i < fields.length; i++) {\n    var name = fields[i];\n    var value = this.read(withType);\n    if (name !== INNER_CLASS_LABEL) {\n      result.$[name] = value;\n    }\n  }\n\n  if (/Exception$/.test(cls.name)) {\n    result.$ = new JavaExceptionError(result, withType);\n  }\n\n  return handle(result, withType);\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x43,\n  0x4f,\n  [0x60, 0x6f],\n], 'readObject');\n\n/**\n * v2.0\n * ```\n * ref ::= Q(x51) int\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##ref\n * ```\n *\n * Each map or list is stored into an array as it is parsed.\n * ref selects one of the stored objects. The first object is numbered '0'.\n *\n * @return {Number}\n */\nproto.readRefId = function (withType) {\n  var code = this.byteBuffer.get();\n  if (code === 0x51) {\n    return this.readInt();\n  }\n\n  this.throwError('readRef', code);\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x51,\n], 'readRef');\n\nproto._readFixedLengthItems = function (len, list, withType) {\n  for (var i = 0; i < len; i++) {\n    list.push(this.read(withType));\n  }\n};\n\n/**\n * read an array from buffer\n *\n * v2.0\n * ```\n * list ::= x55 type value* 'Z'   # variable-length list\n *      ::= 'V(x56)' type int value*   # fixed-length list\n *      ::= x57 value* 'Z'        # variable-length untyped list\n *      ::= x58 int value*        # fixed-length untyped list\n *      ::= [x70-77] type value*  # fixed-length typed list\n *      ::= [x78-7f] value*       # fixed-length untyped list\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##list\n * ```\n * An ordered list, like an array.\n * The two list productions are a fixed-length list and a variable length list.\n * Both lists have a type.\n * The type string may be an arbitrary UTF-8 string understood by the service.\n *\n * fixed length list:\n * Hessian 2.0 allows a compact form of the list for successive lists of\n * the same type where the length is known beforehand.\n * The type and length are encoded by integers,\n * where the type is a reference to an earlier specified type.\n *\n * @param {Boolean} withType if need retain the type info\n * @return {Array}\n * @api public\n */\nproto.readArray = function (withType) {\n  var code = this.byteBuffer.get();\n  var type;\n  var result;\n  var list = [];\n  var length = null;\n\n  if (code === 0x56) {\n    type = this.readType();\n    length = this.readInt();\n  } else if (code === 0x58) {\n    length = this.readInt();\n  } else if (code >= 0x78 && code <= 0x7f) {\n    length = code - 0x78;\n  } else if (code >= 0x70 && code <= 0x77) {\n    type = this.readType();\n    length = code - 0x70;\n  }\n\n  debug('readArray() type: %s, code: %s', type, code);\n\n  if (type) {\n    result = {\n      $class: type,\n      $: list\n    };\n  } else {\n    result = list;\n  }\n\n  this._addRef(result);\n  this._readFixedLengthItems(length, list, withType);\n\n  if (!withType) {\n    return list;\n  }\n\n  return result;\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x56,\n  0x58,\n  [0x70, 0x77],\n  [0x78, 0x7f],\n], 'readArray');\n\nproto._readMap = function (map, withType) {\n  var code = this.byteBuffer.get(this.byteBuffer.position());\n  map = map || {};\n\n  if (supportES6Map) {\n    Object.defineProperty(map, '$map', {\n      value: new Map(),\n      enumerable: false,\n    });\n  }\n\n  var k;\n  var v;\n  // Z(0x5a) list/map terminator\n  while (code !== 0x5a) {\n    k = this.read(withType);\n    v = this.read(withType);\n    var key = is.object(k) && k.name ? k.name : k;\n    map[key] = v;\n    if (supportES6Map) {\n      map.$map.set(k, v);\n    }\n\n    code = this.byteBuffer.get(this.byteBuffer.position());\n  }\n\n  // got [Z], move forward 1 byte\n  this.byteBuffer.skip(1);\n  return map;\n};\n\n/**\n * A sparse array, untyped map (HashMap for Java)\n * hessian 2.0\n * @see http://hessian.caucho.com/doc/hessian-serialization.html#anchor27\n *\n * @return {Object}\n */\nproto.readHashMap = function (withType) {\n  // H: x48\n  var code = this.byteBuffer.get();\n  if (code !== 0x48) {\n    this.throwError('readHashMap', code);\n  }\n\n  var result = {};\n  this._addRef(result);\n  this._readMap(result, withType);\n  return handle({ $class: 'java.util.HashMap', $: result }, withType);\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x48\n], 'readHashMap');\n\n/**\n * read an map from buffer\n *\n * v2.0\n * ```\n * map        ::= M(x4d) [type] (value value)* Z\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##map\n * ```\n * Represents serialized maps and can represent objects.\n * The type element describes the type of the map.\n * The type may be empty, i.e. a zero length.\n * The parser is responsible for choosing a type if one is not specified.\n * For objects, unrecognized keys will be ignored.\n *\n * Each map is added to the reference list. Any time the parser expects a map,\n * it must also be able to support a null or a ref.\n *\n * The type is chosen by the service.\n *\n * @param {Boolean} withType if need retain the type info\n * @return {Object}\n * @api public\n */\nproto.readMap = function (withType) {\n  var code = this.byteBuffer.get();\n  if (code !== 0x4d) {\n    this.throwError('readMap', code);\n  }\n\n  var type = this.readType();\n  debug('readMap() got type: %j, withType: %s', type, withType);\n  if (!type) {\n    var map = {};\n    this._addRef(map);\n    this._readMap(map);\n    return handle({ $class: 'java.util.HashMap', $: map }, withType);\n  }\n\n  var result = {\n    $class: type,\n    $: {}\n  };\n\n  // obj maybe refers to itself\n  this._addRef(result);\n  this._readMap(result.$, withType);\n\n  if (/Exception$/.test(type)) {\n    result.$ = new JavaExceptionError(result);\n  }\n\n  return handle(result, withType);\n};\n\nutils.addByteCodes(BYTE_CODES, [\n  0x4d\n], 'readMap');\n\nmodule.exports = Decoder;\n"
  },
  {
    "path": "lib/v2/encoder.js",
    "content": "'use strict';\n\nvar debug = require('util').debuglog('hessian:v2:encoder');\nvar is = require('is-type-of');\nvar util = require('util');\nvar Long = require('long');\nvar utility = require('utility');\nvar javaObject = require('../object');\nvar EncoderV1 = require('../v1/encoder');\nvar supportES6Map = require('../utils').supportES6Map;\n\nfunction Encoder(options) {\n  EncoderV1.call(this, options);\n\n  this._classRefs = [];\n  this._classRefFields = {};\n  this._typeRefs = [];\n}\n\nutil.inherits(Encoder, EncoderV1);\n\nvar proto = Encoder.prototype;\n\n/**\n * clean the buf\n */\nproto.reset = proto.clean = function () {\n  EncoderV1.prototype.clean.call(this);\n  this._classRefs = [];\n  this._classRefFields = {};\n  this._typeRefs = [];\n  return this;\n};\n\nvar INT_DIRECT_MIN = -0x10; // -16\nvar INT_DIRECT_MAX = 0x2f;  // 47\nvar INT_ZERO = 0x90;        // 144\n\nvar INT_BYTE_MIN = -0x800;  // -2048\nvar INT_BYTE_MAX = 0x7ff;   // 2047\nvar INT_BYTE_ZERO = 0xc8;   // 200\n\nvar INT_SHORT_MIN = -0x40000; // -262144\nvar INT_SHORT_MAX = 0x3ffff;  // 262143\nvar INT_SHORT_ZERO = 0xd4;    // 212\n\n/**\n * encode int\n *\n * v1.0\n * ```\n * int ::= I(x49) b3 b2 b1 b0\n * ```\n *\n * v2.0\n * ```\n * int ::= I(x49) b3 b2 b1 b0\n *     ::= [x80-xbf]\n *     ::= [xc0-xcf] b0\n *     ::= [xd0-xd7] b1 b0\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##int\n * ```\n */\nproto.writeInt = function (val) {\n  this._assertType('writeInt', 'int32', val);\n  if (INT_DIRECT_MIN <= val && val <= INT_DIRECT_MAX) {\n    this.byteBuffer.put(val + INT_ZERO);\n  } else if (INT_BYTE_MIN <= val && val <= INT_BYTE_MAX) {\n    var b0 = val & 0xff;\n    var code = (val >> 8) + INT_BYTE_ZERO;\n    this.byteBuffer.put(code).put(b0);\n  } else if (INT_SHORT_MIN <= val && val <= INT_SHORT_MAX) {\n    var b1b0 = val & 0xffff;\n    var code = (val >> 16) + INT_SHORT_ZERO;\n    this.byteBuffer.put(code).putUInt16(b1b0);\n  } else {\n    this.byteBuffer\n      .put(0x49)\n      .putInt(val);\n  }\n  return this;\n};\n\n/**\n * encode long\n *\n * warning: we won't check if the long value is out of bound, be careful!\n *\n * v1.0\n * ```\n * long ::= L(x4c) b7 b6 b5 b4 b3 b2 b1 b0\n * ```\n *\n * v2.0\n * ```\n * long ::= L(x4c) b7 b6 b5 b4 b3 b2 b1 b0\n *      ::= [xd8-xef]\n *      ::= [xf0-xff] b0\n *      ::= [x38-x3f] b1 b0\n *      ::= x4c b3 b2 b1 b0\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##long\n * ```\n * A 64-bit signed integer. An long is represented by the octet x4c ('L' )\n * followed by the 8-bytes of the integer in big-endian order.\n *\n * single octet longs:\n * Longs between -8 and 15 are represented by a single octet in the range xd8 to xef.\n * ```\n * value = (code - 0xe0)\n * ```\n *\n * two octet longs:\n * Longs between -2048 and 2047 are encoded in two octets with the leading byte in the range xf0 to xff.\n * ```\n * value = ((code - 0xf8) << 8) + b0\n * ```\n *\n * three octet longs:\n * Longs between -262144 and 262143 are encoded in three octets with the leading byte in the range x38 to x3f.\n * ```\n * value = ((code - 0x3c) << 16) + (b1 << 8) + b0\n * ```\n *\n * four octet longs:\n * Longs between which fit into 32-bits are encoded in five octets with the leading byte x59.\n * ```\n * value = (b3 << 24) + (b2 << 16) + (b1 << 8) + b0\n * ```\n */\nproto.writeLong = function (val) {\n  if (typeof val === 'string') {\n    if (!utility.isSafeNumberString(val)) {\n      val = Long.fromString(val);\n    } else {\n      val = Number(val);\n    }\n  } else if (Long.isLong(val) && (val.high === 0 || val.high === -1)) {\n    val = val.toNumber();\n  }\n\n  if (typeof val === 'number') {\n    if (val >= -8 && val <= 15) {\n      this.byteBuffer.put(val + 0xe0);\n    } else if (val >= -2048 && val <= 2047) {\n      var b0 = val & 0xff;\n      var code = (val >> 8) + 0xf8;\n      this.byteBuffer.put(code).put(b0);\n    } else if (val >= -262144 && val <= 262143) {\n      var b1b0 = val & 0xffff;\n      var code = (val >> 16) + 0x3c;\n      this.byteBuffer.put(code).putUInt16(b1b0);\n    } else if (val >= -0x80000000 && val <= 0x7fffffff) {\n      // 32-bit integer cast to long\n      this.byteBuffer.put(0x59).putInt32(val);\n    } else {\n      this.byteBuffer\n        .put(0x4c) // 'L'\n        .putLong(val);\n    }\n  } else {\n    this.byteBuffer\n      .put(0x4c) // 'L'\n      .putLong(val);\n  }\n  return this;\n};\n\n/**\n * encode double\n *\n * v1.0\n * ```\n * double ::= D(x44) b7 b6 b5 b4 b3 b2 b1 b0\n * ```\n *\n * v2.0\n * ```\n * double ::= D(x44) b7 b6 b5 b4 b3 b2 b1 b0\n *        ::= x5b\n *        ::= x5c\n *        ::= x5d(byte) b0\n *        ::= x5e(short) b1 b0\n *        ::= x5f(float) b3 b2 b1 b0\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##double\n * ```\n * The double 0.0 can be represented by the octet x5b\n * The double 1.0 can be represented by the octet x5c\n *\n * double octet:\n * Doubles between -128.0 and 127.0 with no fractional component\n * can be represented in two octets by casting the byte value to a double.\n * ```\n * value = (double) b0\n * ```\n *\n * double short:\n * Doubles between -32768.0 (-0x8000) and 32767.0(0x8000 - 1) with no fractional component\n * can be represented in three octets by casting the short value to a double.\n * ```\n * value = (double) (256 * b1 + b0)\n * ```\n *\n * double float:\n * Doubles which are equivalent to their 32-bit float representation\n * can be represented as the 4-octet float and then cast to double.\n */\nproto.writeDouble = function (val) {\n  var intValue = parseInt(val);\n  if (intValue === val) {\n    if (val === 0) {\n      this.byteBuffer.put(0x5b);\n      return this;\n    } else if (val === 1) {\n      this.byteBuffer.put(0x5c);\n      return this;\n    } else if (-0x80 <= intValue && intValue < 0x80) {\n      this.byteBuffer.put(0x5d).put(intValue);\n      return this;\n    } else if (-0x8000 <= intValue && intValue < 0x8000) {\n      this.byteBuffer.put(0x5e).putInt16(intValue);\n      return this;\n    }\n  }\n\n  var mills = parseInt(val * 1000, 10);\n  if (is.int32(mills) && mills * 0.001 === val) {\n    // // 32-bit integer cast to double\n    this.byteBuffer.put(0x5f).putInt32(mills);\n    return this;\n  }\n\n  this.byteBuffer.put(0x44).putDouble(val);\n  return this;\n};\n\n/**\n * Writes a date to the stream.\n *\n * date ::= x4a b7 b6 b5 b4 b3 b2 b1 b0\n *      ::= x4b b4 b3 b2 b1 b0\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##date\n *\n * @param time the date in milliseconds from the epoch in UTC\n */\nproto.writeDate = function (milliEpoch) {\n  if (milliEpoch instanceof Date) {\n    milliEpoch = milliEpoch.getTime();\n  }\n\n  this._assertType('writeDate', 'number', milliEpoch);\n\n  if ((milliEpoch % 60000) === 0) {\n    // compact date\n    var minutes = milliEpoch / 60000;\n    if (minutes >= -0x80000000 && minutes <= 0x7fffffff) {\n      this.byteBuffer\n        .put(0x4b)\n        .putInt32(minutes);\n      return this;\n    }\n  }\n\n  this.byteBuffer\n    .putChar(0x4a)\n    .putLong(milliEpoch);\n  return this;\n};\n\n/**\n * encode buffer\n *\n * v1.0\n * ```\n * binary ::= [x62(b)] b1 b0 <binary-data> binary  # non-final chunk\n *        ::= x42(B) b1 b0 <binary-data>           # final chunk\n * ```\n *\n * v2.0\n * ```\n * binary ::= x41(A) b1 b0 <binary-data> binary    # non-final chunk\n *        ::= x42(B) b1 b0 <binary-data>           # final chunk\n *        ::= [x20-x2f] <binary-data>              # binary data of length 0-15\n *        ::= [x34-x37] b0 <binary-data>           # binary data of length 0-1023\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##binary\n * ```\n * The octet x42 ('B') encodes the final chunk and\n * x62 ('b') represents any non-final chunk.\n * Each chunk has a 16-bit length value.\n *\n * len = 256 * b1 + b0 # max length 32768(0x8000)\n *\n * Binary data with length less than 15 may be encoded by a single octet length [x20-x2f].\n *\n * len = code - 0x20\n */\nproto.writeBytes = function (buf) {\n  this._assertType('writeBytes', 'buffer', buf);\n  if (buf.length <= 15) {\n    this.byteBuffer.put(buf.length + 0x20).put(buf);\n    return this;\n  }\n\n  var offset = 0;\n  var left = buf.length - offset;\n  while (left > 4093) {\n    this.byteBuffer\n      .put(0x41) // 'A'\n      .putUInt16(4093)\n      .put(buf.slice(offset, offset + 4093));\n\n    offset += 4093;\n    left = buf.length - offset;\n  }\n\n  if (left <= 15) {\n    this.byteBuffer\n      .put(left + 0x20)\n      .put(buf.slice(offset));\n  } else if (left <= 1023) {\n    this.byteBuffer\n      .put((left >> 8) + 0x34)\n      .put(left)\n      .put(buf.slice(offset));\n  } else {\n    this.byteBuffer\n      .put(0x42) // 'B'\n      .putUInt16(left)\n      .put(buf.slice(offset));\n  }\n  return this;\n};\n\n/**\n * encode string\n *\n * v1.0\n * ```\n * string ::= s(x73) b1 b0 <utf8-data> string  # non-final chunk\n *        ::= S(x53) b1 b0 <utf8-data>         # string of length 0-65535\n * ```\n *\n * v2.0\n * ```\n * string ::= R(x52) b1 b0 <utf8-data> string  # non-final chunk\n *        ::= S(x53) b1 b0 <utf8-data>         # string of length 0-65535\n *        ::= [x00-x1f] <utf8-data>            # string of length 0-31\n *        ::= [x30-x33] b0 <utf8-data>         # string of length 0-1023\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##string\n * ```\n * A 16-bit unicode character string encoded in UTF-8. Strings are encoded in chunks.\n * x53 ('S') represents the final chunk and x52 ('R') represents any non-final chunk.\n * Each chunk has a 16-bit unsigned integer length value.\n *\n * The length is the number of 16-bit (0x8000) characters, which may be different than the number of bytes.\n * String chunks may not split surrogate pairs.\n *\n * short strings:\n * Strings with length less than 32 may be encoded with a single octet length [x00-x1f].\n * ```\n * [x00-x1f] <utf8-data>\n * ```\n */\nproto.writeString = function (str) {\n  this._assertType('writeString', 'string', str);\n\n  var length = str.length;\n  var strOffset = 0;\n  var sublen;\n  while (length > 0x8000) {\n    sublen = 0x8000;\n    // chunk can't end in high surrogate\n    var tail = str.charCodeAt(strOffset + sublen - 1);\n    if (0xd800 <= tail && tail <= 0xdbff) {\n      debug('writeString got tail: 0x%s', tail.toString(16));\n      sublen--;\n    }\n\n    this.byteBuffer\n      .put(0x52)\n      .putUInt16(sublen)\n      .putRawString(str.slice(strOffset, strOffset + sublen));\n\n    length -= sublen;\n    strOffset += sublen;\n    debug('writeString strOffset: %s, length: %s, sublen: %s', strOffset, length, sublen);\n  }\n\n  debug('writeString left length: %s', length);\n  if (length <= 31) {\n    // short strings\n    this.byteBuffer.put(length);\n  } else if (length <= 1023) {\n    this.byteBuffer\n      .put(48 + (length >> 8))\n      .put(length);\n  } else {\n    this.byteBuffer\n      .putChar('S')\n      .put(length >> 8)\n      .put(length);\n  }\n\n  this.byteBuffer.putRawString(str.slice(strOffset));\n  return this;\n};\n\nvar _typecache = {};\n\n/**\n * encode type\n *\n * v1.0\n * ```\n * type ::= 0x74(t) type-string-length(putUInt16) type-string(putRawString)\n * ```\n *\n * v2.0\n * ```\n * type ::= type-string(putRawString)\n *      ::= type-ref(writeInt)\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##type\n * ```\n *\n * A map or list includes a type attribute indicating the type name of the map or\n * list for object-oriented languages.\n *\n * Each type is added to the type map for future reference.\n *\n * type references:\n * Repeated type strings MAY use the type map to refer to a previously used type.\n * The type reference is zero-based over all the types encountered during parsing.\n */\nproto.writeType = function (type) {\n  type = type || '';\n  if (!type) {\n    return;\n  }\n\n  var ref = this._typeRefs.indexOf(type);\n  if (ref >= 0) {\n    this.writeInt(ref);\n  } else {\n    this._typeRefs.push(type);\n    if (_typecache[type]) {\n      this.byteBuffer.put(_typecache[type]);\n    } else {\n      var start = this.byteBuffer.position();\n      this.writeString(type);\n      var end = this.byteBuffer.position();\n      _typecache[type] = this.byteBuffer.copy(start, end);\n    }\n  }\n  return this;\n};\n\n/**\n * encode ref\n *\n * v1.0\n * ```\n * ref ::= R(0x52) int(putInt)\n * ```\n *\n * v2.0\n * ```\n * ref ::= (0x51) int(putInt)\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##ref\n * ```\n *\n * Each map or list is stored into an array as it is parsed.\n * ref selects one of the stored objects. The first object is numbered '0'.\n */\nproto.writeRef = function (value) {\n  this.byteBuffer.put(0x51);\n  this.writeInt(value);\n  return this;\n};\n\nvar _classcache = {};\n\n/**\n *\n * v2.0\n * ```\n * class-def  ::= 'C' string int string*\n * object     ::= 'O' int value*\n *            ::= [x60-x6f] value*\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##object\n * ```\n */\nproto._writeObjectBegin = function (type, fields) {\n  debug('_writeObjectBegin() type: %s', type);\n  var ref = this._classRefs.indexOf(type);\n  if (ref >= 0) {\n    if (ref <= 15) {\n      this.byteBuffer.put(0x60 + ref);\n    } else {\n      // O(x4f) type-string-length(writeInt) type-string(putRawString)\n      this.byteBuffer.putChar('O');\n      this.writeInt(ref);\n    }\n    return ref;\n  } else {\n    // class definition\n    this.byteBuffer.putChar('C');\n    this._classRefs.push(type);\n    this._classRefFields[type] = fields;\n    if (_classcache[type]) {\n      this.byteBuffer.put(_classcache[type]);\n    } else {\n      var start = this.byteBuffer.position();\n      this.writeString(type);\n      var end = this.byteBuffer.position();\n      _classcache[type] = this.byteBuffer.copy(start, end);\n    }\n    return -1;\n  }\n};\n\n// class definition:\n//\n// The object definition includes a mandatory type string, the number of fields,\n// and the field names. The object definition is stored in the object definition\n// map and will be referenced by object instances with an integer reference.\n//\n// object instantiation:\n//\n// The object instantiation creates a new object based on a previous definition.\n// The integer value refers to the object definition.\n//\n// type format: length(writeInt) stringbytes(putRawString)\nproto._writeObject = function (obj) {\n  var className = obj.$class;\n  var realObj = obj.$;\n  // hessian 2.0\n  // field defined sort must same as java Class defined\n  var keys = Object.keys(realObj);\n  var ref = this._writeObjectBegin(className, keys);\n  if (ref === -1) {\n    // writeDefinition20\n    // out.writeClassFieldLength(_fields.length);\n    this.writeInt(keys.length);\n    // write field names\n    for (var i = 0; i < keys.length; i++) {\n      var key = keys[i];\n      this.writeString(key);\n    }\n    this._writeObjectBegin(className);\n  }\n  keys = this._classRefFields[className];\n  // writeInstance\n  for (var i = 0; i < keys.length; i++) {\n    var key = keys[i];\n    this.write(realObj[key]);\n  }\n\n  return this;\n};\n\n/**\n * A sparse array\n *\n * ```\n * untyped map    ::= 'H' (value value)* 'Z'\n *\n * @see http://hessian.caucho.com/doc/hessian-serialization.html##map\n * ```\n *\n * @param {Object} obj simple obj\n * @return {this}\n */\nproto._writeHashMap = function (obj, type) {\n  debug('_writeHashMap() %j, fields: %j', obj);\n\n  if (type) {\n    this.byteBuffer.put(0x4d);\n    this.writeType(type);\n  } else {\n    this.byteBuffer.put(0x48); // H\n  }\n\n  if (supportES6Map && obj instanceof Map) {\n    obj.forEach(function (value, key) {\n      this.write(key);\n      this.write(value);\n    }, this);\n  } else {\n    // hash map must sort keys\n    var keys = Object.keys(obj).sort();\n    for (var i = 0; i < keys.length; i++) {\n      var k = keys[i];\n      this.writeString(k);\n      this.write(obj[k]);\n    }\n  }\n  this.byteBuffer.putChar('Z');\n  return this;\n};\n\n// Writes the list header to the stream.\n//\n// list ::= x55 type value* 'Z'   # variable-length list\n//      ::= 'V' type int value*   # fixed-length list\n//      ::= x57 value* 'Z'        # variable-length untyped list\n//      ::= x58 int value*        # fixed-length untyped list\n//      ::= [x70-77] type value*  # fixed-length typed list\n//      ::= [x78-7f] value*       # fixed-length untyped list\n//\n// @see http://hessian.caucho.com/doc/hessian-serialization.html##list\nproto._writeListBegin = function (length, type) {\n  if (length < 0) {\n    if (!type) {\n      this.byteBuffer.put(0x57);\n    } else {\n      this.byteBuffer.put(0x55);\n      this.writeType(type);\n    }\n    return true;\n  } else if (length <= 7) {\n    if (!type) {\n      this.byteBuffer.put(120 + length);\n    } else {\n      this.byteBuffer.put(112 + length);\n      this.writeType(type);\n    }\n    return false;\n  } else {\n    if (!type) {\n      this.byteBuffer.put(0x58);\n    } else {\n      this.byteBuffer.put(0x56);\n      this.writeType(type);\n    }\n    this.writeInt(length);\n    return false;\n  }\n};\n\nmodule.exports = Encoder;\n"
  },
  {
    "path": "lib/v2_optimize/decoder.js",
    "content": "'use strict';\n\nvar util = require('util');\nvar DecoderV2 = require('../v2/decoder');\nvar DecoderV1 = require('../v1/decoder');\n\nfunction Decoder(buf, classRefs) {\n  DecoderV2.call(this, buf);\n  this.classes = classRefs; // using passed in ref array\n}\n\nutil.inherits(Decoder, DecoderV2);\n\nvar proto = Decoder.prototype;\n\nproto.clean = function () {\n  DecoderV1.prototype.clean.call(this); // can not clean `this.classes`\n  this.types = [];\n  return this;\n};\n\nmodule.exports = Decoder;\n"
  },
  {
    "path": "lib/v2_optimize/encoder.js",
    "content": "'use strict';\n\nvar util = require('util');\nvar EncoderV2 = require('../v2/encoder');\nvar EncoderV1 = require('../v1/encoder');\n\nfunction Encoder(options) {\n  EncoderV2.call(this, options);\n\n  this._classRefs = options.classRefs;\n  this._classRefFields = options.classRefFields;\n  this._typeRefs = [];\n}\n\nutil.inherits(Encoder, EncoderV2);\n\nvar proto = Encoder.prototype;\n\n/**\n * clean the buf\n */\nproto.reset = proto.clean = function () {\n  EncoderV1.prototype.clean.call(this);\n  this._typeRefs = [];\n  return this;\n};\n\nmodule.exports = Encoder;\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"hessian.js\",\n  \"version\": \"2.11.0\",\n  \"description\": \"Hessian Serialization written by pure JavaScript, support all kind of types in Java.\",\n  \"main\": \"index.js\",\n  \"files\": [\n    \"index.js\",\n    \"lib\"\n  ],\n  \"scripts\": {\n    \"test\": \"egg-bin test\",\n    \"test-cov\": \"egg-bin cov\",\n    \"lint\": \"jshint .\",\n    \"ci\": \"npm run lint && npm run test-cov\",\n    \"benchmark\": \"node benchmark/encode.js && node benchmark/decode.js\",\n    \"contributor\": \"git-contributor\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://github.com/node-modules/hessian.js.git\"\n  },\n  \"keywords\": [\n    \"hessian\",\n    \"protocol\",\n    \"java\",\n    \"rpc\",\n    \"serialization\"\n  ],\n  \"author\": \"dead_horse <dead_horse@qq.com>\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/node-modules/hessian.js/issues\",\n    \"email\": \"dead_horse@qq.com\"\n  },\n  \"homepage\": \"https://github.com/node-modules/hessian.js\",\n  \"dependencies\": {\n    \"byte\": \"^2.0.0\",\n    \"is-type-of\": \"^1.2.1\",\n    \"long\": \"^4.0.0\",\n    \"utility\": \"^1.16.1\"\n  },\n  \"devDependencies\": {\n    \"beautify-benchmark\": \"^0.2.4\",\n    \"benchmark\": \"^2.1.4\",\n    \"egg-bin\": \"^6.3.0\",\n    \"git-contributor\": \"^2.0.0\",\n    \"js-to-java\": \"^2.6.1\",\n    \"jshint\": \"^2.10.2\"\n  },\n  \"engines\": {\n    \"node\": \">= 0.12.0\"\n  }\n}\n"
  },
  {
    "path": "test/array.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst hessian = require('..');\n\ndescribe('array.test.js', function () {\n  it('should write null v1', function () {\n    var b = hessian.encode([\n      {\n        $class: '[java.lang.Integer',\n        $: null\n      },\n      {\n        $class: '[java.lang.Integer',\n        $: [1]\n      }\n    ]);\n    var a = hessian.decode(b);\n    assert.deepEqual(a, [null, [1]]);\n  });\n\n  it('should write undefined v1', function () {\n    var b = hessian.encode([\n      {\n        $class: '[java.lang.Integer',\n        $: undefined\n      },\n      {\n        $class: '[java.lang.Integer',\n        $: [1]\n      }\n    ]);\n    var a = hessian.decode(b);\n    assert.deepEqual(a, [null, [1]]);\n  });\n\n  it('should write null v2', function () {\n    var b = hessian.encode([\n      {\n        $class: '[java.lang.Integer',\n        $: null\n      },\n      {\n        $class: '[java.lang.Integer',\n        $: [1]\n      }\n    ], '2.0');\n    var a = hessian.decode(b, '2.0');\n    assert.deepEqual(a, [null, [1]]);\n  });\n\n  it('should write undefined v2', function () {\n    var b = hessian.encode([\n      {\n        $class: '[java.lang.Integer',\n        $: undefined\n      },\n      {\n        $class: '[java.lang.Integer',\n        $: [1]\n      }\n    ], '2.0');\n    var a = hessian.decode(b, '2.0');\n    assert.deepEqual(a, [null, [1]]);\n  });\n});\n"
  },
  {
    "path": "test/binary.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst hessian = require('..');\nconst utils = require('./utils');\n\ndescribe('binary.test.js', function () {\n  it('should read \"foo\" binary', function () {\n    hessian.decode(Buffer.concat([new Buffer(['B'.charCodeAt(0), 0x00, 0x03]), new Buffer('foo')]));\n  });\n\n  it('should write \"foo\"', function () {\n    assert.deepEqual(\n      hessian.encode(new Buffer('foo')),\n      Buffer.concat([new Buffer(['B'.charCodeAt(0), 0x00, 0x03]), new Buffer('foo')])\n    );\n  });\n\n  it('should read and write empty binary', function () {\n    var empty = hessian.decode(new Buffer(['B'.charCodeAt(0), 0x00, 0x00]));\n    assert(Buffer.isBuffer(empty));\n    assert(empty.length === 0);\n\n    assert.deepEqual(\n      hessian.encode(new Buffer('')),\n      new Buffer(['B'.charCodeAt(0), 0x00, 0x00])\n    );\n  });\n\n  it('should write and read as java impl', function () {\n    var bytes = new Buffer(65535);\n    bytes.fill(0x41);\n    var buf = hessian.encode(bytes, '1.0');\n    assert(buf.length === utils.bytes('v1/bytes/65535').length);\n    assert.deepEqual(buf, utils.bytes('v1/bytes/65535'));\n    assert.deepEqual(hessian.decode(utils.bytes('v1/bytes/65535'), '1.0'), bytes);\n\n    var bytes = new Buffer(32768);\n    bytes.fill(0x41);\n    var buf = hessian.encode(bytes, '1.0');\n    assert(buf.length === utils.bytes('v1/bytes/32768').length);\n    assert.deepEqual(buf, utils.bytes('v1/bytes/32768'));\n    assert.deepEqual(hessian.decode(utils.bytes('v1/bytes/32768'), '1.0'), bytes);\n\n    var bytes = new Buffer(32769);\n    bytes.fill(0x41);\n    var buf = hessian.encode(bytes, '1.0');\n    assert(buf.length === utils.bytes('v1/bytes/32769').length);\n    assert.deepEqual(buf, utils.bytes('v1/bytes/32769'));\n    assert.deepEqual(hessian.decode(utils.bytes('v1/bytes/32769'), '1.0'), bytes);\n\n    var bytes = new Buffer(32767);\n    bytes.fill(0x41);\n    var buf = hessian.encode(bytes, '1.0');\n    assert(buf.length === utils.bytes('v1/bytes/32767').length);\n    assert.deepEqual(buf, utils.bytes('v1/bytes/32767'));\n    assert.deepEqual(hessian.decode(utils.bytes('v1/bytes/32767'), '1.0'), bytes);\n\n    var bytes = new Buffer(32769);\n    bytes.fill(0x41);\n    var buf = hessian.encode(bytes, '1.0');\n    assert(buf.length === utils.bytes('v1/bytes/32769').length);\n    assert.deepEqual(buf, utils.bytes('v1/bytes/32769'));\n    assert.deepEqual(hessian.decode(utils.bytes('v1/bytes/32769'), '1.0'), bytes);\n\n    var bytes = new Buffer(42769);\n    bytes.fill(0x41);\n    var buf = hessian.encode(bytes, '1.0');\n    assert(buf.length === utils.bytes('v1/bytes/42769').length);\n    assert.deepEqual(buf, utils.bytes('v1/bytes/42769'));\n    assert.deepEqual(hessian.decode(utils.bytes('v1/bytes/42769'), '1.0'), bytes);\n\n    var bytes = new Buffer(82769);\n    bytes.fill(0x41);\n    var buf = hessian.encode(bytes, '1.0');\n    assert(buf.length === utils.bytes('v1/bytes/82769').length);\n    assert.deepEqual(buf, utils.bytes('v1/bytes/82769'));\n    assert.deepEqual(hessian.decode(utils.bytes('v1/bytes/82769'), '1.0'), bytes);\n  });\n\n  describe('v2.0', function () {\n    it('should read zero length binary data', function () {\n      var buf = hessian.decode(new Buffer([0x20]), '2.0');\n      assert(buf.length === 0);\n      assert.deepEqual(buf, new Buffer(0));\n    });\n\n    it('should read short datas', function () {\n      var decoder = new hessian.DecoderV2(new Buffer([0x20, 0x23, 0x23, 0x02, 0x03, 0x20]));\n      var buf = decoder.read();\n      assert(buf.length === 0);\n      assert.deepEqual(buf, new Buffer(0));\n\n      buf = decoder.read();\n      assert(buf.length === 3);\n      assert.deepEqual(buf, new Buffer([0x23, 2, 3]));\n\n      buf = decoder.read();\n      assert(buf.length === 0);\n      assert.deepEqual(buf, new Buffer(0));\n      decoder.clean();\n    });\n\n    it('should read max length short datas', function () {\n      var input = new Buffer(16);\n      input.fill(0x2f);\n      input[0] = 0x2f;\n      var buf = hessian.decode(input, '2.0');\n      assert(buf.length === 15);\n      var output = new Buffer(15);\n      output.fill(0x2f);\n      assert.deepEqual(buf, output);\n\n      var buf15 = new Buffer(15);\n      buf15.fill(0x41);\n      assert.deepEqual(hessian.encode(buf15, '2.0'), utils.bytes('v2/bytes/15'));\n      assert.deepEqual(hessian.decode(utils.bytes('v2/bytes/15'), '2.0'), buf15);\n\n      var buf16 = new Buffer(16);\n      buf16.fill(0x41);\n      assert.deepEqual(hessian.encode(buf16, '2.0'), utils.bytes('v2/bytes/16'));\n      assert.deepEqual(hessian.decode(utils.bytes('v2/bytes/16'), '2.0'), buf16);\n    });\n\n    it('should read long binary', function () {\n      var buf = hessian.encode(new Buffer(65535), '2.0');\n      assert(buf[0] === 0x41);\n      hessian.decode(buf, '2.0');\n\n      buf = hessian.encode(new Buffer(65536), '2.0');\n      hessian.decode(buf, '2.0');\n\n      buf = hessian.encode(new Buffer(65535 * 2 - 10), '2.0');\n      hessian.decode(buf, '2.0');\n    });\n\n    it('should write short binary', function () {\n      assert.deepEqual(hessian.encode(new Buffer(''), '2.0'), new Buffer([0x20]));\n    });\n\n    it('should write and read as java impl', function () {\n      var bytes = new Buffer(65535);\n      bytes.fill(0x41);\n      var buf = hessian.encode(bytes, '2.0');\n      assert(buf.length === utils.bytes('v2/bytes/65535').length);\n      assert.deepEqual(buf, utils.bytes('v2/bytes/65535'));\n      assert.deepEqual(hessian.decode(utils.bytes('v2/bytes/65535'), '2.0'), bytes);\n\n      var bytes = new Buffer(32768);\n      bytes.fill(0x41);\n      var buf = hessian.encode(bytes, '2.0');\n      assert(buf.length === utils.bytes('v2/bytes/32768').length);\n      assert.deepEqual(buf, utils.bytes('v2/bytes/32768'));\n      assert.deepEqual(hessian.decode(utils.bytes('v2/bytes/32768'), '2.0'), bytes);\n\n      var bytes = new Buffer(32769);\n      bytes.fill(0x41);\n      var buf = hessian.encode(bytes, '2.0');\n      assert(buf.length === utils.bytes('v2/bytes/32769').length);\n      assert.deepEqual(buf, utils.bytes('v2/bytes/32769'));\n      assert.deepEqual(hessian.decode(utils.bytes('v2/bytes/32769'), '2.0'), bytes);\n\n      var bytes = new Buffer(32767);\n      bytes.fill(0x41);\n      var buf = hessian.encode(bytes, '2.0');\n      assert(buf.length === utils.bytes('v2/bytes/32767').length);\n      assert.deepEqual(buf, utils.bytes('v2/bytes/32767'));\n      assert.deepEqual(hessian.decode(utils.bytes('v2/bytes/32767'), '2.0'), bytes);\n\n      var bytes = new Buffer(32769);\n      bytes.fill(0x41);\n      var buf = hessian.encode(bytes, '2.0');\n      assert(buf.length === utils.bytes('v2/bytes/32769').length);\n      assert.deepEqual(buf, utils.bytes('v2/bytes/32769'));\n      assert.deepEqual(hessian.decode(utils.bytes('v2/bytes/32769'), '2.0'), bytes);\n\n      var bytes = new Buffer(42769);\n      bytes.fill(0x41);\n      var buf = hessian.encode(bytes, '2.0');\n      assert(buf.length === utils.bytes('v2/bytes/42769').length);\n      assert.deepEqual(buf, utils.bytes('v2/bytes/42769'));\n      assert.deepEqual(hessian.decode(utils.bytes('v2/bytes/42769'), '2.0'), bytes);\n\n      var bytes = new Buffer(82769);\n      bytes.fill(0x41);\n      var buf = hessian.encode(bytes, '2.0');\n      assert(buf.length === utils.bytes('v2/bytes/82769').length);\n      assert.deepEqual(buf, utils.bytes('v2/bytes/82769'));\n      assert.deepEqual(hessian.decode(utils.bytes('v2/bytes/82769'), '2.0'), bytes);\n    });\n  });\n});\n"
  },
  {
    "path": "test/boolean.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst hessian = require('..');\n\ndescribe('boolean.test.js', function () {\n  it('should read true and false', function () {\n    assert(hessian.decode(new Buffer('T')) === true);\n    assert(hessian.decode(new Buffer('F')) === false);\n  });\n\n  it('should write true and false', function () {\n    assert.deepEqual(hessian.encode(true), new Buffer('T'));\n    assert.deepEqual(hessian.encode(false), new Buffer('F'));\n  });\n\n  describe('v2.0', function () {\n    it('should read write as 1.0', function () {\n      assert.deepEqual(hessian.encode(true, '2.0'), new Buffer('T'));\n      assert.deepEqual(hessian.encode(false, '2.0'), new Buffer('F'));\n      assert(hessian.decode(new Buffer('T'), '2.0') === true);\n      assert(hessian.decode(new Buffer('F'), '2.0') === false);\n    });\n  });\n});\n"
  },
  {
    "path": "test/convert.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst java = require('js-to-java');\nconst hessian = require('..');\n\ndescribe('test/convert.test.js', function() {\n  [\n    '1.0', '2.0'\n  ].forEach(function(version) {\n    describe(version, function() {\n      it('should convert java.util.Locale to com.caucho.hessian.io.LocaleHandle', function() {\n        var buf1 = hessian.encode(java.Locale('zh_CN'), version);\n        var buf2 = hessian.encode({\n          $class: 'java.util.Locale',\n          $: 'zh_CN',\n        }, version);\n        assert.deepEqual(buf1, buf2);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "test/custom_handler.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst hessian = require('..');\nconst supportES6Map = require('../lib/utils').supportES6Map;\n\ndescribe('utils.test.js', function () {\n  describe('v1.0', function () {\n  \tit('should decode with custom handler', function () {\n  \t\thessian.registerDecodeHandler('java.math.BigDecimal', function (result) {\n        return {\n          $class: result.$class,\n          $: result.$.value,\n        };\n  \t\t});\n      var o = { $class: 'java.math.BigDecimal', $: { value: '100.06' } };\n      var buf = hessian.encode(o, '1.0');\n      var output = hessian.decode(buf, '1.0');\n      assert(output === '100.06');\n      hessian.deregisterDecodeHandler('java.math.BigDecimal');\n      output = hessian.decode(buf, '1.0');\n      assert.deepEqual(output, { value: '100.06' });\n  \t});\n\n  \tif (!supportES6Map) {\n  \t\treturn;\n  \t}\n\n  \tit('should decode map with custom handler', function () {\n  \t\thessian.registerDecodeHandler('java.util.HashMap', function (result) {\n        return {\n          $class: result.$class,\n          $: result.$.$map,\n        };\n  \t\t});\n      var map = new Map();\n      map.set(1, 'fee');\n      map.set(2, 'fie');\n      map.set(3, 'foe');\n      var buf = hessian.encode({\n        $class: 'java.util.HashMap',\n        $: map\n      }, '1.0');\n      var output = hessian.decode(buf, '1.0');\n      assert(output instanceof Map);\n      assert(output.get(1) === 'fee');\n      assert(output.get(2) === 'fie');\n      assert(output.get(3) === 'foe');\n      hessian.deregisterDecodeHandler('java.util.HashMap');\n  \t});\n  });\n\n  describe('v2.0', function () {\n  \tit('should decode with custom handler', function () {\n  \t\thessian.registerDecodeHandler('java.math.BigDecimal', function (result) {\n        return {\n          $class: result.$class,\n          $: result.$.value,\n        };\n  \t\t});\n      var o = { $class: 'java.math.BigDecimal', $: { value: '100.06' } };\n      var buf = hessian.encode(o, '2.0');\n      var output = hessian.decode(buf, '2.0');\n      assert(output === '100.06');\n      hessian.deregisterDecodeHandler('java.math.BigDecimal');\n      output = hessian.decode(buf, '2.0');\n      assert.deepEqual(output, { value: '100.06' });\n  \t});\n\n    it('should decode with custom handler if has ref', function () {\n  \t\thessian.registerDecodeHandler('java.math.BigDecimal', function (result) {\n        return {\n          $class: result.$class,\n          $: result.$.value,\n        };\n  \t\t});\n      var o = { $class: 'java.math.BigDecimal', $: { value: '100.06' } };\n      var map = new Map();\n      map.set(1, o);\n      map.set(2, o);\n      var buf = hessian.encode({\n        $class: 'java.util.HashMap',\n        $: map\n      }, '2.0');\n      var output = hessian.decode(buf, '2.0');\n      /**\n       * fix problem like ref object reuse\n       */\n      assert(output[1] === '100.06');\n      assert(output[2] === '100.06');\n      hessian.deregisterDecodeHandler('java.math.BigDecimal');\n      output = hessian.decode(buf, '2.0');\n      assert.deepEqual(output, {'1': { value: '100.06'}, '2': { value: '100.06' }});\n  \t});\n\n    it('should decode with custom handler if has ref and has circular ref', function () {\n      var circularObj = { value: '100.06' };\n      circularObj.ref = circularObj;\n  \t\thessian.registerDecodeHandler('java.test.circular', function (result) {\n        // must modify result in place to avoid circular problem\n        return {\n          $class: result.$class,\n          $: result.$,\n        };\n  \t\t});\n      var o = { $class: 'java.test.circular', $: circularObj };\n      var map = new Map();\n      map.set(1, o);\n      map.set(2, o);\n      var buf = hessian.encode({\n        $class: 'java.util.HashMap',\n        $: map\n      }, '2.0');\n      var output = hessian.decode(buf, '2.0');\n      /**\n       * fix problem like ref object reuse\n       */\n      assert(output[1].value === '100.06');\n      assert(output[2].value === '100.06');\n      assert(output[1].ref.ref.ref.ref.value === '100.06');\n      hessian.deregisterDecodeHandler('java.test.circular');\n  \t});\n\n  \tif (!supportES6Map) {\n  \t\treturn;\n  \t}\n\n  \tit('should decode map with custom handler', function () {\n  \t\thessian.registerDecodeHandler('java.util.HashMap', function (result) {\n        return {\n          $class: result.$class,\n          $: result.$.$map,\n        };\n  \t\t});\n      var map = new Map();\n      map.set(1, 'fee');\n      map.set(2, 'fie');\n      map.set(3, 'foe');\n      var buf = hessian.encode({\n        $class: 'java.util.HashMap',\n        $: map\n      }, '2.0');\n      var output = hessian.decode(buf, '2.0');\n      assert(output instanceof Map);\n      assert(output.get(1) === 'fee');\n      assert(output.get(2) === 'fie');\n      assert(output.get(3) === 'foe');\n      hessian.deregisterDecodeHandler('java.util.HashMap');\n  \t});\n  });\n});\n"
  },
  {
    "path": "test/date.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst hessian = require('..');\nconst utils = require('./utils');\n\ndescribe('date.test.js', function () {\n  var dateBuffer = new Buffer(['d'.charCodeAt(0), 0x00, 0x00, 0x00, 0xd0, 0x4b, 0x92, 0x84, 0xb8]);\n\n  it('should read date 2:51:31 May 8, 1998', function () {\n    var d = hessian.decode(dateBuffer);\n    assert(Object.prototype.toString.call(d) === '[object Date]');\n    assert(d.getFullYear() === 1998);\n    assert(d.getTime() === 894621091000);\n    assert(d.toUTCString() === 'Fri, 08 May 1998 09:51:31 GMT');\n    assert(d.toISOString() === '1998-05-08T09:51:31.000Z');\n  });\n\n  it('should write date 2:51:31 May 8, 1998', function () {\n    assert.deepEqual(hessian.encode(new Date(894621091000)), dateBuffer);\n  });\n\n  it('should write date 0 and read', function () {\n    assert.deepEqual(\n      hessian.encode(new Date(0)),\n      new Buffer(['d'.charCodeAt(0), 0, 0, 0, 0, 0, 0, 0, 0])\n    );\n  });\n\n  it('should read date 09:51:31 May 8, 1998 UTC', function () {\n    var d = hessian.decode(utils.bytes('v1/date/894621091000'), '1.0');\n    assert(Object.prototype.toString.call(d) === '[object Date]');\n    assert(d.getFullYear() === 1998);\n    assert(d.getTime() === 894621091000);\n    assert(d.toUTCString() === 'Fri, 08 May 1998 09:51:31 GMT');\n    assert(d.toISOString() === '1998-05-08T09:51:31.000Z');\n  });\n\n  it('should read date 09:51:00 May 8, 1998 UTC', function () {\n    var d = hessian.decode(utils.bytes('v1/date/894621060000'), '1.0');\n    assert(Object.prototype.toString.call(d) === '[object Date]');\n    assert(d.getFullYear() === 1998);\n    assert(d.getTime() === 894621060000);\n    assert(d.toUTCString() === 'Fri, 08 May 1998 09:51:00 GMT');\n    assert(d.toISOString() === '1998-05-08T09:51:00.000Z');\n  });\n\n  it('should write date', function () {\n    var now = new Date(1398280514000);\n    assert.deepEqual(hessian.encode(now, '1.0'), utils.bytes('v1/date/now'));\n    // read it\n    assert.deepEqual(hessian.decode(utils.bytes('v1/date/now'), '1.0'), now);\n  });\n\n  describe('hessian 2.0', function () {\n    it('should read date 09:51:31 May 8, 1998 UTC', function () {\n      var d = hessian.decode(utils.bytes('v2/date/894621091000'), '2.0');\n      assert(Object.prototype.toString.call(d) === '[object Date]');\n      assert(d.getFullYear() === 1998);\n      assert(d.getTime() === 894621091000);\n      assert(d.toUTCString() === 'Fri, 08 May 1998 09:51:31 GMT');\n      assert(d.toISOString() === '1998-05-08T09:51:31.000Z');\n    });\n\n    it('should read Compact: date in minutes, 09:51:00 May 8, 1998 UTC', function () {\n      var d = hessian.decode(utils.bytes('v2/date/894621060000'), '2.0');\n      assert(Object.prototype.toString.call(d) === '[object Date]');\n      assert(d.getFullYear() === 1998);\n      assert(d.getTime() === 894621060000);\n      assert(d.toUTCString() === 'Fri, 08 May 1998 09:51:00 GMT');\n      assert(d.toISOString() === '1998-05-08T09:51:00.000Z');\n    });\n\n    it('should write and read date, Thu, 23 Jan 6053 02:08:00 GMT', function () {\n      // Maximum of 32-bit integer\n      var overflow32BitInt = Math.pow(2, 31);\n      var milliseconds = overflow32BitInt * 60000;\n      var date = new Date();\n      date.setTime(milliseconds);\n\n      var bytes = utils.bytes('v2/date/' + milliseconds.toString());\n\n      assert.deepEqual(hessian.encode(date, '2.0'), bytes);\n      assert.deepEqual(hessian.decode(bytes, '2.0'), date);\n    });\n\n    it('should write and read date, Wed, 08 Dec -2114 21:53:00 GMT (2115 B.C.)', function () {\n      // Minimum of 32-bit integer\n      var overflow32BitInt = -1 * (Math.pow(2, 31) + 1);\n      var milliseconds = overflow32BitInt * 60000;\n      var date = new Date();\n      date.setTime(milliseconds);\n\n      var bytes = utils.bytes('v2/date/' + milliseconds.toString());\n\n      assert.deepEqual(hessian.encode(date, '2.0'), bytes);\n      assert.deepEqual(hessian.decode(bytes, '2.0'), date);\n    });\n\n\n    it('should write and read date', function () {\n      var now = new Date(1398280514000);\n      assert.deepEqual(hessian.encode(now, '2.0'), utils.bytes('v2/date/now'));\n      // read it\n      assert.deepEqual(hessian.decode(utils.bytes('v2/date/now'), '2.0'), now);\n    });\n\n    it('should write and read Wed Jan 04 1950 00:00:00 GMT+0800 (CST)', function () {\n      var date = new Date('Wed Jan 04 1950 00:00:00 GMT+0800 (CST)');\n      var bin = new Buffer('4bff5f8c60', 'hex');\n      assert.deepEqual(hessian.encode(date, '2.0'), bin);\n      assert.deepEqual(hessian.decode(bin, '2.0'), date);\n    });\n\n    // it('should read 1.0 format', function () {\n    //   hessian.decode(utils.bytes('v1/date/894621091000'), '2.0').getTime()\n    //     .should.equal(894621091000);\n    //   hessian.decode(utils.bytes('v1/date/894621060000'), '2.0').getTime()\n    //     .should.equal(894621060000);\n    //   hessian.decode(utils.bytes('v1/date/now'), '2.0').getTime()\n    //     .should.equal(1398280514000);\n    // });\n  });\n});\n"
  },
  {
    "path": "test/decode.circular.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst hessian = require('..');\nconst utils = require('./utils');\n\ndescribe('test/decode.circular.test.js', function () {\n\n  it('v1 decode()', function () {\n    var data = new Buffer([77, 116, 0, 49, 99, 111, 109, 46, 97, 108, 105, 112, 97, 121, 46, 99, 111, 110, 102, 105, 103, 115, 101, 114, 118, 101, 114, 46, 99, 111, 110, 102, 114, 101, 103, 95, 116, 101, 115, 116, 46, 79, 110, 108, 105, 110, 101, 77, 111, 100, 117, 108, 101, 83, 0, 6, 109, 111, 100, 117, 108, 101, 83, 0, 1, 97, 83, 0, 4, 100, 101, 115, 99, 83, 0, 1, 98, 83, 0, 8, 118, 101, 114, 115, 105, 111, 110, 115, 86, 108, 0, 0, 0, 1, 77, 116, 0, 57, 99, 111, 109, 46, 97, 108, 105, 112, 97, 121, 46, 99, 111, 110, 102, 105, 103, 115, 101, 114, 118, 101, 114, 46, 99, 111, 110, 102, 114, 101, 103, 95, 116, 101, 115, 116, 46, 79, 110, 108, 105, 110, 101, 77, 111, 100, 117, 108, 101, 36, 86, 101, 114, 115, 105, 111, 110, 83, 0, 7, 118, 101, 114, 115, 105, 111, 110, 83, 0, 1, 99, 83, 0, 6, 97, 115, 115, 101, 116, 115, 86, 108, 0, 0, 0, 1, 83, 0, 1, 105, 122, 83, 0, 6, 116, 104, 105, 115, 36, 48, 82, 0, 0, 0, 0, 122, 122, 122]);\n    var rs = hessian.decode(data);\n    assert(\n      JSON.stringify(rs) === '{\"module\":\"a\",\"desc\":\"b\",\"versions\":[{\"version\":\"c\",\"assets\":[\"i\"]}]}'\n    );\n  });\n\n\n  it('v2 decode()', function () {\n    var javabuf = utils.bytes('v2/object/ConnectionRequest');\n    var connreq1 = hessian.decode(javabuf, '2.0');\n    assert(connreq1.ctx && connreq1.ctx.id);\n    assert(JSON.stringify(connreq1) === '{\"ctx\":{\"id\":101}}');\n  });\n\n});\n"
  },
  {
    "path": "test/double.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst java = require('js-to-java');\nconst hessian = require('..');\nconst utils = require('./utils');\n\ndescribe('double.test.js', function () {\n  var doubleBuffer = new Buffer(['D'.charCodeAt(0),\n    0x40, 0x28, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00]);\n\n  it('should read double 12.25', function () {\n    assert(hessian.decode(doubleBuffer) === 12.25);\n  });\n\n  it('should write double 12.25', function () {\n    assert.deepEqual(hessian.encode(12.25), doubleBuffer);\n    assert.deepEqual(hessian.encode(java.double(12.25)), doubleBuffer);\n    assert.deepEqual(hessian.encode({\n      $class: 'double',\n      $: 12.25\n    }), doubleBuffer);\n  });\n\n  it('should write double 100', function () {\n    assert.deepEqual(\n      hessian.encode(java.double(100)),\n      new Buffer(['D'.charCodeAt(0), 0x40, 0x59, 0, 0, 0, 0, 0, 0])\n    );\n  });\n\n  it('should write double 0', function () {\n    assert.deepEqual(\n      hessian.encode(java.double(0)),\n      new Buffer(['D'.charCodeAt(0), 0, 0, 0, 0, 0, 0, 0, 0])\n    );\n  });\n\n  it('should write as java impl', function () {\n    assert.deepEqual(hessian.encode(java.double(0), '1.0'), utils.bytes('v1/double/0'));\n    assert.deepEqual(hessian.encode(java.double(0.0), '1.0'), utils.bytes('v1/double/0'));\n    assert.deepEqual(hessian.encode(java.double(1), '1.0'), utils.bytes('v1/double/1'));\n    assert.deepEqual(hessian.encode(java.double(1.0), '1.0'), utils.bytes('v1/double/1'));\n    assert.deepEqual(hessian.encode(java.double(10), '1.0'), utils.bytes('v1/double/10'));\n    assert.deepEqual(\n      hessian.encode(java.double(10.123), '1.0'),\n      utils.bytes('v1/double/10.123')\n    );\n    assert.deepEqual(hessian.encode(java.double(10.1), '1.0'), utils.bytes('v1/double/10.1'));\n    assert.deepEqual(hessian.encode(java.double(-128), '1.0'), utils.bytes('v1/double/-128'));\n    assert.deepEqual(\n      hessian.encode(java.double(-127.9999), '1.0'),\n      utils.bytes('v1/double/-127.9999')\n    );\n    assert.deepEqual(hessian.encode(java.double(127), '1.0'), utils.bytes('v1/double/127'));\n    assert.deepEqual(\n      hessian.encode(java.double(126.9989), '1.0'),\n      utils.bytes('v1/double/126.9989')\n    );\n    assert.deepEqual(\n      hessian.encode(java.double(-32768), '1.0'),\n      utils.bytes('v1/double/-32768')\n    );\n    assert.deepEqual(\n      hessian.encode(java.double(-32767.999), '1.0'),\n      utils.bytes('v1/double/-32767.999')\n    );\n    assert.deepEqual(hessian.encode(java.double(32767), '1.0'), utils.bytes('v1/double/32767'));\n    assert.deepEqual(\n      hessian.encode(java.double(32766.99999), '1.0'),\n      utils.bytes('v1/double/32766.99999')\n    );\n    assert.deepEqual(hessian.encode(java.double(32768), '1.0'), utils.bytes('v1/double/32768'));\n    assert.deepEqual(\n      hessian.encode(java.double(32767.99999), '1.0'),\n      utils.bytes('v1/double/32767.99999')\n    );\n\n    // float byte\n    assert.deepEqual(\n      hessian.encode(java.double(-2147483649), '1.0'),\n      utils.bytes('v1/double/-2147483649')\n    );\n    assert.deepEqual(\n      hessian.encode(java.double(-2147483648), '1.0'),\n      utils.bytes('v1/double/-2147483648')\n    );\n    assert.deepEqual(\n      hessian.encode(java.double(-2147483647), '1.0'),\n      utils.bytes('v1/double/-2147483647')\n    );\n    assert.deepEqual(\n      hessian.encode(java.double(-2147483610.123), '1.0'),\n      utils.bytes('v1/double/-2147483610.123')\n    );\n    assert.deepEqual(\n      hessian.encode(java.double(2147483648), '1.0'),\n      utils.bytes('v1/double/2147483648')\n    );\n    assert.deepEqual(\n      hessian.encode(java.double(2147483647), '1.0'),\n      utils.bytes('v1/double/2147483647')\n    );\n    assert.deepEqual(\n      hessian.encode(java.double(2147483646), '1.0'),\n      utils.bytes('v1/double/2147483646')\n    );\n    assert.deepEqual(\n      hessian.encode(java.double(2147483646.456), '1.0'),\n      utils.bytes('v1/double/2147483646.456')\n    );\n  });\n\n  it('should read java bin format', function () {\n    assert(hessian.decode(utils.bytes('v1/double/0'), '1.0') === 0);\n    assert(hessian.decode(utils.bytes('v1/double/1'), '1.0') === 1);\n    assert(hessian.decode(utils.bytes('v1/double/10'), '1.0') === 10);\n    assert(hessian.decode(utils.bytes('v1/double/10.123'), '1.0') === 10.123);\n    assert(hessian.decode(utils.bytes('v1/double/10.1'), '1.0') === 10.1);\n    assert(hessian.decode(utils.bytes('v1/double/-128'), '1.0') === -128);\n    assert(hessian.decode(utils.bytes('v1/double/-127.9999'), '1.0') === -127.9999);\n    assert(hessian.decode(utils.bytes('v1/double/127'), '1.0') === 127);\n    assert(hessian.decode(utils.bytes('v1/double/126.9989'), '1.0') === 126.9989);\n    assert(hessian.decode(utils.bytes('v1/double/-32768'), '1.0') === -32768);\n    assert(hessian.decode(utils.bytes('v1/double/-32767.999'), '1.0') === -32767.999);\n    assert(hessian.decode(utils.bytes('v1/double/32767'), '1.0') === 32767);\n    assert(\n      hessian.decode(utils.bytes('v1/double/32766.99999'), '1.0') === 32766.99999\n    );\n    assert(hessian.decode(utils.bytes('v1/double/32768'), '1.0') === 32768);\n    assert(\n      hessian.decode(utils.bytes('v1/double/32767.99999'), '1.0') === 32767.99999\n    );\n    assert(\n      hessian.decode(utils.bytes('v1/double/-2147483649'), '1.0') === -2147483649\n    );\n    assert(\n      hessian.decode(utils.bytes('v1/double/-2147483648'), '1.0') === -2147483648\n    );\n    assert(\n      hessian.decode(utils.bytes('v1/double/-2147483647'), '1.0') === -2147483647\n    );\n    assert(\n      hessian.decode(utils.bytes('v1/double/-2147483610.123'), '1.0') === -2147483610.123\n    );\n    assert(hessian.decode(utils.bytes('v1/double/2147483648'), '1.0') === 2147483648);\n    assert(hessian.decode(utils.bytes('v1/double/2147483647'), '1.0') === 2147483647);\n    assert(hessian.decode(utils.bytes('v1/double/2147483646'), '1.0') === 2147483646);\n    assert(\n      hessian.decode(utils.bytes('v1/double/2147483646.456'), '1.0') === 2147483646.456\n    );\n  });\n\n  describe('v2.0', function () {\n    it('should read 0.0 and 1.0', function () {\n      assert(hessian.decode(new Buffer([0x5b]), '2.0') === 0.0);\n      assert(hessian.decode(new Buffer([0x5c]), '2.0') === 1.0);\n    });\n\n    it('should read 8 bits double', function () {\n      assert(hessian.decode(new Buffer([0x5d, 0x00]), '2.0') === 0.0);\n      assert(hessian.decode(new Buffer([0x5d, 0x01]), '2.0') === 1.0);\n      assert(hessian.decode(new Buffer([0x5d, 0x80]), '2.0') === -128.0);\n      assert(hessian.decode(new Buffer([0x5d, 0x7f]), '2.0') === 127.0);\n    });\n\n    it('should read 16 bits double', function () {\n      assert(hessian.decode(new Buffer([0x5e, 0x00, 0x00]), '2.0') === 0.0);\n      assert(hessian.decode(new Buffer([0x5e, 0x00, 0x01]), '2.0') === 1.0);\n      assert(hessian.decode(new Buffer([0x5e, 0x00, 0x80]), '2.0') === 128.0);\n      assert(hessian.decode(new Buffer([0x5e, 0x00, 0x7f]), '2.0') === 127.0);\n      assert(hessian.decode(new Buffer([0x5e, 0x80, 0x00]), '2.0') === -32768.0);\n      assert(hessian.decode(new Buffer([0x5e, 0x7f, 0xff]), '2.0') === 32767.0);\n    });\n\n    it('should read 32 bits float double', function () {\n      assert(hessian.decode(new Buffer([0x5f, 0x00, 0x00, 0x00, 0x00]), '2.0') === 0.0);\n      assert(hessian.decode(new Buffer([0x5f, 0x00, 0x00, 0x2f, 0xda]), '2.0') === 12.25);\n    });\n\n    it('should read normal double', function () {\n      assert(\n        hessian.decode(new Buffer([0x44, 0x40, 0x24, 0, 0, 0, 0, 0, 0]), '2.0') === 10.0\n      );\n    });\n\n    it('should write 0.0 and 1.0', function () {\n      assert.deepEqual(hessian.encode(java.double(0), '2.0'), new Buffer([0x5b]));\n      assert.deepEqual(hessian.encode(java.double(0.0), '2.0'), new Buffer([0x5b]));\n\n      assert.deepEqual(hessian.encode(java.double(1), '2.0'), new Buffer([0x5c]));\n      assert.deepEqual(hessian.encode(java.double(1.0), '2.0'), new Buffer([0x5c]));\n    });\n\n    it('should write as java impl', function () {\n      assert.deepEqual(hessian.encode(java.double(0), '2.0'), utils.bytes('v2/double/0'));\n      assert.deepEqual(hessian.encode(java.double(0.0), '2.0'), utils.bytes('v2/double/0'));\n      assert.deepEqual(hessian.encode(java.double(1), '2.0'), utils.bytes('v2/double/1'));\n      assert.deepEqual(hessian.encode(java.double(1.0), '2.0'), utils.bytes('v2/double/1'));\n      assert.deepEqual(hessian.encode(java.double(10), '2.0'), utils.bytes('v2/double/10'));\n      assert.deepEqual(\n        hessian.encode(java.double(10.123), '2.0'),\n        utils.bytes('v2/double/10.123')\n      );\n      assert.deepEqual(hessian.encode(java.double(10.1), '2.0'), utils.bytes('v2/double/10.1'));\n      assert.deepEqual(hessian.encode(java.double(-128), '2.0'), utils.bytes('v2/double/-128'));\n      assert.deepEqual(\n        hessian.encode(java.double(-127.9999), '2.0'),\n        utils.bytes('v2/double/-127.9999')\n      );\n      assert.deepEqual(hessian.encode(java.double(127), '2.0'), utils.bytes('v2/double/127'));\n      assert.deepEqual(\n        hessian.encode(java.double(126.9989), '2.0'),\n        utils.bytes('v2/double/126.9989')\n      );\n      assert.deepEqual(\n        hessian.encode(java.double(-32768), '2.0'),\n        utils.bytes('v2/double/-32768')\n      );\n      assert.deepEqual(\n        hessian.encode(java.double(-32767.999), '2.0'),\n        utils.bytes('v2/double/-32767.999')\n      );\n      assert.deepEqual(hessian.encode(java.double(32767), '2.0'), utils.bytes('v2/double/32767'));\n      assert.deepEqual(\n        hessian.encode(java.double(32766.99999), '2.0'),\n        utils.bytes('v2/double/32766.99999')\n      );\n      assert.deepEqual(hessian.encode(java.double(32768), '2.0'), utils.bytes('v2/double/32768'));\n      assert.deepEqual(\n        hessian.encode(java.double(32767.99999), '2.0'),\n        utils.bytes('v2/double/32767.99999')\n      );\n\n      // float byte\n      assert(hessian.encode(java.double(-0x800000), '2.0').length === 9);\n      assert.deepEqual(hessian.encode(java.double(-0x800000), '2.0'), utils.bytes('v2/double/-0x800000'));\n      assert(hessian.encode(java.double(-0x80000000), '2.0').length === 9);\n      assert.deepEqual(hessian.encode(java.double(-0x80000000), '2.0'), utils.bytes('v2/double/-0x80000000'));\n      assert.deepEqual(hessian.encode(java.double(-2147483649), '2.0'), utils.bytes('v2/double/-2147483649'));\n      assert.deepEqual(hessian.encode(java.double(-2147483648), '2.0'), utils.bytes('v2/double/-2147483648'));\n      // hessian.encode(java.double(-2147483647), '2.0').should.eql(utils.bytes('v2/double/-2147483647'));\n      assert.deepEqual(\n        hessian.encode(java.double(-2147483610.123), '2.0'),\n        utils.bytes('v2/double/-2147483610.123')\n      );\n      // hessian.encode(java.double(2147483648), '2.0').should.eql(utils.bytes('v2/double/2147483648'));\n      // hessian.encode(java.double(2147483647), '2.0').should.eql(utils.bytes('v2/double/2147483647'));\n      // hessian.encode(java.double(2147483646), '2.0').should.eql(utils.bytes('v2/double/2147483646'));\n      assert.deepEqual(\n        hessian.encode(java.double(2147483646.456), '2.0'),\n        utils.bytes('v2/double/2147483646.456')\n      );\n    });\n\n    it('should read java bin format', function () {\n      assert(hessian.decode(utils.bytes('v2/double/0'), '2.0') === 0);\n      assert(hessian.decode(utils.bytes('v2/double/1'), '2.0') === 1);\n      assert(hessian.decode(utils.bytes('v2/double/10'), '2.0') === 10);\n      assert(hessian.decode(utils.bytes('v2/double/10.123'), '2.0') === 10.123);\n      assert(hessian.decode(utils.bytes('v2/double/10.1'), '2.0') === 10.1);\n      assert(hessian.decode(utils.bytes('v2/double/-128'), '2.0') === -128);\n      assert(hessian.decode(utils.bytes('v2/double/-127.9999'), '2.0') === -127.9999);\n      assert(hessian.decode(utils.bytes('v2/double/127'), '2.0') === 127);\n      assert(hessian.decode(utils.bytes('v2/double/126.9989'), '2.0') === 126.9989);\n      assert(hessian.decode(utils.bytes('v2/double/-32768'), '2.0') === -32768);\n      assert(hessian.decode(utils.bytes('v2/double/-32767.999'), '2.0') === -32767.999);\n      assert(hessian.decode(utils.bytes('v2/double/32767'), '2.0') === 32767);\n      assert(\n        hessian.decode(utils.bytes('v2/double/32766.99999'), '2.0') === 32766.99999\n      );\n      assert(hessian.decode(utils.bytes('v2/double/32768'), '2.0') === 32768);\n      assert(\n        hessian.decode(utils.bytes('v2/double/32767.99999'), '2.0') === 32767.99999\n      );\n\n      // float byte\n      assert(hessian.decode(utils.bytes('v2/double/-0x800000'), '2.0') === -0x800000);\n      assert(\n        hessian.decode(utils.bytes('v2/double/-0x80000000'), '2.0') === -0x80000000\n      );\n      assert(\n        hessian.decode(utils.bytes('v2/double/-2147483649'), '2.0') === -2147483649\n      );\n      assert(\n        hessian.decode(utils.bytes('v2/double/-2147483648'), '2.0') === -2147483648\n      );\n      assert(\n        hessian.decode(utils.bytes('v2/double/-2147483647'), '2.0') === -2147483647\n      );\n      assert(\n        hessian.decode(utils.bytes('v2/double/-2147483610.123'), '2.0') === -2147483610.123\n      );\n      assert(hessian.decode(utils.bytes('v2/double/2147483648'), '2.0') === 2147483648);\n      assert(hessian.decode(utils.bytes('v2/double/2147483647'), '2.0') === 2147483647);\n      assert(hessian.decode(utils.bytes('v2/double/2147483646'), '2.0') === 2147483646);\n      assert(\n        hessian.decode(utils.bytes('v2/double/2147483646.456'), '2.0') === 2147483646.456\n      );\n    });\n\n    it('should read java hessian 1.0 bin format', function () {\n      assert(hessian.decode(utils.bytes('v1/double/0'), '2.0') === 0);\n      assert(hessian.decode(utils.bytes('v1/double/1'), '2.0') === 1);\n      assert(hessian.decode(utils.bytes('v1/double/10'), '2.0') === 10);\n      assert(hessian.decode(utils.bytes('v1/double/10.123'), '2.0') === 10.123);\n      assert(hessian.decode(utils.bytes('v1/double/10.1'), '2.0') === 10.1);\n      assert(hessian.decode(utils.bytes('v1/double/-128'), '2.0') === -128);\n      assert(hessian.decode(utils.bytes('v1/double/-127.9999'), '2.0') === -127.9999);\n      assert(hessian.decode(utils.bytes('v1/double/127'), '2.0') === 127);\n      assert(hessian.decode(utils.bytes('v1/double/126.9989'), '2.0') === 126.9989);\n      assert(hessian.decode(utils.bytes('v1/double/-32768'), '2.0') === -32768);\n      assert(hessian.decode(utils.bytes('v1/double/-32767.999'), '2.0') === -32767.999);\n      assert(hessian.decode(utils.bytes('v1/double/32767'), '2.0') === 32767);\n      assert(\n        hessian.decode(utils.bytes('v1/double/32766.99999'), '2.0') === 32766.99999\n      );\n      assert(hessian.decode(utils.bytes('v1/double/32768'), '2.0') === 32768);\n      assert(\n        hessian.decode(utils.bytes('v1/double/32767.99999'), '2.0') === 32767.99999\n      );\n      assert(\n        hessian.decode(utils.bytes('v1/double/-2147483649'), '2.0') === -2147483649\n      );\n      assert(\n        hessian.decode(utils.bytes('v1/double/-2147483648'), '2.0') === -2147483648\n      );\n      assert(\n        hessian.decode(utils.bytes('v1/double/-2147483647'), '2.0') === -2147483647\n      );\n      assert(\n        hessian.decode(utils.bytes('v1/double/-2147483610.123'), '2.0') === -2147483610.123\n      );\n      assert(hessian.decode(utils.bytes('v1/double/2147483648'), '2.0') === 2147483648);\n      assert(hessian.decode(utils.bytes('v1/double/2147483647'), '2.0') === 2147483647);\n      assert(hessian.decode(utils.bytes('v1/double/2147483646'), '2.0') === 2147483646);\n      assert(\n        hessian.decode(utils.bytes('v1/double/2147483646.456'), '2.0') === 2147483646.456\n      );\n    });\n  });\n});\n"
  },
  {
    "path": "test/exception.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst hessian = require('..');\nconst utils = require('./utils');\n\ndescribe('exception.test.js', function () {\n  describe('v1.0', function () {\n    it('should read java exception as js error', function () {\n      var ioe = hessian.decode(utils.bytes('v1/exception/IOException'));\n      assert(ioe instanceof Error);\n      assert(ioe.name === 'java.io.IOException');\n      assert(ioe.message === 'this is a java IOException instance');\n      assert(\n        ioe.stack === 'java.io.IOException: this is a java IOException instance\\n    at hessian.Main.main (Main.java:1283)'\n      );\n\n      var ioe = hessian.decode(utils.bytes('v1/exception/IOException'), true);\n      assert(ioe.$ instanceof Error);\n      assert(ioe.$.name === 'java.io.IOException');\n      assert(ioe.$.message === 'this is a java IOException instance');\n      assert(\n        ioe.$.stack === 'java.io.IOException: this is a java IOException instance\\n    at hessian.Main.main (Main.java:1283)'\n      );\n\n      var e = hessian.decode(utils.bytes('v1/exception/UndeclaredThrowableException'));\n      assert(e instanceof Error);\n      assert((e instanceof Error) === true);\n      assert(e.name === 'java.io.IOException');\n      assert(e.message === 'this is a java IOException instance');\n      assert(\n        e.stack === 'java.io.IOException: this is a java IOException instance\\n    at hessian.Main.main (Main.java:1283)'\n      );\n      assert(e.cause);\n      assert(e.cause.detailMessage === 'this is a java IOException instance');\n\n      var e = hessian.decode(utils.bytes('v1/exception/UndeclaredThrowableException'), true);\n      assert(e.$ instanceof Error);\n      assert(e.$.name === 'java.io.IOException');\n      assert(e.$.message === 'this is a java IOException instance');\n      assert(\n        e.$.stack === 'java.io.IOException: this is a java IOException instance\\n    at hessian.Main.main (Main.java:1283)'\n      );\n      assert(e.$.cause);\n      assert(e.$.cause.$class === 'java.io.IOException');\n      assert(e.$.cause.$ instanceof Error);\n      assert(e.$.cause.$.name === 'java.io.IOException');\n\n      var e = hessian.decode(utils.bytes('v1/exception/UndeclaredThrowableException2'));\n      assert(e instanceof Error);\n      assert((e instanceof Error) === true);\n      assert(e.name === 'java.io.IOException');\n      assert(e.message === '模拟测试异常; this is a java IOException instance');\n      assert(\n        e.stack === 'java.io.IOException: 模拟测试异常; this is a java IOException instance\\n    at hessian.Main.main (Main.java:1303)'\n      );\n\n      var e = hessian.decode(utils.bytes('v1/exception/UndeclaredThrowableException2'), true);\n      assert(e.$ instanceof Error);\n      assert(e.$.name === 'java.io.IOException');\n      assert(e.$.message === '模拟测试异常; this is a java IOException instance');\n      assert(\n        e.$.stack === 'java.io.IOException: 模拟测试异常; this is a java IOException instance\\n    at hessian.Main.main (Main.java:1303)'\n      );\n    });\n  });\n\n  describe('v2.0', function () {\n    it('should read java exception as js error', function () {\n      var ioe = hessian.decode(utils.bytes('v2/exception/IOException'), '2.0');\n      assert(ioe instanceof Error);\n      assert((ioe instanceof Error) === true);\n      assert(ioe.name === 'java.io.IOException');\n      assert(ioe.message === 'this is a java IOException instance');\n      assert(\n        ioe.stack === 'java.io.IOException: this is a java IOException instance\\n    at hessian.Main.main (Main.java:1283)'\n      );\n\n      var e = hessian.decode(utils.bytes('v2/exception/UndeclaredThrowableException'), '2.0');\n      assert(e instanceof Error);\n      assert(e.name === 'java.io.IOException');\n      assert(e.message === 'this is a java IOException instance');\n      assert(\n        e.stack === 'java.io.IOException: this is a java IOException instance\\n    at hessian.Main.main (Main.java:1283)'\n      );\n\n      var e = hessian.decode(utils.bytes('v2/exception/UndeclaredThrowableException2'), '2.0');\n      assert(e instanceof Error);\n      assert(e.name === 'java.io.IOException');\n      assert(e.message === '模拟测试异常; this is a java IOException instance');\n      assert(e.stack === 'java.io.IOException: 模拟测试异常; this is a java IOException instance\\n    at hessian.Main.main (Main.java:1303)');\n\n      var e = hessian.decode(utils.bytes('v2/exception/UndeclaredThrowableException3'), '2.0');\n      assert(e instanceof Error);\n      assert(e.name === 'com.taobao.hsf.exception.HSFServiceAddressNotFoundException');\n      assert(e.message === 'HSFServiceAddressNotFoundException-');\n      assert(e.cause.stackTrace.length === 56);\n    });\n\n    // it('should read hessian 1.0 exception', function () {\n    //   var ioe = hessian.decode(utils.bytes('v1/exception/IOException'), '2.0');\n    //   ioe.should.be.an.Error;\n    //   should.ok((ioe instanceof Error) === true);\n    //   ioe.name.should.equal('java.io.IOException');\n    //   ioe.message.should.equal('this is a java IOException instance');\n    //   ioe.stack.should.equal('java.io.IOException: this is a java IOException instance\\n    at hessian.Main.main (Main.java:1283)');\n\n    //   var e = hessian.decode(utils.bytes('v1/exception/UndeclaredThrowableException'), '2.0');\n    //   e.should.be.an.Error;\n    //   should.ok((e instanceof Error) === true);\n    //   e.name.should.equal('java.io.IOException');\n    //   e.message.should.equal('this is a java IOException instance');\n    //   e.stack.should.equal('java.io.IOException: this is a java IOException instance\\n    at hessian.Main.main (Main.java:1283)');\n\n    //   var e = hessian.decode(utils.bytes('v1/exception/UndeclaredThrowableException2'), '2.0');\n    //   e.should.be.an.Error;\n    //   should.ok((e instanceof Error) === true);\n    //   e.name.should.equal('java.io.IOException');\n    //   e.message.should.equal('模拟测试异常; this is a java IOException instance');\n    //   e.stack.should.equal('java.io.IOException: 模拟测试异常; this is a java IOException instance\\n    at hessian.Main.main (Main.java:1303)');\n    // });\n  });\n});\n"
  },
  {
    "path": "test/fixtures/4k.txt",
    "content": "/*!\n * hessian.js - test/double.test.js\n *\n * Copyright(c) 2014\n * MIT Licensed\n *\n * Authors:\n *   fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)\n */\n\n\"use strict\";\n\n/**\n * Module dependencies.\n */\n\nvar should = require('should');\nvar java = require('js-to-java');\nvar hessian = require('../');\n\ndescribe('double.test.js', function () {\n  var doubleBuffer = new Buffer(['D'.charCodeAt(0),\n    0x40, 0x28, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00]);\n\n  it('should read double 12.25', function () {\n    hessian.decode(doubleBuffer).should.equal(12.25);\n  });\n\n  it('should write double 12.25', function () {\n    hessian.encode(12.25).should.eql(doubleBuffer);\n    hessian.encode(java.double(12.25)).should.eql(doubleBuffer);\n    hessian.encode({\n      $class: 'double',\n      $: 12.25\n    }).should.eql(doubleBuffer);\n  });\n\n  it('should write double 100', function () {\n    hessian.encode(java.double(100)).should.eql(\n      new Buffer(['D'.charCodeAt(0), 0x40, 0x59, 0, 0, 0, 0, 0, 0]));\n  });\n\n  it('should write double 0', function () {\n    hessian.encode(java.double(0)).should.eql(\n      new Buffer(['D'.charCodeAt(0), 0, 0, 0, 0, 0, 0, 0, 0]));\n  });\n\n  describe('v2.0', function () {\n    it('should read 0.0 and 1.0', function () {\n      hessian.decode(new Buffer([0x5b]), '2.0').should.equal(0.0);\n      hessian.decode(new Buffer([0x5c]), '2.0').should.equal(1.0);\n    });\n\n    it('should read 8 bits double', function () {\n      hessian.decode(new Buffer([0x5d, 0x00]), '2.0').should.equal(0.0);\n      hessian.decode(new Buffer([0x5d, 0x01]), '2.0').should.equal(1.0);\n      hessian.decode(new Buffer([0x5d, 0x80]), '2.0').should.equal(-128.0);\n      hessian.decode(new Buffer([0x5d, 0x7f]), '2.0').should.equal(127.0);\n    });\n\n    it('should read 16 bits double', function () {\n      hessian.decode(new Buffer([0x5e, 0x00, 0x00]), '2.0').should.equal(0.0);\n      hessian.decode(new Buffer([0x5e, 0x00, 0x01]), '2.0').should.equal(1.0);\n      hessian.decode(new Buffer([0x5e, 0x00, 0x80]), '2.0').should.equal(128.0);\n      hessian.decode(new Buffer([0x5e, 0x00, 0x7f]), '2.0').should.equal(127.0);\n      hessian.decode(new Buffer([0x5e, 0x80, 0x00]), '2.0').should.equal(-32768.0);\n      hessian.decode(new Buffer([0x5e, 0x7f, 0xff]), '2.0').should.equal(32767.0);\n    });\n\n    it('should read 32 bits float double', function () {\n      hessian.decode(new Buffer([0x5f, 0x00, 0x00, 0x00, 0x00]), '2.0').should.equal(0.0);\n      hessian.decode(new Buffer([0x5f, 0x41, 0x44, 0x00, 0x00]), '2.0').should.equal(12.25);\n    });\n\n    it('should read normal double', function () {\n      hessian.decode(new Buffer([0x44, 0x40, 0x24, 0, 0, 0, 0, 0, 0]), '2.0').should.equal(10.0);\n    });\n\n    it('should write 0.0 and 1.0', function () {\n      hessian.encode(java.double(0), '2.0').should.eql(new Buffer([0x5b]));\n      hessian.encode(java.double(0.0), '2.0').should.eql(new Buffer([0x5b]));\n\n      hessian.encode(java.double(1), '2.0').should.eql(new Buffer([0x5c]));\n      hessian.encode(java.double(1.0), '2.0').should.eql(new Buffer([0x5c]));\n    });\n\n    it('should write big double', function () {\n      hessian.encode(java.double(10), '2.0')\n        .should.eql(new Buffer([0x44, 0x40, 0x24, 0, 0, 0, 0, 0, 0]));\n    });\n  });\n});\n/*!\n * hessian.js - test/double.test.js\n *\n * Copyright(c) 2014\n * MIT Licensed\n *\n * Authors:\n *   fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)\n */\n\n\"use strict\";\n\n/**\n * Module dependencies.\n */\n\nvar should = require('should');\nvar java = require('js-to-java');\nvar hessian = require('../');\n\ndescribe('double.test.js', function () {\n  var doubleBuffer = new Buffer(['D'.charCodeAt(0),\n    0x40, 0x28, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00]);\n\n  it('should read double 12.25', function () {\n    hessian.decode(doubleBuffer).should.equal(12.25);\n  });\n\n  it('should write double 12.25', function () {\n    hessian.encode(12.25).should.eql(doubleBuffer);\n    hessian.encode(java.double(12.25)).should.eql(doubleBuffer);\n    hessian.encode({\n      $class: 'double',\n      $: 12.25\n    }).should.eql(doubleBuffer);\n  });\n\n  it('should write double 100', function () {\n    hessian.encode(java.double(100)).should.eql(\n      new Buffer(['D'.charCodeAt(0), 0x40, 0x59, 0, 0, 0, 0, 0, 0]));\n  });\n\n  it('should write double 0', function () {\n    hessian.encode(java.double(0)).should.eql(\n      new Buffer(['D'.charCodeAt(0), 0, 0, 0, 0, 0, 0, 0, 0]));\n  });\n\n  describe('v2.0', function () {\n    it('should read 0.0 and 1.0', function () {\n      hessian.decode(new Buffer([0x5b]), '2.0').should.equal(0.0);\n      hessian.decode(new Buffer([0x5c]), '2.0').should.equal(1.0);\n    });\n\n    it('should read 8 bits double', function () {\n      hessian.decode(new Buffer([0x5d, 0x00]), '2.0').should.equal(0.0);\n      hessian.decode(new Buffer([0x5d, 0x01]), '2.0').should.equal(1.0);\n      hessian.decode(new Buffer([0x5d, 0x80]), '2.0').should.equal(-128.0);\n      hessian.decode(new Buffer([0x5d, 0x7f]), '2.0').should.equal(127.0);\n    });\n\n    it('should read 16 bits double', function () {\n      hessian.decode(new Buffer([0x5e, 0x00, 0x00]), '2.0').should.equal(0.0);\n      hessian.decode(new Buffer([0x5e, 0x00, 0x01]), '2.0').should.equal(1.0);\n      hessian.decode(new Buffer([0x5e, 0x00, 0x80]), '2.0').should.equal(128.0);\n      hessian.decode(new Buffer([0x5e, 0x00, 0x7f]), '2.0').should.equal(127.0);\n      hessian.decode(new Buffer([0x5e, 0x80, 0x00]), '2.0').should.equal(-32768.0);\n      hessian.decode(new Buffer([0x5e, 0x7f, 0xff]), '2.0').should.equal(32767.0);\n    });\n\n    it('should read 32 bits float double', function () {\n      hessian.decode(new Buffer([0x5f, 0x00, 0x00, 0x00, 0x00]), '2.0').should.equal(0.0);\n      hessian.decode(new Buffer([0x5f, 0x41, 0x44, 0x00, 0x00]), '2.0').should.equal(12.25);\n    });\n\n    it('should read normal double', function () {\n      hessian.decode(new Buffer([0x44, 0x40, 0x24, 0, 0, 0, 0, 0, 0]), '2.0').should.equal(10.0);\n    });\n\n    it('should write 0.0 and 1.0', function () {\n      hessian.encode(java.double(0), '2.0').should.eql(new Buffer([0x5b]));\n      hessian.encode(java.double(0.0), '2.0').should.eql(new Buffer([0x5b]));\n\n      hessian.encode(java.double(1), '2.0').should.eql(new Buffer([0x5c]));\n      hessian.encode(java.double(1.0), '2.0').should.eql(new Buffer([0x5c]));\n    });\n\n    it('should write big double', function () {\n      hessian.encode(java.double(10), '2.0')\n        .should.eql(new Buffer([0x44, 0x40, 0x24, 0, 0, 0, 0, 0, 0]));\n    });\n  });\n});\n/*!\n * hessian.js - test/double.test.js\n *\n * Copyright(c) 2014\n * MIT Licensed\n *\n * Authors:\n *   fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)\n */\n\n\"use strict\";\n\n/**\n * Module dependencies.\n */\n\nvar should = require('should');\nvar java = require('js-to-java');\nvar hessian = require('../');\n\ndescribe('double.test.js', function () {\n  var doubleBuffer = new Buffer(['D'.charCodeAt(0),\n    0x40, 0x28, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00]);\n\n  it('should read double 12.25', function () {\n    hessian.decode(doubleBuffer).should.equal(12.25);\n  });\n\n  it('should write double 12.25', function () {\n    hessian.encode(12.25).should.eql(doubleBuffer);\n    hessian.encode(java.double(12.25)).should.eql(doubleBuffer);\n    hessian.encode({\n      $class: 'double',\n      $: 12.25\n    }).should.eql(doubleBuffer);\n  });\n\n  it('should write double 100', function () {\n    hessian.encode(java.double(100)).should.eql(\n      new Buffer(['D'.charCodeAt(0), 0x40, 0x59, 0, 0, 0, 0, 0, 0]));\n  });\n\n  it('should write double 0', function () {\n    hessian.encode(java.double(0)).should.eql(\n      new Buffer(['D'.charCodeAt(0), 0, 0, 0, 0, 0, 0, 0, 0]));\n  });\n\n  describe('v2.0', function () {\n    it('should read 0.0 and 1.0', function () {\n      hessian.decode(new Buffer([0x5b]), '2.0').should.equal(0.0);\n      hessian.decode(new Buffer([0x5c]), '2.0').should.equal(1.0);\n    });\n\n    it('should read 8 bits double', function () {\n      hessian.decode(new Buffer([0x5d, 0x00]), '2.0').should.equal(0.0);\n      hessian.decode(new Buffer([0x5d, 0x01]), '2.0').should.equal(1.0);\n      hessian.decode(new Buffer([0x5d, 0x80]), '2.0').should.equal(-128.0);\n      hessian.decode(new Buffer([0x5d, 0x7f]), '2.0').should.equal(127.0);\n    });\n\n    it('should read 16 bits double', function () {\n      hessian.decode(new Buffer([0x5e, 0x00, 0x00]), '2.0').should.equal(0.0);\n      hessian.decode(new Buffer([0x5e, 0x00, 0x01]), '2.0').should.equal(1.0);\n      hessian.decode(new Buffer([0x5e, 0x00, 0x80]), '2.0').should.equal(128.0);\n      hessian.decode(new Buffer([0x5e, 0x00, 0x7f]), '2.0').should.equal(127.0);\n      hessian.decode(new Buffer([0x5e, 0x80, 0x00]), '2.0').should.equal(-32768.0);\n      hessian.decode(new Buffer([0x5e, 0x7f, 0xff]), '2.0').should.equal(32767.0);\n    });\n\n    it('should read 32 bits float double', function () {\n      hessian.decode(new Buffer([0x5f, 0x00, 0x00, 0x00, 0x00]), '2.0').should.equal(0.0);\n      hessian.decode(new Buffer([0x5f, 0x41, 0x44, 0x00, 0x00]), '2.0').should.equal(12.25);\n    });\n\n    it('should read normal double', function () {\n      hessian.decode(new Buffer([0x44, 0x40, 0x24, 0, 0, 0, 0, 0, 0]), '2.0').should.equal(10.0);\n    });\n\n    it('should write 0.0 and 1.0', function () {\n      hessian.encode(java.double(0), '2.0').should.eql(new Buffer([0x5b]));\n      hessian.encode(java.double(0.0), '2.0').should.eql(new Buffer([0x5b]));\n\n      hessian.encode(java.double(1), '2.0').should.eql(new Buffer([0x5c]));\n      hessian.encode(java.double(1.0), '2.0').should.eql(new Buffer([0x5c]));\n    });\n\n    it('should write big double', function () {\n      hessian.encode(java.double(10), '2.0')\n        .should.eql(new Buffer([0x44, 0x40, 0x24, 0, 0, 0, 0, 0, 0]));\n    });\n  });\n});\n"
  },
  {
    "path": "test/int.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst hessian = require('..');\nconst utils = require('./utils');\n\ndescribe('int.test.js', function () {\n  it('should read integer 300', function () {\n    assert(\n      hessian.decode(new Buffer(['I'.charCodeAt(0), 0x00, 0x00, 0x01, 0x2c])) === 300\n    );\n  });\n\n  it('should write integer 300', function () {\n    assert.deepEqual(\n      hessian.encode(300),\n      new Buffer(['I'.charCodeAt(0), 0x00, 0x00, 0x01, 0x2c])\n    );\n  });\n\n  it('should write integer 0', function () {\n    assert.deepEqual(hessian.encode(0), new Buffer(['I'.charCodeAt(0), 0, 0, 0, 0]));\n  });\n\n  it('should write number as java write', function () {\n    assert.deepEqual(hessian.encode(0, '1.0'), utils.bytes('v1/number/0'));\n    assert.deepEqual(hessian.encode(1), utils.bytes('v1/number/1'));\n    assert.deepEqual(hessian.encode(10), utils.bytes('v1/number/10'));\n    assert.deepEqual(hessian.encode(16), utils.bytes('v1/number/16'));\n    assert.deepEqual(hessian.encode(2047), utils.bytes('v1/number/2047'));\n    assert.deepEqual(hessian.encode(255, '1.0'), utils.bytes('v1/number/255'));\n    assert.deepEqual(hessian.encode(256, '1.0'), utils.bytes('v1/number/256'));\n    assert.deepEqual(hessian.encode(262143, '1.0'), utils.bytes('v1/number/262143'));\n    assert.deepEqual(hessian.encode(262144, '1.0'), utils.bytes('v1/number/262144'));\n    assert.deepEqual(hessian.encode(46, '1.0'), utils.bytes('v1/number/46'));\n    assert.deepEqual(hessian.encode(47, '1.0'), utils.bytes('v1/number/47'));\n\n    assert.deepEqual(hessian.encode(-16, '1.0'), utils.bytes('v1/number/-16'));\n    assert.deepEqual(hessian.encode(-2048, '1.0'), utils.bytes('v1/number/-2048'));\n    assert.deepEqual(hessian.encode(-256), utils.bytes('v1/number/-256'));\n    assert.deepEqual(hessian.encode(-262144, '1.0'), utils.bytes('v1/number/-262144'));\n    assert.deepEqual(hessian.encode(-262145, '1.0'), utils.bytes('v1/number/-262145'));\n  });\n\n  it('should read java number bin', function () {\n    assert(hessian.decode(utils.bytes('v1/number/0'), '1.0') === 0);\n    assert(hessian.decode(utils.bytes('v1/number/1'), '1.0') === 1);\n    assert(hessian.decode(utils.bytes('v1/number/10'), '1.0') === 10);\n    assert(hessian.decode(utils.bytes('v1/number/16'), '1.0') === 16);\n    assert(hessian.decode(utils.bytes('v1/number/2047'), '1.0') === 2047);\n    assert(hessian.decode(utils.bytes('v1/number/255'), '1.0') === 255);\n    assert(hessian.decode(utils.bytes('v1/number/256'), '1.0') === 256);\n    assert(hessian.decode(utils.bytes('v1/number/262143'), '1.0') === 262143);\n    assert(hessian.decode(utils.bytes('v1/number/262144'), '1.0') === 262144);\n    assert(hessian.decode(utils.bytes('v1/number/46'), '1.0') === 46);\n    assert(hessian.decode(utils.bytes('v1/number/47'), '1.0') === 47);\n    assert(hessian.decode(utils.bytes('v1/number/-16'), '1.0') === -16);\n    assert(hessian.decode(utils.bytes('v1/number/-2048'), '1.0') === -2048);\n    assert(hessian.decode(utils.bytes('v1/number/-256'), '1.0') === -256);\n    assert(hessian.decode(utils.bytes('v1/number/-262144'), '1.0') === -262144);\n    assert(hessian.decode(utils.bytes('v1/number/-262145'), '1.0') === -262145);\n  });\n\n  describe('v2.0', function () {\n    it('should read compact integers', function () {\n      assert(hessian.decode(new Buffer([0x90]), '2.0') === 0);\n      assert(hessian.decode(new Buffer([0x80]), '2.0') === -16);\n      assert(hessian.decode(new Buffer([0xbf]), '2.0') === 47);\n\n      assert(hessian.decode(new Buffer([0xc8, 0x00]), '2.0') === 0);\n      assert(hessian.decode(new Buffer([0xc0, 0x00]), '2.0') === -2048);\n      assert(hessian.decode(new Buffer([0xc7, 0x00]), '2.0') === -256);\n      assert(hessian.decode(new Buffer([0xcf, 0xff]), '2.0') === 2047);\n\n      assert(hessian.decode(new Buffer([0xd4, 0x00, 0x00]), '2.0') === 0);\n      assert(hessian.decode(new Buffer([0xd0, 0x00, 0x00]), '2.0') === -262144);\n      assert(hessian.decode(new Buffer([0xd7, 0xff, 0xff]), '2.0') === 262143);\n\n      assert(\n        hessian.decode(new Buffer(['I'.charCodeAt(0), 0x00, 0x00, 0x00, 0x00]), '2.0') === 0\n      );\n      assert(\n        hessian.decode(new Buffer(['I'.charCodeAt(0), 0x00, 0x00, 0x01, 0x2c]), '2.0') === 300\n      );\n    });\n\n    it('should write number as java write', function () {\n      assert.deepEqual(hessian.encode(0, '2.0'), utils.bytes('v2/number/0'));\n      assert.deepEqual(hessian.encode(1, '2.0'), utils.bytes('v2/number/1'));\n      assert.deepEqual(hessian.encode(10, '2.0'), utils.bytes('v2/number/10'));\n      assert.deepEqual(hessian.encode(16, '2.0'), utils.bytes('v2/number/16'));\n      assert.deepEqual(hessian.encode(2047, '2.0'), utils.bytes('v2/number/2047'));\n      assert.deepEqual(hessian.encode(255, '2.0'), utils.bytes('v2/number/255'));\n      assert.deepEqual(hessian.encode(256, '2.0'), utils.bytes('v2/number/256'));\n      assert.deepEqual(hessian.encode(262143, '2.0'), utils.bytes('v2/number/262143'));\n      assert.deepEqual(hessian.encode(262144, '2.0'), utils.bytes('v2/number/262144'));\n      assert.deepEqual(hessian.encode(46, '2.0'), utils.bytes('v2/number/46'));\n      assert.deepEqual(hessian.encode(47, '2.0'), utils.bytes('v2/number/47'));\n      assert.deepEqual(hessian.encode(-16, '2.0'), utils.bytes('v2/number/-16'));\n      assert.deepEqual(hessian.encode(-2048, '2.0'), utils.bytes('v2/number/-2048'));\n      assert.deepEqual(hessian.encode(-256, '2.0'), utils.bytes('v2/number/-256'));\n      assert.deepEqual(hessian.encode(-262144, '2.0'), utils.bytes('v2/number/-262144'));\n      assert.deepEqual(hessian.encode(-262145, '2.0'), utils.bytes('v2/number/-262145'));\n    });\n\n    it('should read java number bin', function () {\n      assert(hessian.decode(utils.bytes('v2/number/0'), '2.0') === 0);\n      assert(hessian.decode(utils.bytes('v2/number/1'), '2.0') === 1);\n      assert(hessian.decode(utils.bytes('v2/number/10'), '2.0') === 10);\n      assert(hessian.decode(utils.bytes('v2/number/16'), '2.0') === 16);\n      assert(hessian.decode(utils.bytes('v2/number/2047'), '2.0') === 2047);\n      assert(hessian.decode(utils.bytes('v2/number/255'), '2.0') === 255);\n      assert(hessian.decode(utils.bytes('v2/number/256'), '2.0') === 256);\n      assert(hessian.decode(utils.bytes('v2/number/262143'), '2.0') === 262143);\n      assert(hessian.decode(utils.bytes('v2/number/262144'), '2.0') === 262144);\n      assert(hessian.decode(utils.bytes('v2/number/46'), '2.0') === 46);\n      assert(hessian.decode(utils.bytes('v2/number/47'), '2.0') === 47);\n      assert(hessian.decode(utils.bytes('v2/number/-16'), '2.0') === -16);\n      assert(hessian.decode(utils.bytes('v2/number/-2048'), '2.0') === -2048);\n      assert(hessian.decode(utils.bytes('v2/number/-256'), '2.0') === -256);\n      assert(hessian.decode(utils.bytes('v2/number/-262144'), '2.0') === -262144);\n      assert(hessian.decode(utils.bytes('v2/number/-262145'), '2.0') === -262145);\n    });\n\n    it('should read hessian 1.0 number bin', function () {\n      assert(hessian.decode(utils.bytes('v1/number/0'), '2.0') === 0);\n      assert(hessian.decode(utils.bytes('v1/number/1'), '2.0') === 1);\n      assert(hessian.decode(utils.bytes('v1/number/10'), '2.0') === 10);\n      assert(hessian.decode(utils.bytes('v1/number/16'), '2.0') === 16);\n      assert(hessian.decode(utils.bytes('v1/number/2047'), '2.0') === 2047);\n      assert(hessian.decode(utils.bytes('v1/number/255'), '2.0') === 255);\n      assert(hessian.decode(utils.bytes('v1/number/256'), '2.0') === 256);\n      assert(hessian.decode(utils.bytes('v1/number/262143'), '2.0') === 262143);\n      assert(hessian.decode(utils.bytes('v1/number/262144'), '2.0') === 262144);\n      assert(hessian.decode(utils.bytes('v1/number/46'), '2.0') === 46);\n      assert(hessian.decode(utils.bytes('v1/number/47'), '2.0') === 47);\n      assert(hessian.decode(utils.bytes('v1/number/-16'), '2.0') === -16);\n      assert(hessian.decode(utils.bytes('v1/number/-2048'), '2.0') === -2048);\n      assert(hessian.decode(utils.bytes('v1/number/-256'), '2.0') === -256);\n      assert(hessian.decode(utils.bytes('v1/number/-262144'), '2.0') === -262144);\n      assert(hessian.decode(utils.bytes('v1/number/-262145'), '2.0') === -262145);\n    });\n\n    it('should write compact integers', function () {\n      // -16 ~ 47\n      var buf = hessian.encode(0, '2.0');\n      assert(buf.length === 1);\n      assert(buf[0] === 0x90);\n      assert.deepEqual(buf, new Buffer([0x90]));\n\n      buf = hessian.encode(1, '2.0');\n      assert(buf.length === 1);\n      assert(buf[0] === 0x91);\n      assert.deepEqual(buf, new Buffer([0x91]));\n\n      buf = hessian.encode(-16, '2.0');\n      assert(buf.length === 1);\n      assert(buf[0] === 0x80);\n      assert.deepEqual(buf, new Buffer([0x80]));\n\n      buf = hessian.encode(46, '2.0');\n      assert(buf.length === 1);\n      assert(buf[0] === 0xbe);\n      assert.deepEqual(buf, new Buffer([0xbe]));\n\n      buf = hessian.encode(47, '2.0');\n      assert(buf.length === 1);\n      assert(buf[0] === 0xbf);\n      assert.deepEqual(buf, new Buffer([0xbf]));\n\n      // -2048 ~ 2047\n      buf = hessian.encode(-2048, '2.0');\n      assert(buf.length === 2);\n      assert(buf[0] === 0xc0);\n      assert(buf[1] === 0x00);\n      assert.deepEqual(buf, new Buffer([0xc0, 0x00]));\n\n      buf = hessian.encode(-256, '2.0');\n      assert(buf.length === 2);\n      assert(buf[0] === 0xc7);\n      assert(buf[1] === 0x00);\n      assert.deepEqual(buf, new Buffer([0xc7, 0x00]));\n\n      buf = hessian.encode(255, '2.0');\n      assert(buf.length === 2);\n      assert(buf[0] === 0xc8);\n      assert(buf[1] === 0xff);\n      assert.deepEqual(buf, new Buffer([0xc8, 0xff]));\n\n      buf = hessian.encode(256, '2.0');\n      assert(buf.length === 2);\n      assert(buf[0] === 0xc9);\n      assert(buf[1] === 0x00);\n      assert.deepEqual(buf, new Buffer([0xc9, 0x00]));\n\n      buf = hessian.encode(2047, '2.0');\n      assert(buf.length === 2);\n      assert(buf[0] === 0xcf);\n      assert(buf[1] === 0xff);\n      assert.deepEqual(buf, new Buffer([0xcf, 0xff]));\n\n      // -262144 ~ 262143\n      buf = hessian.encode(-262144, '2.0');\n      assert(buf.length === 3);\n      assert(buf[0] === 0xd0);\n      assert(buf[1] === 0x00);\n      assert(buf[2] === 0x00);\n      assert.deepEqual(buf, new Buffer([0xd0, 0x00, 0x00]));\n\n      buf = hessian.encode(262143, '2.0');\n      assert(buf.length === 3);\n      assert(buf[0] === 0xd7);\n      assert(buf[1] === 0xff);\n      assert(buf[2] === 0xff);\n      assert.deepEqual(buf, new Buffer([0xd7, 0xff, 0xff]));\n\n      // 262144\n      buf = hessian.encode(262144, '2.0');\n      assert(buf.length === 5);\n      assert(buf[0] === 'I'.charCodeAt(0));\n      assert(buf[1] === 0x00);\n      assert(buf[2] === 0x04);\n      assert(buf[3] === 0x00);\n      assert(buf[4] === 0x00);\n      assert.deepEqual(buf, new Buffer(['I'.charCodeAt(0), 0x00, 0x04, 0x00, 0x00]));\n\n      buf = hessian.encode(-262145, '2.0');\n      assert(buf.length === 5);\n      assert(buf[0] === 'I'.charCodeAt(0));\n      assert(buf[1] === 0xff);\n      assert(buf[2] === 0xfb);\n      assert(buf[3] === 0xff);\n      assert(buf[4] === 0xff);\n      assert.deepEqual(buf, new Buffer(['I'.charCodeAt(0), 0xff, 0xfb, 0xff, 0xff]));\n    });\n  });\n});\n"
  },
  {
    "path": "test/list.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst java = require('js-to-java');\nconst hessian = require('..');\nconst utils = require('./utils');\n\ndescribe('list.test.js', function () {\n  var intListBuffer = Buffer.concat([\n    new Buffer([\n      'V'.charCodeAt(0),\n      't'.charCodeAt(0), 0x00, 0x04\n    ]),\n    new Buffer('[int'),\n    new Buffer([\n      'l'.charCodeAt(0), 0, 0, 0, 0x02,\n      'I'.charCodeAt(0), 0, 0, 0, 0x00,\n      'I'.charCodeAt(0), 0, 0, 0, 0x01,\n      'z'.charCodeAt(0)\n    ])\n  ]);\n\n  it('should read int[] = {0, 1}', function () {\n    assert.deepEqual(hessian.decode(intListBuffer), [0, 1]);\n    assert.deepEqual(hessian.decode(intListBuffer, true), {\n      '$class': '[int',\n      '$': [ { '$class': 'int', '$': 0 }, { '$class': 'int', '$': 1 } ]\n    });\n  });\n\n  it('should write int[] = {0, 1}', function () {\n    var buf = hessian.encode(java.array.int([0, 1]));\n    assert(Buffer.isBuffer(buf));\n    assert(buf.length === intListBuffer.length);\n    assert.deepEqual(buf, intListBuffer);\n\n    assert.deepEqual(hessian.encode({\n      $class: '[int',\n      $: [0, 1]\n    }), intListBuffer);\n\n    // empty list\n    var empty = Buffer.concat([\n      new Buffer([\n        'V'.charCodeAt(0),\n        't'.charCodeAt(0), 0x00, 0x04\n      ]),\n      new Buffer('[int'),\n      new Buffer([\n        'l'.charCodeAt(0), 0, 0, 0, 0x00,\n        'z'.charCodeAt(0)\n      ])\n    ]);\n    assert.deepEqual(hessian.decode(empty), []);\n  });\n\n  it('should read write anonymous variable-length list = {0, null, \"foobar\"}', function () {\n    var anonymousList = Buffer.concat([\n      new Buffer('V'),\n      new Buffer([\n        'I'.charCodeAt(0), 0, 0, 0, 0x00,\n        'N'.charCodeAt(0),\n        'S'.charCodeAt(0), 0, 0x06,\n      ]),\n      new Buffer('foobar'),\n      new Buffer('z'),\n    ]);\n\n    assert.deepEqual(hessian.decode(anonymousList), [0, null, 'foobar']);\n\n    // empty\n    var emptyList = Buffer.concat([\n      new Buffer('V'),\n      new Buffer('z'),\n    ]);\n    assert.deepEqual(hessian.decode(emptyList), []);\n  });\n\n  it('should write and read untyped list', function () {\n    assert.deepEqual(hessian.encode([1, 2, 'foo'], '1.0'), utils.bytes('v1/list/untyped_list'));\n    assert.deepEqual(hessian.encode([], '1.0'), utils.bytes('v1/list/untyped_[]'));\n\n    assert.deepEqual(hessian.decode(utils.bytes('v1/list/untyped_list'), '1.0'), [1, 2, 'foo']);\n    assert.deepEqual(hessian.decode(utils.bytes('v1/list/untyped_list'), '1.0', true), {\n      $class: 'java.util.ArrayList',\n      $: [\n        { '$class': 'int', '$': 1 },\n        { '$class': 'int', '$': 2 },\n        { '$class': 'java.lang.String', '$': 'foo' }\n      ]\n    });\n    assert.deepEqual(hessian.decode(utils.bytes('v1/list/untyped_[]'), '1.0'), []);\n    assert.deepEqual(\n      hessian.decode(utils.bytes('v1/list/untyped_<String>[foo,bar]'), '1.0', true),\n      {\n        $class: 'java.util.ArrayList',\n        $: [\n          { '$class': 'java.lang.String', '$': 'foo' },\n          { '$class': 'java.lang.String', '$': 'bar' }\n        ]\n      }\n    );\n\n    // java.util.ArrayList as simple\n    assert.deepEqual(hessian.encode({\n      $class: 'java.util.ArrayList',\n      $: [1, 2, 'foo']\n    }, '1.0'), utils.bytes('v1/list/untyped_list'));\n  });\n\n  it('should write and read typed fixed-length list', function () {\n    assert.deepEqual(hessian.encode({\n      $class: 'hessian.demo.SomeArrayList',\n      $: ['ok', 'some list']\n    }, '1.0'), utils.bytes('v1/list/typed_list'));\n    assert.deepEqual(hessian.decode(utils.bytes('v1/list/typed_list'), '1.0', true), {\n        '$class': 'hessian.demo.SomeArrayList',\n        '$': [\n          { '$class': 'java.lang.String', '$': 'ok' },\n          { '$class': 'java.lang.String', '$': 'some list' }\n        ]\n      });\n\n    assert.deepEqual(\n      hessian.decode(utils.bytes('v1/list/typed_list'), '1.0'),\n      [ 'ok', 'some list' ]\n    );\n\n    var list = {\n      $class: '[int',\n      $: [1, 2, 3]\n    };\n    assert.deepEqual(hessian.encode(list, '1.0'), utils.bytes('v1/list/[int'));\n    assert.deepEqual(hessian.decode(utils.bytes('v1/list/[int'), '1.0'), [1, 2, 3]);\n    assert.deepEqual(hessian.decode(utils.bytes('v1/list/[int'), '1.0', true), {\n      '$class': '[int',\n      '$': [\n        { '$class': 'int', '$': 1 },\n        { '$class': 'int', '$': 2 },\n        { '$class': 'int', '$': 3 }\n      ]\n    });\n\n    var strs = {\n      $class: '[string',\n      $: ['1', '@', '3']\n    };\n    assert.deepEqual(hessian.encode(strs, '1.0'), utils.bytes('v1/list/[string'));\n    assert.deepEqual(hessian.decode(utils.bytes('v1/list/[string'), '1.0', true), {\n      '$class': '[string',\n      '$': [\n        { '$class': 'java.lang.String', '$': '1' },\n        { '$class': 'java.lang.String', '$': '@' },\n        { '$class': 'java.lang.String', '$': '3' }\n      ]\n    });\n  });\n\n  describe('v2.0', function () {\n    it('should write and read untyped list', function () {\n      assert.deepEqual(hessian.encode([1, 2, 'foo'], '2.0'), utils.bytes('v2/list/untyped_list'));\n      assert.deepEqual(hessian.encode([], '2.0'), utils.bytes('v2/list/untyped_[]'));\n\n      assert.deepEqual(hessian.decode(utils.bytes('v2/list/untyped_list'), '2.0'), [1, 2, 'foo']);\n      assert.deepEqual(hessian.decode(utils.bytes('v2/list/untyped_list'), '2.0', true), [1, 2, 'foo']);\n      assert.deepEqual(hessian.decode(utils.bytes('v2/list/untyped_list_8'), '2.0'), ['1', '2', '3', '4', '5', '6', '7', '8']);\n      assert.deepEqual(hessian.decode(utils.bytes('v2/list/untyped_list_8'), '2.0', true), ['1', '2', '3', '4', '5', '6', '7', '8']);\n      assert.deepEqual(hessian.decode(utils.bytes('v2/list/untyped_[]'), '2.0'), []);\n      assert.deepEqual(hessian.decode(utils.bytes('v2/list/untyped_<String>[foo,bar]'), '2.0', true), ['foo', 'bar']);\n\n      // java.util.ArrayList as simple\n      assert.deepEqual(hessian.encode({\n        $class: 'java.util.ArrayList',\n        $: [1, 2, 'foo']\n      }, '2.0'), utils.bytes('v2/list/untyped_list'));\n      // encode again should cache class\n      assert.deepEqual(hessian.encode({\n        $class: 'java.util.ArrayList',\n        $: [1, 2, 'foo']\n      }, '2.0'), utils.bytes('v2/list/untyped_list'));\n\n      // java.util.ArrayList length larger than 7\n      assert.deepEqual(hessian.encode({\n        $class: 'java.util.ArrayList',\n        $: ['1', '2', '3', '4', '5', '6', '7', '8']\n      }, '2.0'), utils.bytes('v2/list/untyped_list_8'));\n      assert.deepEqual(hessian.encode({\n        $class: 'java.util.ArrayList',\n        $: ['1', '2', '3', '4', '5', '6', '7', '8']\n      }, '2.0'), utils.bytes('v2/list/untyped_list_8'));\n    });\n\n    it('should write and read typed fixed-length list', function () {\n      assert.deepEqual(hessian.encode({\n        $class: 'hessian.demo.SomeArrayList',\n        $: ['ok', 'some list']\n      }, '2.0'), utils.bytes('v2/list/typed_list'));\n      // encode again should use type cache\n      assert.deepEqual(hessian.encode({\n        $class: 'hessian.demo.SomeArrayList',\n        $: ['ok', 'some list']\n      }, '2.0'), utils.bytes('v2/list/typed_list'));\n      assert.deepEqual(hessian.encode({\n        $class: 'hessian.demo.SomeArrayList',\n        $: ['1', '2', '3', '4', '5', '6', '7', '8']\n      }, '2.0'), utils.bytes('v2/list/typed_list_8'));\n\n      assert.deepEqual(hessian.decode(utils.bytes('v2/list/typed_list'), '2.0', true), {\n          '$class': 'hessian.demo.SomeArrayList',\n          '$': [ 'ok', 'some list' ]\n        });\n      assert.deepEqual(hessian.decode(utils.bytes('v2/list/typed_list_8'), '2.0', true), {\n          '$class': 'hessian.demo.SomeArrayList',\n          '$': ['1', '2', '3', '4', '5', '6', '7', '8']\n        });\n\n      assert.deepEqual(hessian.decode(utils.bytes('v2/list/typed_list_8'), '2.0'), ['1', '2', '3', '4', '5', '6', '7', '8']);\n\n      var list = {\n        $class: '[int',\n        $: [1, 2, 3]\n      };\n      assert.deepEqual(hessian.encode(list, '2.0'), utils.bytes('v2/list/[int'));\n      assert.deepEqual(hessian.encode(list, '2.0'), utils.bytes('v2/list/[int'));\n\n      assert.deepEqual(hessian.decode(utils.bytes('v2/list/[int'), '2.0'), [1, 2, 3]);\n      // encode again should use type cache\n      assert.deepEqual(hessian.decode(utils.bytes('v2/list/[int'), '2.0', true), list);\n\n      var strs = {\n        $class: '[string',\n        $: ['1', '@', '3']\n      };\n      assert.deepEqual(hessian.encode(strs, '2.0'), utils.bytes('v2/list/[string'));\n      assert.deepEqual(hessian.decode(utils.bytes('v2/list/[string'), '2.0', true), strs);\n    });\n  });\n});\n"
  },
  {
    "path": "test/long.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst java = require('js-to-java');\nconst Long = require('long');\nconst hessian = require('..');\nconst utils = require('./utils');\n\ndescribe('long.test.js', function () {\n  var longBuffer = new Buffer(['L'.charCodeAt(0), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2c]);\n\n  it('should write {$class: \"java.lang.Long\", $: null} => null', function () {\n    var obj = hessian.decode(hessian.encode({\n      $class: \"java.lang.Long\", $: null\n    }));\n    assert(obj === null);\n  });\n\n  it('should read long 300', function () {\n    assert(hessian.decode(longBuffer) === 300);\n  });\n\n  it('should write long 300', function () {\n    assert.deepEqual(hessian.encode({\n      $class: 'long',\n      $: 300\n    }), longBuffer);\n    assert.deepEqual(hessian.encode(java.long(300)), longBuffer);\n    assert.deepEqual(hessian.encode(java.long(300)), longBuffer);\n    assert.deepEqual(hessian.encode(java.long(Long.fromNumber(300))), longBuffer);\n    assert.deepEqual(hessian.encode(Long.fromNumber(300)), longBuffer);\n  });\n\n  it('should write long 0', function () {\n    assert.deepEqual(\n      hessian.encode(java.long(0)),\n      new Buffer(['L'.charCodeAt(0), 0, 0, 0, 0, 0, 0, 0, 0])\n    );\n  });\n\n  it('should write and read equal java impl', function () {\n    assert.deepEqual(hessian.encode(java.long(Long.fromNumber(15)), '2.0'), utils.bytes('v2/long/15'));\n    assert.deepEqual(hessian.encode(java.long(Long.fromNumber(-8)), '2.0'), utils.bytes('v2/long/-8'));\n    assert.deepEqual(hessian.encode(java.long(Long.fromNumber(-2048)), '2.0'), utils.bytes('v2/long/-2048'));\n    assert.deepEqual(hessian.encode(java.long(Long.fromNumber(2047)), '2.0'), utils.bytes('v2/long/2047'));\n    assert.deepEqual(hessian.encode(java.long(Long.fromNumber(-262144)), '2.0'), utils.bytes('v2/long/-262144'));\n    assert.deepEqual(hessian.encode(java.long(Long.fromNumber(262143)), '2.0'), utils.bytes('v2/long/262143'));\n    assert.deepEqual(hessian.encode(java.long(Long.fromNumber(-2147483648)), '2.0'), utils.bytes('v2/long/-2147483648'));\n    assert.deepEqual(hessian.encode(java.long(Long.fromNumber(2147483647)), '2.0'), utils.bytes('v2/long/2147483647'));\n\n    assert.deepEqual(hessian.encode(java.long(0), '1.0'), utils.bytes('v1/long/0'));\n    assert(hessian.decode(utils.bytes('v1/long/0')) === 0);\n    assert.deepEqual(hessian.encode(java.long(-8), '1.0'), utils.bytes('v1/long/-8'));\n    assert(hessian.decode(utils.bytes('v1/long/-8')) === -8);\n    assert.deepEqual(hessian.encode(java.long(-7), '1.0'), utils.bytes('v1/long/-7'));\n    assert(hessian.decode(utils.bytes('v1/long/-7')) === -7);\n    assert.deepEqual(hessian.encode(java.long(15), '1.0'), utils.bytes('v1/long/15'));\n    assert(hessian.decode(utils.bytes('v1/long/15')) === 15);\n    assert.deepEqual(hessian.encode(java.long(14), '1.0'), utils.bytes('v1/long/14'));\n    assert(hessian.decode(utils.bytes('v1/long/14')) === 14);\n    assert.deepEqual(hessian.encode(java.long(-9), '1.0'), utils.bytes('v1/long/-9'));\n    assert(hessian.decode(utils.bytes('v1/long/-9')) === -9);\n    assert.deepEqual(hessian.encode(java.long(16), '1.0'), utils.bytes('v1/long/16'));\n    assert(hessian.decode(utils.bytes('v1/long/16')) === 16);\n    assert.deepEqual(hessian.encode(java.long(255), '1.0'), utils.bytes('v1/long/255'));\n    assert(hessian.decode(utils.bytes('v1/long/255')) === 255);\n    assert.deepEqual(hessian.encode(java.long(-2048), '1.0'), utils.bytes('v1/long/-2048'));\n    assert(hessian.decode(utils.bytes('v1/long/-2048')) === -2048);\n    assert.deepEqual(hessian.encode(java.long(2047), '1.0'), utils.bytes('v1/long/2047'));\n    assert(hessian.decode(utils.bytes('v1/long/2047')) === 2047);\n    assert.deepEqual(hessian.encode(java.long(262143), '1.0'), utils.bytes('v1/long/262143'));\n    assert(hessian.decode(utils.bytes('v1/long/262143')) === 262143);\n    assert.deepEqual(hessian.encode(java.long(-262144), '1.0'), utils.bytes('v1/long/-262144'));\n    assert(hessian.decode(utils.bytes('v1/long/-262144')) === -262144);\n    assert.deepEqual(hessian.encode(java.long(2048), '1.0'), utils.bytes('v1/long/2048'));\n    assert(hessian.decode(utils.bytes('v1/long/2048')) === 2048);\n    assert.deepEqual(hessian.encode(java.long(-2049), '1.0'), utils.bytes('v1/long/-2049'));\n    assert(hessian.decode(utils.bytes('v1/long/-2049')) === -2049);\n    assert.deepEqual(\n      hessian.encode(java.long(-2147483648), '1.0'),\n      utils.bytes('v1/long/-2147483648')\n    );\n    assert(hessian.decode(utils.bytes('v1/long/-2147483648')) === -2147483648);\n    assert.deepEqual(\n      hessian.encode(java.long(-2147483647), '1.0'),\n      utils.bytes('v1/long/-2147483647')\n    );\n    assert(hessian.decode(utils.bytes('v1/long/-2147483647')) === -2147483647);\n    assert.deepEqual(\n      hessian.encode(java.long(2147483647), '1.0'),\n      utils.bytes('v1/long/2147483647')\n    );\n    assert(hessian.decode(utils.bytes('v1/long/2147483647')) === 2147483647);\n    assert.deepEqual(\n      hessian.encode(java.long(2147483646), '1.0'),\n      utils.bytes('v1/long/2147483646')\n    );\n    assert(hessian.decode(utils.bytes('v1/long/2147483646')) === 2147483646);\n    assert.deepEqual(\n      hessian.encode(java.long(2147483648), '1.0'),\n      utils.bytes('v1/long/2147483648')\n    );\n    assert(hessian.decode(utils.bytes('v1/long/2147483648')) === 2147483648);\n  });\n\n  describe('v2.0', function () {\n    it('should read compact long', function () {\n      assert(hessian.decode(new Buffer([0xe0]), '2.0') === 0);\n      assert(hessian.decode(new Buffer([0xd8]), '2.0') === -8);\n      assert(hessian.decode(new Buffer([0xef]), '2.0') === 15);\n\n      assert(hessian.decode(new Buffer([0xf8, 0x00]), '2.0') === 0);\n      assert(hessian.decode(new Buffer([0xf0, 0x00]), '2.0') === -2048);\n      assert(hessian.decode(new Buffer([0xf7, 0x00]), '2.0') === -256);\n      assert(hessian.decode(new Buffer([0xff, 0xff]), '2.0') === 2047);\n\n      assert(hessian.decode(new Buffer([0x3c, 0x00, 0x00]), '2.0') === 0);\n      assert(hessian.decode(new Buffer([0x38, 0x00, 0x00]), '2.0') === -262144);\n      assert(hessian.decode(new Buffer([0x3f, 0xff, 0xff]), '2.0') === 262143);\n\n      // four octet longs\n      assert(hessian.decode(new Buffer([0x59, 0x00, 0x00, 0x00, 0x00]), '2.0') === 0);\n      assert(hessian.decode(new Buffer([0x59, 0x00, 0x00, 0x01, 0x2c]), '2.0') === 300);\n      assert(hessian.decode(new Buffer([0x59, 0x7f, 0xff, 0xff, 0xff]), '2.0') === 2147483647);\n      assert(hessian.decode(new Buffer([0x59, 0x80, 0x00, 0x00, 0x00]), '2.0') === -2147483648);\n\n      assert(hessian.decode(new Buffer([0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), '2.0') === 0);\n      assert(hessian.decode(new Buffer([0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2c]), '2.0') === 300);\n      assert(hessian.decode(new Buffer([0x4c, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff]), '2.0') === 2147483647);\n    });\n\n    it('should read normal long', function () {\n      assert(\n        hessian.decode(new Buffer([0x4c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00]), '2.0') === 2147483648\n      );\n    });\n\n    it('should write compact long', function () {\n      // -8 ~ 15\n      var buf = hessian.encode(java.long(0), '2.0');\n      assert(buf.length === 1);\n      assert(buf[0] === 0xe0);\n      assert.deepEqual(buf, new Buffer([0xe0]));\n\n      buf = hessian.encode(java.long(-8), '2.0');\n      assert(buf.length === 1);\n      assert(buf[0] === 0xd8);\n      assert.deepEqual(buf, new Buffer([0xd8]));\n\n      buf = hessian.encode(java.long(-7), '2.0');\n      assert(buf.length === 1);\n      assert(buf[0] === 0xd9);\n      assert.deepEqual(buf, new Buffer([0xd9]));\n\n      buf = hessian.encode(java.long(15), '2.0');\n      assert(buf.length === 1);\n      assert(buf[0] === 0xef);\n      assert.deepEqual(buf, new Buffer([0xef]));\n\n      buf = hessian.encode(java.long(14), '2.0');\n      assert(buf.length === 1);\n      assert(buf[0] === 0xee);\n      assert.deepEqual(buf, new Buffer([0xee]));\n\n      // -2048 ~ 2047\n      buf = hessian.encode(java.long(-9), '2.0');\n      assert(buf.length === 2);\n      assert(buf[0] === 0xf7);\n      assert(buf[1] === 0xf7);\n      assert.deepEqual(buf, new Buffer([0xf7, 0xf7]));\n\n      buf = hessian.encode(java.long(16), '2.0');\n      assert(buf.length === 2);\n      assert(buf[0] === 0xf8);\n      assert(buf[1] === 0x10);\n      assert.deepEqual(buf, new Buffer([0xf8, 0x10]));\n\n      buf = hessian.encode(java.long(255), '2.0');\n      assert(buf.length === 2);\n      assert(buf[0] === 0xf8);\n      assert(buf[1] === 0xff);\n      assert.deepEqual(buf, new Buffer([0xf8, 0xff]));\n\n      buf = hessian.encode(java.long(-2048), '2.0');\n      assert(buf.length === 2);\n      assert(buf[0] === 0xf0);\n      assert(buf[1] === 0);\n      assert.deepEqual(buf, new Buffer([0xf0, 0x00]));\n\n      buf = hessian.encode(java.long(2047), '2.0');\n      assert(buf.length === 2);\n      assert(buf[0] === 0xff);\n      assert(buf[1] === 0xff);\n      assert.deepEqual(buf, new Buffer([0xff, 0xff]));\n\n      // -262144 ~ 262143\n      buf = hessian.encode(java.long(262143), '2.0');\n      assert(buf.length === 3);\n      assert(buf[0] === 0x3f);\n      assert(buf[1] === 0xff);\n      assert(buf[2] === 0xff);\n      assert.deepEqual(buf, new Buffer([0x3f, 0xff, 0xff]));\n\n      buf = hessian.encode(java.long(-262144), '2.0');\n      assert(buf.length === 3);\n      assert(buf[0] === 0x38);\n      assert(buf[1] === 0);\n      assert(buf[2] === 0);\n      assert.deepEqual(buf, new Buffer([0x38, 0x00, 0x00]));\n\n      buf = hessian.encode(java.long(2048), '2.0');\n      assert(buf.length === 3);\n      assert(buf[0] === 0x3c);\n      assert(buf[1] === 0x08);\n      assert(buf[2] === 0x00);\n      assert.deepEqual(buf, new Buffer([0x3c, 0x08, 0x00]));\n\n      buf = hessian.encode(java.long(-2049), '2.0');\n      assert(buf.length === 3);\n      assert(buf[0] === 0x3b);\n      assert(buf[1] === 0xf7);\n      assert(buf[2] === 0xff);\n      assert.deepEqual(buf, new Buffer([0x3b, 0xf7, 0xff]));\n\n      // -2147483648 ~ 2147483647\n      buf = hessian.encode(java.long(-2147483648), '2.0');\n      assert(buf.length === 5);\n      assert(buf[0] === 0x59);\n      assert(buf[1] === 0x80);\n      assert(buf[2] === 0x00);\n      assert(buf[3] === 0x00);\n      assert(buf[4] === 0x00);\n      assert.deepEqual(buf, new Buffer([0x59, 0x80, 0x00, 0x00, 0x00]));\n\n      buf = hessian.encode(java.long(2147483647), '2.0');\n      assert(buf.length === 5);\n      assert(buf[0] === 0x59);\n      assert(buf[1] === 0x7f);\n      assert(buf[2] === 0xff);\n      assert(buf[3] === 0xff);\n      assert(buf[4] === 0xff);\n      assert.deepEqual(buf, new Buffer([0x59, 0x7f, 0xff, 0xff, 0xff]));\n\n      // L\n      buf = hessian.encode(java.long(2147483648), '2.0');\n      assert(buf.length === 9);\n      assert.deepEqual(buf, new Buffer([0x4c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00]));\n    });\n\n    it('should write { $class: \"long\": $: \"...\" } ok', function () {\n      // -8 ~ 15\n      var buf = hessian.encode(java.long('0'), '2.0');\n      assert(buf.length === 1);\n      assert(buf[0] === 0xe0);\n      assert.deepEqual(buf, new Buffer([0xe0]));\n\n      buf = hessian.encode(java.long('-8'), '2.0');\n      assert(buf.length === 1);\n      assert(buf[0] === 0xd8);\n      assert.deepEqual(buf, new Buffer([0xd8]));\n\n      buf = hessian.encode(java.long('-7'), '2.0');\n      assert(buf.length === 1);\n      assert(buf[0] === 0xd9);\n      assert.deepEqual(buf, new Buffer([0xd9]));\n\n      buf = hessian.encode(java.long('15'), '2.0');\n      assert(buf.length === 1);\n      assert(buf[0] === 0xef);\n      assert.deepEqual(buf, new Buffer([0xef]));\n\n      buf = hessian.encode(java.long('14'), '2.0');\n      assert(buf.length === 1);\n      assert(buf[0] === 0xee);\n      assert.deepEqual(buf, new Buffer([0xee]));\n\n      // -2048 ~ 2047\n      buf = hessian.encode(java.long('-9'), '2.0');\n      assert(buf.length === 2);\n      assert(buf[0] === 0xf7);\n      assert(buf[1] === 0xf7);\n      assert.deepEqual(buf, new Buffer([0xf7, 0xf7]));\n\n      buf = hessian.encode(java.long('16'), '2.0');\n      assert(buf.length === 2);\n      assert(buf[0] === 0xf8);\n      assert(buf[1] === 0x10);\n      assert.deepEqual(buf, new Buffer([0xf8, 0x10]));\n\n      buf = hessian.encode(java.long('255'), '2.0');\n      assert(buf.length === 2);\n      assert(buf[0] === 0xf8);\n      assert(buf[1] === 0xff);\n      assert.deepEqual(buf, new Buffer([0xf8, 0xff]));\n\n      buf = hessian.encode(java.long('-2048'), '2.0');\n      assert(buf.length === 2);\n      assert(buf[0] === 0xf0);\n      assert(buf[1] === 0);\n      assert.deepEqual(buf, new Buffer([0xf0, 0x00]));\n\n      buf = hessian.encode(java.long('2047'), '2.0');\n      assert(buf.length === 2);\n      assert(buf[0] === 0xff);\n      assert(buf[1] === 0xff);\n      assert.deepEqual(buf, new Buffer([0xff, 0xff]));\n\n      // -262144 ~ 262143\n      buf = hessian.encode(java.long('262143'), '2.0');\n      assert(buf.length === 3);\n      assert(buf[0] === 0x3f);\n      assert(buf[1] === 0xff);\n      assert(buf[2] === 0xff);\n      assert.deepEqual(buf, new Buffer([0x3f, 0xff, 0xff]));\n\n      buf = hessian.encode(java.long('-262144'), '2.0');\n      assert(buf.length === 3);\n      assert(buf[0] === 0x38);\n      assert(buf[1] === 0);\n      assert(buf[2] === 0);\n      assert.deepEqual(buf, new Buffer([0x38, 0x00, 0x00]));\n\n      buf = hessian.encode(java.long('2048'), '2.0');\n      assert(buf.length === 3);\n      assert(buf[0] === 0x3c);\n      assert(buf[1] === 0x08);\n      assert(buf[2] === 0x00);\n      assert.deepEqual(buf, new Buffer([0x3c, 0x08, 0x00]));\n\n      buf = hessian.encode(java.long('-2049'), '2.0');\n      assert(buf.length === 3);\n      assert(buf[0] === 0x3b);\n      assert(buf[1] === 0xf7);\n      assert(buf[2] === 0xff);\n      assert.deepEqual(buf, new Buffer([0x3b, 0xf7, 0xff]));\n\n      // -2147483648 ~ 2147483647\n      buf = hessian.encode(java.long('-2147483648'), '2.0');\n      assert(buf.length === 5);\n      assert(buf[0] === 0x59);\n      assert(buf[1] === 0x80);\n      assert(buf[2] === 0x00);\n      assert(buf[3] === 0x00);\n      assert(buf[4] === 0x00);\n      assert.deepEqual(buf, new Buffer([0x59, 0x80, 0x00, 0x00, 0x00]));\n\n      buf = hessian.encode(java.long('2147483647'), '2.0');\n      assert(buf.length === 5);\n      assert(buf[0] === 0x59);\n      assert(buf[1] === 0x7f);\n      assert(buf[2] === 0xff);\n      assert(buf[3] === 0xff);\n      assert(buf[4] === 0xff);\n      assert.deepEqual(buf, new Buffer([0x59, 0x7f, 0xff, 0xff, 0xff]));\n\n      // L\n      buf = hessian.encode(java.long('2147483648'), '2.0');\n      assert(buf.length === 9);\n      assert.deepEqual(buf, new Buffer([0x4c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00]));\n\n      // unsafe long value\n      buf = hessian.encode(java.long('9007199254740992'), '2.0');\n      assert(buf.length === 9);\n      assert.deepEqual(buf, new Buffer([0x4c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]));\n    });\n\n    it('should write and read equal java impl', function () {\n      assert.deepEqual(hessian.encode(java.long(0), '2.0'), utils.bytes('v2/long/0'));\n      assert(hessian.decode(utils.bytes('v2/long/0'), '2.0') === 0);\n      assert.deepEqual(hessian.encode(java.long(-8), '2.0'), utils.bytes('v2/long/-8'));\n      assert(hessian.decode(utils.bytes('v2/long/-8'), '2.0') === -8);\n      assert.deepEqual(hessian.encode(java.long(-7), '2.0'), utils.bytes('v2/long/-7'));\n      assert(hessian.decode(utils.bytes('v2/long/-7'), '2.0') === -7);\n      assert.deepEqual(hessian.encode(java.long(15), '2.0'), utils.bytes('v2/long/15'));\n      assert(hessian.decode(utils.bytes('v2/long/15'), '2.0') === 15);\n      assert.deepEqual(hessian.encode(java.long(14), '2.0'), utils.bytes('v2/long/14'));\n      assert(hessian.decode(utils.bytes('v2/long/14'), '2.0') === 14);\n      assert.deepEqual(hessian.encode(java.long(-9), '2.0'), utils.bytes('v2/long/-9'));\n      assert(hessian.decode(utils.bytes('v2/long/-9'), '2.0') === -9);\n      assert.deepEqual(hessian.encode(java.long(16), '2.0'), utils.bytes('v2/long/16'));\n      assert(hessian.decode(utils.bytes('v2/long/16'), '2.0') === 16);\n      assert.deepEqual(hessian.encode(java.long(255), '2.0'), utils.bytes('v2/long/255'));\n      assert.deepEqual(\n        hessian.encode(java.long(Long.fromNumber(255)), '2.0'),\n        utils.bytes('v2/long/255')\n      );\n      assert.deepEqual(hessian.encode(Long.fromNumber(255), '2.0'), utils.bytes('v2/long/255'));\n\n      assert(hessian.decode(utils.bytes('v2/long/255'), '2.0') === 255);\n      assert.deepEqual(hessian.encode(java.long(-2048), '2.0'), utils.bytes('v2/long/-2048'));\n      assert(hessian.decode(utils.bytes('v2/long/-2048'), '2.0') === -2048);\n      assert.deepEqual(hessian.encode(java.long(2047), '2.0'), utils.bytes('v2/long/2047'));\n      assert(hessian.decode(utils.bytes('v2/long/2047'), '2.0') === 2047);\n      assert.deepEqual(hessian.encode(java.long(262143), '2.0'), utils.bytes('v2/long/262143'));\n      assert(hessian.decode(utils.bytes('v2/long/262143'), '2.0') === 262143);\n      assert.deepEqual(hessian.encode(java.long(-262144), '2.0'), utils.bytes('v2/long/-262144'));\n      assert(hessian.decode(utils.bytes('v2/long/-262144'), '2.0') === -262144);\n      assert.deepEqual(hessian.encode(java.long(2048), '2.0'), utils.bytes('v2/long/2048'));\n      assert(hessian.decode(utils.bytes('v2/long/2048'), '2.0') === 2048);\n      assert.deepEqual(hessian.encode(java.long(-2049), '2.0'), utils.bytes('v2/long/-2049'));\n      assert(hessian.decode(utils.bytes('v2/long/-2049'), '2.0') === -2049);\n      assert.deepEqual(\n        hessian.encode(java.long(-2147483648), '2.0'),\n        utils.bytes('v2/long/-2147483648')\n      );\n      assert(hessian.decode(utils.bytes('v2/long/-2147483648'), '2.0') === -2147483648);\n      assert.deepEqual(\n        hessian.encode(java.long(-2147483647), '2.0'),\n        utils.bytes('v2/long/-2147483647')\n      );\n      assert(hessian.decode(utils.bytes('v2/long/-2147483647'), '2.0') === -2147483647);\n      assert.deepEqual(\n        hessian.encode(java.long(2147483647), '2.0'),\n        utils.bytes('v2/long/2147483647')\n      );\n      assert(hessian.decode(utils.bytes('v2/long/2147483647'), '2.0') === 2147483647);\n      assert.deepEqual(\n        hessian.encode(java.long(2147483646), '2.0'),\n        utils.bytes('v2/long/2147483646')\n      );\n      assert(hessian.decode(utils.bytes('v2/long/2147483646'), '2.0') === 2147483646);\n      assert.deepEqual(\n        hessian.encode(java.long(2147483648), '2.0'),\n        utils.bytes('v2/long/2147483648')\n      );\n      assert(hessian.decode(utils.bytes('v2/long/2147483648'), '2.0') === 2147483648);\n    });\n\n    it('should read 1.0 bin as well', function () {\n      assert(hessian.decode(utils.bytes('v1/long/0'), '2.0') === 0);\n      assert(hessian.decode(utils.bytes('v1/long/-8'), '2.0') === -8);\n      assert(hessian.decode(utils.bytes('v1/long/-7'), '2.0') === -7);\n      assert(hessian.decode(utils.bytes('v1/long/15'), '2.0') === 15);\n      assert(hessian.decode(utils.bytes('v1/long/14'), '2.0') === 14);\n      assert(hessian.decode(utils.bytes('v1/long/-9'), '2.0') === -9);\n      assert(hessian.decode(utils.bytes('v1/long/16'), '2.0') === 16);\n      assert(hessian.decode(utils.bytes('v1/long/255'), '2.0') === 255);\n      assert(hessian.decode(utils.bytes('v1/long/-2048'), '2.0') === -2048);\n      assert(hessian.decode(utils.bytes('v1/long/2047'), '2.0') === 2047);\n      assert(hessian.decode(utils.bytes('v1/long/262143'), '2.0') === 262143);\n      assert(hessian.decode(utils.bytes('v1/long/-262144'), '2.0') === -262144);\n      assert(hessian.decode(utils.bytes('v1/long/2048'), '2.0') === 2048);\n      assert(hessian.decode(utils.bytes('v1/long/-2049'), '2.0') === -2049);\n      assert(hessian.decode(utils.bytes('v1/long/-2147483648'), '2.0') === -2147483648);\n      assert(hessian.decode(utils.bytes('v1/long/-2147483647'), '2.0') === -2147483647);\n      assert(hessian.decode(utils.bytes('v1/long/2147483647'), '2.0') === 2147483647);\n      assert(hessian.decode(utils.bytes('v1/long/2147483646'), '2.0') === 2147483646);\n      assert(hessian.decode(utils.bytes('v1/long/2147483648'), '2.0') === 2147483648);\n    });\n  });\n});\n"
  },
  {
    "path": "test/map.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst hessian = require('..');\nconst utils = require('./utils');\nconst supportES6Map = require('../lib/utils').supportES6Map;\n\ndescribe('map.test.js', function() {\n  it('should read Serialization of a Java Object', function() {\n    // public class Car implements Serializable {\n    //   String model = \"Beetle\";\n    //   String color = \"aquamarine\";\n    //   int mileage = 65536;\n    // }\n    //\n    // =>\n    //\n    // M t x00 x13 com.caucho.test.Car\n    //   S x00 x05 model\n    //   S x00 x06 Beetle\n\n    //   S x00 x05 color\n    //   S x00 x0a aquamarine\n\n    //   S x00 x07 mileage\n    //   I x00 x01 x00 x00\n    //   z\n\n    var mapBuffer = Buffer.concat([\n      new Buffer('M'),\n      new Buffer([\n        't'.charCodeAt(0), 0x00, 0x13,\n      ]),\n      new Buffer('com.caucho.test.Car'),\n      new Buffer([\n        'S'.charCodeAt(0), 0x00, 0x05,\n      ]),\n      new Buffer('model'),\n      new Buffer([\n        'S'.charCodeAt(0), 0x00, 0x06,\n      ]),\n      new Buffer('Beetle'),\n\n      new Buffer([\n        'S'.charCodeAt(0), 0x00, 0x05,\n      ]),\n      new Buffer('color'),\n      new Buffer([\n        'S'.charCodeAt(0), 0x00, 0x0a,\n      ]),\n      new Buffer('aquamarine'),\n\n      new Buffer([\n        'S'.charCodeAt(0), 0x00, 0x07,\n      ]),\n      new Buffer('mileage'),\n      new Buffer([\n        'I'.charCodeAt(0), 0x00, 0x01, 0x00, 0x00,\n      ]),\n\n      new Buffer('z'),\n    ]);\n\n    assert.deepEqual(hessian.decode(mapBuffer), {\n      model: 'Beetle',\n      color: 'aquamarine',\n      mileage: 65536\n    });\n\n    assert.deepEqual(hessian.decode(mapBuffer, true), {\n      '$class': 'com.caucho.test.Car',\n      '$': {\n        model: { '$class': 'java.lang.String', '$': 'Beetle' },\n        color: { '$class': 'java.lang.String', '$': 'aquamarine' },\n        mileage: { '$class': 'int', '$': 65536 }\n      }\n    });\n  });\n\n  it('should write {hasOwnProperty: 1, a: 0, b: false, c: null} obj', function() {\n    /* jshint -W001 */\n    var buf = hessian.encode({ hasOwnProperty: 1, a: 0, b: false, c: null });\n    assert(Buffer.isBuffer(buf));\n    assert.deepEqual(hessian.decode(buf), { hasOwnProperty: 1, a: 0, b: false, c: null });\n  });\n\n  it('should read A sparse array', function() {\n    // map = new HashMap();\n    // map.put(new Integer(1), \"fee\");\n    // map.put(new Integer(16), \"fie\");\n    // map.put(new Integer(256), \"foe\");\n    var mapBuffer = Buffer.concat([\n      new Buffer('M'),\n      new Buffer([\n        'I'.charCodeAt(0), 0, 0, 0, 0x01,\n      ]),\n      new Buffer([\n        'S'.charCodeAt(0), 0x00, 0x03,\n      ]),\n      new Buffer('fee'),\n\n      new Buffer([\n        'I'.charCodeAt(0), 0, 0, 0, 0x10,\n      ]),\n      new Buffer([\n        'S'.charCodeAt(0), 0x00, 0x03,\n      ]),\n      new Buffer('fie'),\n\n      new Buffer([\n        'I'.charCodeAt(0), 0, 0, 0x01, 0x00,\n      ]),\n      new Buffer([\n        'S'.charCodeAt(0), 0x00, 0x03,\n      ]),\n      new Buffer('foe'),\n\n      new Buffer('z'),\n    ]);\n\n    assert.deepEqual(hessian.decode(mapBuffer), {\n      '1': 'fee',\n      '16': 'fie',\n      '256': 'foe',\n    });\n  });\n\n  it('should write js object to no type hash map', function() {\n    var buf = hessian.encode({ foo: '' });\n    assert.deepEqual(buf, utils.bytes('v1/map/foo_empty'));\n    assert.deepEqual(hessian.decode(utils.bytes('v1/map/foo_empty'), '1.0'), {\n      foo: ''\n    });\n\n    assert.deepEqual(hessian.encode({\n      '123': 456,\n      foo: 'bar',\n      zero: 0,\n      '中文key': '中文哈哈value',\n    }), utils.bytes('v1/map/foo_bar'));\n\n    // read it\n    assert.deepEqual(hessian.decode(utils.bytes('v1/map/foo_bar'), '1.0'), {\n      foo: 'bar',\n      '中文key': '中文哈哈value',\n      '123': 456,\n      zero: 0,\n    });\n  });\n\n  it('should decode successful when key is null', function() {\n    var data = new Buffer([77, 116, 0, 0, 78, 83, 0, 4, 110, 117, 108, 108, 122]);\n    var rv = hessian.decode(data);\n    assert.deepEqual(rv, { null: 'null' });\n\n    if (!supportES6Map) {\n      // pass if not support es6 Map\n      return;\n    }\n\n    assert(rv.$map);\n    assert(rv.$map instanceof Map);\n    assert(rv.$map.size === 1);\n    assert(rv.$map.get(null) === 'null');\n  });\n\n  it('should write es6 Map to java.util.Map', function() {\n    if (!supportES6Map) {\n      // pass if not support es6 Map\n      return;\n    }\n\n    var map = new Map();\n    map.set({ '$class': 'java.lang.Long', '$': 123 }, 123456);\n    map.set({ '$class': 'java.lang.Long', '$': 123456 }, 123);\n    var buf = hessian.encode({ '$class': 'java.util.Map', '$': map });\n    // decode auto transfer key to string\n    var result = hessian.decode(buf);\n    assert.deepEqual(result, {\n      '123': 123456,\n      '123456': 123\n    });\n\n    assert(result.$map);\n    assert(result.$map instanceof Map);\n    assert(result.$map.size === 2);\n\n    assert(result.$map.get(123) === 123456);\n    assert(result.$map.get(123456) === 123);\n  });\n\n  it('should write es6 Map to java.util.HashMap', function() {\n    if (!supportES6Map) {\n      // pass if not support es6 Map\n      return;\n    }\n\n    var map = new Map();\n    map.set({ '$class': 'java.lang.Long', '$': 123 }, 123456);\n    map.set({ '$class': 'java.lang.Long', '$': 123456 }, 123);\n    var buf = hessian.encode(map);\n    assert.deepEqual(buf, utils.bytes('v1/map/generic'));\n\n    buf = hessian.encode({ '$class': 'java.util.HashMap', '$': map });\n    assert.deepEqual(buf, utils.bytes('v1/map/generic'));\n\n    // decode auto transfer key to string\n    var result = hessian.decode(utils.bytes('v1/map/generic'), '1.0');\n    assert.deepEqual(result, {\n      '123': 123456,\n      '123456': 123\n    });\n\n    assert(result.$map);\n    assert(result.$map instanceof Map);\n    assert(result.$map.size === 2);\n\n    assert(result.$map.get(123) === 123456);\n    assert(result.$map.get(123456) === 123);\n  });\n\n  it('should encode & decode custom map type', function() {\n     var buf = new Buffer('5674001E636F6D2E616C69626162612E666173746A736F6E2E4A534F4E41727261796C000000034D74001F636F6D2E616C69626162612E666173746A736F6E2E4A534F4E4F626A65637453000D44415445204F46204249525448530013323031362F31322F31322031323A31323A313253000946554C4C204E414D45530005446F652030530003414745490000000A7A4D74001F636F6D2E616C69626162612E666173746A736F6E2E4A534F4E4F626A65637453000D44415445204F46204249525448530013323031362F31322F31322031323A31323A313253000946554C4C204E414D45530005446F652031530003414745490000000A7A4D74001F636F6D2E616C69626162612E666173746A736F6E2E4A534F4E4F626A6563745300037878785300037979797A7A', 'hex');\n     var obj = hessian.decode(buf, '1.0', true);\n     assert.deepEqual(obj, {\n       $class: 'com.alibaba.fastjson.JSONArray',\n       $: [\n        {\n         $class: 'com.alibaba.fastjson.JSONObject',\n         $: {\n          'DATE OF BIRTH': {\n            $class: 'java.lang.String',\n            $: '2016/12/12 12:12:12',\n          },\n          'FULL NAME': {\n            $class: 'java.lang.String',\n            $: 'Doe 0',\n          },\n          AGE: {\n            $: 10,\n            $class: 'int',\n          }\n         }\n        },\n        {\n         $class: 'com.alibaba.fastjson.JSONObject',\n         $: {\n          'DATE OF BIRTH': {\n            $class: 'java.lang.String',\n            $: '2016/12/12 12:12:12',\n          },\n          'FULL NAME': {\n            $class: 'java.lang.String',\n            $: 'Doe 1',\n          },\n          AGE: {\n            $: 10,\n            $class: 'int',\n          }\n         }\n        },\n        {\n         $class: 'com.alibaba.fastjson.JSONObject',\n         $: {\n          xxx: {\n            $class: 'java.lang.String',\n            $: 'yyy',\n          }\n         }\n        }\n       ]\n      });\n\n     var buf2 = hessian.encode(obj, '1.0', {\n      'com.alibaba.fastjson.JSONObject': true,\n     });\n     var obj2 = hessian.decode(buf2, '1.0', true);\n     assert.deepEqual(obj, obj2);\n  });\n\n  describe('v2.0', function() {\n    // map = new HashMap();\n    // map.put(new Integer(1), \"fee\");\n    // map.put(new Integer(16), \"fie\");\n    // map.put(new Integer(256), \"foe\");\n    var hashmapBuffer = Buffer.concat([\n      new Buffer([\n        0x48,\n        0x01, // 1\n        0x31,\n        0x03\n      ]),\n      new Buffer('fee'), // 'fee'\n      new Buffer([\n        0x02, // 16\n        0x31,\n        0x36,\n        0x03\n      ]),\n      new Buffer('fie'), // 'fie'\n      new Buffer([\n        0x03,\n        0x32, // 256\n        0x35,\n        0x36,\n        0x03\n      ]),\n      new Buffer('foe'), // 'foe'\n      new Buffer('Z')\n    ]);\n\n    it('should write a java Class instance', function() {\n      var encoder = new hessian.EncoderV2();\n      var car = {\n        $class: 'hessian.demo.Car',\n        $: {\n          // field defined sort must same as java Class defined\n          a: 'a',\n          c: 'c',\n          b: 'b',\n          model: 'Beetle',\n          color: 'aquamarine',\n          mileage: 65536,\n        }\n      };\n      var buf = encoder.write(car).get();\n      assert.deepEqual(buf, utils.bytes('v2/map/car'));\n    });\n\n    it('should read java hash map', function() {\n      assert.deepEqual(hessian.decode(hashmapBuffer, '2.0'), {\n        1: 'fee',\n        16: 'fie',\n        256: 'foe'\n      });\n    });\n\n    it('should read a Circular java Object', function() {\n      var car = hessian.decode(utils.bytes('v2/map/car'), '2.0');\n      assert.deepEqual(car, {\n        a: 'a',\n        c: 'c',\n        b: 'b',\n        model: 'Beetle',\n        color: 'aquamarine',\n        mileage: 65536\n      });\n\n      var obj = hessian.decode(utils.bytes('v2/map/car1'), '2.0');\n      [ 'color', 'model', 'mileage', 'self', 'prev' ].forEach(function(p) {\n        assert(Object.prototype.hasOwnProperty.call(obj, p));\n      });\n      assert(obj.self === obj);\n      assert(!obj.prev);\n      [ 'color', 'model', 'mileage', 'self', 'prev' ].forEach(function(p) {\n        assert(Object.prototype.hasOwnProperty.call(obj.self, p));\n      });\n    });\n\n    it('should write js object to no type hash map', function() {\n      var encoder = new hessian.EncoderV2();\n      var buf = encoder.write({ foo: '' }).get();\n      assert.deepEqual(buf, utils.bytes('v2/map/foo_empty'));\n      assert.deepEqual(hessian.decode(utils.bytes('v2/map/foo_empty'), '2.0'), {\n        foo: ''\n      });\n\n      encoder = new hessian.EncoderV2();\n      buf = encoder.write({\n        foo: 'bar',\n        '中文key': '中文哈哈value',\n        '123': 456,\n        zero: 0,\n      }).get();\n      assert.deepEqual(buf, utils.bytes('v2/map/foo_bar'));\n\n      // read it\n      assert.deepEqual(hessian.decode(utils.bytes('v2/map/foo_bar'), '2.0'), {\n        foo: 'bar',\n        '中文key': '中文哈哈value',\n        '123': 456,\n        zero: 0,\n      });\n    });\n\n    // it('should read hessian 1.0 hash map', function () {\n    //   hessian.decode(utils.bytes('v1/map/foo_empty'), '2.0').should.eql({\n    //     foo: ''\n    //   });\n    //   hessian.decode(utils.bytes('v1/map/foo_bar'), '2.0').should.eql({\n    //     foo: 'bar',\n    //     '中文key': '中文哈哈value',\n    //     '123': 456,\n    //     zero: 0,\n    //   });\n    // });\n\n    it('should write simple map to java hash map', function() {\n      // map = new HashMap();\n      // map.put(new Integer(1), \"fee\");\n      // map.put(new Integer(16), \"fie\");\n      // map.put(new Integer(256), \"foe\");\n      // ---\n\n      // H           # untyped map (HashMap for Java)\n      //   x91       # 1\n      //   x03 fee   # \"fee\"\n\n      //   xa0       # 16\n      //   x03 fie   # \"fie\"\n\n      //   xc9 x00   # 256\n      //   x03 foe   # \"foe\"\n\n      //   Z\n      var map = {\n        1: \"fee\",\n        2: \"fie\",\n        3: \"foe\"\n      };\n      var encoder = new hessian.EncoderV2();\n      var buf = encoder.write(map).get();\n      assert.deepEqual(hessian.decode(buf, '2.0'), map);\n\n      // writeRef\n      var bufRef = encoder.write(map).get();\n      assert.deepEqual(hessian.decode(bufRef, '2.0'), map);\n      assert.deepEqual(bufRef.slice(buf.length), new Buffer([0x51, 0x90]));\n\n      var buf2 = hessian.encode({\n        $class: 'java.util.HashMap',\n        $: map\n      }, '2.0');\n      assert.deepEqual(buf2, buf);\n      assert.deepEqual(hessian.decode(buf2, '2.0'), map);\n    });\n\n    it('should decode map with type', function() {\n\n      assert.deepEqual(hessian.decode(utils.bytes('v2/map/hashtable'), '2.0'), {\n        'foo': 'bar',\n        '中文key': '中文哈哈value'\n      });\n\n    });\n\n    it('should write es6 Map to java.util.Map', function() {\n      if (!supportES6Map) {\n        // pass if not support es6 Map\n        return;\n      }\n\n      var map = new Map();\n      map.set({ '$class': 'java.lang.Long', '$': 123 }, 123456);\n      map.set({ '$class': 'java.lang.Long', '$': 123456 }, 123);\n      var buf = hessian.encode({ '$class': 'java.util.Map', '$': map }, '2.0');\n      // decode auto transfer key to string\n      var result = hessian.decode(buf, '2.0');\n      assert.deepEqual(result, {\n        '123': 123456,\n        '123456': 123\n      });\n\n      assert(result.$map);\n      assert(result.$map instanceof Map);\n      assert(result.$map.size === 2);\n\n      assert(result.$map.get(123) === 123456);\n      assert(result.$map.get(123456) === 123);\n    });\n\n    it('should write es6 Map to java.util.HashMap', function() {\n      if (!supportES6Map) {\n        // pass if not support es6 Map\n        return;\n      }\n\n      var map = new Map();\n      map.set({ '$class': 'java.lang.Long', '$': 123 }, 123456);\n      map.set({ '$class': 'java.lang.Long', '$': 123456 }, 123);\n      var encoder = new hessian.EncoderV2();\n      var buf = encoder.write(map).get();\n      assert.deepEqual(buf, utils.bytes('v2/map/generic'));\n\n      encoder.reset();\n\n      buf = encoder.write({ '$class': 'java.util.HashMap', '$': map }).get();\n      assert.deepEqual(buf, utils.bytes('v2/map/generic'));\n\n      // decode auto transfer key to string\n      var result = hessian.decode(utils.bytes('v2/map/generic'), '2.0');\n      assert.deepEqual(result, {\n        '123': 123456,\n        '123456': 123\n      });\n\n      assert(result.$map);\n      assert(result.$map instanceof Map);\n      assert(result.$map.size === 2);\n\n      assert(result.$map.get(123) === 123456);\n      assert(result.$map.get(123456) === 123);\n    });\n\n    it('should read java.util.HashMap', function() {\n      if (!supportES6Map || !Array.from) {\n        // pass if not support es6 Map\n        return;\n      }\n\n      var buf = new Buffer('43302c636f6d2e74616f62616f2e63756e2e74726164652e726573756c746d6f64656c2e526573756c744d6f64656c940773756363657373086572726f724d7367096572726f72436f6465046461746160544e4e4843303d636f6d2e74616f62616f2e63756e2e74726164652e7472616465706c6174666f726d2e706172616d2e5061636b6167655175657279506172616d73564f93066974656d49640a616374697669747949640a6469766973696f6e4964614c000002006a3b9b5204313233343daef1e2613c411f04313233343daef13e895f5a', 'hex');\n      var res = new hessian.DecoderV2(buf).read();\n\n      assert(res.data);\n      assert(res.data.$map);\n      assert(res.data.$map instanceof Map);\n      assert(res.data.$map.size === 2);\n\n      var keys = Array.from(res.data.$map.keys());\n      var values = Array.from(res.data.$map.values());\n\n      assert.deepEqual(keys[0], { itemId: 2200805546834, activityId: '1234', divisionId: 110321 });\n      assert.deepEqual(keys[1], { itemId: 16671, activityId: '1234', divisionId: 110321 });\n\n      assert(values[0] === 2);\n      assert(values[1] === 166239);\n\n      var plainObject = JSON.parse(JSON.stringify(res.data));\n      assert.deepEqual(plainObject, { '[object Object]': 166239 });\n    });\n\n    it('should encode & decode custom map type', function() {\n       var buf = new Buffer('731E636F6D2E616C69626162612E666173746A736F6E2E4A534F4E41727261794D1F636F6D2E616C69626162612E666173746A736F6E2E4A534F4E4F626A6563740D44415445204F4620424952544813323031362F31322F31322031323A31323A31320946554C4C204E414D4505446F652030034147459A5A4D910D44415445204F4620424952544813323031362F31322F31322031323A31323A31320946554C4C204E414D4505446F652031034147459A5A4D9103787878037979795A', 'hex');\n       var obj = hessian.decode(buf, '2.0', true);\n       assert.deepEqual(obj, {\n         $class: 'com.alibaba.fastjson.JSONArray',\n         $: [\n          {\n           $class: 'com.alibaba.fastjson.JSONObject',\n           $: {\n            'DATE OF BIRTH': '2016/12/12 12:12:12',\n            'FULL NAME': 'Doe 0',\n            AGE: 10\n           }\n          },\n          {\n           $class: 'com.alibaba.fastjson.JSONObject',\n           $: {\n            'DATE OF BIRTH': '2016/12/12 12:12:12',\n            'FULL NAME': 'Doe 1',\n            AGE: 10\n           }\n          },\n          {\n           $class: 'com.alibaba.fastjson.JSONObject',\n           $: {\n            xxx: 'yyy'\n           }\n          }\n         ]\n        });\n\n       var buf2 = hessian.encode(obj, '2.0');\n       var obj2 = hessian.decode(buf2, '2.0', true);\n       assert.deepEqual(obj, obj2);\n    });\n  });\n\n});\n"
  },
  {
    "path": "test/null.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst hessian = require('..');\n\ndescribe('null.test.js', function () {\n  it('should read null', function () {\n    var a = hessian.decode(new Buffer('N'));\n    assert(a === null);\n  });\n\n  it('should write null', function () {\n    assert.deepEqual(hessian.encode(null), new Buffer('N'));\n  });\n\n  describe('v2.0', function () {\n    it('should read write as 1.0', function () {\n      assert.deepEqual(hessian.encode(null, '2.0'), new Buffer('N'));\n      assert(hessian.decode(new Buffer('N'), '2.0') === null);\n    });\n  });\n});\n"
  },
  {
    "path": "test/object.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst hessian = require('..');\nconst utils = require('./utils');\nconst supportES6Map = require('../lib/utils').supportES6Map;\n\ndescribe('object.test.js', function () {\n  describe('v1.0', function () {\n\n    it('should skip function', function() {\n      var o = { foo: 'bar', fn: function() {} };\n      var buf = hessian.encode(o, '1.0');\n      var output = hessian.decode(buf, '1.0');\n      assert.deepEqual(output, { foo: 'bar', fn: null });\n    });\n\n    it('should write null for property like: { a: { \"$class\": \"yyy.yyy\", \"$\": null } }', function () {\n      var o = { '$class': 'xxx.xxx',\n                '$': { a: { '$class': 'yyy.yyy', '$': null } } };\n      var rightBuf = new Buffer('4d7400077878782e787878530001614e7a', 'hex');\n\n      var buf = hessian.encode(o, '1.0');\n      assert(buf.length === rightBuf.length);\n      assert.deepEqual(buf, rightBuf);\n    });\n\n    it('should write object for property like: { a: { \"$class\": \"yyy.yyy\", \"$\": {} } }', function () {\n      var o = { '$class': 'xxx.xxx',\n                '$': { a: { '$class': 'yyy.yyy', '$': {} } } };\n      var rightBuf = new Buffer('4d7400077878782e787878530001614d7400077979792e7979797a7a', 'hex');\n\n      var buf = hessian.encode(o, '1.0');\n      assert(buf.length === rightBuf.length);\n      assert.deepEqual(buf, rightBuf);\n    });\n\n    it('should _assertType error when encode wrong object', function () {\n      var req = {\n        $class: 'com.alipay.x.biz.User',\n        $: 'abc'\n      };\n      var rs;\n      var buf;\n      try {\n        buf = hessian.encode(req, '1.0');\n      } catch (err) {\n        rs = err;\n      }\n      assert(rs);\n      assert(rs.message.indexOf('com.alipay.x.biz.User') >= 0);\n      assert(!buf);\n    });\n\n    it('should decode and encode ConnectionRequest', function () {\n      var javabuf = utils.bytes('v1/object/ConnectionRequest');\n      var connreq = hessian.decode(javabuf, '1.0', true);\n      var jsconnreq = {\n        $class: 'hessian.ConnectionRequest',\n        $: {\n          ctx: {\n            $class: 'hessian.ConnectionRequest$RequestContext',\n            $: {\n              id: {\n                $class: 'int',\n                $: 101\n              },\n              // 'this$0': null\n            }\n          }\n        }\n      };\n\n      // jsconnreq.$.ctx.$.this$0 = jsconnreq;\n      assert.deepEqual(connreq, jsconnreq);\n      var jsbuf = hessian.encode(connreq, '1.0');\n      var jsbuf2 = hessian.encode(jsconnreq, '1.0');\n      // because of skip field this$0, the length of course not eql.\n      // jsbuf2.should.length(javabuf.length);\n      // jsbuf2.should.eql(javabuf);\n\n      // jsbuf.should.length(javabuf.length);\n      // jsbuf.should.eql(javabuf);\n\n      var jsbuf2Again = hessian.encode(jsconnreq, '1.0');\n      assert.deepEqual(jsbuf2Again, jsbuf2);\n    });\n\n    it('should write enum Color', function () {\n      assert.deepEqual(hessian.encode({\n        $class: 'hessian.Main$Color',\n        $: {\n          name: 'RED'\n        }\n      }, '1.0'), utils.bytes('v1/enum/red'));\n\n      assert.deepEqual(hessian.encode({\n        $class: 'hessian.Main$Color',\n        $: {\n          name: 'GREEN'\n        }\n      }, '1.0'), utils.bytes('v1/enum/green'));\n\n      assert.deepEqual(hessian.encode({\n        $class: 'hessian.Main$Color',\n        $: {\n          name: 'BLUE'\n        }\n      }, '1.0'), utils.bytes('v1/enum/blue'));\n    });\n\n    it('should write enum with ref', function () {\n      // list = new ArrayList();\n      // list.add(Color.BLUE);\n      // list.add(Color.RED);\n      // list.add(Color.GREEN);\n      assert.deepEqual(hessian.encode([\n        {\n          $class: 'hessian.Main$Color',\n          $: {\n            name: 'BLUE'\n          }\n        },\n        {\n          $class: 'hessian.Main$Color',\n          $: {\n            name: 'RED'\n          }\n        },\n        {\n          $class: 'hessian.Main$Color',\n          $: {\n            name: 'GREEN'\n          }\n        },\n      ], '1.0'), utils.bytes('v1/enum/lists'));\n    });\n\n    it('should read enum Color', function () {\n      // enum Color {\n      //   RED,\n      //   GREEN,\n      //   BLUE,\n      // }\n\n      assert.deepEqual(hessian.decode(utils.bytes('v1/enum/red'), '1.0'), {\n        name: 'RED'\n      });\n\n      assert.deepEqual(hessian.decode(utils.bytes('v1/enum/green'), '1.0', true), {\n        '$class': 'hessian.Main$Color',\n        '$': {\n          name: { '$class': 'java.lang.String', '$': 'GREEN' }\n        }\n      });\n\n      assert.deepEqual(hessian.decode(utils.bytes('v1/enum/blue'), '1.0'), {\n        name: 'BLUE'\n      });\n\n      assert.deepEqual(hessian.decode(utils.bytes('v1/enum/green'), '1.0'), {\n        name: 'GREEN'\n      });\n\n      assert.deepEqual(hessian.decode(utils.bytes('v1/enum/red'), '1.0', true), {\n        '$class': 'hessian.Main$Color',\n        '$': {\n          name: { '$class': 'java.lang.String', '$': 'RED' }\n        }\n      });\n\n      assert.deepEqual(\n        hessian.decode(utils.bytes('v1/enum/lists'), '1.0'),\n        [ { name: 'BLUE' }, { name: 'RED' }, { name: 'GREEN' } ]\n      );\n\n      assert.deepEqual(hessian.decode(utils.bytes('v1/enum/lists'), '1.0', true), {\n        $class: 'java.util.ArrayList',\n        $: [\n          { '$class': 'hessian.Main$Color', '$': { name: { '$class': 'java.lang.String', '$': 'BLUE' } } },\n          { '$class': 'hessian.Main$Color', '$': { name: { '$class': 'java.lang.String', '$': 'RED' } } },\n          { '$class': 'hessian.Main$Color', '$': { name: { '$class': 'java.lang.String', '$': 'GREEN' } } }\n        ]\n      });\n    });\n\n    it('should write \"{$class: \"hessian.test.demo.Car\", $: {a: 1}}\"', function () {\n      var obj = {\n        $class: 'hessian.test.demo.Car',\n        $: {a: 1, b: 'map'}\n      };\n      var buf = hessian.encode(obj, '1.0');\n      assert(buf[0] === 0x4d); // 'M'\n      assert.deepEqual(hessian.decode(buf, '1.0'), obj.$);\n      assert.deepEqual(hessian.decode(buf, '1.0', true), {\n        '$class': 'hessian.test.demo.Car',\n        '$': {\n          a: { '$class': 'int', '$': 1 },\n          b: { '$class': 'java.lang.String', '$': 'map' }\n        }\n      });\n    });\n\n    it('should read and write one car list', function () {\n      assert.deepEqual(hessian.decode(utils.bytes('v1/map/one_car_list'), '1.0'), [\n        { a: 'a',\n          c: 'c',\n          b: 'b',\n          model: 'model 1',\n          color: 'aquamarine',\n          mileage: 65536 }\n      ]);\n\n      var cars = hessian.decode(utils.bytes('v1/map/one_car_list'), '1.0', true);\n      assert.deepEqual(cars, {\n        $class: 'java.util.ArrayList',\n        $: [\n          {\n            '$class': 'hessian.demo.Car',\n            '$': {\n              a: { '$class': 'java.lang.String', '$': 'a' },\n              c: { '$class': 'java.lang.String', '$': 'c' },\n              b: { '$class': 'java.lang.String', '$': 'b' },\n              model: { '$class': 'java.lang.String', '$': 'model 1' },\n              color: { '$class': 'java.lang.String', '$': 'aquamarine' },\n              mileage: { '$class': 'int', '$': 65536 }\n            }\n          }\n        ]\n      });\n\n      assert.deepEqual(hessian.encode(cars, '1.0'), utils.bytes('v1/map/one_car_list'));\n    });\n\n    it('should read and write two car list', function () {\n      assert.deepEqual(hessian.decode(utils.bytes('v1/map/two_car_list'), '1.0'), [\n        { a: 'a',\n          c: 'c',\n          b: 'b',\n          model: 'model 1',\n          color: 'aquamarine',\n          mileage: 65536 },\n        { a: 'a',\n          c: 'c',\n          b: 'b',\n          model: 'model 2',\n          color: 'aquamarine',\n          mileage: 65536 }\n      ]);\n\n      var cars = hessian.decode(utils.bytes('v1/map/two_car_list'), '1.0', true);\n      assert.deepEqual(cars, {\n        $class: 'java.util.ArrayList',\n        $: [\n          {\n            '$class': 'hessian.demo.Car',\n            '$': {\n              a: { '$class': 'java.lang.String', '$': 'a' },\n              c: { '$class': 'java.lang.String', '$': 'c' },\n              b: { '$class': 'java.lang.String', '$': 'b' },\n              model: { '$class': 'java.lang.String', '$': 'model 1' },\n              color: { '$class': 'java.lang.String', '$': 'aquamarine' },\n              mileage: { '$class': 'int', '$': 65536 }\n            }\n          }, {\n            '$class': 'hessian.demo.Car',\n            '$': {\n              a: { '$class': 'java.lang.String', '$': 'a' },\n              c: { '$class': 'java.lang.String', '$': 'c' },\n              b: { '$class': 'java.lang.String', '$': 'b' },\n              model: { '$class': 'java.lang.String', '$': 'model 2' },\n              color: { '$class': 'java.lang.String', '$': 'aquamarine' },\n              mileage: { '$class': 'int', '$': 65536 }\n            }\n          }\n        ]\n      });\n\n      var buf = hessian.encode(cars, '1.0');\n      assert(buf.length === utils.bytes('v1/map/two_car_list').length);\n      assert.deepEqual(buf, utils.bytes('v1/map/two_car_list'));\n    });\n\n    it('should read and write many cars', function () {\n      // list = new ArrayList();\n      // list.add(new Car(\"model 1\"));\n      // list.add(new Car(\"model 2\"));\n      // list.add(new Car(\"model 3\"));\n      assert.deepEqual(hessian.decode(utils.bytes('v1/map/car_list'), '1.0'), [\n        { a: 'a',\n          c: 'c',\n          b: 'b',\n          model: 'model 1',\n          color: 'aquamarine',\n          mileage: 65536 },\n        { a: 'a',\n          c: 'c',\n          b: 'b',\n          model: 'model 2',\n          color: 'aquamarine',\n          mileage: 65536 },\n        { a: 'a',\n          c: 'c',\n          b: 'b',\n          model: 'model 3',\n          color: 'aquamarine',\n          mileage: 65536 }\n      ]);\n\n      var cars = hessian.decode(utils.bytes('v1/map/car_list'), '1.0', true);\n      assert.deepEqual(cars, {\n        $class: 'java.util.ArrayList',\n        $: [\n          {\n            '$class': 'hessian.demo.Car',\n            '$': {\n              a: { '$class': 'java.lang.String', '$': 'a' },\n              c: { '$class': 'java.lang.String', '$': 'c' },\n              b: { '$class': 'java.lang.String', '$': 'b' },\n              model: { '$class': 'java.lang.String', '$': 'model 1' },\n              color: { '$class': 'java.lang.String', '$': 'aquamarine' },\n              mileage: { '$class': 'int', '$': 65536 }\n            }\n          }, {\n            '$class': 'hessian.demo.Car',\n            '$': {\n              a: { '$class': 'java.lang.String', '$': 'a' },\n              c: { '$class': 'java.lang.String', '$': 'c' },\n              b: { '$class': 'java.lang.String', '$': 'b' },\n              model: { '$class': 'java.lang.String', '$': 'model 2' },\n              color: { '$class': 'java.lang.String', '$': 'aquamarine' },\n              mileage: { '$class': 'int', '$': 65536 }\n            }\n          }, {\n            '$class': 'hessian.demo.Car',\n            '$': {\n              a: { '$class': 'java.lang.String', '$': 'a' },\n              c: { '$class': 'java.lang.String', '$': 'c' },\n              b: { '$class': 'java.lang.String', '$': 'b' },\n              model: { '$class': 'java.lang.String', '$': 'model 3' },\n              color: { '$class': 'java.lang.String', '$': 'aquamarine' },\n              mileage: { '$class': 'int', '$': 65536 }\n            }\n          }\n        ]\n      });\n\n      assert.deepEqual(hessian.encode(cars, '1.0'), utils.bytes('v1/map/car_list'));\n    });\n\n    describe('java.util.concurrent.atomic.AtomicLong', function () {\n      it('should read and write', function () {\n        var javabuf = utils.bytes('v1/object/AtomicLong0');\n        var a0 = hessian.decode(javabuf);\n        assert.deepEqual(a0, {value: 0});\n        var a0 = hessian.decode(javabuf, true);\n        assert.deepEqual(a0, {\n          $class: 'java.util.concurrent.atomic.AtomicLong',\n          $: {\n            value: {\n              $: 0,\n              $class: 'long'\n            }\n          }\n        });\n        assert.deepEqual(hessian.encode(a0), javabuf);\n\n        javabuf = utils.bytes('v1/object/AtomicLong1');\n        var a1 = hessian.decode(javabuf);\n        assert.deepEqual(a1, {value: 1});\n        var a1 = hessian.decode(javabuf, true);\n        assert.deepEqual(a1, {\n          $class: 'java.util.concurrent.atomic.AtomicLong',\n          $: {\n            value: {\n              $: 1,\n              $class: 'long'\n            }\n          }\n        });\n        assert.deepEqual(hessian.encode(a1), javabuf);\n      });\n    });\n  });\n\n  describe('v2.0', function () {\n    it('should skip function', function() {\n      var o = { foo: 'bar', fn: function() {} };\n      var buf = hessian.encode(o, '2.0');\n      var output = hessian.decode(buf, '2.0');\n      assert.deepEqual(output, { foo: 'bar', fn: null });\n    });\n\n    it('should decode and encode ConnectionRequest', function () {\n      var javabuf = utils.bytes('v2/object/ConnectionRequest');\n      var connreq1 = hessian.decode(javabuf, '2.0');\n      assert(connreq1.ctx);\n      assert(connreq1.ctx.id === 101); // 'this$0'\n\n      var connreq = hessian.decode(javabuf, '2.0', true);\n      var jsconnreq = {\n        $class: 'hessian.ConnectionRequest',\n        $: {\n          ctx: {\n            $class: 'hessian.ConnectionRequest$RequestContext',\n            $: {\n              id: 101,\n              // 'this$0': null\n            }\n          }\n        }\n      };\n\n      // jsconnreq.$.ctx.$.this$0 = jsconnreq;\n      assert.deepEqual(jsconnreq, connreq);\n      var jsbuf = hessian.encode(connreq, '2.0');\n      var jsbuf2 = hessian.encode(jsconnreq, '2.0');\n      // jsbuf2.should.length(javabuf.length);\n      // jsbuf2.should.eql(javabuf);\n\n      // jsbuf.should.length(javabuf.length);\n      // jsbuf.should.eql(javabuf);\n    });\n\n    it('should decode hessian 1.0 ConnectionRequest', function () {\n      var javabuf = utils.bytes('v1/object/ConnectionRequest');\n      var connreq = hessian.decode(javabuf, '1.0', true);\n      assert(connreq.$class === 'hessian.ConnectionRequest');\n      assert(connreq.$.ctx.$class === 'hessian.ConnectionRequest$RequestContext');\n    });\n\n    it('should write enum Color', function () {\n      assert.deepEqual(hessian.encode({\n        $class: 'hessian.Main$Color',\n        $: {\n          name: 'RED'\n        }\n      }, '2.0'), utils.bytes('v2/enum/red'));\n\n      assert.deepEqual(hessian.encode({\n        $class: 'hessian.Main$Color',\n        $: {\n          name: 'GREEN'\n        }\n      }, '2.0'), utils.bytes('v2/enum/green'));\n\n      assert.deepEqual(hessian.encode({\n        $class: 'hessian.Main$Color',\n        $: {\n          name: 'BLUE'\n        }\n      }, '2.0'), utils.bytes('v2/enum/blue'));\n    });\n\n    it('should write enum with ref', function () {\n      // list = new ArrayList();\n      // list.add(Color.BLUE);\n      // list.add(Color.RED);\n      // list.add(Color.GREEN);\n      assert.deepEqual(hessian.encode([\n        {\n          $class: 'hessian.Main$Color',\n          $: {\n            name: 'BLUE'\n          }\n        },\n        {\n          $class: 'hessian.Main$Color',\n          $: {\n            name: 'RED'\n          }\n        },\n        {\n          $class: 'hessian.Main$Color',\n          $: {\n            name: 'GREEN'\n          }\n        },\n      ], '2.0'), utils.bytes('v2/enum/lists'));\n    });\n\n    it('should read enum Color', function () {\n      // enum Color {\n      //   RED,\n      //   GREEN,\n      //   BLUE,\n      // }\n\n      // enum format:\n      // O type 1 \"name\" o ref name-value\n      assert.deepEqual(hessian.decode(utils.bytes('v2/enum/red'), '2.0'), {\n        name: 'RED'\n      });\n\n      assert.deepEqual(hessian.decode(utils.bytes('v2/enum/green'), '2.0', true), {\n        $class: 'hessian.Main$Color',\n        $: {\n          name: 'GREEN'\n        }\n      });\n\n      assert.deepEqual(hessian.decode(utils.bytes('v2/enum/blue'), '2.0'), {\n        name: 'BLUE'\n      });\n\n      assert.deepEqual(hessian.decode(utils.bytes('v2/enum/green'), '2.0'), {\n        name: 'GREEN'\n      });\n\n      assert.deepEqual(hessian.decode(utils.bytes('v2/enum/red'), '2.0', true), {\n        $class: 'hessian.Main$Color',\n        $: {\n          name: 'RED'\n        }\n      });\n\n      assert.deepEqual(\n        hessian.decode(utils.bytes('v2/enum/lists'), '2.0'),\n        [ { name: 'BLUE' }, { name: 'RED' }, { name: 'GREEN' } ]\n      );\n\n      assert.deepEqual(hessian.decode(utils.bytes('v2/enum/lists'), '2.0', true), [\n        { '$class': 'hessian.Main$Color', '$': { name: 'BLUE' } },\n        { '$class': 'hessian.Main$Color', '$': { name: 'RED' } },\n        { '$class': 'hessian.Main$Color', '$': { name: 'GREEN' } }\n      ]);\n    });\n\n    it('should write \"{$class: \"hessian.test.demo.Car\", $: {a: 1}}\"', function () {\n      var obj = {\n        $class: 'hessian.test.demo.Car',\n        $: {a: 1, b: 'map'}\n      };\n      var buf = hessian.encode(obj, '2.0');\n      assert(buf[0] === 0x43);\n      assert.deepEqual(hessian.decode(buf, '2.0'), obj.$);\n      assert.deepEqual(hessian.decode(buf, '2.0', true), obj);\n    });\n\n    it('should read one car list', function () {\n      assert.deepEqual(hessian.decode(utils.bytes('v2/map/one_car_list'), '2.0'), [\n        { a: 'a',\n          c: 'c',\n          b: 'b',\n          model: 'model 1',\n          color: 'aquamarine',\n          mileage: 65536 }\n      ]);\n\n      var cars = hessian.decode(utils.bytes('v2/map/one_car_list'), '2.0', true);\n      assert.deepEqual(cars, [\n        {\n          $class: 'hessian.demo.Car',\n          $: {\n            a: 'a',\n            c: 'c',\n            b: 'b',\n            model: 'model 1',\n            color: 'aquamarine',\n            mileage: 65536 }\n        }\n      ]);\n\n      assert.deepEqual(hessian.encode(cars, '2.0'), utils.bytes('v2/map/one_car_list'));\n    });\n\n    it('should read two car list', function () {\n      assert.deepEqual(hessian.decode(utils.bytes('v2/map/two_car_list'), '2.0'), [\n        { a: 'a',\n          c: 'c',\n          b: 'b',\n          model: 'model 1',\n          color: 'aquamarine',\n          mileage: 65536 },\n        { a: 'a',\n          c: 'c',\n          b: 'b',\n          model: 'model 2',\n          color: 'aquamarine',\n          mileage: 65536 }\n      ]);\n\n      var cars = hessian.decode(utils.bytes('v2/map/two_car_list'), '2.0', true);\n      assert.deepEqual(cars, [\n        {\n          $class: 'hessian.demo.Car',\n          $: {\n            a: 'a',\n            c: 'c',\n            b: 'b',\n            model: 'model 1',\n            color: 'aquamarine',\n            mileage: 65536 }\n        },\n        {\n          $class: 'hessian.demo.Car',\n          $: {\n            a: 'a',\n            c: 'c',\n            b: 'b',\n            model: 'model 2',\n            color: 'aquamarine',\n            mileage: 65536 }\n        }\n      ]);\n\n      var buf = hessian.encode(cars, '2.0');\n      assert(buf.length === utils.bytes('v2/map/two_car_list').length);\n      assert.deepEqual(buf, utils.bytes('v2/map/two_car_list'));\n    });\n\n    it('should read many cars', function () {\n      // list = new ArrayList();\n      // list.add(new Car(\"model 1\"));\n      // list.add(new Car(\"model 2\"));\n      // list.add(new Car(\"model 3\"));\n      assert.deepEqual(hessian.decode(utils.bytes('v2/map/car_list'), '2.0'), [\n        { a: 'a',\n          c: 'c',\n          b: 'b',\n          model: 'model 1',\n          color: 'aquamarine',\n          mileage: 65536 },\n        { a: 'a',\n          c: 'c',\n          b: 'b',\n          model: 'model 2',\n          color: 'aquamarine',\n          mileage: 65536 },\n        { a: 'a',\n          c: 'c',\n          b: 'b',\n          model: 'model 3',\n          color: 'aquamarine',\n          mileage: 65536 }\n      ]);\n\n      var cars = hessian.decode(utils.bytes('v2/map/car_list'), '2.0', true);\n      assert.deepEqual(cars, [\n        { '$class': 'hessian.demo.Car',\n          '$':\n           { a: 'a',\n             c: 'c',\n             b: 'b',\n             model: 'model 1',\n             color: 'aquamarine',\n             mileage: 65536 } },\n        { '$class': 'hessian.demo.Car',\n          '$':\n           { a: 'a',\n             c: 'c',\n             b: 'b',\n             model: 'model 2',\n             color: 'aquamarine',\n             mileage: 65536 } },\n        { '$class': 'hessian.demo.Car',\n          '$':\n           { a: 'a',\n             c: 'c',\n             b: 'b',\n             model: 'model 3',\n             color: 'aquamarine',\n             mileage: 65536 } }\n      ]);\n\n      assert.deepEqual(hessian.encode(cars, '2.0'), utils.bytes('v2/map/car_list'));\n    });\n\n    describe('java.util.concurrent.atomic.AtomicLong', function () {\n      it('should read and write', function () {\n        var javabuf = utils.bytes('v2/object/AtomicLong0');\n        var a0 = hessian.decode(javabuf, '2.0');\n        assert.deepEqual(a0, {value: 0});\n        var a0 = hessian.decode(javabuf, '2.0', true);\n        assert.deepEqual(a0, {\n          $class: 'java.util.concurrent.atomic.AtomicLong',\n          $: {\n            value: 0\n          }\n        });\n        assert.deepEqual(hessian.encode({\n          $class: 'java.util.concurrent.atomic.AtomicLong',\n          $: {\n            value: {\n              $class: 'long',\n              $: 0\n            }\n          }\n        }, '2.0'), javabuf);\n\n        javabuf = utils.bytes('v2/object/AtomicLong1');\n        var a1 = hessian.decode(javabuf, '2.0');\n        assert.deepEqual(a1, {value: 1});\n        var a1 = hessian.decode(javabuf, '2.0', true);\n        assert.deepEqual(a1, {\n          $class: 'java.util.concurrent.atomic.AtomicLong',\n          $: {\n            value: 1\n          }\n        });\n        assert.deepEqual(hessian.encode({\n          $class: 'java.util.concurrent.atomic.AtomicLong',\n          $: {\n            value: {\n              $class: 'long',\n              $: 1\n            }\n          }\n        }, '2.0'), javabuf);\n      });\n    });\n  });\n\n\n  if (supportES6Map) {\n    describe('map key object', function() {\n\n      it('enum should use name v1', function() {\n        var key = {\n          $class: 'com.hessian.enums.TestEnum',\n          $: {\n            name: 'KEY',\n          },\n        };\n        var obj = new Map();\n        obj.set(key, 'hello');\n        var buf = hessian.encode(obj);\n        var rs = hessian.decode(buf);\n        assert.deepEqual(rs, { 'KEY': 'hello' });\n      });\n\n      it('use obj when name property missing', function() {\n        var key = {\n          $class: 'com.hessian.enums.TestEnum',\n          $: {\n            name1: 'KEY',\n          },\n        };\n        var obj = new Map();\n        obj.set(key, 'hello');\n        var buf = hessian.encode(obj);\n        var rs = hessian.decode(buf);\n        assert.deepEqual(rs, { '[object Object]': 'hello' });\n      });\n\n      it('enum should use name v2', function() {\n        var key = {\n          $class: 'com.hessian.enums.TestEnum',\n          $: {\n            name: 'KEY',\n          },\n        };\n        var obj = new Map();\n        obj.set(key, 'hello');\n        var buf = hessian.encode(obj, '2.0');\n        var rs = hessian.decode(buf, '2.0');\n        assert.deepEqual(rs, { 'KEY': 'hello' });\n      });\n\n    });\n  }\n\n\n\n});\n"
  },
  {
    "path": "test/string.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst hessian = require('..');\nconst utils = require('./utils');\n\ndescribe('string.test.js', function () {\n  var helloBuffer = Buffer.concat([new Buffer(['S'.charCodeAt(0), 0x00, 0x05]),\n    new Buffer('hello')]);\n\n  it('should read string', function () {\n    assert(hessian.decode(helloBuffer) === 'hello');\n    assert(hessian.decode(Buffer.concat([new Buffer(['s'.charCodeAt(0), 0x00, 0x07]),\n        new Buffer('hello, '), new Buffer(['S'.charCodeAt(0), 0x00, 0x05]),\n        new Buffer('world')])) === 'hello, world');\n  });\n\n  it('should write string', function () {\n    var s = hessian.encode('hello');\n    assert(Buffer.isBuffer(s));\n    assert(s.length === 8);\n    assert.deepEqual(s, helloBuffer);\n  });\n\n  it('should read write empty string', function () {\n    assert(hessian.decode(new Buffer(['S'.charCodeAt(0), 0, 0])) === '');\n    assert.deepEqual(hessian.encode(''), new Buffer(['S'.charCodeAt(0), 0, 0]));\n  });\n\n  it('should read and write utf8 string as java', function () {\n    var str = '';\n    for (var i = 0; i < 32767; i++) {\n      str += '锋';\n    }\n    assert.deepEqual(hessian.encode(str, '1.0'), utils.bytes('v1/string/utf8_32767'));\n    assert(hessian.decode(utils.bytes('v1/string/utf8_32767')) === str);\n\n    var str = '';\n    for (var i = 0; i < 32768; i++) {\n      str += '锋';\n    }\n    assert.deepEqual(hessian.encode(str, '1.0'), utils.bytes('v1/string/utf8_32768'));\n    assert(hessian.decode(utils.bytes('v1/string/utf8_32768')) === str);\n\n    var str = '';\n    for (var i = 0; i < 32769; i++) {\n      str += '锋';\n    }\n    assert.deepEqual(hessian.encode(str, '1.0'), utils.bytes('v1/string/utf8_32769'));\n    assert(hessian.decode(utils.bytes('v1/string/utf8_32769')) === str);\n\n    var str = '';\n    for (var i = 0; i < 65534; i++) {\n      str += '锋';\n    }\n    assert.deepEqual(hessian.encode(str, '1.0'), utils.bytes('v1/string/utf8_65534'));\n    assert(hessian.decode(utils.bytes('v1/string/utf8_65534')) === str);\n\n    var str = '';\n    for (var i = 0; i < 65535; i++) {\n      str += '锋';\n    }\n    assert.deepEqual(hessian.encode(str, '1.0'), utils.bytes('v1/string/utf8_65535'));\n    assert(hessian.decode(utils.bytes('v1/string/utf8_65535')) === str);\n\n    var str = '';\n    for (var i = 0; i < 65536; i++) {\n      str += '锋';\n    }\n    assert.deepEqual(hessian.encode(str, '1.0'), utils.bytes('v1/string/utf8_65536'));\n    assert(hessian.decode(utils.bytes('v1/string/utf8_65536')) === str);\n\n    var str = '';\n    for (var i = 0; i < 65537; i++) {\n      str += '锋';\n    }\n    assert.deepEqual(hessian.encode(str, '1.0'), utils.bytes('v1/string/utf8_65537'));\n    assert(hessian.decode(utils.bytes('v1/string/utf8_65537')) === str);\n  });\n\n  it('should write string same as java write', function () {\n    assert.deepEqual(hessian.encode('', '1.0'), utils.bytes('v1/string/empty'));\n    assert.deepEqual(hessian.encode('foo'), utils.bytes('v1/string/foo'));\n    assert.deepEqual(hessian.encode('中文 Chinese', '1.0'), utils.bytes('v1/string/chinese'));\n    var text4k = utils.string('4k');\n    assert.deepEqual(hessian.encode(text4k, '1.0'), utils.bytes('v1/string/text4k'));\n    assert(hessian.decode(utils.bytes('v1/string/text4k')) === text4k);\n\n    var largeBuf = new Buffer(32767);\n    largeBuf.fill(0x41);\n    assert.deepEqual(\n      hessian.encode(largeBuf.toString(), '1.0'),\n      utils.bytes('v1/string/large_string_32767')\n    );\n    assert(\n      hessian.decode(utils.bytes('v1/string/large_string_32767')) === largeBuf.toString()\n    );\n\n    var largeBuf = new Buffer(32768);\n    largeBuf.fill(0x41);\n    assert.deepEqual(\n      hessian.encode(largeBuf.toString(), '1.0'),\n      utils.bytes('v1/string/large_string_32768')\n    );\n    assert(\n      hessian.decode(utils.bytes('v1/string/large_string_32768')) === largeBuf.toString()\n    );\n\n    var largeBuf = new Buffer(32769);\n    largeBuf.fill(0x41);\n    assert.deepEqual(\n      hessian.encode(largeBuf.toString(), '1.0'),\n      utils.bytes('v1/string/large_string_32769')\n    );\n    assert(\n      hessian.decode(utils.bytes('v1/string/large_string_32769')) === largeBuf.toString()\n    );\n\n    var largeBuf = new Buffer(65534);\n    largeBuf.fill(0x41);\n    assert.deepEqual(\n      hessian.encode(largeBuf.toString(), '1.0'),\n      utils.bytes('v1/string/large_string_65534')\n    );\n    assert(\n      hessian.decode(utils.bytes('v1/string/large_string_65534')) === largeBuf.toString()\n    );\n\n    var largeBuf = new Buffer(65535);\n    largeBuf.fill(0x41);\n    assert.deepEqual(\n      hessian.encode(largeBuf.toString(), '1.0'),\n      utils.bytes('v1/string/large_string_65535')\n    );\n    assert(\n      hessian.decode(utils.bytes('v1/string/large_string_65535')) === largeBuf.toString()\n    );\n\n    var largeBuf = new Buffer(65536);\n    largeBuf.fill(0x41);\n    assert.deepEqual(\n      hessian.encode(largeBuf.toString(), '1.0'),\n      utils.bytes('v1/string/large_string_65536')\n    );\n    assert(\n      hessian.decode(utils.bytes('v1/string/large_string_65536')) === largeBuf.toString()\n    );\n\n    var largeBuf = new Buffer(65537);\n    largeBuf.fill(0x41);\n    assert.deepEqual(\n      hessian.encode(largeBuf.toString(), '1.0'),\n      utils.bytes('v1/string/large_string_65537')\n    );\n    assert(\n      hessian.decode(utils.bytes('v1/string/large_string_65537')) === largeBuf.toString()\n    );\n\n  });\n\n  it.skip('should write string same as java write exclude', function () {\n    var largeString = new Array(65535);\n    for (var i = 0; i < largeString.length; i += 2) {\n      largeString[i] = '\\ud800';\n      // largeString[i] = String.fromCharCode(0xd800);\n      if (i + 1 < largeString.length) {\n        largeString[i + 1] = '\\udbff';\n        // largeString[i + 1] = String.fromCharCode(0xdbff);\n      }\n    }\n    largeString = largeString.join('');\n    assert.deepEqual(\n      hessian.encode(largeString, '1.0'),\n      utils.bytes('v1/string/large_string_chars')\n    );\n    // read it\n    assert(\n      hessian.decode(utils.bytes('v1/string/large_string_chars')) === largeString\n    );\n  });\n\n  describe('v2.0', function () {\n    it('should read short strings', function () {\n      assert(hessian.decode(new Buffer([0x00]), '2.0') === '');\n      assert(hessian.decode(new Buffer([0x00]), '2.0', true) === '');\n      assert(hessian.decode(Buffer.concat([new Buffer([0x05]),\n        new Buffer('hello')]), '2.0') === 'hello');\n      assert(hessian.decode(new Buffer([0x01, 0xc3, 0x83]), '2.0') === '\\u00c3');\n      assert(hessian.decode(Buffer.concat([new Buffer([0x09]),\n        new Buffer('hello, 中文')]), '2.0') === 'hello, 中文');\n    });\n\n    it('should read \"hello\" in long form', function () {\n      assert(hessian.decode(Buffer.concat([new Buffer(['S'.charCodeAt(0), 0x00, 0x05]),\n        new Buffer('hello')]), '2.0') === 'hello');\n    });\n\n    it('should read split into two chunks: s and short strings', function () {\n      assert(hessian.decode(Buffer.concat([new Buffer([0x52, 0x00, 0x07]),\n        new Buffer('hello, '), new Buffer([0x05]), new Buffer('world')]), '2.0') === 'hello, world');\n    });\n\n    it('should write short strings', function () {\n      assert.deepEqual(hessian.encode('', '2.0'), new Buffer([0x00]));\n      assert.deepEqual(hessian.encode('foo', '2.0'), Buffer.concat([\n        new Buffer([0x03]),\n        new Buffer('foo')\n      ]));\n      assert.deepEqual(hessian.encode('0123456789012345678901234567890', '2.0'), Buffer.concat([\n        new Buffer([0x1f]),\n        new Buffer('0123456789012345678901234567890')\n      ]));\n\n      // var len32Buf = new Buffer(2);\n      // len32Buf.writeInt16BE(32, 0);\n      assert.deepEqual(hessian.encode('01234567890123456789012345678901', '2.0'), Buffer.concat([\n          new Buffer([0x30, 0x20]),\n          // len32Buf,\n          new Buffer('01234567890123456789012345678901')\n        ])\n      );\n\n      var largeBuf = new Buffer(65535);\n      largeBuf.fill(0x41);\n      hessian.encode(largeBuf.toString(), '2.0');\n\n      largeBuf = new Buffer(65535 * 3 + 100);\n      largeBuf.fill(0x41);\n      hessian.encode(largeBuf.toString(), '2.0');\n    });\n\n    it('should read java string', function () {\n      assert(hessian.decode(utils.bytes('v2/string/empty'), '2.0') === '');\n      assert(hessian.decode(utils.bytes('v2/string/foo'), '2.0') === 'foo');\n      assert(hessian.decode(utils.bytes('v2/string/chinese'), '2.0') === '中文 Chinese');\n      assert(\n        hessian.decode(utils.bytes('v2/string/text4k'), '2.0') === utils.string('4k')\n      );\n\n      var largeBuf = new Buffer(32767);\n      largeBuf.fill(0x41);\n      assert(\n        hessian.decode(utils.bytes('v2/string/large_string_32767'), '2.0') === largeBuf.toString()\n      );\n\n      var largeBuf = new Buffer(32768);\n      largeBuf.fill(0x41);\n      assert(\n        hessian.decode(utils.bytes('v2/string/large_string_32768'), '2.0') === largeBuf.toString()\n      );\n\n      var largeBuf = new Buffer(32769);\n      largeBuf.fill(0x41);\n      assert(\n        hessian.decode(utils.bytes('v2/string/large_string_32769'), '2.0') === largeBuf.toString()\n      );\n\n      var largeBuf = new Buffer(65534);\n      largeBuf.fill(0x41);\n      assert(\n        hessian.decode(utils.bytes('v2/string/large_string_65534'), '2.0') === largeBuf.toString()\n      );\n\n      var largeBuf = new Buffer(65535);\n      largeBuf.fill(0x41);\n      assert(\n        hessian.decode(utils.bytes('v2/string/large_string_65535'), '2.0') === largeBuf.toString()\n      );\n\n      var largeBuf = new Buffer(65536);\n      largeBuf.fill(0x41);\n      assert(\n        hessian.decode(utils.bytes('v2/string/large_string_65536'), '2.0') === largeBuf.toString()\n      );\n\n      var largeBuf = new Buffer(65537);\n      largeBuf.fill(0x41);\n      assert(\n        hessian.decode(utils.bytes('v2/string/large_string_65537'), '2.0') === largeBuf.toString()\n      );\n    });\n\n    it('should write string same as java write', function () {\n      assert.deepEqual(hessian.encode('', '2.0'), utils.bytes('v2/string/empty'));\n      assert.deepEqual(hessian.encode('foo', '2.0'), utils.bytes('v2/string/foo'));\n      assert.deepEqual(hessian.encode('中文 Chinese', '2.0'), utils.bytes('v2/string/chinese'));\n      var text4k = utils.string('4k');\n      assert.deepEqual(hessian.encode(text4k, '2.0'), utils.bytes('v2/string/text4k'));\n\n      var largeBuf = new Buffer(32767);\n      largeBuf.fill(0x41);\n      assert.deepEqual(\n        hessian.encode(largeBuf.toString(), '2.0'),\n        utils.bytes('v2/string/large_string_32767')\n      );\n      var largeBuf = new Buffer(32768);\n      largeBuf.fill(0x41);\n      assert.deepEqual(\n        hessian.encode(largeBuf.toString(), '2.0'),\n        utils.bytes('v2/string/large_string_32768')\n      );\n      var largeBuf = new Buffer(32769);\n      largeBuf.fill(0x41);\n      assert.deepEqual(\n        hessian.encode(largeBuf.toString(), '2.0'),\n        utils.bytes('v2/string/large_string_32769')\n      );\n\n      var largeBuf = new Buffer(65534);\n      largeBuf.fill(0x41);\n      assert.deepEqual(\n        hessian.encode(largeBuf.toString(), '2.0'),\n        utils.bytes('v2/string/large_string_65534')\n      );\n\n      var largeBuf = new Buffer(65535);\n      largeBuf.fill(0x41);\n      assert.deepEqual(\n        hessian.encode(largeBuf.toString(), '2.0'),\n        utils.bytes('v2/string/large_string_65535')\n      );\n\n      var largeBuf = new Buffer(65536);\n      largeBuf.fill(0x41);\n      assert.deepEqual(\n        hessian.encode(largeBuf.toString(), '2.0'),\n        utils.bytes('v2/string/large_string_65536')\n      );\n\n      var largeBuf = new Buffer(65537);\n      largeBuf.fill(0x41);\n      assert.deepEqual(\n        hessian.encode(largeBuf.toString(), '2.0'),\n        utils.bytes('v2/string/large_string_65537')\n      );\n\n    });\n\n    it.skip('should write string same as java write exclude', function () {\n      var largeString = new Array(65535);\n      for (var i = 0; i < largeString.length; i += 2) {\n        largeString[i] = String.fromCharCode(0xd800);\n        if (i + 1 < largeString.length) {\n          largeString[i + 1] = String.fromCharCode(0xdbff);\n        }\n      }\n      largeString = largeString.join('');\n      assert.deepEqual(\n        hessian.encode(largeString, '2.0'),\n        utils.bytes('v2/string/large_string_chars')\n      );\n    });\n\n    it('should read and write utf8 string as java', function () {\n      var str = '';\n      for (var i = 0; i < 32767; i++) {\n        str += '锋';\n      }\n      assert.deepEqual(hessian.encode(str, '2.0'), utils.bytes('v2/string/utf8_32767'));\n      assert(hessian.decode(utils.bytes('v2/string/utf8_32767'), '2.0') === str);\n      assert(hessian.decode(utils.bytes('v1/string/utf8_32767'), '2.0') === str);\n\n      var str = '';\n      for (var i = 0; i < 32768; i++) {\n        str += '锋';\n      }\n      assert.deepEqual(hessian.encode(str, '2.0'), utils.bytes('v2/string/utf8_32768'));\n      assert(hessian.decode(utils.bytes('v2/string/utf8_32768'), '2.0') === str);\n      assert(hessian.decode(utils.bytes('v1/string/utf8_32768'), '2.0') === str);\n\n      var str = '';\n      for (var i = 0; i < 32769; i++) {\n        str += '锋';\n      }\n      assert.deepEqual(hessian.encode(str, '2.0'), utils.bytes('v2/string/utf8_32769'));\n      assert(hessian.decode(utils.bytes('v2/string/utf8_32769'), '2.0') === str);\n      // hessian.decode(utils.bytes('v1/string/utf8_32769'), '2.0').should.equal(str);\n\n      var str = '';\n      for (var i = 0; i < 65534; i++) {\n        str += '锋';\n      }\n      assert.deepEqual(hessian.encode(str, '2.0'), utils.bytes('v2/string/utf8_65534'));\n      assert(hessian.decode(utils.bytes('v2/string/utf8_65534'), '2.0') === str);\n      // hessian.decode(utils.bytes('v1/string/utf8_65534'), '2.0').should.equal(str);\n\n      var str = '';\n      for (var i = 0; i < 65535; i++) {\n        str += '锋';\n      }\n      assert.deepEqual(hessian.encode(str, '2.0'), utils.bytes('v2/string/utf8_65535'));\n      assert(hessian.decode(utils.bytes('v2/string/utf8_65535'), '2.0') === str);\n      // hessian.decode(utils.bytes('v1/string/utf8_65535'), '2.0').should.equal(str);\n\n      var str = '';\n      for (var i = 0; i < 65536; i++) {\n        str += '锋';\n      }\n      assert.deepEqual(hessian.encode(str, '2.0'), utils.bytes('v2/string/utf8_65536'));\n      assert(hessian.decode(utils.bytes('v2/string/utf8_65536'), '2.0') === str);\n      // hessian.decode(utils.bytes('v1/string/utf8_65536'), '2.0').should.equal(str);\n\n      var str = '';\n      for (var i = 0; i < 65537; i++) {\n        str += '锋';\n      }\n      assert.deepEqual(hessian.encode(str, '2.0'), utils.bytes('v2/string/utf8_65537'));\n      assert(hessian.decode(utils.bytes('v2/string/utf8_65537'), '2.0') === str);\n      // hessian.decode(utils.bytes('v1/string/utf8_65537'), '2.0').should.equal(str);\n    });\n  });\n});\n"
  },
  {
    "path": "test/utils.js",
    "content": "'use strict';\n\nvar fs = require('fs');\nvar path = require('path');\nvar fixtures = path.join(__dirname, 'fixtures');\n\nexports.bytes = function (name) {\n  return fs.readFileSync(path.join(fixtures, name + '.bin'));\n};\n\nexports.string = function (name) {\n  return fs.readFileSync(path.join(fixtures, name + '.txt'), 'utf8');\n};\n"
  },
  {
    "path": "test/utils.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst utils = require('../lib/utils');\n\ndescribe('utils.test.js', function () {\n  describe('getSerializer()', function () {\n    it('should [int get writeArray', function () {\n      assert(utils.getSerializer('[int') === 'writeArray');\n    });\n\n    it('should [string get writeArray', function () {\n      assert(utils.getSerializer('[string') === 'writeArray');\n    });\n  });\n});\n"
  },
  {
    "path": "test/v1.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst fs = require('fs');\nconst path = require('path');\nconst hessian = require('..');\nconst Encoder = hessian.Encoder;\nconst Decoder = hessian.Decoder;\nconst utils = require('../lib/utils');\n\nvar encoder = new Encoder();\nvar decoder = new Decoder();\n\nvar fixtureString = fs.readFileSync(path.join(__dirname, 'support', 'fixture.dat'), 'utf8');\nvar fixtureBytes = fs.readFileSync(path.join(__dirname, 'support', 'fixture.png'));\n\ndescribe('hessian v1', function () {\n  afterEach(function () {\n    encoder.clean();\n    decoder.clean();\n  });\n\n  describe('null', function () {\n    it('should write and read null ok', function () {\n      var buf = encoder.writeNull().get();\n      assert.deepEqual(buf, new Buffer('N'));\n\n      decoder.init(buf);\n      assert(decoder.readNull() === null);\n    });\n  });\n\n  describe('bool', function () {\n    it('should write and read true ok', function () {\n      var buf = encoder.writeBool(true).get();\n      assert.deepEqual(buf, new Buffer('T'));\n\n      assert(decoder.init(buf).readBool() === true);\n    });\n\n    it('should write and read false ok', function () {\n      var buf = encoder.writeBool(false).get();\n      assert.deepEqual(buf, Buffer.from('F'));\n\n      assert(decoder.init(buf).readBool() === false);\n    });\n  });\n\n  describe('int', function () {\n    it('should write and read int ok', function () {\n      var tests = [\n        [-10000, '<Buffer 49 ff ff d8 f0>'],\n        [-1, '<Buffer 49 ff ff ff ff>'],\n        [0, '<Buffer 49 00 00 00 00>'],\n        [100000, '<Buffer 49 00 01 86 a0>'],\n        [Math.pow(2, 31) - 1, '<Buffer 49 7f ff ff ff>'],\n      ];\n\n      tests.forEach(function (t) {\n        var buf = encoder.writeInt(t[0]).get();\n        assert(buf.inspect() === t[1]);\n        decoder.init(buf);\n        assert(decoder.readInt() === t[0]);\n        encoder.clean();\n        decoder.clean();\n      });\n    });\n\n    it('should write int error', function () {\n      var tests = [\n        1.1,\n        Math.pow(2, 31),\n        -Math.pow(2, 31) - 1\n      ];\n\n      tests.forEach(function (t, idx) {\n        assert.throws(function () {\n          var buf = encoder.writeInt(t);\n        }, new RegExp('hessian writeInt expect input type is `int32`, but got `number` : ' + tests[idx] + ' '));\n      });\n    });\n\n    it('should read int error', function () {\n      var tests = [\n        [new Buffer([0x48, 0x00, 0x00, 0x00, 0x00]), /hessian readInt only accept label `I` but got unexpect label `H`/],\n      ];\n      tests.forEach(function (t) {\n        assert.throws(function () {\n          decoder.init(t[0]).readInt();\n        }, t[1]);\n      });\n    });\n  });\n\n  describe('long', function () {\n    it('should write and read long ok', function () {\n      var tests = [\n        ['-9223372036854775808', '<Buffer 4c 80 00 00 00 00 00 00 00>'],\n        [-10000, '<Buffer 4c ff ff ff ff ff ff d8 f0>'],\n        [-1, '<Buffer 4c ff ff ff ff ff ff ff ff>'],\n        [0, '<Buffer 4c 00 00 00 00 00 00 00 00>'],\n        [10000, '<Buffer 4c 00 00 00 00 00 00 27 10>'],\n        [9007199254740991, '<Buffer 4c 00 1f ff ff ff ff ff ff>'],\n        ['9007199254740992', '<Buffer 4c 00 20 00 00 00 00 00 00>'],\n        ['9007199254740993', '<Buffer 4c 00 20 00 00 00 00 00 01>'],\n        ['9223372036854775807', '<Buffer 4c 7f ff ff ff ff ff ff ff>'],\n      ];\n\n      tests.forEach(function (t) {\n        var buf = encoder.writeLong(t[0]).get();\n        assert(buf.inspect() === t[1]);\n        assert.deepEqual(decoder.init(buf).readLong(), t[0]);\n        encoder.clean();\n        decoder.clean();\n      });\n    });\n\n    it('should write long error', function () {\n      var tests = [\n        '-9223372036854775.1',\n        '92233720368547758111'\n      ];\n\n      tests.forEach(function (t) {\n        var buf = encoder.writeLong(t).get();\n        assert.notStrictEqual(decoder.init(buf).readLong(), t);\n      });\n    });\n\n    it('should read long error', function () {\n      var tests = [\n        [new Buffer([0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),\n        /hessian readLong only accept label `L` but got unexpect label `K`/]\n      ];\n      tests.forEach(function (t) {\n        assert.throws(function () {\n          decoder.init(t[0]).readLong();\n        }, t[1]);\n      });\n    });\n  });\n\n  describe('double', function () {\n    it('should write and read double ok', function () {\n      var tests = [\n        [-1e100, '<Buffer 44 d4 b2 49 ad 25 94 c3 7d>'],\n        [-1.123, '<Buffer 44 bf f1 f7 ce d9 16 87 2b>'],\n        [-1, '<Buffer 44 bf f0 00 00 00 00 00 00>'],\n        [0, '<Buffer 44 00 00 00 00 00 00 00 00>'],\n        [1, '<Buffer 44 3f f0 00 00 00 00 00 00>'],\n        [1.111, '<Buffer 44 3f f1 c6 a7 ef 9d b2 2d>'],\n        // 1e320\n        [Infinity, '<Buffer 44 7f f0 00 00 00 00 00 00>'],\n      ];\n\n      tests.forEach(function (t) {\n        var buf = encoder.writeDouble(t[0]).get();\n        assert(buf.inspect() === t[1]);\n        assert(decoder.init(buf).readDouble() === t[0]);\n        encoder.clean();\n        decoder.clean();\n      });\n    });\n\n    it('should read double error', function () {\n      var tests = [\n        [new Buffer([0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),\n        /hessian readDouble only accept label `D` but got unexpect label `E`/]\n      ];\n      tests.forEach(function (t) {\n        assert.throws(function () {\n          decoder.init(t[0]).readDouble();\n        }, t[1]);\n      });\n    });\n  });\n\n  describe('date', function () {\n    it('should write and read Date ok', function () {\n      var tests = [\n        [new Date('2010-10-10'), '<Buffer 64 00 00 01 2b 93 6f d0 00>'],\n        [new Date(0), '<Buffer 64 00 00 00 00 00 00 00 00>'],\n      ];\n\n      tests.forEach(function (t) {\n        var buf = encoder.writeDate(t[0]).get();\n        assert(buf.inspect() === t[1]);\n        assert.deepEqual(decoder.init(buf).readDate(), t[0]);\n        encoder.clean();\n        decoder.clean();\n      });\n    });\n\n    it('should read date error', function () {\n      var tests = [\n        [new Buffer([0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),\n        /hessian readDate only accept label `d` but got unexpect label `e`/]\n      ];\n      tests.forEach(function (t) {\n        assert.throws(function () {\n          decoder.init(t[0]).readDate();\n        }, t[1]);\n      });\n    });\n  });\n\n  describe('bytes', function () {\n    it('should write and read small bytes ok', function () {\n      var inputBuffer = new Buffer([1, 2, 3, 4, 5]);\n      var buf = encoder.writeBytes(inputBuffer).get();\n      assert.equal(buf.inspect(), '<Buffer 42 00 05 01 02 03 04 05>');\n      assert.deepEqual(decoder.init(buf).readBytes(), inputBuffer);\n    });\n\n    it('should write and read big bytes ok', function () {\n      var inputBuffer = fixtureBytes;\n      var inputLength = inputBuffer.length;\n      var buf = encoder.writeBytes(inputBuffer).get();\n      assert.equal(buf.length, inputLength +\n        Math.ceil(inputLength / utils.MAX_BYTE_TRUNK_SIZE) * 3);\n      assert.deepEqual(decoder.init(buf).readBytes(), inputBuffer);\n    });\n\n    it('should read bytes error', function () {\n      var tests = [\n        [new Buffer([0x41, 0x00, 0x02, 0x00]), /hessian readBytes only accept label `b,B` but got unexpect label `A`/],\n        [new Buffer([0x62, 0x00, 0x01, 0x00, 0x01]), /hessian readBytes only accept label `b,B` but got unexpect label `\\u0001`/],\n      ];\n\n      tests.forEach(function (t) {\n        assert.throws(function () {\n          var buf = decoder.init(t[0]).readBytes();\n        }, t[1]);\n      });\n    });\n\n    it('should bytes length equal MAX_BYTE_TRUNK_SIZE work', function () {\n      var oneTrunkBuf = Buffer.alloc(utils.MAX_BYTE_TRUNK_SIZE);\n      var buf = encoder.writeBytes(oneTrunkBuf).get();\n      assert.deepEqual(decoder.init(buf).readBytes(), oneTrunkBuf);\n\n      encoder.clean();\n      var twoTrunkBuf = Buffer.alloc(utils.MAX_BYTE_TRUNK_SIZE * 2);\n      buf = encoder.writeBytes(twoTrunkBuf).get();\n      assert.deepEqual(decoder.init(buf).readBytes(), twoTrunkBuf);\n    });\n\n    it('should write type error', function () {\n      assert.throws(function () {\n        encoder.writeBytes();\n      }, /hessian writeBytes expect input type is `buffer`, but got `undefined` : undefined /);\n      assert.throws(function () {\n        encoder.writeBytes('');\n      }, /hessian writeBytes expect input type is `buffer`, but got `string` : \"\" /);\n      assert.throws(function () {\n        encoder.writeBytes(null);\n      }, /hessian writeBytes expect input type is `buffer`, but got `object` : null /);\n      assert.throws(function () {\n        encoder.writeBytes(100);\n      }, /hessian writeBytes expect input type is `buffer`, but got `number` : 100 /);\n    });\n\n    it('should write and read empty bytes', function () {\n      var buf = encoder.writeBytes(new Buffer('')).get();\n      assert.deepEqual(decoder.init(buf).readBytes(), new Buffer(''));\n    });\n  });\n\n  describe('string', function () {\n    it('should write and read small string ok', function () {\n      var inputStr = '你好，hessian.∆∆˚œø∂πß∂µ';\n      var buf = encoder.writeString(inputStr).get();\n      assert(\n        buf.inspect() === '<Buffer 53 00 15 e4 bd a0 e5 a5 bd ef bc 8c 68 65 73 73 69 61 6e 2e e2 88 86 e2 88 86 cb 9a c5 93 c3 b8 e2 88 82 cf 80 c3 9f e2 88 82 c2 b5>'\n      );\n      assert(decoder.init(buf).readString() === inputStr);\n    });\n\n    it('should write and read big string ok', function () {\n      var inputStr = fixtureString;\n      var inputStrLength = inputStr.length;\n      var buf = encoder.writeString(inputStr).get();\n      assert.equal(buf.length, Buffer.from(inputStr).length +\n        Math.ceil(inputStrLength / utils.MAX_CHAR_TRUNK_SIZE) * 3);\n      assert(decoder.init(buf).readString() === inputStr);\n    });\n\n    it('should read string error', function () {\n      var tests = [\n        [new Buffer([0x72, 0x00, 0x02, 0x00]), /hessian readString error, unexpect string code: 0x72/],\n        [new Buffer([0x73, 0x00, 0x01, 0x00, 0x01]), /hessian readString error, unexpect string code: 0x1/],\n        [new Buffer([0x73, 0x00, 0x01, 0xf0, 0x20]), /string is not valid UTF-8 encode/],\n      ];\n\n      tests.forEach(function (t) {\n        assert.throws(function () {\n          var buf = decoder.init(t[0]).readString();\n        }, t[1]);\n      });\n    });\n\n    it('should write type error', function () {\n      assert.throws(function () {\n        encoder.writeString();\n      }, /hessian writeString expect input type is `string`, but got `undefined` : undefined /);\n      // v0.10.28 return [1,2,3,4,5]\n      // (function () {\n      //   encoder.writeString(new Buffer([1,2,3,4,5]));\n      // }).should.throw('hessian writeString expect input type is `string`, but got `object` : {\"type\":\"Buffer\",\"data\":[1,2,3,4,5]} ');\n      assert.throws(function () {\n        encoder.writeString(null);\n      }, /hessian writeString expect input type is `string`, but got `object` : null /);\n      assert.throws(function () {\n        encoder.writeString(100);\n      }, /hessian writeString expect input type is `string`, but got `number` : 100 /);\n    });\n\n    it('should string length equal MAX_CHAR_TRUNK_SIZE work', function () {\n      var oneTrunkString = new Buffer(utils.MAX_CHAR_TRUNK_SIZE);\n      oneTrunkString.fill(0x41);\n      oneTrunkString = oneTrunkString.toString();\n      var buf = encoder.writeString(oneTrunkString).get();\n      assert.deepEqual(decoder.init(buf).readString(), oneTrunkString);\n      encoder.clean();\n\n      var twoTrunkString = new Buffer(utils.MAX_CHAR_TRUNK_SIZE * 2);\n      twoTrunkString.fill(0x41);\n      twoTrunkString = twoTrunkString.toString();\n      buf = encoder.writeString(twoTrunkString).get();\n      assert.deepEqual(decoder.init(buf).read(), twoTrunkString);\n    });\n\n    it('should write and read empty string', function () {\n      var buf = encoder.writeString('').get();\n      assert(decoder.init(buf).read() === '');\n    });\n  });\n\n  describe('object', function () {\n    it('should write and get simple object ok', function () {\n      var testObject = {\n        a: 1,\n        b: 'string',\n        c: true,\n        d: 1.1,\n        e: Math.pow(2, 40),\n        f: [1, 2, 3, '4', true, 5],\n        g: {a: 1, b: true, c: 'string'}\n      };\n      var buf = encoder.writeObject(testObject).get();\n      assert.deepEqual(decoder.init(buf).readObject(), testObject);\n    });\n\n    it('should write null obejct ok', function () {\n      var nullObject = null;\n      var nullBuf = encoder.writeObject(nullObject).get();\n      assert(decoder.init(nullBuf).read() === null);\n    });\n\n    it('should write and read object with circular ok', function () {\n      var testObject = {\n        a: 1,\n        b: 'string',\n        c: {},\n        d: [1, 2]\n      };\n      testObject.c.a = testObject;\n      testObject.d.push(testObject.c);\n\n      var buf = encoder.writeObject(testObject).get();\n      var res = decoder.init(buf).readObject();\n      assert(res.a === testObject.a);\n      assert(res.b === testObject.b);\n      assert(res.c.a.a === testObject.a);\n      assert(res.c.a.b === testObject.b);\n      assert(res.d[2].a.a === testObject.a);\n      assert(res.d[2].a.b === testObject.b);\n    });\n\n    it('should write and read complex object ok', function () {\n      var testObject = {\n        $class: 'com.hessian.TestObject',\n        $: {\n          a: 1,\n          b: {$class: 'java.util.List', $: [1, 2, 3]}\n        }\n      };\n\n      var buf = encoder.writeObject(testObject).get();\n      var res = decoder.init(buf).readObject();\n      assert.deepEqual(res, {a:1, b:[1, 2, 3]});\n      var resWithType = decoder.init(buf).readObject(true);\n      assert.deepEqual(resWithType, {\n        '$class': 'com.hessian.TestObject',\n        '$': {\n          a: { '$class': 'int', '$': 1 },\n          b: {\n            '$class': 'java.util.List',\n            '$': [\n              { '$class': 'int', '$': 1 },\n              { '$class': 'int', '$': 2 },\n              { '$class': 'int', '$': 3 }\n            ]\n          }\n        }\n      });\n    });\n\n    it('should read complex object type use positon ok', function () {\n      var testObject = {\n        $class: 'com.hessian.TestObject',\n        $: {\n          a: 1,\n          b: {$class: 'java.util.List', $: [1, 2, 3]}\n        }\n      };\n\n      var buf = encoder.writeObject(testObject).get();\n      decoder.init(buf);\n      assert(decoder.position() === 0);\n      decoder.position(1); //skip 'M'\n      assert(decoder.readType() === 'com.hessian.TestObject');\n      assert(decoder.position() === 26);\n      assert.deepEqual(decoder.position(0).readObject(true), {\n        '$class': 'com.hessian.TestObject',\n        '$': {\n          a: { '$class': 'int', '$': 1 },\n          b: {\n            '$class': 'java.util.List',\n            '$': [\n              { '$class': 'int', '$': 1 },\n              { '$class': 'int', '$': 2 },\n              { '$class': 'int', '$': 3 }\n            ]\n          }\n        }\n      });\n    });\n\n    it('should write \"java.util.HashMap\" treat as {}', function () {\n      var testObject = {\n        $class: 'java.util.HashMap',\n        $: {foo: 'bar'}\n      };\n      var buf = encoder.writeObject(testObject).get();\n      encoder.clean();\n\n      assert.deepEqual(buf, encoder.writeObject({foo: 'bar'}).get());\n      assert.deepEqual(decoder.init(buf).read(), {foo: 'bar'});\n      assert.deepEqual(decoder.init(buf).read(true), {\n        '$class': 'java.util.HashMap',\n        '$': {\n          foo: { '$class': 'java.lang.String', '$': 'bar' }\n        }\n      });\n    });\n\n    it('should write type error', function () {\n      assert.throws(function () {\n        encoder.writeObject('123');\n      }, /hessian writeObject \\/ writeMap expect input type is `object`, but got `string` : \"123\" /);\n      assert.throws(function () {\n        encoder.writeObject(1.111);\n      }, /hessian writeObject \\/ writeMap expect input type is `object`, but got `number` : 1.111 /);\n      assert.throws(function () {\n        encoder.writeObject(100);\n      }, /hessian writeObject \\/ writeMap expect input type is `object`, but got `number` : 100 /);\n    });\n  });\n\n  describe('array', function () {\n    it('should write and read simple array ok', function () {\n      var testArray = [1, true, 'string', 1.1, new Date()];\n      var buf = encoder.writeArray(testArray).get();\n      assert.deepEqual(decoder.init(buf).readArray(), testArray);\n    });\n\n    it('should write circular array ok', function () {\n      var testArray = [1];\n      testArray.push(testArray);\n      var buf = encoder.writeArray(testArray).get();\n      var res = decoder.init(buf).readArray();\n      assert(res[0] === testArray[0]);\n      assert(res[1][1][1][0] === testArray[0]);\n    });\n\n    it('should write and read complex array ok', function () {\n      var testArray = {\n        $class: 'java.util.Set',\n        $: [{\n          $class: 'java.util.List',\n          $: [1, 2, 3]\n        }]\n      };\n      var buf = encoder.writeArray(testArray).get();\n      assert.deepEqual(decoder.init(buf).readArray(), [[1, 2, 3]]);\n      assert.deepEqual(decoder.init(buf).readArray(true), {\n        '$class': 'java.util.Set',\n        '$': [\n          {\n            '$class': 'java.util.List',\n            '$': [\n              { '$class': 'int', '$': 1 },\n              { '$class': 'int', '$': 2 },\n              { '$class': 'int', '$': 3 }\n            ]\n          }\n        ]\n      });\n    });\n\n    it('should write \"java.util.ArrayList\" treat as []', function () {\n      var testArray = {\n        $class: 'java.util.ArrayList',\n        $: [1, 2, 3]\n      };\n      var buf = encoder.writeArray(testArray).get();\n      encoder.clean();\n\n      assert.deepEqual(buf, encoder.writeArray([1, 2, 3]).get());\n      assert.deepEqual(decoder.init(buf).read(), [1, 2, 3]);\n      assert.deepEqual(decoder.init(buf).read(true), {\n        $class: 'java.util.ArrayList',\n        $: [\n          { '$class': 'int', '$': 1 },\n          { '$class': 'int', '$': 2 },\n          { '$class': 'int', '$': 3 }\n        ]\n      });\n    });\n\n    it('should read unexpect end label', function () {\n      var buf = encoder.writeArray([1, 2, 3]).get();\n      buf[buf.length - 1] = 40;\n      assert.throws(function () {\n        decoder.init(buf).read('hessian readArray error, unexpect end label: (');\n      });\n    });\n\n    it('should write type error', function () {\n      assert.throws(function () {\n        encoder.writeArray();\n      }, /hessian writeArray input type invalid/);\n      assert.throws(function () {\n        encoder.writeArray('123');\n      }, /hessian writeArray input type invalid/);\n      assert.throws(function () {\n        encoder.writeArray(1.111);\n      }, /hessian writeArray input type invalid/);\n      assert.throws(function () {\n        encoder.writeArray(100);\n      }, /hessian writeArray input type invalid/);\n    });\n  });\n\n  describe('java.lang.Object', function () {\n    it('should encode and decode ok', function () {\n      [\n        100,\n        'string',\n        true,\n        new Date(),\n        [1, 2, 3],\n        {foo: 'bar'}\n      ].forEach(function(val) {\n        var buf = encoder.write({$class:'java.lang.Object', $: val}).get();\n        encoder.clean();\n        assert.deepEqual(decoder.init(buf).read(), val);\n      });\n    });\n  });\n\n  describe('encode and decode', function () {\n    it('should encode and decode work ok', function () {\n      var now = new Date();\n      var tests = [\n        [1, {$class: 'int', $: 1}],\n        [1.1, {$class: 'double', $: 1.1}],\n        [-10, {$class: 'int', $: -10}],\n        [Math.pow(2, 50), { '$class': 'long', '$': Math.pow(2, 50)}],\n        [{$class: 'long', $: '288230376151711740'}],\n        [{$class: 'boolean', $: 1}, {$class: 'boolean', $: true}],\n        [now, {'$class': 'java.util.Date', $: now}],\n        [true, {$class: 'boolean', $: true}],\n        [false, {$class: 'boolean', $: false}],\n        [null],\n        [undefined],\n        [{ a: 1, b: [true, false], c: now, d: {}, e: null }, {\n            $class: 'java.util.HashMap',\n            $:{\n              a: { '$class': 'int', '$': 1 },\n              b: {\n                $class: 'java.util.ArrayList',\n                $: [ { '$class': 'boolean', '$': true }, { '$class': 'boolean', '$': false } ]\n              },\n              c: { '$class': 'java.util.Date', '$': now },\n              d: { '$class': 'java.util.HashMap', '$': {} },\n              e: null\n            }\n          }\n        ]\n      ];\n      tests.forEach(function (t) {\n        var buf = hessian.encode(t[0]);\n        var res = hessian.decode(buf, true);\n        if (res) {\n          assert.deepEqual(res, t[1] || t[0]);\n        } else {\n          /* jshint eqeqeq: false */\n          assert(res == t[0]);\n        }\n      });\n    });\n\n    it('should decode error', function () {\n      var buf = new Buffer([0x50, 0x11]);\n      assert.throws(function() {\n        hessian.decode(buf);\n      }, /hessian read got an unexpect code: 0x50/);\n    });\n  });\n});\n"
  },
  {
    "path": "test/v2.decode.cache.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst hessian = require('..');\nconst utils = require('./utils');\nconst supportES6Map = require('../lib/utils').supportES6Map;\n\nconst cache = new Map();\n\ndescribe('v2.decode.cache.test.js', function () {\n  var decode = hessian.decode;\n  // ensure all v2 decode use classCache\n  before(function() {\n    hessian.decode = function(buf, version, options) {\n      if (version !== '2.0') {\n        return decode(buf, version, options);\n      }\n\n      if (!options) {\n        options = {};\n      }\n      if (typeof options === 'boolean') {\n        options = { withType: options };\n      }\n      if (!options.classCache) {\n        options.classCache = cache;\n      }\n      return decode(buf, version, options);\n    };\n  });\n\n  // reset and check cache\n  after(function() {\n    assert(cache.size);\n    hessian.decode = decode;\n  });\n\n  for (var i = 0; i<= 3; i++) {\n    describe('repeat ' + i, function() {\n      it('should skip function', function() {\n        var o = { foo: 'bar', fn: function() {} };\n        var buf = hessian.encode(o, '2.0');\n        var output = hessian.decode(buf, '2.0');\n        assert.deepEqual(output, { foo: 'bar', fn: null });\n      });\n\n      it('should decode and encode ConnectionRequest', function () {\n        var javabuf = utils.bytes('v2/object/ConnectionRequest');\n        var connreq1 = hessian.decode(javabuf, '2.0');\n        assert(connreq1.ctx);\n        assert(connreq1.ctx.id === 101); // 'this$0'\n\n        var connreq = hessian.decode(javabuf, '2.0', true);\n        var jsconnreq = {\n          $class: 'hessian.ConnectionRequest',\n          $: {\n            ctx: {\n              $class: 'hessian.ConnectionRequest$RequestContext',\n              $: {\n                id: 101,\n                // 'this$0': null\n              }\n            }\n          }\n        };\n\n        // jsconnreq.$.ctx.$.this$0 = jsconnreq;\n        assert.deepEqual(jsconnreq, connreq);\n        var jsbuf = hessian.encode(connreq, '2.0');\n        var jsbuf2 = hessian.encode(jsconnreq, '2.0');\n      });\n\n      it('should read enum Color', function () {\n        // enum Color {\n        //   RED,\n        //   GREEN,\n        //   BLUE,\n        // }\n\n        // enum format:\n        // O type 1 \"name\" o ref name-value\n        assert.deepEqual(hessian.decode(utils.bytes('v2/enum/red'), '2.0'), {\n          name: 'RED'\n        });\n\n        assert.deepEqual(hessian.decode(utils.bytes('v2/enum/green'), '2.0', true), {\n          $class: 'hessian.Main$Color',\n          $: {\n            name: 'GREEN'\n          }\n        });\n\n        assert.deepEqual(hessian.decode(utils.bytes('v2/enum/blue'), '2.0'), {\n          name: 'BLUE'\n        });\n\n        assert.deepEqual(hessian.decode(utils.bytes('v2/enum/green'), '2.0'), {\n          name: 'GREEN'\n        });\n\n        assert.deepEqual(hessian.decode(utils.bytes('v2/enum/red'), '2.0', true), {\n          $class: 'hessian.Main$Color',\n          $: {\n            name: 'RED'\n          }\n        });\n\n        assert.deepEqual(\n          hessian.decode(utils.bytes('v2/enum/lists'), '2.0'),\n          [ { name: 'BLUE' }, { name: 'RED' }, { name: 'GREEN' } ]\n        );\n\n        assert.deepEqual(hessian.decode(utils.bytes('v2/enum/lists'), '2.0', true), [\n          { '$class': 'hessian.Main$Color', '$': { name: 'BLUE' } },\n          { '$class': 'hessian.Main$Color', '$': { name: 'RED' } },\n          { '$class': 'hessian.Main$Color', '$': { name: 'GREEN' } }\n        ]);\n      });\n\n      it('should write \"{$class: \"hessian.test.demo.Car\", $: {a: 1, b: \"map\"}}\"', function () {\n        var obj = {\n          $class: 'hessian.test.demo.Car',\n          $: {a: 1, b: 'map'}\n        };\n        var buf = hessian.encode(obj, '2.0');\n        assert(buf[0] === 0x43);\n        assert.deepEqual(hessian.decode(buf, '2.0'), obj.$);\n        assert.deepEqual(hessian.decode(buf, '2.0', true), obj);\n      });\n\n      it('should write \"{$class: \"hessian.test.demo.Car\", $: {a: 1, b: \"map\", c: 2}}\"', function () {\n        var obj = {\n          $class: 'hessian.test.demo.Car',\n          $: {a: 1, b: 'map', c: 2}\n        };\n        var buf = hessian.encode(obj, '2.0');\n        assert(buf[0] === 0x43);\n        assert.deepEqual(hessian.decode(buf, '2.0'), obj.$);\n        assert.deepEqual(hessian.decode(buf, '2.0', true), obj);\n      });\n\n      it('should read one car list', function () {\n        assert.deepEqual(hessian.decode(utils.bytes('v2/map/one_car_list'), '2.0'), [\n          { a: 'a',\n            c: 'c',\n            b: 'b',\n            model: 'model 1',\n            color: 'aquamarine',\n            mileage: 65536 }\n        ]);\n\n        var cars = hessian.decode(utils.bytes('v2/map/one_car_list'), '2.0', true);\n        assert.deepEqual(cars, [\n          {\n            $class: 'hessian.demo.Car',\n            $: {\n              a: 'a',\n              c: 'c',\n              b: 'b',\n              model: 'model 1',\n              color: 'aquamarine',\n              mileage: 65536 }\n          }\n        ]);\n\n        assert.deepEqual(hessian.encode(cars, '2.0'), utils.bytes('v2/map/one_car_list'));\n      });\n\n      it('should read two car list', function () {\n        assert.deepEqual(hessian.decode(utils.bytes('v2/map/two_car_list'), '2.0'), [\n          { a: 'a',\n            c: 'c',\n            b: 'b',\n            model: 'model 1',\n            color: 'aquamarine',\n            mileage: 65536 },\n          { a: 'a',\n            c: 'c',\n            b: 'b',\n            model: 'model 2',\n            color: 'aquamarine',\n            mileage: 65536 }\n        ]);\n\n        var cars = hessian.decode(utils.bytes('v2/map/two_car_list'), '2.0', true);\n        assert.deepEqual(cars, [\n          {\n            $class: 'hessian.demo.Car',\n            $: {\n              a: 'a',\n              c: 'c',\n              b: 'b',\n              model: 'model 1',\n              color: 'aquamarine',\n              mileage: 65536 }\n          },\n          {\n            $class: 'hessian.demo.Car',\n            $: {\n              a: 'a',\n              c: 'c',\n              b: 'b',\n              model: 'model 2',\n              color: 'aquamarine',\n              mileage: 65536 }\n          }\n        ]);\n\n        var buf = hessian.encode(cars, '2.0');\n        assert(buf.length === utils.bytes('v2/map/two_car_list').length);\n        assert.deepEqual(buf, utils.bytes('v2/map/two_car_list'));\n      });\n\n      it('should read many cars', function () {\n        // list = new ArrayList();\n        // list.add(new Car(\"model 1\"));\n        // list.add(new Car(\"model 2\"));\n        // list.add(new Car(\"model 3\"));\n        assert.deepEqual(hessian.decode(utils.bytes('v2/map/car_list'), '2.0'), [\n          { a: 'a',\n            c: 'c',\n            b: 'b',\n            model: 'model 1',\n            color: 'aquamarine',\n            mileage: 65536 },\n          { a: 'a',\n            c: 'c',\n            b: 'b',\n            model: 'model 2',\n            color: 'aquamarine',\n            mileage: 65536 },\n          { a: 'a',\n            c: 'c',\n            b: 'b',\n            model: 'model 3',\n            color: 'aquamarine',\n            mileage: 65536 }\n        ]);\n\n        var cars = hessian.decode(utils.bytes('v2/map/car_list'), '2.0', true);\n        assert.deepEqual(cars, [\n          { '$class': 'hessian.demo.Car',\n            '$':\n             { a: 'a',\n               c: 'c',\n               b: 'b',\n               model: 'model 1',\n               color: 'aquamarine',\n               mileage: 65536 } },\n          { '$class': 'hessian.demo.Car',\n            '$':\n             { a: 'a',\n               c: 'c',\n               b: 'b',\n               model: 'model 2',\n               color: 'aquamarine',\n               mileage: 65536 } },\n          { '$class': 'hessian.demo.Car',\n            '$':\n             { a: 'a',\n               c: 'c',\n               b: 'b',\n               model: 'model 3',\n               color: 'aquamarine',\n               mileage: 65536 } }\n        ]);\n\n        assert.deepEqual(hessian.encode(cars, '2.0'), utils.bytes('v2/map/car_list'));\n      });\n\n      describe('java.util.concurrent.atomic.AtomicLong', function () {\n        it('should read and write', function () {\n          var javabuf = utils.bytes('v2/object/AtomicLong0');\n          var a0 = hessian.decode(javabuf, '2.0');\n          assert.deepEqual(a0, {value: 0});\n          var a0 = hessian.decode(javabuf, '2.0', true);\n          assert.deepEqual(a0, {\n            $class: 'java.util.concurrent.atomic.AtomicLong',\n            $: {\n              value: 0\n            }\n          });\n          assert.deepEqual(hessian.encode({\n            $class: 'java.util.concurrent.atomic.AtomicLong',\n            $: {\n              value: {\n                $class: 'long',\n                $: 0\n              }\n            }\n          }, '2.0'), javabuf);\n\n          javabuf = utils.bytes('v2/object/AtomicLong1');\n          var a1 = hessian.decode(javabuf, '2.0');\n          assert.deepEqual(a1, {value: 1});\n          var a1 = hessian.decode(javabuf, '2.0', true);\n          assert.deepEqual(a1, {\n            $class: 'java.util.concurrent.atomic.AtomicLong',\n            $: {\n              value: 1\n            }\n          });\n          assert.deepEqual(hessian.encode({\n            $class: 'java.util.concurrent.atomic.AtomicLong',\n            $: {\n              value: {\n                $class: 'long',\n                $: 1\n              }\n            }\n          }, '2.0'), javabuf);\n        });\n      });\n\n      if (supportES6Map) {\n        describe('map key object', function() {\n          it('enum should use name v2', function() {\n            var key = {\n              $class: 'com.hessian.enums.TestEnum',\n              $: {\n                name: 'KEY',\n              },\n            };\n            var obj = new Map();\n            obj.set(key, 'hello');\n            var buf = hessian.encode(obj, '2.0');\n            var rs = hessian.decode(buf, '2.0');\n            assert.deepEqual(rs, { 'KEY': 'hello' });\n          });\n        });\n      }\n    });\n  }\n});\n"
  },
  {
    "path": "test/v2.list.encode.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst java = require('js-to-java');\nconst hessian = require('..');\n\ndescribe('hessian v2', function () {\n  it('v2 list encode should ok', function () {\n    var arg = {\n      \"$class\": \"com.x.Site\",\n      \"$\": {\n        \"id\": {\n          \"$class\": \"long\",\n          \"$\": 1637\n        },\n        \"groupId\": {\n          \"$class\": \"long\",\n          \"$\": 2\n        },\n        \"description\": {\n          \"$class\": \"java.lang.String\",\n          \"$\": \"\"\n        },\n        \"name\": {\n          \"$class\": \"java.lang.String\",\n          \"$\": \"acltimeout1\"\n        },\n        \"url\": {\n          \"$class\": \"java.lang.String\",\n          \"$\": \"https://pages.x.com\"\n        },\n        \"spma\": {\n          \"$class\": \"java.lang.String\",\n          \"$\": \"a2279\"\n        },\n        \"extendFields\": {\n          \"$class\": \"java.util.List\",\n          \"$\": [\n            {\n              \"$class\": \"com.x.ExtendField\",\n              \"$\": {\n                \"fieldKey\": {\n                  \"$class\": \"java.lang.String\",\n                  \"$\": \"site-tmc\"\n                },\n                \"bizId\": {\n                  \"$class\": \"long\",\n                  \"$\": 1637\n                },\n                \"fieldValue\": {\n                  \"$class\": \"java.lang.String\",\n                  \"$\": \"1\"\n                },\n                \"id\": {\n                  \"$class\": \"long\",\n                  \"$\": 0\n                },\n                \"type\": {\n                  \"$class\": \"int\",\n                  \"$\": 0\n                },\n                \"status\": {\n                  \"$class\": \"int\",\n                  \"$\": 0\n                },\n                \"metaId\": {\n                  \"$class\": \"long\",\n                  \"$\": 0\n                },\n                \"valueType\": null,\n                \"gmtCreate\": null,\n                \"gmtModified\": null\n              }\n            },\n            {\n              \"$class\": \"com.x.ExtendField\",\n              \"$\": {\n                \"fieldKey\": {\n                  \"$class\": \"java.lang.String\",\n                  \"$\": \"site-solution\"\n                },\n                \"bizId\": {\n                  \"$class\": \"long\",\n                  \"$\": 1637\n                },\n                \"fieldValue\": {\n                  \"$class\": \"java.lang.String\",\n                  \"$\": \"base\"\n                },\n                \"id\": {\n                  \"$class\": \"long\",\n                  \"$\": 0\n                },\n                \"type\": {\n                  \"$class\": \"int\",\n                  \"$\": 0\n                },\n                \"status\": {\n                  \"$class\": \"int\",\n                  \"$\": 0\n                },\n                \"metaId\": {\n                  \"$class\": \"long\",\n                  \"$\": 0\n                },\n                \"valueType\": null,\n                \"gmtCreate\": null,\n                \"gmtModified\": null\n              }\n            },\n            {\n              \"$class\": \"com.x.ExtendField\",\n              \"$\": {\n                \"bizId\": {\n                  \"$class\": \"long\",\n                  \"$\": 1637\n                },\n                \"fieldKey\": {\n                  \"$class\": \"java.lang.String\",\n                  \"$\": \"site-template-whitelist\"\n                },\n                \"fieldValue\": {\n                  \"$class\": \"java.lang.String\",\n                  \"$\": \"julu\"\n                },\n                \"id\": {\n                  \"$class\": \"long\",\n                  \"$\": 0\n                },\n                \"type\": {\n                  \"$class\": \"int\",\n                  \"$\": 0\n                },\n                \"status\": {\n                  \"$class\": \"int\",\n                  \"$\": 0\n                },\n                \"metaId\": {\n                  \"$class\": \"long\",\n                  \"$\": 0\n                },\n                \"valueType\": null,\n                \"gmtCreate\": null,\n                \"gmtModified\": null\n              }\n            },\n            {\n              \"$class\": \"com.x.ExtendField\",\n              \"$\": {\n                \"bizId\": {\n                  \"$class\": \"long\",\n                  \"$\": 1637\n                },\n                \"fieldKey\": {\n                  \"$class\": \"java.lang.String\",\n                  \"$\": \"site-owner\"\n                },\n                \"fieldValue\": {\n                  \"$class\": \"java.lang.String\",\n                  \"$\": \"julu\"\n                },\n                \"id\": {\n                  \"$class\": \"long\",\n                  \"$\": 0\n                },\n                \"type\": {\n                  \"$class\": \"int\",\n                  \"$\": 0\n                },\n                \"status\": {\n                  \"$class\": \"int\",\n                  \"$\": 0\n                },\n                \"metaId\": {\n                  \"$class\": \"long\",\n                  \"$\": 0\n                },\n                \"valueType\": null,\n                \"gmtCreate\": null,\n                \"gmtModified\": null\n              }\n            }\n          ]\n        },\n        \"engName\": null,\n        \"ownerWorkIds\": null,\n        \"status\": {\n          \"$class\": \"int\",\n          \"$\": 0\n        },\n        \"creator\": null,\n        \"mobileUrl\": null,\n        \"groupName\": null,\n        \"gmtCreate\": null,\n        \"gmtModified\": null\n      }\n    };\n\n    var bytes = hessian.encode(arg, '2.0');\n    var rs = hessian.decode(bytes, '2.0');\n    assert.deepEqual(java.revert(arg), rs);\n\n    hessian.encoderV2.reset();\n    assert(hessian.encoderV2._classRefs.length === 0);\n    assert(hessian.encoderV2._typeRefs.length === 0);\n    assert(Object.keys(hessian.encoderV2._classRefFields).length === 0);\n  });\n});\n"
  },
  {
    "path": "test/v2.optimize.endecode.test.js",
    "content": "'use strict';\n\nconst assert = require('assert');\nconst hessian = require('..');\nconst DecoderV2 = require('../lib/v2_optimize/decoder');\nconst EncoderV2 = require('../lib/v2_optimize/encoder');\n\nvar cache = [];\n\ndescribe('v2.optimize.endecode.test.js', function () {\n  var decode = hessian.decode;\n  var encode = hessian.encode;\n  var encoder = new EncoderV2({\n    size: 1024 * 1024,\n    classRefs: [],\n    classRefFields: {},\n  });\n  before(function() {\n    hessian.decode = function(buf, version, withType) {\n      return new DecoderV2(buf, cache).read(withType);\n    };\n\n    hessian.encode = function(obj) {\n      encoder.reset();\n      return encoder.write(obj).get();\n    };\n  });\n\n  // reset and check cache\n  after(function() {\n    assert(cache.length);\n    hessian.decode = decode;\n    hessian.encode = encode;\n  });\n\n  describe('encode/decode', function () {\n    it('should encode/decode class and match ref', function () {\n      var obj = {\n        $class: 'hessian.test.demo.Car',\n        $: { a: 1, b: 'map' }\n      };\n      var buf = hessian.encode(obj);\n      assert(buf[0] === 0x43);\n      assert.deepEqual(hessian.decode(buf), obj.$);\n      assert.deepEqual(hessian.decode(buf, '2.0', true), obj);\n\n      buf = hessian.encode(obj);\n      assert(buf[0] === 0x60);\n      assert.deepEqual(hessian.decode(buf), obj.$);\n      assert.deepEqual(hessian.decode(buf, '2.0', true), obj);\n    });\n\n    it('should reset encoder ok', function () {\n      encoder.byteBuffer.putChar('o');\n      encoder.objects.ok = true;\n      encoder._typeRefs.push('ok');\n      encoder.reset();\n      assert.equal(encoder.byteBuffer._offset, 0);\n      assert.equal(Object.keys(encoder.objects).length, 0);\n      assert.equal(encoder._typeRefs.length, 0);\n    });\n\n    it('should clean decoder ok', function () {\n      var decoder = new DecoderV2([], []);\n      var byteBuffer = decoder.byteBuffer;\n      decoder.refId = 1;\n      decoder.refMap = {a: 1};\n      decoder.types.push(1);\n      decoder.clean();\n      assert.notEqual(byteBuffer, decoder.byteBuffer);\n      assert.equal(decoder.refId, 0);\n      assert.equal(Object.keys(decoder.refMap).length, 0);\n      assert.equal(decoder.types.length, 0);\n    });\n  });\n});\n"
  }
]