Skip to content

Commit 8b656ad

Browse files
committed
Add documentation, and @inlinable / @usableFromInline.
1 parent 91f4958 commit 8b656ad

File tree

9 files changed

+150
-30
lines changed

9 files changed

+150
-30
lines changed

Sources/Patterns/Decoder.swift

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,36 @@
66
//
77

88
extension Parser where Input == String {
9+
/// Decodes all matches found in `string` into an array of `T`.
10+
@inlinable
911
public func decode<T>(_ type: [T].Type, from string: String) throws -> [T] where T: Decodable {
1012
try matches(in: string).map { try $0.decode(type.Element.self, from: string) }
1113
}
1214

15+
/// Decodes the first match found in `string` into a value of type `type`.
16+
@inlinable
1317
public func decodeFirst<T>(_ type: T.Type, from string: String) throws -> T? where T: Decodable {
1418
try match(in: string, at: string.startIndex).map { try $0.decode(type.self, from: string) }
1519
}
1620
}
1721

1822
extension Parser.Match where Input == String {
23+
/// Decodes this match found in `string` into a value of type `type`.
24+
@inlinable
1925
public func decode<T>(_ type: T.Type, from string: String) throws -> T where T: Decodable {
20-
return try type.init(from: MatchDecoder(match: self, string: string))
26+
try type.init(from: MatchDecoder(match: self, string: string))
2127
}
2228

2329
public struct MatchDecoder: Decoder {
30+
@usableFromInline
2431
let match: Parser.Match
32+
@usableFromInline
2533
let string: String
2634

2735
public let codingPath: [CodingKey]
2836
public var userInfo: [CodingUserInfoKey: Any] { [:] }
2937

38+
@inlinable
3039
init(match: Parser.Match, string: String, codingPath: [CodingKey] = []) {
3140
let namePrefix = codingPath.first.map { $0.stringValue }
3241
let captures = namePrefix.map { namePrefix in
@@ -40,52 +49,77 @@ extension Parser.Match where Input == String {
4049
self.codingPath = codingPath
4150
}
4251

52+
@inlinable
4353
public func container<Key>(keyedBy _: Key.Type) throws -> KeyedDecodingContainer<Key> where Key: CodingKey {
44-
return KeyedDecodingContainer(KDC(codingPath: codingPath, matchDecoder: self))
54+
KeyedDecodingContainer(KDC(codingPath: codingPath, matchDecoder: self))
4555
}
4656

57+
@inlinable
4758
public func unkeyedContainer() throws -> UnkeyedDecodingContainer {
4859
UDC(codingPath: codingPath, values: match.captures.map { $0.range }, string: string)
4960
}
5061

62+
@inlinable
5163
public func singleValueContainer() throws -> SingleValueDecodingContainer {
5264
guard match.captures.count < 2 else {
65+
let property = codingPath.map { "\($0.stringValue)" }.joined(separator: ".")
5366
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath, debugDescription:
54-
"Property '\(codingPath.map { "\($0.stringValue)" }.joined(separator: "."))' needs a single value, but multiple captures exists."))
67+
"Property '\(property)' needs a single value, but multiple captures exists."))
5568
}
5669
let range = match.captures.first?.range ?? match.endIndex ..< match.endIndex
5770
return StringDecoder(string: String(string[range]), codingPath: codingPath)
5871
}
5972

73+
@usableFromInline
6074
struct UDC: UnkeyedDecodingContainer {
75+
@usableFromInline
6176
var codingPath: [CodingKey]
77+
@usableFromInline
6278
let values: [Range<Pattern.Input.Index>]
79+
@usableFromInline
6380
let string: String
6481

82+
@usableFromInline
83+
init(codingPath: [CodingKey], values: [Range<Pattern.Input.Index>], string: String) {
84+
self.codingPath = codingPath
85+
self.values = values
86+
self.string = string
87+
}
88+
89+
@usableFromInline
6590
var count: Int? { values.count }
91+
@usableFromInline
6692
var isAtEnd: Bool { currentIndex >= values.endIndex }
93+
@usableFromInline
6794
var currentIndex: Int = 0
6895

96+
@usableFromInline
6997
mutating func decodeNil() throws -> Bool { false }
7098

71-
mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> where NestedKey: CodingKey {
99+
@usableFromInline
100+
mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type)
101+
throws -> KeyedDecodingContainer<NestedKey> where NestedKey: CodingKey {
72102
fatalError("Not implemented yet. If you want to help with that, go to https://github.com/kareman/Patterns")
73103
}
74104

105+
@usableFromInline
75106
mutating func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
76107
fatalError("Not implemented yet. If you want to help with that, go to https://github.com/kareman/Patterns")
77108
}
78109

110+
@usableFromInline
79111
mutating func superDecoder() throws -> Decoder {
80112
fatalError("Not implemented yet. If you want to help with that, go to https://github.com/kareman/Patterns")
81113
}
82114

