Skip to content

Commit 07db273

Browse files
committed
Parse bool directly
This gives a 6x speedup parsing "repeated bool" fields in text format, bringing text performance here in line with JSON performance.
1 parent 9501879 commit 07db273

File tree

1 file changed

+42
-6
lines changed

1 file changed

+42
-6
lines changed

Sources/SwiftProtobuf/TextFormatScanner.swift

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,10 @@ private let asciiUpperE = UInt8(ascii: "E")
5454
private let asciiLowerF = UInt8(ascii: "f")
5555
private let asciiUpperF = UInt8(ascii: "F")
5656
private let asciiLowerI = UInt8(ascii: "i")
57+
private let asciiLowerL = UInt8(ascii: "l")
5758
private let asciiLowerN = UInt8(ascii: "n")
5859
private let asciiLowerR = UInt8(ascii: "r")
60+
private let asciiLowerS = UInt8(ascii: "s")
5961
private let asciiLowerT = UInt8(ascii: "t")
6062
private let asciiUpperT = UInt8(ascii: "T")
6163
private let asciiLowerU = UInt8(ascii: "u")
@@ -720,6 +722,28 @@ internal struct TextFormatScanner {
720722
return d
721723
}
722724

725+
private mutating func skipOptionalKeywordCaseSensitive(bytes: [UInt8]) -> Bool {
726+
let start = p
727+
for b in bytes {
728+
if p == end || p[0] != b{
729+
p = start
730+
return false
731+
}
732+
p += 1
733+
}
734+
if p == end {
735+
return true
736+
}
737+
let c = p[0]
738+
if ((c >= asciiUpperA && c <= asciiUpperZ)
739+
|| (c >= asciiLowerA && c <= asciiLowerZ)) {
740+
p = start
741+
return false
742+
}
743+
skipWhitespace()
744+
return true
745+
}
746+
723747
private mutating func skipOptionalKeyword(bytes: [UInt8]) -> Bool {
724748
let start = p
725749
for b in bytes {
@@ -817,15 +841,27 @@ internal struct TextFormatScanner {
817841
throw TextFormatDecodingError.malformedText
818842
}
819843
let c = p[0]
844+
p += 1
820845
switch c {
821-
case asciiZero, asciiOne, asciiLowerF, asciiUpperF, asciiLowerT, asciiUpperT:
822-
switch parseIdentifier() {
823-
case "0", "f", "false", "False":
846+
case asciiZero:
847+
return false
848+
case asciiOne:
849+
return true
850+
case asciiLowerF, asciiUpperF:
851+
let alse = [asciiLowerA, asciiLowerL, asciiLowerS, asciiLowerE]
852+
if p == end
853+
|| skipOptionalKeywordCaseSensitive(bytes: alse)
854+
|| ((p[0] < asciiUpperA || p[0] > asciiUpperZ)
855+
&& (p[0] < asciiLowerA || p[0] > asciiLowerZ)) {
824856
return false
825-
case "1", "t", "true", "True":
857+
}
858+
case asciiLowerT, asciiUpperT:
859+
let rue = [asciiLowerR, asciiLowerU, asciiLowerE]
860+
if p == end
861+
|| skipOptionalKeywordCaseSensitive(bytes: rue)
862+
|| ((p[0] < asciiUpperA || p[0] > asciiUpperZ)
863+
&& (p[0] < asciiLowerA || p[0] > asciiLowerZ)) {
826864
return true
827-
default:
828-
break
829865
}
830866
default:
831867
break

0 commit comments

Comments
 (0)