forked from brianc/node-pg-types
/
binaryParsers.js
142 lines (118 loc) · 3.1 KB
/
binaryParsers.js
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
var parseInt64 = require('pg-int8')
var parseNumeric = require('pg-numeric')
var parseInt16 = function (value) {
return value.readInt16BE(0)
}
var parseInt32 = function (value) {
return value.readInt32BE(0)
}
var parseFloat32 = function (value) {
return value.readFloatBE(0)
}
var parseFloat64 = function (value) {
return value.readDoubleBE(0)
}
var parseDate = function (isUTC, value) {
var rawValue = 0x100000000 * value.readInt32BE(0) + value.readUInt32BE(4)
// discard usecs and shift from 2000 to 1970
var result = new Date((rawValue / 1000) + 946684800000)
if (!isUTC) {
result.setTime(result.getTime() + result.getTimezoneOffset() * 60000)
}
// add microseconds to the date
result.usec = rawValue % 1000
result.getMicroSeconds = function () {
return this.usec
}
result.setMicroSeconds = function (value) {
this.usec = value
}
result.getUTCMicroSeconds = function () {
return this.usec
}
return result
}
var parseArray = function (value) {
var dim = value.readInt32BE(0)
var elementType = value.readUInt32BE(8)
var offset = 12
var dims = []
for (var i = 0; i < dim; i++) {
// parse dimension
dims[i] = value.readInt32BE(offset)
offset += 4
// ignore lower bounds
offset += 4
}
var parseElement = function (elementType) {
// parse content length
var length = value.readInt32BE(offset)
offset += 4
// parse null values
if (length === -1) {
return null
}
var result
if (elementType === 0x17) {
// int
result = value.readInt32BE(offset)
offset += length
return result
} else if (elementType === 0x14) {
// bigint
result = parseInt64(value.slice(offset, offset += length))
return result
} else if (elementType === 0x19) {
// string
result = value.toString('utf8', offset, offset += length)
return result
} else {
throw new Error('ElementType not implemented: ' + elementType)
}
}
var parse = function (dimension, elementType) {
var array = []
var i
if (dimension.length > 1) {
var count = dimension.shift()
for (i = 0; i < count; i++) {
array[i] = parse(dimension, elementType)
}
dimension.unshift(count)
} else {
for (i = 0; i < dimension[0]; i++) {
array[i] = parseElement(elementType)
}
}
return array
}
return parse(dims, elementType)
}
var parseText = function (value) {
return value.toString('utf8')
}
var parseBool = function (value) {
if (value === null) return null
return value[0] !== 0
}
var init = function (register) {
register(20, parseInt64)
register(21, parseInt16)
register(23, parseInt32)
register(26, parseInt32)
register(1700, parseFloat)
register(700, parseFloat32)
register(701, parseFloat64)
register(16, parseBool)
register(1114, parseDate.bind(null, false))
register(1184, parseDate.bind(null, true))
register(1000, parseArray)
register(1007, parseArray)
register(1016, parseArray)
register(1008, parseArray)
register(1009, parseArray)
register(25, parseText)
}
module.exports = {
init: init
}