Skip to content

Commit ceaef7b

Browse files
denghongcaidead-horse
authored andcommitted
feat: hessian2 optimize codec (#97)
1 parent cf0ef8b commit ceaef7b

5 files changed

Lines changed: 165 additions & 0 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,9 @@ xd8 - xef # one-octet compact long (-x8 to xf, xe0 is 0)
401401
xf0 - xff # two-octet compact long (-x800 to x7ff, xf8 is 0)
402402
```
403403

404+
## About Hessian 2.0 Optimized Decoder
405+
Hessian 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.
406+
404407
## Licences
405408

406409
[MIT](LICENSE)

lib/v2/encoder.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ var proto = Encoder.prototype;
4141
proto.reset = proto.clean = function () {
4242
EncoderV1.prototype.clean.call(this);
4343
this._classRefs = [];
44+
this._classRefFields = {};
4445
this._typeRefs = [];
4546
return this;
4647
};

lib/v2_optimize/decoder.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* hessian.js - lib/v2_optimize/decoder.js
3+
*
4+
* Copyright(c)
5+
* MIT Licensed
6+
*
7+
* Authors:
8+
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
9+
* denghongcai <admin@dhcouse.com> (https://www.dhc.house)
10+
*
11+
*/
12+
13+
"use strict";
14+
15+
/**
16+
* Module dependencies.
17+
*/
18+
19+
var util = require('util');
20+
var DecoderV2 = require('../v2/decoder');
21+
var DecoderV1 = require('../v1/decoder');
22+
23+
function Decoder(buf, classRefs) {
24+
DecoderV2.call(this, buf);
25+
this.classes = classRefs; // using passed in ref array
26+
}
27+
28+
util.inherits(Decoder, DecoderV2);
29+
30+
var proto = Decoder.prototype;
31+
32+
proto.clean = function () {
33+
DecoderV1.prototype.clean.call(this); // can not clean `this.classes`
34+
this.types = [];
35+
return this;
36+
};
37+
38+
module.exports = Decoder;

lib/v2_optimize/encoder.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* hessian.js - lib/v2/encoder.js
3+
*
4+
* Copyright(c)
5+
* MIT Licensed
6+
*
7+
* Authors:
8+
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
9+
* denghongcai <admin@dhcouse.com> (https://www.dhc.house)
10+
*
11+
*/
12+
13+
"use strict";
14+
15+
/**
16+
* Module dependencies.
17+
*/
18+
19+
var debug = require('debug')('hessian:v2_optimize:encoder');
20+
var util = require('util');
21+
var EncoderV2 = require('../v2/encoder');
22+
var EncoderV1 = require('../v1/encoder');
23+
24+
function Encoder(options) {
25+
EncoderV2.call(this, options);
26+
27+
this._classRefs = options.classRefs;
28+
this._classRefFields = options.classRefFields;
29+
this._typeRefs = [];
30+
}
31+
32+
util.inherits(Encoder, EncoderV2);
33+
34+
var proto = Encoder.prototype;
35+
36+
/**
37+
* clean the buf
38+
*/
39+
proto.reset = proto.clean = function () {
40+
EncoderV1.prototype.clean.call(this);
41+
this._typeRefs = [];
42+
return this;
43+
};
44+
45+
module.exports = Encoder;

test/v2.optimize.endecode.test.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
'use strict';
2+
3+
var assert = require('assert');
4+
var hessian = require('../');
5+
var utils = require('./utils');
6+
var supportES6Map = require('../lib/utils').supportES6Map;
7+
var DecoderV2 = require('../lib/v2_optimize/decoder');
8+
var EncoderV2 = require('../lib/v2_optimize/encoder');
9+
10+
var cache = [];
11+
12+
describe('v2.optimize.endecode.test.js', function () {
13+
var decode = hessian.decode;
14+
var encode = hessian.encode;
15+
var encoder = new EncoderV2({
16+
size: 1024 * 1024,
17+
classRefs: [],
18+
classRefFields: {},
19+
});
20+
before(function() {
21+
hessian.decode = function(buf, version, withType) {
22+
return new DecoderV2(buf, cache).read(withType);
23+
};
24+
25+
hessian.encode = function(obj) {
26+
encoder.reset();
27+
return encoder.write(obj).get();
28+
};
29+
});
30+
31+
// reset and check cache
32+
after(function() {
33+
assert(cache.length);
34+
hessian.decode = decode;
35+
hessian.encode = encode;
36+
});
37+
38+
describe('encode/decode', function () {
39+
it('should encode/decode class and match ref', function () {
40+
var obj = {
41+
$class: 'hessian.test.demo.Car',
42+
$: { a: 1, b: 'map' }
43+
};
44+
var buf = hessian.encode(obj);
45+
assert(buf[0] === 0x43);
46+
assert.deepEqual(hessian.decode(buf), obj.$);
47+
assert.deepEqual(hessian.decode(buf, '2.0', true), obj);
48+
49+
buf = hessian.encode(obj);
50+
assert(buf[0] === 0x60);
51+
assert.deepEqual(hessian.decode(buf), obj.$);
52+
assert.deepEqual(hessian.decode(buf, '2.0', true), obj);
53+
});
54+
55+
it('should reset encoder ok', function () {
56+
encoder.byteBuffer.putChar('o');
57+
encoder.objects.ok = true;
58+
encoder._typeRefs.push('ok');
59+
encoder.reset();
60+
assert.equal(encoder.byteBuffer._offset, 0);
61+
assert.equal(Object.keys(encoder.objects).length, 0);
62+
assert.equal(encoder._typeRefs.length, 0);
63+
});
64+
65+
it('should clean decoder ok', function () {
66+
var decoder = new DecoderV2([], []);
67+
var byteBuffer = decoder.byteBuffer;
68+
decoder.refId = 1;
69+
decoder.refMap = {a: 1};
70+
decoder.types.push(1);
71+
decoder.clean();
72+
assert.notEqual(byteBuffer, decoder.byteBuffer);
73+
assert.equal(decoder.refId, 0);
74+
assert.equal(Object.keys(decoder.refMap).length, 0);
75+
assert.equal(decoder.types.length, 0);
76+
});
77+
});
78+
});

0 commit comments

Comments
 (0)