Skip to content

Commit 6476674

Browse files
committed
Merge branch 'develop' into main
2 parents 580f94c + 36df02b commit 6476674

File tree

15 files changed

+511
-56
lines changed

15 files changed

+511
-56
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ http
4848
.listen(1337)
4949
```
5050

51+
Macro also provides additional Node-like modules, such as:
52+
- `fs`
53+
- `path`
54+
- `jsonfile`
55+
- `JSON`
56+
- `basicAuth`
57+
- `querystring`
58+
5159

5260
## Environment Variables
5361

Sources/Macro/Macro.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ public typealias jsonfile = JSONFileModule
3535

3636
// MARK: - Submodules in `http` Target
3737

38+
@_exported import class http.IncomingMessage
39+
@_exported import class http.ServerResponse
3840
import enum http.HTTPModule
3941
import enum http.BasicAuthModule
4042
import enum http.QueryStringModule

Sources/MacroCore/EnvironmentValues.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ public extension EnvironmentValues {
111111

112112
static let empty = EnvironmentValues()
113113

114+
@inlinable
115+
var isEmpty : Bool { return values.isEmpty }
116+
@inlinable
117+
var count : Int { return values.count }
118+
114119
@inlinable
115120
subscript<K: EnvironmentKey>(key: K.Type) -> K.Value {
116121
set {

Sources/MacroCore/Streams/Concat.swift

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ public func concat(maximumSize: Int = _defaultConcatMaximumSize,
6161
* Create those objects using the `concat` function.
6262
*/
6363
public class ConcatByteStream: WritableByteStream,
64-
WritableByteStreamType, WritableStreamType
64+
WritableByteStreamType, WritableStreamType,
65+
CustomStringConvertible
6566
{
6667
// TBD: This should be duplex? Or is the duplex a "compacting stream"?
6768

@@ -118,6 +119,31 @@ public class ConcatByteStream: WritableByteStream,
118119
finishListeners.removeAll()
119120
errorListeners .removeAll()
120121
}
122+
123+
124+
// MARK: - CustomStringConvertible
125+
126+
open var description: String {
127+
var ms = "<Concat[\(ObjectIdentifier(self))]:"
128+
defer { ms += ">" }
129+
130+
let count = writableBuffer.count
131+
if writableCorked {
132+
if count > 0 {
133+
ms += " corked=#\(count)"
134+
}
135+
else {
136+
ms += " corked(empty)"
137+
}
138+
}
139+
else {
140+
ms += " buffered=#\(count)"
141+
}
142+
143+
if writableEnded { ms += " ended" }
144+
145+
return ms
146+
}
121147
}
122148

123149
public enum ConcatError: Swift.Error {

Sources/fs/File.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public func readFile(on eventLoop : EventLoop? = nil,
2323
yield : @escaping ( Error?, Buffer? ) -> Void)
2424
{
2525
let module = MacroCore.shared.retain()
26+
let loop = module.fallbackEventLoop(eventLoop)
2627

2728
FileSystemModule.threadPool.submit { shouldRun in
2829
let result : Result<Buffer, Error>
@@ -40,7 +41,7 @@ public func readFile(on eventLoop : EventLoop? = nil,
4041
result = .failure(ChannelError.ioOnClosedChannel)
4142
}
4243

43-
module.fallbackEventLoop(eventLoop).execute {
44+
loop.execute {
4445
yield(result.jsError, result.jsValue)
4546
module.release()
4647
}
@@ -53,7 +54,8 @@ public func readFile(on eventLoop : EventLoop? = nil,
5354
yield : @escaping ( Error?, String? ) -> Void)
5455
{
5556
let module = MacroCore.shared.retain()
56-
57+
let loop = module.fallbackEventLoop(eventLoop)
58+
5759
FileSystemModule.threadPool.submit { shouldRun in
5860
let result : Result<String, Error>
5961

@@ -73,7 +75,7 @@ public func readFile(on eventLoop : EventLoop? = nil,
7375
result = .failure(ChannelError.ioOnClosedChannel)
7476
}
7577

76-
module.fallbackEventLoop(eventLoop).execute {
78+
loop.execute {
7779
yield(result.jsError, result.jsValue)
7880
module.release()
7981
}
@@ -101,7 +103,8 @@ public func writeFile(on eventLoop : EventLoop? = nil,
101103
whenDone: @escaping ( Error? ) -> Void)
102104
{
103105
let module = MacroCore.shared.retain()
104-
106+
let loop = module.fallbackEventLoop(eventLoop)
107+
105108
FileSystemModule.threadPool.submit { shouldRun in
106109
let yieldError : Swift.Error?
107110

@@ -118,7 +121,7 @@ public func writeFile(on eventLoop : EventLoop? = nil,
118121
yieldError = ChannelError.ioOnClosedChannel
119122
}
120123

121-
module.fallbackEventLoop(eventLoop).execute {
124+
loop.execute {
122125
whenDone(yieldError)
123126
module.release()
124127
}

Sources/fs/JSONFile.swift

Lines changed: 144 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,44 @@ public extension JSONFileModule {
2626
// Note: Why not use fs.readFile etc? Because we want to serialize/deserialize
2727
// on the background thread.
2828

29+
/**
30+
* Reads a file as JSON.
31+
*
32+
* This uses Foundation `JSONSerialization`, the returned objects are the
33+
* respective Swift objects wrapped in `Any`.
34+
*
35+
* The JSON parsing happens on the I/O thread (`fs.threadPool`).
36+
*
37+
* Example:
38+
*
39+
* jsonfile.readFile("/tmp/myfile.json) { error, value in
40+
* if let error = error {
41+
* console.error("loading failed:", error)
42+
* }
43+
* else {
44+
* print("Loaded JSON:", value)
45+
* }
46+
* }
47+
*
48+
* - Parameters:
49+
* - eventLoop: The NIO EventLoop to call the callback on. Defaults to the
50+
* current EventLoop, if available.
51+
* - path: The path of the file to read from.
52+
* - options: The `JSONSerialization.ReadingOptions`, defaults to none
53+
* - yield: Callback which is called when the reading and decoding
54+
* succeeded or failed. The first argument is the Error if one
55+
* occurred, the second argument the JSON objects read (or the
56+
* error).
57+
*/
2958
static func readFile(on eventLoop : EventLoop? = nil,
3059
_ path : String,
3160
options : JSONSerialization.ReadingOptions = [],
3261
yield : @escaping ( Swift.Error?, Any ) -> Void)
3362
-> Void
3463
{
3564
let module = MacroCore.shared.retain()
36-
65+
let loop = module.fallbackEventLoop(eventLoop)
66+
3767
FileSystemModule.threadPool.submit { shouldRun in
3868
let result : Any
3969
let resultError : Swift.Error?
@@ -56,12 +86,40 @@ public extension JSONFileModule {
5686
resultError = ChannelError.ioOnClosedChannel
5787
}
5888

59-
module.fallbackEventLoop(eventLoop).execute {
89+
loop.execute {
6090
yield(resultError, result)
6191
module.release()
6292
}
6393
}
6494
}
95+
96+
/**
97+
* Writes JSON objects to a file.
98+
*
99+
* This uses Foundation `JSONSerialization`, the expected objects are the
100+
* respective Swift objects wrapped in `Any`.
101+
* There is also a `Codable` version of `writeFile`.
102+
*
103+
* The JSON generation happens on the I/O thread (`fs.threadPool`).
104+
*
105+
* Example:
106+
*
107+
* try jsonfile.writeFile("/tmp/myfile.json", [ "key": "value" ]) { err in
108+
* if let err = err {
109+
* print("Writing failed:", err)
110+
* }
111+
* }
112+
*
113+
* - Parameters:
114+
* - eventLoop: The NIO EventLoop to call the callback on. Defaults to the
115+
* current EventLoop, if available.
116+
* - path: The path of the file to write to.
117+
* - json: The JSON objects representing the structure to write.
118+
* - options: The `JSONSerialization.WritingOptions`, defaults to none
119+
* - yield: Callback which is called when the encoding and writing
120+
* succeeded or failed. The first argument carries the Error
121+
* if one occurred, or nil.
122+
*/
65123
static func writeFile(on eventLoop : EventLoop? = nil,
66124
_ path : String,
67125
_ json : Any,
@@ -70,6 +128,7 @@ public extension JSONFileModule {
70128
-> Void
71129
{
72130
let module = MacroCore.shared.retain()
131+
let loop = module.fallbackEventLoop(eventLoop)
73132

74133
FileSystemModule.threadPool.submit { shouldRun in
75134
let resultError : Swift.Error?
@@ -89,12 +148,39 @@ public extension JSONFileModule {
89148
resultError = ChannelError.ioOnClosedChannel
90149
}
91150

92-
module.fallbackEventLoop(eventLoop).execute {
151+
loop.execute {
93152
yield(resultError)
94153
module.release()
95154
}
96155
}
97156
}
157+
158+
/**
159+
* Writes JSON objects to a file.
160+
*
161+
* This uses Foundation `JSONEncoder`, the expected objects are Swift values
162+
* conforming to the Swift `Encodable` protocol.
163+
*
164+
* The JSON generation happens on the I/O thread (`fs.threadPool`).
165+
*
166+
* Example:
167+
*
168+
* try jsonfile.writeFile("/tmp/myfile.json", [ "key": "value" ]) { err in
169+
* if let err = err {
170+
* print("Writing failed:", err)
171+
* }
172+
* }
173+
*
174+
* - Parameters:
175+
* - eventLoop: The NIO EventLoop to call the callback on. Defaults to the
176+
* current EventLoop, if available.
177+
* - path: The path of the file to write to.
178+
* - json: The `Encodable` JSON objects to write.
179+
* - options: The `JSONSerialization.WritingOptions`, defaults to none
180+
* - yield: Callback which is called when the encoding and writing
181+
* succeeded or failed. The first argument carries the Error
182+
* if one occurred, or nil.
183+
*/
98184
static func writeFile<T>(on eventLoop : EventLoop? = nil,
99185
_ path : String,
100186
_ json : T,
@@ -104,6 +190,7 @@ public extension JSONFileModule {
104190
where T: Encodable
105191
{
106192
let module = MacroCore.shared.retain()
193+
let loop = module.fallbackEventLoop(eventLoop)
107194

108195
FileSystemModule.threadPool.submit { shouldRun in
109196
let resultError : Swift.Error?
@@ -122,13 +209,29 @@ public extension JSONFileModule {
122209
resultError = ChannelError.ioOnClosedChannel
123210
}
124211

125-
module.fallbackEventLoop(eventLoop).execute {
212+
loop.execute {
126213
yield(resultError)
127214
module.release()
128215
}
129216
}
130217
}
131218

219+
/**
220+
* Reads a file as JSON.
221+
*
222+
* This uses Foundation `JSONSerialization`, the returned objects are the
223+
* respective Swift objects wrapped in `Any`.
224+
*
225+
* Example:
226+
*
227+
* let json = try jsonfile.readFileSync("/tmp/myfile.json)
228+
* print("Loaded JSON:", json)
229+
*
230+
* - Parameters:
231+
* - path: The path of the file to read from.
232+
* - options: The `JSONSerialization.ReadingOptions`, defaults to none
233+
*/
234+
@inlinable
132235
static func readFileSync(_ path : String,
133236
options : JSONSerialization.ReadingOptions = [])
134237
throws -> Any
@@ -138,6 +241,23 @@ public extension JSONFileModule {
138241
return json
139242
}
140243

244+
/**
245+
* Writes JSON objects to a file.
246+
*
247+
* This uses Foundation `JSONSerialization`, the expected objects are the
248+
* respective Swift objects wrapped in `Any`.
249+
* There is also a `Codable` version of `writeFile`.
250+
*
251+
* Example:
252+
*
253+
* try jsonfile.writeFileSync("/tmp/myfile.json", [ "key": "value" ]
254+
*
255+
* - Parameters:
256+
* - path: The path of the file to write to.
257+
* - json: The JSON objects representing the structure to write.
258+
* - options: The `JSONSerialization.WritingOptions`, defaults to none
259+
*/
260+
@inlinable
141261
static func writeFileSync(_ path : String,
142262
_ json : Any,
143263
options : JSONSerialization.WritingOptions = [])
@@ -148,6 +268,26 @@ public extension JSONFileModule {
148268
try data.write(to: URL(fileURLWithPath: path), options: [.atomic])
149269
}
150270

271+
/**
272+
* Writes JSON objects to a file.
273+
*
274+
* This uses Foundation `JSONEncoder`, the expected objects are Swift values
275+
* conforming to the Swift `Encodable` protocol.
276+
*
277+
* Example:
278+
*
279+
* try jsonfile.writeFile("/tmp/myfile.json", [ "key": "value" ]) { err in
280+
* if let err = err {
281+
* print("Writing failed:", err)
282+
* }
283+
* }
284+
*
285+
* - Parameters:
286+
* - path: The path of the file to write to.
287+
* - json: The `Encodable` JSON objects to write.
288+
* - options: The `JSONSerialization.WritingOptions`, defaults to none
289+
*/
290+
@inlinable
151291
static func writeFileSync<T>(_ path : String,
152292
_ json : T,
153293
options : JSONSerialization.WritingOptions = [])

Sources/fs/Promise.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ public extension promise {
6060

6161
static func readFile(on eventLoop : EventLoop? = nil,
6262
_ path : String,
63-
_ encoding : String.Encoding) -> EventLoopFuture<String>
63+
_ encoding : String.Encoding)
64+
-> EventLoopFuture<String>
6465
{
6566
let module = MacroCore.shared.retain()
6667
let eventLoop = module.fallbackEventLoop(eventLoop)

0 commit comments

Comments
 (0)