passforios/pass/Models/QRKeyScanner.swift

74 lines
2.1 KiB
Swift
Raw Normal View History

//
// QRKeyScanner.swift
// pass
//
// Created by Danny Moesch on 19.08.20.
// Copyright © 2020 Bob Sun. All rights reserved.
//
struct QRKeyScanner {
enum Result: Equatable {
case lookingForStart
case wrongKeyType(ScannableKeyType)
case completed
case scanned(Int)
var message: String {
switch self {
case .lookingForStart:
return "LookingForStartingFrame.".localize()
case let .wrongKeyType(keyType):
return "Scan\(keyType.visibility)Key.".localize()
case .completed:
return "Done".localize()
case let .scanned(count):
return "ScannedQrCodes(%d)".localize(count)
}
}
var unrolled: (accepted: Bool, message: String) {
if self == .completed {
return (true, message)
}
return (false, message)
}
}
private var segments = [String]()
private var previousResult = Result.lookingForStart
let keyType: ScannableKeyType
init(keyType: ScannableKeyType) {
self.keyType = keyType
}
var scannedKey: String {
segments.joined()
}
mutating func add(segment: String) -> Result {
// Skip duplicated segments.
guard segment != segments.last else {
return previousResult
}
// Check whether we have found the first block.
guard !segments.isEmpty || segment.contains(keyType.headerStart) else {
// Check whether we are scanning the wrong key type.
if let counterKeyType = keyType.counterType, segment.contains(counterKeyType.headerStart) {
previousResult = .wrongKeyType(counterKeyType)
}
return previousResult
}
// Update the list of scanned segments and return.
segments.append(segment)
if scannedKey.contains(keyType.footerStart), scannedKey.trimmed.hasSuffix(keyType.footerEnd) {
return .completed
}
previousResult = .scanned(segments.count)
return previousResult
}
}