/ node_modules / pg-protocol / src / buffer-writer.ts
buffer-writer.ts
 1  //binary data writer tuned for encoding binary specific to the postgres binary protocol
 2  
 3  export class Writer {
 4    private buffer: Buffer
 5    private offset: number = 5
 6    private headerPosition: number = 0
 7    constructor(private size = 256) {
 8      this.buffer = Buffer.allocUnsafe(size)
 9    }
10  
11    private ensure(size: number): void {
12      const remaining = this.buffer.length - this.offset
13      if (remaining < size) {
14        const oldBuffer = this.buffer
15        // exponential growth factor of around ~ 1.5
16        // https://stackoverflow.com/questions/2269063/buffer-growth-strategy
17        const newSize = oldBuffer.length + (oldBuffer.length >> 1) + size
18        this.buffer = Buffer.allocUnsafe(newSize)
19        oldBuffer.copy(this.buffer)
20      }
21    }
22  
23    public addInt32(num: number): Writer {
24      this.ensure(4)
25      this.buffer[this.offset++] = (num >>> 24) & 0xff
26      this.buffer[this.offset++] = (num >>> 16) & 0xff
27      this.buffer[this.offset++] = (num >>> 8) & 0xff
28      this.buffer[this.offset++] = (num >>> 0) & 0xff
29      return this
30    }
31  
32    public addInt16(num: number): Writer {
33      this.ensure(2)
34      this.buffer[this.offset++] = (num >>> 8) & 0xff
35      this.buffer[this.offset++] = (num >>> 0) & 0xff
36      return this
37    }
38  
39    public addCString(string: string): Writer {
40      if (!string) {
41        this.ensure(1)
42      } else {
43        const len = Buffer.byteLength(string)
44        this.ensure(len + 1) // +1 for null terminator
45        this.buffer.write(string, this.offset, 'utf-8')
46        this.offset += len
47      }
48  
49      this.buffer[this.offset++] = 0 // null terminator
50      return this
51    }
52  
53    public addString(string: string = ''): Writer {
54      const len = Buffer.byteLength(string)
55      this.ensure(len)
56      this.buffer.write(string, this.offset)
57      this.offset += len
58      return this
59    }
60  
61    public add(otherBuffer: Buffer): Writer {
62      this.ensure(otherBuffer.length)
63      otherBuffer.copy(this.buffer, this.offset)
64      this.offset += otherBuffer.length
65      return this
66    }
67  
68    private join(code?: number): Buffer {
69      if (code) {
70        this.buffer[this.headerPosition] = code
71        //length is everything in this packet minus the code
72        const length = this.offset - (this.headerPosition + 1)
73        this.buffer.writeInt32BE(length, this.headerPosition + 1)
74      }
75      return this.buffer.slice(code ? 0 : 5, this.offset)
76    }
77  
78    public flush(code?: number): Buffer {
79      const result = this.join(code)
80      this.offset = 5
81      this.headerPosition = 0
82      this.buffer = Buffer.allocUnsafe(this.size)
83      return result
84    }
85  }