mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-16 22:41:38 +00:00
* refactor(apps): reuse watch approval transport models * fix(ios): satisfy exact identifier lint
106 lines
3.3 KiB
Swift
106 lines
3.3 KiB
Swift
import Foundation
|
|
|
|
struct ExactOpaqueIdentifierKey: Hashable, Sendable {
|
|
let rawValue: String
|
|
private let bytes: [UInt8]
|
|
|
|
init(_ rawValue: String) {
|
|
self.rawValue = rawValue
|
|
self.bytes = Array(rawValue.utf8)
|
|
}
|
|
|
|
static func == (lhs: Self, rhs: Self) -> Bool {
|
|
lhs.bytes == rhs.bytes
|
|
}
|
|
|
|
func hash(into hasher: inout Hasher) {
|
|
hasher.combine(self.bytes)
|
|
}
|
|
|
|
var notificationComponent: String {
|
|
let hexDigits = Array("0123456789ABCDEF".utf8)
|
|
// Keep dots encoded so gateway and approval components cannot collapse into
|
|
// the same notification identifier when their separator moves.
|
|
let encoded = self.bytes.flatMap { byte -> [UInt8] in
|
|
switch byte {
|
|
case 0x30...0x39, 0x41...0x5A, 0x61...0x7A, 0x2D, 0x5F, 0x7E:
|
|
[byte]
|
|
default:
|
|
[0x25, hexDigits[Int(byte >> 4)], hexDigits[Int(byte & 0x0F)]]
|
|
}
|
|
}
|
|
return String(encoded.map { Character(UnicodeScalar($0)) })
|
|
}
|
|
}
|
|
|
|
enum ExactOpaqueIdentifier {
|
|
static func exact(_ value: String?) -> String? {
|
|
guard let value, !value.isEmpty else { return nil }
|
|
return value
|
|
}
|
|
|
|
static func key(_ value: String?) -> ExactOpaqueIdentifierKey? {
|
|
self.exact(value).map(ExactOpaqueIdentifierKey.init)
|
|
}
|
|
}
|
|
|
|
enum ExecApprovalIdentifier {
|
|
typealias Key = ExactOpaqueIdentifierKey
|
|
|
|
static func exact(_ value: String?) -> String? {
|
|
guard let value = ExactOpaqueIdentifier.exact(value), value != ".", value != ".." else {
|
|
return nil
|
|
}
|
|
return value
|
|
}
|
|
|
|
static func key(_ value: String?) -> Key? {
|
|
self.exact(value).map(Key.init)
|
|
}
|
|
|
|
static func matches(_ lhs: String, _ rhs: String) -> Bool {
|
|
guard let lhsKey = self.key(lhs), let rhsKey = self.key(rhs) else { return false }
|
|
return lhsKey == rhsKey
|
|
}
|
|
|
|
static func sortsBefore(_ lhs: String, _ rhs: String) -> Bool {
|
|
Array(lhs.utf8).lexicographicallyPrecedes(Array(rhs.utf8))
|
|
}
|
|
}
|
|
|
|
enum GatewayStableIdentifier {
|
|
typealias Key = ExactOpaqueIdentifierKey
|
|
|
|
static func exact(_ value: String?) -> String? {
|
|
ExactOpaqueIdentifier.exact(value)
|
|
}
|
|
|
|
static func key(_ value: String?) -> Key? {
|
|
ExactOpaqueIdentifier.key(value)
|
|
}
|
|
|
|
static func matches(_ lhs: String, _ rhs: String) -> Bool {
|
|
guard let lhsKey = self.key(lhs), let rhsKey = self.key(rhs) else { return false }
|
|
return lhsKey == rhsKey
|
|
}
|
|
|
|
static func matches(_ lhs: String?, _ rhs: String?) -> Bool {
|
|
guard let lhsKey = self.key(lhs), let rhsKey = self.key(rhs) else { return false }
|
|
return lhsKey == rhsKey
|
|
}
|
|
|
|
static func sortsBefore(_ lhs: String, _ rhs: String) -> Bool {
|
|
Array(lhs.utf8).lexicographicallyPrecedes(Array(rhs.utf8))
|
|
}
|
|
|
|
/// Storage attributes can apply Unicode equivalence. Encode the original UTF-8
|
|
/// bytes so canonically equivalent gateway owners remain separate persisted keys.
|
|
static func storageComponent(_ value: String) -> String? {
|
|
guard let value = self.exact(value) else { return nil }
|
|
return Data(value.utf8).base64EncodedString()
|
|
.replacingOccurrences(of: "+", with: "-")
|
|
.replacingOccurrences(of: "/", with: "_")
|
|
.replacingOccurrences(of: "=", with: "")
|
|
}
|
|
}
|