BufferReader.ts
· 4.4 KiB · TypeScript
Raw
export default class BufferReader {
#buffer: Buffer
#offset: number
#length = 0
/// Yields BufferReaders, splitting when it hits newline
static *getPackets(data: Buffer) {
let reader = new BufferReader(data)
yield reader
// while(reader.nextBuffer != null) {
// reader = new BufferReader(reader.nextBuffer)
// yield reader
// }
return null
}
static new(size: number) {
return new BufferReader(Buffer.alloc(size))
}
constructor(data: Buffer) {
if(!data) throw new Error("buffer is null or undefined")
// console.log(data.byteLength, data.length, data.toString('hex'))
this.#buffer = data
this.#offset = 0
this.#length = data.byteLength
}
get buffer() {
return this.#buffer.subarray()
}
get offset() {
return this.#offset
}
get length() {
return this.#length
}
get isEOF() {
return this.#offset >= this.#length || this.#curChar == 0xa // new line
}
get IsRecordSeparator() {
return this.#curChar === BufferReader.RecordSeparator
}
get #curChar() {
return this.#buffer.at(this.#offset)
}
static get RecordSeparator() {
return 0x1e
}
peekByte(): number {
return this.#buffer.readInt8(this.#offset)
}
readByte(): number {
const value = this.#buffer.readInt8(this.#offset)
this.#offset += 1
return value
}
readShort(): number {
const value = this.#buffer.readInt16LE(this.#offset)
this.#offset += 2
return value
}
readInt(): number {
const value = this.#buffer.readInt32LE(this.#offset)
this.#offset += 4
return value
}
readFloat(): number {
const value = this.#buffer.readFloatLE(this.#offset)
this.#offset += 4
return value
}
readString(): string {
let start = this.#offset
// Read until null term
while(this.#offset < this.#length) {
if(this.#curChar === 0x0) {
return this.#buffer.subarray(start, this.#offset++).toString()
}
this.#offset++
}
throw new Error("No null term found")
}
/// Yields a BufferReader for every record in a packet
*readRecords() {
while(!this.isEOF) {
const length = this.readByte()
const endRecord = this.#offset + length
yield new BufferReader(this.#buffer.subarray(this.#offset, endRecord))
this.#offset = endRecord + 1
}
return null
}
#expand(newSize?: number) {
if(!newSize) newSize = 2 * this.buffer.length
if(newSize < this.#buffer.length) throw new Error("new size must be greater than the current size")
const newBuffer = Buffer.alloc(newSize)
this.buffer.copy(newBuffer, 0, 0, this.buffer.length)
this.#buffer = newBuffer
this.#length = newSize
}
writeByte(value: number) {
if(this.#offset + 1 >= this.#length) this.#expand()
this.#buffer.writeInt8(value, this.#offset)
this.#offset++
return this
}
writeShort(value: number) {
if(this.#offset + 2 >= this.#length) this.#expand()
this.#buffer.writeInt16LE(value, this.#offset)
this.#offset += 2
return this
}
writeInt(value: number) {
if(this.#offset + 4 >= this.#length) this.#expand()
this.#buffer.writeInt32LE(value, this.#offset)
this.#offset += 4
return this
}
writeFloat(value: number) {
if(this.#offset + 4 >= this.#length) this.#expand()
this.#buffer.writeFloatLE(value, this.#offset)
this.#offset += 4
return this
}
writeString(value: string) {
if(this.#offset + value.length + 1 >= this.#length) this.#expand(this.#length + value.length + 1)
if(value == undefined) value = ""
this.#buffer.write(value + "\0", this.#offset, "ascii")
this.#offset += value.length + 1
return this
}
// get nextBuffer() {
// if(this.#curChar == 0xa && this.#offset + 1 < this.#buffer.length) {
// return this.#buffer.subarray(this.#offset + 1)
// } else {
// return null
// }
// }
at(i: number): number {
return this.#buffer.at(i)
}
next(): number | null {
if(this.#offset == this.#length) return null
return this.readByte()
}
}
1 | export default class BufferReader { |
2 | #buffer: Buffer |
3 | #offset: number |
4 | #length = 0 |
5 | |
6 | /// Yields BufferReaders, splitting when it hits newline |
7 | static *getPackets(data: Buffer) { |
8 | let reader = new BufferReader(data) |
9 | yield reader |
10 | // while(reader.nextBuffer != null) { |
11 | // reader = new BufferReader(reader.nextBuffer) |
12 | // yield reader |
13 | // } |
14 | return null |
15 | } |
16 | |
17 | static new(size: number) { |
18 | return new BufferReader(Buffer.alloc(size)) |
19 | } |
20 | |
21 | constructor(data: Buffer) { |
22 | if(!data) throw new Error("buffer is null or undefined") |
23 | // console.log(data.byteLength, data.length, data.toString('hex')) |
24 | this.#buffer = data |
25 | this.#offset = 0 |
26 | this.#length = data.byteLength |
27 | |
28 | } |
29 | |
30 | get buffer() { |
31 | return this.#buffer.subarray() |
32 | } |
33 | |
34 | get offset() { |
35 | return this.#offset |
36 | } |
37 | |
38 | get length() { |
39 | return this.#length |
40 | } |
41 | |
42 | get isEOF() { |
43 | return this.#offset >= this.#length || this.#curChar == 0xa // new line |
44 | } |
45 | |
46 | get IsRecordSeparator() { |
47 | return this.#curChar === BufferReader.RecordSeparator |
48 | } |
49 | |
50 | get #curChar() { |
51 | return this.#buffer.at(this.#offset) |
52 | } |
53 | |
54 | static get RecordSeparator() { |
55 | return 0x1e |
56 | } |
57 | |
58 | peekByte(): number { |
59 | return this.#buffer.readInt8(this.#offset) |
60 | } |
61 | |
62 | readByte(): number { |
63 | const value = this.#buffer.readInt8(this.#offset) |
64 | this.#offset += 1 |
65 | return value |
66 | } |
67 | |
68 | readShort(): number { |
69 | const value = this.#buffer.readInt16LE(this.#offset) |
70 | this.#offset += 2 |
71 | return value |
72 | } |
73 | |
74 | readInt(): number { |
75 | const value = this.#buffer.readInt32LE(this.#offset) |
76 | this.#offset += 4 |
77 | return value |
78 | } |
79 | |
80 | readFloat(): number { |
81 | const value = this.#buffer.readFloatLE(this.#offset) |
82 | this.#offset += 4 |
83 | return value |
84 | } |
85 | |
86 | readString(): string { |
87 | let start = this.#offset |
88 | // Read until null term |
89 | while(this.#offset < this.#length) { |
90 | if(this.#curChar === 0x0) { |
91 | return this.#buffer.subarray(start, this.#offset++).toString() |
92 | } |
93 | this.#offset++ |
94 | } |
95 | throw new Error("No null term found") |
96 | } |
97 | |
98 | /// Yields a BufferReader for every record in a packet |
99 | *readRecords() { |
100 | while(!this.isEOF) { |
101 | const length = this.readByte() |
102 | const endRecord = this.#offset + length |
103 | yield new BufferReader(this.#buffer.subarray(this.#offset, endRecord)) |
104 | this.#offset = endRecord + 1 |
105 | } |
106 | return null |
107 | } |
108 | |
109 | #expand(newSize?: number) { |
110 | if(!newSize) newSize = 2 * this.buffer.length |
111 | if(newSize < this.#buffer.length) throw new Error("new size must be greater than the current size") |
112 | const newBuffer = Buffer.alloc(newSize) |
113 | this.buffer.copy(newBuffer, 0, 0, this.buffer.length) |
114 | this.#buffer = newBuffer |
115 | this.#length = newSize |
116 | } |
117 | |
118 | |
119 | writeByte(value: number) { |
120 | if(this.#offset + 1 >= this.#length) this.#expand() |
121 | this.#buffer.writeInt8(value, this.#offset) |
122 | this.#offset++ |
123 | return this |
124 | } |
125 | |
126 | writeShort(value: number) { |
127 | if(this.#offset + 2 >= this.#length) this.#expand() |
128 | this.#buffer.writeInt16LE(value, this.#offset) |
129 | this.#offset += 2 |
130 | return this |
131 | } |
132 | |
133 | writeInt(value: number) { |
134 | if(this.#offset + 4 >= this.#length) this.#expand() |
135 | this.#buffer.writeInt32LE(value, this.#offset) |
136 | this.#offset += 4 |
137 | return this |
138 | } |
139 | |
140 | writeFloat(value: number) { |
141 | if(this.#offset + 4 >= this.#length) this.#expand() |
142 | this.#buffer.writeFloatLE(value, this.#offset) |
143 | this.#offset += 4 |
144 | return this |
145 | } |
146 | |
147 | writeString(value: string) { |
148 | if(this.#offset + value.length + 1 >= this.#length) this.#expand(this.#length + value.length + 1) |
149 | if(value == undefined) value = "" |
150 | this.#buffer.write(value + "\0", this.#offset, "ascii") |
151 | this.#offset += value.length + 1 |
152 | return this |
153 | } |
154 | |
155 | // get nextBuffer() { |
156 | // if(this.#curChar == 0xa && this.#offset + 1 < this.#buffer.length) { |
157 | // return this.#buffer.subarray(this.#offset + 1) |
158 | // } else { |
159 | // return null |
160 | // } |
161 | // } |
162 | |
163 | at(i: number): number { |
164 | return this.#buffer.at(i) |
165 | } |
166 | |
167 | next(): number | null { |
168 | if(this.#offset == this.#length) return null |
169 | return this.readByte() |
170 | } |
171 | } |