-
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathStreamBuffer.luau
More file actions
124 lines (102 loc) · 2.55 KB
/
Copy pathStreamBuffer.luau
File metadata and controls
124 lines (102 loc) · 2.55 KB
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
--!native
--!optimize 2
--[[
StreamBuffer
A growable wrapper around Luau's `buffer` type.
Why: we don't know the final size of an INST/PROP/PRNT chunk up front
without walking the whole instance tree twice. Instead:
1. start with a reasonably-sized buffer (default 4KB)
2. double capacity whenever a write would overflow it
3. buffer.copy old -> new on grow
]]
local StreamBuffer = {}
StreamBuffer.__index = StreamBuffer
local DEFAULT_CAPACITY = 4096
function StreamBuffer.new(initialCapacity)
local cap = initialCapacity or DEFAULT_CAPACITY
return setmetatable({
buf = buffer.create(cap),
len = 0,
cap = cap,
}, StreamBuffer)
end
function StreamBuffer:reserve(extra)
local needed = self.len + extra
if needed <= self.cap then
return
end
local newCap = self.cap
while newCap < needed do
newCap *= 2
end
local newBuf = buffer.create(newCap)
buffer.copy(newBuf, 0, self.buf, 0, self.len)
self.buf = newBuf
self.cap = newCap
end
function StreamBuffer:allocRegion(size)
self:reserve(size)
local base = self.len
self.len += size
return base
end
function StreamBuffer:writeu8(v)
self:reserve(1)
buffer.writeu8(self.buf, self.len, v)
self.len += 1
end
function StreamBuffer:writeu16(v)
self:reserve(2)
buffer.writeu16(self.buf, self.len, v)
self.len += 2
end
function StreamBuffer:writei16(v)
self:reserve(2)
buffer.writei16(self.buf, self.len, v)
self.len += 2
end
function StreamBuffer:writeu32(v)
self:reserve(4)
buffer.writeu32(self.buf, self.len, v)
self.len += 4
end
function StreamBuffer:writei32(v)
self:reserve(4)
buffer.writei32(self.buf, self.len, v)
self.len += 4
end
function StreamBuffer:writef32(v)
self:reserve(4)
buffer.writef32(self.buf, self.len, v)
self.len += 4
end
function StreamBuffer:writef64(v)
self:reserve(8)
buffer.writef64(self.buf, self.len, v)
self.len += 8
end
function StreamBuffer:writestring(s)
local n = #s
self:reserve(n)
buffer.writestring(self.buf, self.len, s)
self.len += n
end
function StreamBuffer:writeLenString(s)
self:writeu32(#s)
self:writestring(s)
end
function StreamBuffer:fill(value, count)
self:reserve(count)
buffer.fill(self.buf, self.len, value, count)
self.len += count
end
-- Absolute-offset single-byte write into an already-reserved region.
-- `offset` is a byte offset from the start of the buffer, NOT relative to
-- self.len. Caller must have reserved it via allocRegion first.
function StreamBuffer:pokeu8(offset, v)
buffer.writeu8(self.buf, offset, v)
end
function StreamBuffer:tostring()
return buffer.readstring(self.buf, 0, self.len)
end
return StreamBuffer