115+
@usableFromInline
83116
mutating func decode<T>(_ type: T.Type) throws -> T where T: Decodable {
84117
defer { currentIndex += 1 }
85118
let text = String(string[values[currentIndex]])
86119
return try type.init(from: StringDecoder(string: text, codingPath: codingPath))
87120
}
88121

122+
@usableFromInline
89123
mutating func decode<T>(_ type: T.Type) throws -> T where T: Decodable & LosslessStringConvertible {
90124
guard let value = type.init(String(string[values[currentIndex]])) else {
91125
throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath, debugDescription: ""))
@@ -95,82 +129,118 @@ extension Parser.Match where Input == String {
95129
}
96130
}
97131

132+
@usableFromInline
98133
struct KDC<Key: CodingKey>: KeyedDecodingContainerProtocol {
134+
@usableFromInline
99135
var codingPath: [CodingKey] = []
136+
@usableFromInline
100137
var allKeys: [Key] {
101138
matchDecoder.match.names.compactMap(Key.init(stringValue:))
102139
}
103140

141+
@usableFromInline
104142
let matchDecoder: MatchDecoder
105143

144+
@usableFromInline
145+
init(codingPath: [CodingKey] = [], matchDecoder: MatchDecoder) {
146+
self.codingPath = codingPath
147+
self.matchDecoder = matchDecoder
148+
}
149+
150+
@usableFromInline
106151
func capture(for key: CodingKey) throws -> String {
107152
guard let range = matchDecoder.match[one: key.stringValue] else {
108153
throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: codingPath, debugDescription: ""))
109154
}
110155
return String(matchDecoder.string[range])
111156
}
112157

158+
@usableFromInline
113159
func contains(_ key: Key) -> Bool {
114160
matchDecoder.match[one: key.stringValue] == nil
115161
}
116162

163+
@usableFromInline
117164
func decodeNil(forKey key: Key) throws -> Bool {
118165
contains(key)
119166
}
120167

168+
@usableFromInline
121169
func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T: Decodable {
122-
return try type.init(from: MatchDecoder(match: matchDecoder.match, string: matchDecoder.string, codingPath: codingPath + [key]))
170+
return try type.init(from:
171+
MatchDecoder(match: matchDecoder.match, string: matchDecoder.string, codingPath: codingPath + [key]))
123172
}
124173

174+
@usableFromInline
125175
func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T: Decodable & LosslessStringConvertible {
126176
guard let value = type.init(try capture(for: key)) else {
127177
throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: [key], debugDescription: ""))
128178
}
129179
return value
130180
}
131181

132-
func nestedContainer<NestedKey>(keyedBy _: NestedKey.Type, forKey _: Key) throws -> KeyedDecodingContainer<NestedKey> where NestedKey: CodingKey {
182+
@usableFromInline
183+
func nestedContainer<NestedKey>(keyedBy _: NestedKey.Type, forKey _: Key)
184+
throws -> KeyedDecodingContainer<NestedKey> where NestedKey: CodingKey {
133185
fatalError("Not implemented yet. If you want to help with that, go to https://github.com/kareman/Patterns")
134186
}
135187

188+
@usableFromInline
136189
func nestedUnkeyedContainer(forKey _: Key) throws -> UnkeyedDecodingContainer {
137190
fatalError("Not implemented yet. If you want to help with that, go to https://github.com/kareman/Patterns")
138191
}
139192

193+
@usableFromInline
140194
func superDecoder() throws -> Decoder {
141195
fatalError("Not implemented yet. If you want to help with that, go to https://github.com/kareman/Patterns")
142196
}
143197

198+
@usableFromInline
144199
func superDecoder(forKey _: Key) throws -> Decoder {
145200
fatalError("Not implemented yet. If you want to help with that, go to https://github.com/kareman/Patterns")
146201
}
147202
}
148203
}
149204
}
150205

