57 lines
1.5 KiB
JavaScript
57 lines
1.5 KiB
JavaScript
'use strict'
|
|
|
|
const BufferList = require('obuf')
|
|
const { Transform } = require('stream')
|
|
|
|
const State = {
|
|
READ_PREFIX: 1,
|
|
READ_DATA: 2
|
|
}
|
|
|
|
class ByteaDecoder extends Transform {
|
|
constructor () {
|
|
super()
|
|
this._incomingChunks = new BufferList()
|
|
this._state = State.READ_PREFIX
|
|
}
|
|
|
|
_transform (chunk, encoding, callback) {
|
|
this._incomingChunks.push(chunk)
|
|
|
|
while (true) {
|
|
if (this._state === State.READ_PREFIX) {
|
|
if (this._incomingChunks.has(3)) {
|
|
const prefix = this._incomingChunks.take(3)
|
|
const prefixString = prefix.toString()
|
|
if (prefixString !== '\\\\x') {
|
|
return this.emit('error', new Error(`Expected double-escaped postgres bytea hex format prefix, received: '${prefixString}'`))
|
|
}
|
|
this._state = State.READ_DATA
|
|
continue
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
|
|
if (this._state === State.READ_DATA) {
|
|
if (this._incomingChunks.size >= 2) {
|
|
// two hex characters are needed to parse a byte. read even number of chars, and let remainder roll over
|
|
let evenChunk
|
|
const isEvenLength = this._incomingChunks.size % 2 === 0
|
|
if (isEvenLength) {
|
|
evenChunk = this._incomingChunks.take(this._incomingChunks.size)
|
|
} else {
|
|
evenChunk = this._incomingChunks.take(this._incomingChunks.size - 1)
|
|
}
|
|
this.push(Buffer.from(evenChunk.toString(), 'hex'))
|
|
}
|
|
break
|
|
}
|
|
}
|
|
|
|
callback()
|
|
}
|
|
}
|
|
|
|
module.exports = ByteaDecoder
|