The two monolithic XSD content/identity rules only satisfied the OpenAPIKit validation idiom at the wrong granularity: no per-constraint removability, no isolable failing/near-miss tests. Split them into 32 named rules, each finding tagged at its origin and cached per XSDContext so the walk still runs once per document (the #101 decision against duplicating XSD's recursive type resolution still holds). Wired the streaming path's ID/IDREF and identity checks through the same framework instead of calling the validators imperatively, and added the unwrapAndLookup combinator the rule already named as required. Also includes the mandated repo-wide swiftformat/swiftlint pass.
58 lines
2.6 KiB
Swift
58 lines
2.6 KiB
Swift
extension PureXML.Parsing.ByteDecoder {
|
|
/// The JIS X 0212 index, assembled from the vendored parts.
|
|
static let jis0212: [UInt16] = jis0212Part1 + jis0212Part2
|
|
|
|
/// The EUC-JP decoder (the WHATWG `EUC-JP` algorithm): ASCII directly, `0x8E`
|
|
/// then a byte for half-width katakana, `0x8F` then two bytes through JIS X
|
|
/// 0212, and any other lead byte then a byte through JIS X 0208.
|
|
enum EUCJP {
|
|
static func decode(_ bytes: ArraySlice<UInt8>) -> String {
|
|
var scalars = String.UnicodeScalarView()
|
|
var lead: UInt8 = 0
|
|
var useJis0212 = false
|
|
for byte in bytes {
|
|
if lead == 0x8E, (0xA1 ... 0xDF).contains(byte) {
|
|
lead = 0
|
|
scalars.append(Unicode.Scalar(0xFF61 + UInt32(byte) - 0xA1) ?? "\u{FFFD}")
|
|
} else if lead == 0x8F, (0xA1 ... 0xFE).contains(byte) {
|
|
useJis0212 = true
|
|
lead = byte
|
|
} else if lead != 0 {
|
|
let saved = lead
|
|
lead = 0
|
|
let jis0212 = useJis0212
|
|
useJis0212 = false
|
|
if let scalar = twoByteScalar(lead: saved, trail: byte, useJis0212: jis0212) {
|
|
scalars.append(scalar)
|
|
} else {
|
|
scalars.append("\u{FFFD}")
|
|
if byte <= 0x7F {
|
|
scalars.append(Unicode.Scalar(byte))
|
|
}
|
|
}
|
|
} else if byte <= 0x7F {
|
|
scalars.append(Unicode.Scalar(byte))
|
|
} else if byte == 0x8E || byte == 0x8F || (0xA1 ... 0xFE).contains(byte) {
|
|
lead = byte
|
|
} else {
|
|
scalars.append("\u{FFFD}")
|
|
}
|
|
}
|
|
if lead != 0 {
|
|
scalars.append("\u{FFFD}")
|
|
}
|
|
return String(scalars)
|
|
}
|
|
|
|
/// The scalar for a `(lead, trail)` pair, resolved through JIS X 0212 when
|
|
/// `useJis0212`, otherwise JIS X 0208. Nil for an invalid or unmapped pair.
|
|
static func twoByteScalar(lead: UInt8, trail: UInt8, useJis0212: Bool) -> Unicode.Scalar? {
|
|
guard (0xA1 ... 0xFE).contains(lead), (0xA1 ... 0xFE).contains(trail) else { return nil }
|
|
let pointer = (Int(lead) - 0xA1) * 94 + Int(trail) - 0xA1
|
|
let table = useJis0212 ? jis0212 : jis0208
|
|
guard pointer >= 0, pointer < table.count, table[pointer] != 0xFFFF else { return nil }
|
|
return Unicode.Scalar(UInt32(table[pointer]))
|
|
}
|
|
}
|
|
}
|