206+
@usableFromInline
151207
struct StringDecoder: Decoder, SingleValueDecodingContainer {
208+
@usableFromInline
152209
let string: String
210+
@usableFromInline
153211
let codingPath: [CodingKey]
212+
@usableFromInline
154213
var userInfo: [CodingUserInfoKey: Any] = [:]
155214

215+
@usableFromInline
216+
init(string: String, codingPath: [CodingKey], userInfo: [CodingUserInfoKey: Any] = [:]) {
217+
self.string = string
218+
self.codingPath = codingPath
219+
self.userInfo = userInfo
220+
}
221+
222+
@usableFromInline
156223
func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key: CodingKey {
157224
fatalError("Not implemented yet. If you want to help with that, go to https://github.com/kareman/Patterns")
158225
}
159226

227+
@usableFromInline
160228
func unkeyedContainer() throws -> UnkeyedDecodingContainer {
161229
fatalError("Not implemented yet. If you want to help with that, go to https://github.com/kareman/Patterns")
162230
}
163231

164-
func singleValueContainer() throws -> SingleValueDecodingContainer {
165-
self
166-
}
232+
@usableFromInline
233+
func singleValueContainer() throws -> SingleValueDecodingContainer { self }
167234

235+
@usableFromInline
168236
func decodeNil() -> Bool { false }
169237

238+
@usableFromInline
170239
func decode<T>(_ type: T.Type) throws -> T where T: Decodable {
171240
fatalError("Not implemented yet. If you want to help with that, go to https://github.com/kareman/Patterns")
172241
}
173242

243+
@usableFromInline
174244
func decode<T>(_ type: T.Type) throws -> T where T: Decodable & LosslessStringConvertible {
175245
guard let value = type.init(string) else {
176246
throw DecodingError.typeMismatch(type, DecodingError.Context(codingPath: codingPath, debugDescription: ""))

Sources/Patterns/General/General.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ extension Sequence {
108108
}
109109

110110
/// Used like e.g. `let a = optional ?? fatalError("Message")`.
111+
@inlinable
111112
func ?? <T>(b: T?, a: @autoclosure () -> Never) -> T {
112113
if let b = b {
113114
return b
@@ -116,6 +117,7 @@ func ?? <T>(b: T?, a: @autoclosure () -> Never) -> T {
116117
}
117118

118119
/// Used like e.g. `let a = try optional ?? AnError()`.
120+
@inlinable
119121
func ?? <T, E: Error>(b: T?, a: @autoclosure () -> (E)) throws -> T {
120122
if let b = b {
121123
return b

Sources/Patterns/Operations on Patterns/Concatenation.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,46 @@ precedencegroup PatternConcatenationPrecedence {
1212

1313
infix operator : PatternConcatenationPrecedence
1414

15+
/// A pattern which first tries the `first` pattern,
16+
/// if that succeeds it continues with the `second` pattern.
1517
public struct Concat<First: Pattern, Second: Pattern>: Pattern {
1618
public let first: First
1719
public let second: Second
1820
public var description: String { "\(first) \(second)" }
1921

22+
@inlinable
2023
init(_ first: First, _ second: Second) {
2124
self.first = first
2225
self.second = second
2326
}
24-
}
2527

26-
extension Concat {
28+
@inlinable
2729
public func createInstructions(_ instructions: inout Instructions) throws {
2830
try first.createInstructions(&instructions)
2931
try second.createInstructions(&instructions)
3032
}
3133
}
3234

35+
/// First tries the pattern to the left, if that succeeds it tries the pattern to the right.
36+
@inlinable
3337
public func <Left, Right>(lhs: Left, rhs: Right) -> Concat<Left, Right> {
3438
Concat(lhs, rhs)
3539
}
3640

41+
/// First tries the pattern to the left, if that succeeds it tries the pattern to the right.
42+
@inlinable
3743
public func <Right>(lhs: Literal, rhs: Right) -> Concat<Literal, Right> {
3844
Concat(lhs, rhs)
3945
}
4046

47+
/// First tries the pattern to the left, if that succeeds it tries the pattern to the right.
48+
@inlinable
4149
public func <Left>(lhs: Left, rhs: Literal) -> Concat<Left, Literal> {
4250
Concat(lhs, rhs)
4351
}
4452

53+
/// First tries the pattern to the left, if that succeeds it tries the pattern to the right.
54+
@inlinable
4555
public func (lhs: Literal, rhs: Literal) -> Concat<Literal, Literal> {
4656
Concat(lhs, rhs)
4757
}

Sources/Patterns/Operations on Patterns/Not.swift

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,18 @@
55
// Created by Kåre Morstøl on 25/05/2020.
66
//
77

8+
/// A pattern which only succeeds if the `wrapped` pattern fails.
9+
/// The next pattern will continue from where `wrapped` started.
810
public struct NotPattern<Wrapped: Pattern>: Pattern {
911
public let wrapped: Wrapped
1012
public var description: String { "!\(wrapped)" }
1113

14+
@inlinable
15+
init(_ wrapped: Wrapped) {
16+
self.wrapped = wrapped
17+
}
18+
19+
@inlinable
1220
public func createInstructions(_ instructions: inout Instructions) throws {
1321
let wrappedInstructions = try wrapped.createInstructions()
1422
instructions.append(.choice(offset: wrappedInstructions.count + 3))
@@ -18,14 +26,14 @@ public struct NotPattern<Wrapped: Pattern>: Pattern {
1826
}
1927
}
2028

21-
extension Pattern {
22-
public var not: NotPattern<Self> { NotPattern(wrapped: self) }
23-
24-
public static prefix func ! (me: Self) -> NotPattern<Self> {
25-
me.not
26-
}
29+
/// Will only succeed if the following pattern fails. Does not consume any input.
30+
@inlinable
31+
public prefix func ! <P: Pattern>(pattern: P) -> NotPattern<P> {
32+
NotPattern(pattern)
2733
}
2834

29-
public prefix func ! (me: Literal) -> NotPattern<Literal> {
30-
me.not
35+
/// Will only succeed if the following pattern fails. Does not consume any input.
36+
@inlinable
37+
public prefix func ! (pattern: Literal) -> NotPattern<Literal> {
38+
NotPattern(pattern)
3139
}

0 commit comments

Comments
 (0)