Last active 1741880600

BufferReader.ts Raw
1export 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}