-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy patharray.js
More file actions
80 lines (71 loc) · 2.6 KB
/
array.js
File metadata and controls
80 lines (71 loc) · 2.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
var {encodeField, decodeField} = require('./utils')
function ArrayCodec (length_c, direct_c, pointed_c=null, _isNullable = (pointed_c != null)) {
//the minimum size is the length used to encode 0
var empty_size = length_c.bytes
//note. pointed_codec is optional.
//direct_codec must be fixed size.
function encode (value, buffer, start) {
//write the length
length_c.encode(value.length*direct_c.bytes, buffer, start)
var array_start = length_c.bytes
var free = array_start + value.length * direct_c.bytes
//encode into positions, basically the same code as for encoding a struct
//except that the codec's are the same and, the position is i*
for(var i = 0; i < value.length; i++) {
var item = value[i]
var position = array_start + i*direct_c.bytes
free += encodeField(position, direct_c, pointed_c, item, buffer, start, free)
}
encode.bytes = free
}
function decode (buffer, start, end) {
var length = length_c.decode(buffer, start)
var array_start = length_c.bytes
var items = length / direct_c.bytes
if(start + items >= end)
throw new Error('array length out of bounds')
var a = new Array(items)
for(var i = 0; i < items; i++) {
var position = array_start + i*direct_c.bytes
var value = decodeField(position, direct_c, pointed_c, buffer, start, end)
if(value != null)
a[i] = value
}
return a
}
//actually we don't want to decode the field
//we want to either return the direct value
//or a pointer to the indirect.
function dereference (buffer, start, index) {
var length = length_c.decode(buffer, start)
var array_start = length_c.bytes
var items = length / direct_c.bytes
if(index < 0 || index >= items) return undefined
var position = array_start + index*direct_c.bytes
if(!pointed_c)
return start + position //return pointer to direct value
else {
var relp = direct_c.decode(buffer, start + position)
if(relp === 0) return -1
return (start + position) + relp
}
}
//so... we need a method to return the codec at an index.
//an array should always use one field type.
//...and the length isn't addressable.
//in this case,
function reflect (_) {
return pointed_c ? pointed_c : direct_c
}
function encodingLength (value) {
var base = length_c.bytes + direct_c.bytes * value.length
if(pointed_c)
return base + value.reduce((size, item) => size + pointed_c.encodingLength(item), 0)
return base
}
return {
isArray: true,
encode, decode, encodingLength, dereference, reflect
}
}
module.exports = ArrayCodec