@skating/swiftpacket 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,145 @@
1
+ --!strict
2
+ --!optimize 2
3
+
4
+ --[[
5
+ Author: @skaterstudios
6
+ Website: skaterstudios.com
7
+ GitHub: github.com/skatingii/SwiftPacket
8
+ Discord Server: discord.gg/skaterstudios
9
+
10
+ Licensed under the MIT License. You may use, modify, redistribute and sell
11
+ this system freely, as long as this notice and the LICENSE file stay with it.
12
+ ]]
13
+
14
+ const ThreadPool = require("./thread_pool")
15
+
16
+ const Signal = {}
17
+ Signal.__index = Signal
18
+
19
+ const Connection = {}
20
+ Connection.__index = Connection
21
+
22
+ export type SignalFields = {
23
+ Head: Connection?,
24
+ Tail: Connection?,
25
+ }
26
+
27
+ export type ConnectionFields = {
28
+ Connected: boolean,
29
+ Once: boolean,
30
+ Callback: ((...any) -> ())?,
31
+ Thread: thread?,
32
+ Owner: Signal,
33
+ Previous: Connection?,
34
+ Next: Connection?,
35
+ }
36
+
37
+ export type Signal = setmetatable<SignalFields, typeof(Signal)>
38
+ export type Connection = setmetatable<ConnectionFields, typeof(Connection)>
39
+
40
+ function Signal.New(): Signal
41
+ const State: SignalFields = {}
42
+
43
+ const self: Signal = setmetatable(State, Signal)
44
+
45
+ return self
46
+ end
47
+
48
+ const function Attach(Owner: Signal, Callback: ((...any) -> ())?, Thread: thread?, Once: boolean): Connection
49
+ const State: ConnectionFields = {
50
+ Connected = true,
51
+ Once = Once,
52
+ Callback = Callback,
53
+ Thread = Thread,
54
+ Owner = Owner,
55
+ Previous = Owner.Tail,
56
+ }
57
+
58
+ const Node: Connection = setmetatable(State, Connection)
59
+ const Tail = Owner.Tail
60
+
61
+ if Tail then
62
+ Tail.Next = Node
63
+ else
64
+ Owner.Head = Node
65
+ end
66
+
67
+ Owner.Tail = Node
68
+
69
+ return Node
70
+ end
71
+
72
+ function Signal.Connect(self: Signal, Callback: (...any) -> ()): Connection
73
+ return Attach(self, Callback, nil, false)
74
+ end
75
+
76
+ function Signal.Once(self: Signal, Callback: (...any) -> ()): Connection
77
+ return Attach(self, Callback, nil, true)
78
+ end
79
+
80
+ function Signal.Wait(self: Signal): ...any
81
+ Attach(self, nil, coroutine.running(), true)
82
+
83
+ return coroutine.yield()
84
+ end
85
+
86
+ function Signal.Fire(self: Signal, ...: any)
87
+ local Node = self.Head
88
+
89
+ while Node do
90
+ if Node.Connected then
91
+ if Node.Once then
92
+ Node:Disconnect()
93
+ end
94
+
95
+ const Callback = Node.Callback
96
+ const Thread = Node.Thread
97
+
98
+ if Callback then
99
+ ThreadPool.Defer(Callback, ...)
100
+ elseif Thread then
101
+ task.defer(Thread, ...)
102
+ end
103
+ end
104
+
105
+ Node = Node.Next
106
+ end
107
+ end
108
+
109
+ function Signal.DisconnectAll(self: Signal)
110
+ local Node = self.Head
111
+
112
+ while Node do
113
+ Node.Connected = false
114
+ Node = Node.Next
115
+ end
116
+
117
+ self.Head = nil
118
+ self.Tail = nil
119
+ end
120
+
121
+ function Connection.Disconnect(self: Connection)
122
+ if not self.Connected then
123
+ return
124
+ end
125
+
126
+ self.Connected = false
127
+
128
+ const Owner = self.Owner
129
+ const Previous = self.Previous
130
+ const Next = self.Next
131
+
132
+ if Previous then
133
+ Previous.Next = Next
134
+ else
135
+ Owner.Head = Next
136
+ end
137
+
138
+ if Next then
139
+ Next.Previous = Previous
140
+ else
141
+ Owner.Tail = Previous
142
+ end
143
+ end
144
+
145
+ return Signal
@@ -0,0 +1,37 @@
1
+ --!strict
2
+ --!optimize 2
3
+
4
+ --[[
5
+ Author: @skaterstudios
6
+ Website: skaterstudios.com
7
+ GitHub: github.com/skatingii/SwiftPacket
8
+ Discord Server: discord.gg/skaterstudios
9
+
10
+ Licensed under the MIT License. You may use, modify, redistribute and sell
11
+ this system freely, as long as this notice and the LICENSE file stay with it.
12
+ ]]
13
+
14
+ const ThreadPool = {}
15
+
16
+ const Threads: { thread } = {}
17
+
18
+ const function Call(Callback: (...any) -> (), ...: any)
19
+ Callback(...)
20
+ table.insert(Threads, coroutine.running())
21
+ end
22
+
23
+ const function Loop()
24
+ while true do
25
+ Call(coroutine.yield())
26
+ end
27
+ end
28
+
29
+ const function Acquire(): thread
30
+ return table.remove(Threads) or task.spawn(Loop)
31
+ end
32
+
33
+ function ThreadPool.Defer(Callback: (...any) -> (), ...: any)
34
+ task.defer(Acquire(), Callback, ...)
35
+ end
36
+
37
+ return ThreadPool
package/src/wire.luau ADDED
@@ -0,0 +1,218 @@
1
+ --!strict
2
+ --!optimize 2
3
+
4
+ --[[
5
+ Author: @skaterstudios
6
+ Website: skaterstudios.com
7
+ GitHub: github.com/skatingii/SwiftPacket
8
+ Discord Server: discord.gg/skaterstudios
9
+
10
+ Licensed under the MIT License. You may use, modify, redistribute and sell
11
+ this system freely, as long as this notice and the LICENSE file stay with it.
12
+ ]]
13
+
14
+ const Cursor = require("./cursor")
15
+ const Registry = require("./registry")
16
+ const Schema = require("./schema")
17
+
18
+ export type Batch = {
19
+ Count: number,
20
+ Definitions: { Registry.Definition },
21
+ CallIndices: { number },
22
+ Successes: { boolean },
23
+ Starts: { number },
24
+ Counts: { number },
25
+ Values: { any },
26
+ StopOffset: number,
27
+ StopInstances: number,
28
+ }
29
+
30
+ const Wire = {}
31
+
32
+ const ResponseFlag = 32768
33
+ const EventIndex = -1
34
+
35
+ const ReadVarint = Cursor.ReadVarint
36
+ const ReadU16 = Cursor.ReadU16
37
+ const ReadU8 = Cursor.ReadU8
38
+ const Ended = Cursor.Ended
39
+ const Position = Cursor.Position
40
+
41
+ const function VarintSize(Value: number): number
42
+ return if Value < 128 then 1 elseif Value < 16384 then 2 elseif Value < 2097152 then 3 else 4
43
+ end
44
+
45
+ Wire.ResponseFlag = ResponseFlag
46
+ Wire.EventIndex = EventIndex
47
+
48
+ function Wire.Encode(
49
+ Target: Cursor.Cursor,
50
+ Schemas: { Schema.Schema },
51
+ Values: Schema.Arguments,
52
+ Offset: number,
53
+ Name: string
54
+ )
55
+ Cursor.Reset(Target)
56
+ Cursor.Import(Target)
57
+ Schema.WriteArguments(Schemas, Values, Offset, Name)
58
+ Cursor.Export()
59
+ end
60
+
61
+ function Wire.Deliver(Target: Cursor.Cursor, Id: number, CallIndex: number?, Status: number?, Body: Cursor.Cursor?)
62
+ Cursor.Import(Target)
63
+ Cursor.WriteId(Id)
64
+
65
+ if CallIndex then
66
+ Cursor.Allocate(2)
67
+ Cursor.WriteU16(CallIndex)
68
+ end
69
+
70
+ if Status then
71
+ Cursor.Allocate(1)
72
+ Cursor.WriteU8(Status)
73
+ end
74
+
75
+ if Body then
76
+ Cursor.Append(Body)
77
+ end
78
+
79
+ Cursor.Export()
80
+ end
81
+
82
+ function Wire.DeliverResponse(Target: Cursor.Cursor, Id: number, CallIndex: number, Body: Cursor.Cursor?)
83
+ if Body then
84
+ Wire.Deliver(Target, Id, CallIndex + ResponseFlag, 1, Body)
85
+ else
86
+ Wire.Deliver(Target, Id, CallIndex + ResponseFlag, 0, nil)
87
+ end
88
+ end
89
+
90
+ function Wire.EncodeResults(
91
+ Target: Cursor.Cursor,
92
+ Definition: Registry.Definition,
93
+ Results: Schema.Arguments
94
+ ): (boolean, string?)
95
+ const Responses = Definition.Responses
96
+
97
+ if Responses == nil then
98
+ return false, `{Definition.Name} has no response types`
99
+ end
100
+
101
+ if Results[1] ~= true then
102
+ return false, `the handler for {Definition.Name} errored: {tostring(Results[2])}`
103
+ end
104
+
105
+ const Ok, Problem = pcall(Wire.Encode, Target, Responses, Results, 1, "")
106
+
107
+ if not Ok then
108
+ return false, `could not write the response for {Definition.Name}: {tostring(Problem)}`
109
+ end
110
+
111
+ return true, nil
112
+ end
113
+
114
+ function Wire.Size(Id: number, CallIndex: number?, Body: Cursor.Cursor): number
115
+ return VarintSize(Id) + (if CallIndex then 2 else 0) + Body.Offset
116
+ end
117
+
118
+ function Wire.NewBatch(): Batch
119
+ return {
120
+ Count = 0,
121
+ Definitions = {},
122
+ CallIndices = {},
123
+ Successes = {},
124
+ Starts = {},
125
+ Counts = {},
126
+ Values = {},
127
+ StopOffset = 0,
128
+ StopInstances = 0,
129
+ }
130
+ end
131
+
132
+ function Wire.Decode(
133
+ Target: Batch,
134
+ Source: buffer,
135
+ Instances: { any },
136
+ Untrusted: boolean,
137
+ Offset: number,
138
+ StartInstances: number
139
+ ): number?
140
+ Cursor.Load(Source, Instances, Untrusted, Offset, StartInstances)
141
+
142
+ const Definitions = Target.Definitions
143
+ const CallIndices = Target.CallIndices
144
+ const Successes = Target.Successes
145
+ const Starts = Target.Starts
146
+ const Counts = Target.Counts
147
+ const Values = Target.Values
148
+
149
+ local Count = 0
150
+ local Top = 0
151
+
152
+ Target.Count = 0
153
+
154
+ while not Ended() do
155
+ const Id = ReadVarint()
156
+ const Definition = Registry.ById[Id]
157
+
158
+ if Definition == nil then
159
+ const Reached, ReachedInstances = Position()
160
+
161
+ Target.StopOffset = Reached - VarintSize(Id)
162
+ Target.StopInstances = ReachedInstances
163
+
164
+ return Id
165
+ end
166
+
167
+ const Responses = Definition.Responses
168
+ local CallIndex = EventIndex
169
+ local Success = true
170
+ local Schemas = Definition.Arguments
171
+
172
+ if Responses then
173
+ CallIndex = ReadU16()
174
+
175
+ if CallIndex >= ResponseFlag then
176
+ Success = ReadU8() == 1
177
+ Schemas = Responses
178
+ end
179
+ end
180
+
181
+ Count += 1
182
+ Definitions[Count] = Definition
183
+ CallIndices[Count] = CallIndex
184
+ Successes[Count] = Success
185
+ Starts[Count] = Top + 1
186
+
187
+ if Success then
188
+ const Size = #Schemas
189
+
190
+ if Size == 1 then
191
+ Top += 1
192
+ Values[Top] = Schemas[1].Read()
193
+ else
194
+ for Index = 1, Size do
195
+ Top += 1
196
+ Values[Top] = Schemas[Index].Read()
197
+ end
198
+ end
199
+ end
200
+
201
+ Counts[Count] = Top + 1 - Starts[Count]
202
+ Target.Count = Count
203
+ end
204
+
205
+ return nil
206
+ end
207
+
208
+ function Wire.Release(Target: Batch)
209
+ table.clear(Target.Values)
210
+ table.clear(Target.Definitions)
211
+ Target.Count = 0
212
+ end
213
+
214
+ function Wire.Unpack(Values: Schema.Arguments): ...any
215
+ return table.unpack(Values, 1, Values.n)
216
+ end
217
+
218
+ return Wire