diff --git a/Sources/BridgeGeneratorTool/main.swift b/Sources/BridgeGeneratorTool/main.swift index f5a7ada..53854e9 100644 --- a/Sources/BridgeGeneratorTool/main.swift +++ b/Sources/BridgeGeneratorTool/main.swift @@ -367,6 +367,19 @@ let bridgeableTypeAllowlist: Set = [ "PropertyListDecoder", "FileManager", "ProcessInfo", + // File-IO doors. Each gets path/URL gating in `gates(...)` so a + // script can't open a file outside the sandbox via a class init + // (FileHandle(forReadingAtPath:), Bundle(path:), etc.). + "FileHandle", + "Bundle", + "InputStream", + "OutputStream", + "FileWrapper", + // Subprocess: denied entirely under a sandbox via `gates(...)`. + // `Foundation.Process` spawns a real OS subprocess that escapes + // every host gate; the bridge throws `ProcessSandboxDenied` when + // a sandbox is configured. + "Process", // OptionSet-style nested types under bridged classes "JSONEncoder.OutputFormatting", ] @@ -672,6 +685,55 @@ enum GateKind { case networkRequest } +/// Parameter labels that carry a `String`-typed filesystem path. +/// Receiver-driven rules consult this set as part of the per-arg scan +/// (in addition to the conventional first-arg-is-path heuristic for +/// FileManager). Membership here means "this label is a path; the +/// intent is fsRead by default unless the receiver/method overrides". +let pathStringLabelsRead: Set = [ + "atPath", "atFilePath", "fromFile", + "forReadingAtPath", + "contentsOfFile", "withContentsOfFile", "atFile", + // FileManager second-arg labels. `andPath` covers + // `contentsEqual(atPath:andPath:)`; without it the comparison's + // second path slipped past the gate. + "andPath", + // Bundle init / open-by-path doors. `path` is widespread in + // Foundation but only the I/O receivers in `gates(...)` reach + // this set, so keeping it here doesn't gate unrelated APIs. + "path", "filePath", "fileAtPath", +] +/// As above, but for write-shaped path labels. +let pathStringLabelsWrite: Set = [ + "toFile", "forWritingAtPath", "toFileAtPath", + // `forUpdating*` opens for read+write — be conservative and gate + // as a write so a sandbox that allows read but not write still + // denies the open. + "forUpdatingAtPath", + // FileManager second-arg labels for `copyItem(atPath:toPath:)`, + // `moveItem(atPath:toPath:)`, `linkItem(atPath:toPath:)`. The + // first arg is gated by the receiver-rule's positional fallback; + // the label scan picks up the second. + "toPath", "andDestinationPath", +] +/// Parameter labels that carry a `URL`-typed filesystem-or-network +/// resource. Combined with the receiver/method intent to pick the +/// gate kind. `at` and `to` map to the same intent as the method +/// itself (read for `String(contentsOf:)`, write for `Data.write(to:)`, +/// etc.). The catch-all set below leans read; write-shaped methods +/// should be looked up in the receiver-rule's `writeMethods`. +let urlLabelsRead: Set = [ + "at", "from", "url", "contentsOf", "forResource", + "withContentsOf", "fileURL", + // FileManager `setUbiquitous(_:itemAt:destinationURL:)` and + // similar "URL of the item being acted on" labels. + "itemAt", "ofItemAt", +] +let urlLabelsWrite: Set = [ + "to", "atURL", "toURL", "destinationURL", + "withDestinationURL", +] + /// One gate to inject: bind `args[index]` to a local name, then call /// the appropriate authorizer. The bound name replaces the inline /// `try unbox…` in the call expression so we don't double-unbox. @@ -697,134 +759,287 @@ struct GateDirective { /// method itself is read-only metadata (`fileExists`, `attributesOfItem`). /// Embedders that want cheaper introspection can grant a permissive /// sandbox; the policy stays simple. +/// +/// The receiver-driven rules also do a generalised per-parameter scan +/// across all positions: every `String`/`URL` arg whose label looks +/// path-bearing (`pathStringLabelsRead/Write`, `urlLabelsRead/Write`) +/// gets a gate at its position, not just position 0. That closes the +/// holes around methods like `FileManager.setUbiquitous(_:itemAt: +/// destinationURL:)` (where the URL args sit at indices 1+2) and +/// `createSymbolicLink(at:withDestinationURL:)` (both URLs are +/// writes). The receiver-rule supplies a *default intent*; the label +/// scan upgrades it to a more specific intent when the label says so. +/// +/// The argLabels parameter carries the per-position call-site labels +/// (extracted from `sym.names.title`) used by the label scan. Receivers +/// without a known I/O personality return `[]` regardless of labels — +/// labels alone don't unlock gating, the receiver has to opt in. func gates( forReceiver receiverTypeName: String?, methodName: String?, initFor: String? = nil, + argLabels: [String] = [], signature sig: ResolvedSignature ) -> [GateDirective] { - // Identify which arg(s) carry path-or-URL data. Most FileManager / - // URL-init signatures put the path/URL first; a few methods - // (`copyItem`, `moveItem`, `linkItem`) pass two paths. var directives: [GateDirective] = [] - - func appendIfPathish( + var gatedIndices: Set = [] + + /// Gate a `String`/`URL` parameter by absolute position. Skips + /// non-path-shaped args silently so callers can fire-and-forget + /// across an unknown signature. `replace` lets a later, more + /// specific call upgrade the intent (e.g. label scan finding a + /// `to:` write where the receiver default was read). + func gatePathish( _ paramIndex: Int, - kind: GateKind + kind: GateKind, + replace: Bool = false ) { guard paramIndex < sig.parameters.count else { return } let p = sig.parameters[paramIndex] let spelling = p.type.swiftSpelling - // Only path-shaped args: `String` and `URL`. Bool / Int / etc. - // are introspection params — the gate doesn't apply. guard spelling == "String" || spelling == "URL" else { return } + if gatedIndices.contains(paramIndex) { + if replace, let i = directives.firstIndex(where: { $0.argIndex == paramIndex }) { + directives[i] = GateDirective( + argIndex: paramIndex, + argSwiftType: spelling, + boundName: "arg\(paramIndex)", + kind: kind) + } + return + } directives.append(GateDirective( argIndex: paramIndex, argSwiftType: spelling, boundName: "arg\(paramIndex)", kind: kind)) + gatedIndices.insert(paramIndex) } - /// Like `appendIfPathish` but for `URLRequest`-typed args: gate - /// via the request's embedded URL + method. Used for the - /// URLSession overloads that take a `URLRequest` instead of a - /// bare `URL` (`data(for:)`, `upload(for:fromFile:)`, - /// `download(for:)`, etc.) so the network policy fires the same - /// way it does for the URL-arg variants. - func appendIfURLRequestish(_ paramIndex: Int) { + /// `URLRequest`-typed args route to the `.networkRequest` gate + /// (URL + method extracted from the request struct). Used for + /// the URLSession overloads that take a `URLRequest` + /// (`data(for:)`, `upload(for:fromFile:)`, `download(for:)`, …) + /// so the network policy fires the same as the bare-URL + /// overloads. + func gateURLRequest(_ paramIndex: Int) { guard paramIndex < sig.parameters.count else { return } let p = sig.parameters[paramIndex] guard p.type.swiftSpelling == "URLRequest" else { return } + if gatedIndices.contains(paramIndex) { return } directives.append(GateDirective( argIndex: paramIndex, argSwiftType: "URLRequest", boundName: "arg\(paramIndex)", kind: .networkRequest)) + gatedIndices.insert(paramIndex) + } + + /// Walk every parameter and gate any `String`/`URL` arg whose + /// label appears in the path/URL label sets. Pulls intent from + /// the label (writeLabels → fsWrite, readLabels → fsRead). The + /// `defaultIntent` applies when the label doesn't disambiguate + /// — typically the method-name-driven receiver-rule intent. + /// Skips already-gated indices so a receiver's positional rule + /// (e.g. URLSession's index-0 URL = .network) wins over the + /// generic label scan. + func scanByLabel(defaultIntent: GateKind) { + for (i, label) in argLabels.enumerated() { + guard i < sig.parameters.count else { break } + if gatedIndices.contains(i) { continue } + let p = sig.parameters[i] + let spelling = p.type.swiftSpelling + guard spelling == "String" || spelling == "URL" else { continue } + let intent: GateKind? + if spelling == "String" { + if pathStringLabelsWrite.contains(label) { intent = .fsWrite } + else if pathStringLabelsRead.contains(label) { intent = .fsRead } + else { intent = nil } + } else { // URL + if urlLabelsWrite.contains(label) { intent = defaultIntent.isWrite ? defaultIntent : .fsWrite } + else if urlLabelsRead.contains(label) { intent = defaultIntent } + else { intent = nil } + } + guard let intent else { continue } + gatePathish(i, kind: intent) + } } - // FileManager — every method that takes a path or URL. + // FileManager — every method that takes a path or URL. The + // receiver-rule picks the *default intent* by method name; the + // label scan that follows then catches index-1+ URL/path args + // (e.g. `setUbiquitous(_: Bool, itemAt: URL, destinationURL: URL)`, + // `createSymbolicLink(at: URL, withDestinationURL: URL)`) that + // the prior position-0/1 rule missed. if receiverTypeName == "FileManager" || initFor == "FileManager" { - // Pick intent from the method name. Anything that mutates - // disk is `.fsWrite` (or `.fsDelete` for explicit deletes); - // pure inspection is `.fsRead`. Two-path operations - // (`copyItem`, `moveItem`, `linkItem`, `replaceItemAt`) - // gate both paths. let writeMethods: Set = [ "createDirectory", "createFile", "createSymbolicLink", "setAttributes", "changeCurrentDirectoryPath", + "linkItem", "copyItem", "moveItem", "replaceItemAt", + "setUbiquitous", ] let deleteMethods: Set = ["removeItem", "trashItem"] - let twoPathMethods: Set = [ - "copyItem", "moveItem", "linkItem", "replaceItemAt", - ] let intent: GateKind if let m = methodName { if deleteMethods.contains(m) { intent = .fsDelete } else if writeMethods.contains(m) { intent = .fsWrite } - else if twoPathMethods.contains(m) { intent = .fsWrite } else { intent = .fsRead } } else { intent = .fsRead } - if let m = methodName, twoPathMethods.contains(m) { - appendIfPathish(0, kind: intent) - appendIfPathish(1, kind: intent) - } else { - appendIfPathish(0, kind: intent) - } - } - - // URL initializers — `URL(fileURLWithPath:)`, `URL(string:)` — - // bind into a sandbox or network gate so a script can't escape - // by constructing URLs whose origin lies outside the policy. - // Pure URL construction is cheap; the authorize call adds the - // policy enforcement without changing the result. - // - // We only gate `init URL(fileURLWithPath:)` and the - // `String`-shaped `init URL(string:)` here — `URL(filePath:)` - // is a macOS-13+ alias, and the `URL.init(string:relativeTo:)` - // overload routes through the same single-string path. - // `URLComponents` and `URLRequest` get covered by their consumer - // methods (URLSession.data(from:) etc.) rather than at init. - // - // (We deliberately *don't* gate at URL construction time today - // because the current `Sandbox.authorize` is async and many URL - // inits are non-async; the gating happens at the I/O call site.) - - // String / Data file-IO inits — `init String(contentsOf:)`, - // `init String(contentsOfFile:)`, `init Data(contentsOf:)`, - // and the corresponding `.write(to:)` methods. Each takes either - // a `String` path or a `URL` as the first arg. - if initFor == "String" || initFor == "Data" { + // Position-0 fallback for the rare overloads whose label + // doesn't appear in our sets (older Foundation kept some as + // unlabeled `_`). + gatePathish(0, kind: intent) + scanByLabel(defaultIntent: intent) + } + + // URL initializers — pure construction, not gated at init time. + // `Sandbox.authorize` is async; many URL inits are sync. The gate + // fires at the I/O call site (URLSession.data(from:), + // String(contentsOf:), …) regardless of how the URL was built. + + // String / Data / NSString / NSData file-IO inits — read-shaped + // (`init X(contentsOf:)`, `init X(contentsOfFile:)`) take a + // path/URL at index 0; the label-scan picks up `contentsOf` / + // `contentsOfFile` directly. + if initFor == "String" || initFor == "Data" + || initFor == "NSString" || initFor == "NSData" + { if let m = methodName, m.contains("contentsOfFile") || m.contains("contentsOf") { - appendIfPathish(0, kind: .fsRead) + gatePathish(0, kind: .fsRead) + scanByLabel(defaultIntent: .fsRead) } } - if receiverTypeName == "String" || receiverTypeName == "Data" { + if receiverTypeName == "String" || receiverTypeName == "Data" + || receiverTypeName == "NSString" || receiverTypeName == "NSData" + { if methodName == "write" { - // String/Data.write(to: URL/path, …) — first arg. - appendIfPathish(0, kind: .fsWrite) + gatePathish(0, kind: .fsWrite) + scanByLabel(defaultIntent: .fsWrite) } } - // URLSession — the high-level `data(from:)`, `data(for:)`, - // `download(from:)`, `upload(for:fromFile:)`, etc. take either a - // bare `URL` or a `URLRequest` at index 0; some (`upload(for: - // fromFile:)`) carry a second `URL` arg pointing at a local - // file we should also `authorizePath`. + // URLSession — first arg is a network destination (URL or + // URLRequest); the `fromFile:` overloads carry a local-file URL + // at a later index that needs an fsRead gate. The label-scan + // generalises this to any `fromFile:` / `from:` / `forResource:` + // URL arg at any position. if receiverTypeName == "URLSession" { - // First arg: URL → network gate; URLRequest → network gate - // via embedded URL + method. - appendIfPathish(0, kind: .network) - appendIfURLRequestish(0) - // Second arg: a `fromFile:` URL is a real local file the - // session reads to upload — gate as `.fsRead`. The first arg - // already handled the network policy; this one closes the - // file-read door for upload-from-file overloads. - appendIfPathish(1, kind: .fsRead) + gatePathish(0, kind: .network) + gateURLRequest(0) + // Position-1 fsRead retained as a fallback for symbol graphs + // whose label spelling doesn't make it through the extractor. + gatePathish(1, kind: .fsRead) + scanByLabel(defaultIntent: .fsRead) + } + + // FileHandle — `init(forReadingAtPath:)`, + // `init(forWritingAtPath:)`, `init(forUpdatingAtPath:)` plus the + // URL-init variants `init(forReadingFrom:)`, `init(forWritingTo:)`, + // `init(forUpdating:)`. The String-arg labels are in the + // `pathStringLabels*` sets; the URL-arg labels (`forWritingTo` / + // `forUpdating`) aren't in `urlLabelsWrite` because they're + // FileHandle-specific spellings, so we infer the intent from the + // method-label here and fall through to a positional gate. + // `init(fileDescriptor:)` is out of scope — there's no path to + // authorise. Methods on an opened FileHandle (read/write/seek) + // are not gated here; the host process already constrains those + // via fd permissions established at open time. + if initFor == "FileHandle" { + let intent: GateKind + if let m = methodName, + m.contains("forWriting") || m.contains("forUpdating") + { + intent = .fsWrite + } else { + intent = .fsRead + } + scanByLabel(defaultIntent: intent) + if directives.isEmpty { gatePathish(0, kind: intent) } + } + + // Bundle — `init(path:)`, `init(url:)` open a bundle root the + // script later reads resources from. Gate as `.fsRead` so a + // pathological root (`/etc`) gets denied. + // `Bundle.path(forResource:ofType:inDirectory:)` similarly + // returns a path inside the bundle; the gate at the consumer + // call (`String(contentsOfFile:)`) will catch any further hop. + if initFor == "Bundle" || receiverTypeName == "Bundle" { + scanByLabel(defaultIntent: .fsRead) + } + + // OutputStream — `init(toFileAtPath:append:)`, + // `init(url:append:)` open a file for writing. + if initFor == "OutputStream" { + scanByLabel(defaultIntent: .fsWrite) + } + + // InputStream — `init(fileAtPath:)`, `init(url:)` open a file + // for reading. + if initFor == "InputStream" { + scanByLabel(defaultIntent: .fsRead) + } + + // FileWrapper — `init(url:options:)` reads a wrapper from disk; + // `.read(from:options:)` is read-shaped; `.write(to:options: + // originalContentsURL:)` is write-shaped. The label-scan catches + // each via `at` (read) / `to` (write) / `originalContentsURL` + // (read of the prior copy). + if initFor == "FileWrapper" { + scanByLabel(defaultIntent: .fsRead) + } + if receiverTypeName == "FileWrapper" { + let intent: GateKind + if methodName == "write" { intent = .fsWrite } + else { intent = .fsRead } + // `matchesContents(of:)` carries the URL under the `of:` + // label which isn't in `urlLabelsRead` (too generic to add + // globally — appears all over Foundation on non-URL args). + // Gate index 0 positionally so any URL-typed first arg on + // FileWrapper is authorised; the label scan still upgrades + // higher-index args (e.g. `originalContentsURL:`). + gatePathish(0, kind: intent) + scanByLabel(defaultIntent: intent) } return directives } +extension GateKind { + /// True if this kind expresses a write-side operation. Used by + /// the label scan to decide whether a `to:`-shaped URL arg + /// keeps the receiver-default intent or upgrades to fsWrite. + var isWrite: Bool { + switch self { + case .fsWrite, .fsDelete: return true + case .fsRead, .network, .networkRequest: return false + } + } +} + +/// Receiver-type spellings whose every bridge entry must short- +/// circuit with `try denyProcessIfSandboxed()` before doing any host +/// work. Used for `Foundation.Process` — it spawns a real OS +/// subprocess that escapes every host gate (path, network, identity), +/// so the policy is "denied entirely whenever a sandbox is active". +/// Embedders that want subprocess execution under a sandbox bind +/// SwiftBash's virtual-process table instead. +let denyWhenSandboxedReceivers: Set = ["Process"] + +/// Render the deny-when-sandboxed prologue. Wraps the synchronous +/// `denyProcessIfSandboxed()` throw in a `do/catch` that re-raises as +/// a `UserThrowSignal` — same shape as the path/URL gates — so +/// script-side `do/catch` blocks can pattern-match the typed denial +/// instead of seeing it as an opaque host-side error. +func denyPrologueLines(indent: String) -> [String] { + return [ + "\(indent)do {", + "\(indent) try denyProcessIfSandboxed()", + "\(indent)} catch {", + "\(indent) throw UserThrowSignal(value: .opaque(typeName: \"Error\", value: error))", + "\(indent)}", + ] +} + /// Identity-leaking property reads on `ProcessInfo` / `Bundle` / /// `FileManager` get redirected to the bound shell's `HostInfo` / /// `Environment` / `scriptName`. Returns the substitute call @@ -1457,7 +1672,23 @@ enum EmitBucket { enum Platform { case crossPlatform case appleOnly -} + /// Available on macOS / Linux / Windows / Android but NOT on the + /// iOS family (iOS, tvOS, watchOS, visionOS). Currently just + /// `Foundation.Process` — the scl oracle classifies it + /// cross-platform because Linux Foundation has it, but Apple's + /// non-macOS overlays mark it `@available(*, unavailable)`. + case nonIOSOnly +} + +/// Type spellings that require the non-iOS-family guard. The scl +/// oracle classifies these as cross-platform (they exist on at least +/// one non-Apple platform), but Apple's iOS-family Foundation +/// overlays mark them unavailable, so a plain cross-platform emit +/// fails to compile for iOS Simulator. Wrap their per-type bridge +/// file and any runtime-body emits with `#if !os(iOS) && !os(tvOS) +/// && !os(watchOS) && !os(visionOS)`. +let nonIOSOnlyTypes: Set = ["Process"] +let nonIOSGuardCondition = "!os(iOS) && !os(tvOS) && !os(watchOS) && !os(visionOS)" struct EmitEntry { let symbolPath: String // "sqrt(_:)" or "String.foo(...)" @@ -1531,10 +1762,11 @@ func extractBridgeKey(fromCode code: String) -> String? { /// Classify a bridge key against the scl oracle. Without an oracle, /// every entry is cross-platform (legacy behavior). func platform(forBridgeKey key: String) -> Platform { - guard let oracle = sclOracle else { return .crossPlatform } guard let (owner, member) = ownerAndMember(forBridgeKey: key) else { - return .crossPlatform + return sclOracle == nil ? .crossPlatform : .crossPlatform } + if nonIOSOnlyTypes.contains(owner) { return .nonIOSOnly } + guard let oracle = sclOracle else { return .crossPlatform } return oracle.isCrossPlatform(typeName: owner, memberName: member) ? .crossPlatform : .appleOnly } @@ -1656,6 +1888,10 @@ if let oracle = sclOracle { let spelling = bridge.swiftSpelling // Stdlib types and primitive bridges are always present. if stdlibCrossPlatformOwners.contains(spelling) { continue } + // `nonIOSOnlyTypes` get their own guard wrap; never classify + // them Apple-only or the non-Apple platforms (Linux/Windows/ + // Android) lose them. + if nonIOSOnlyTypes.contains(spelling) { continue } if !oracle.isTypeCrossPlatform(spelling) { appleOnlyTypes.insert(spelling) } @@ -1777,11 +2013,20 @@ for annotated in prioritizedSymbols { let key = "method:\(receiverTypeName).\(methodName)" if !claim(key, clashLabel: "\(receiverTypeName).\(methodName)") { continue } let recvUnbox = render(recvType.unboxTemplate, "receiver") + let methodLabels = sig.parameters.map(\.label) let methodGates = gates( forReceiver: receiverTypeName, methodName: methodName, + argLabels: methodLabels, signature: sig) - let methodGated = renderGates(methodGates, sig: sig, indent: " ") + var methodGated = renderGates(methodGates, sig: sig, indent: " ") + // Process: every method is denied when a sandbox is bound. + // Inject the deny check in front of any other gate prologue + // so even a sandbox-passing arg never reaches the + // subprocess-spawning Foundation API. + if denyWhenSandboxedReceivers.contains(receiverTypeName) { + methodGated.prologue.insert(contentsOf: denyPrologueLines(indent: " "), at: 0) + } record(key, bucket: .type(receiverTypeName), code: renderEmit(EmitConfig( registerLine: "\"func \(receiverTypeName).\(methodName)()\": .method", closureParams: "receiver, args", @@ -1831,8 +2076,14 @@ for annotated in prioritizedSymbols { forReceiver: nil, methodName: initMethodName, initFor: receiverTypeName, + argLabels: labels, signature: sig) - let initGated = renderGates(initGates, sig: sig, indent: " ") + var initGated = renderGates(initGates, sig: sig, indent: " ") + // Process: even constructing a Process is denied under sandbox, + // so a script can't capture an instance and pass it around. + if denyWhenSandboxedReceivers.contains(receiverTypeName) { + initGated.prologue.insert(contentsOf: denyPrologueLines(indent: " "), at: 0) + } record(key, bucket: .type(receiverTypeName), code: renderEmit(EmitConfig( registerLine: "\"\(initKey)\": .`init`", closureParams: "args", @@ -1876,6 +2127,13 @@ for annotated in prioritizedSymbols { // unbox where the redirect doesn't need it. let redirected = redirectedPropertyCall( receiver: receiverTypeName, member: memberName) + // Process: every property read/write requires the deny check + // up front so a sandboxed script can't inspect or set + // `arguments`/`environment`/etc. on the way to a `.run()` call. + var propPrologue: [String] = [] + if denyWhenSandboxedReceivers.contains(receiverTypeName) { + propPrologue.append(contentsOf: denyPrologueLines(indent: " ")) + } record(key, bucket: .type(receiverTypeName), code: renderEmit(EmitConfig( registerLine: "\"var \(receiverTypeName).\(memberName): \(propTypeSpelling)\": .computed", closureParams: redirected != nil ? "_" : "receiver", @@ -1888,7 +2146,8 @@ for annotated in prioritizedSymbols { isOptional: propType.isOptional, isThrowing: false, isAsync: false, - tupleElements: [] + tupleElements: [], + prologue: propPrologue ))) // For `var` properties on bridged classes, emit a setter // alongside the getter. The reference can be mutated in place @@ -1902,9 +2161,12 @@ for annotated in prioritizedSymbols { isVarMutable(sym) { let unboxNew = render(propType.bridge.unboxTemplate, "newValue") + let setterDeny = denyWhenSandboxedReceivers.contains(receiverTypeName) + ? denyPrologueLines(indent: " ").joined(separator: "\n") + "\n" + : "" let setterCode = """ \"set var \(receiverTypeName).\(memberName): \(propTypeSpelling)\": .setter { receiver, newValue in - let recv: \(recvType.swiftSpelling) = \(recvUnbox) + \(setterDeny) let recv: \(recvType.swiftSpelling) = \(recvUnbox) recv.\(memberName) = \(unboxNew) }, """ @@ -1953,6 +2215,12 @@ for annotated in prioritizedSymbols { let methodName = sym.names.title.split(separator: "(").first.map(String.init) ?? sym.names.title let key = "static-method:\(receiverTypeName).\(methodName)" if !claim(key, clashLabel: "\(receiverTypeName).\(methodName)") { continue } + // Process: static factories (e.g. `Process.launchedProcess`) + // need the same deny check as instance methods/inits. + var staticPrologue: [String] = [] + if denyWhenSandboxedReceivers.contains(receiverTypeName) { + staticPrologue.append(contentsOf: denyPrologueLines(indent: " ")) + } record(key, bucket: .type(receiverTypeName), code: renderEmit(EmitConfig( registerLine: "\"static func \(receiverTypeName).\(methodName)()\": .staticMethod", closureParams: "args", @@ -1964,7 +2232,8 @@ for annotated in prioritizedSymbols { isOptional: sig.returnIsOptional, isThrowing: isThrowing(sym), isAsync: isAsync(sym), - tupleElements: sig.returnTupleElements + tupleElements: sig.returnTupleElements, + prologue: staticPrologue ))) default: @@ -2206,7 +2475,9 @@ for (usr, bridge) in bridgedTypes { // without an Equatable conformance the auto-comparator can use). // Force those to Apple-only regardless of scl type-presence. let comparatorPlatform: Platform - if bridgeableTypeAllowlist.contains(typeName) + if nonIOSOnlyTypes.contains(typeName) { + comparatorPlatform = .nonIOSOnly + } else if bridgeableTypeAllowlist.contains(typeName) && bridgedClassTypeNames.contains(typeName) { comparatorPlatform = .appleOnly @@ -2303,6 +2574,12 @@ struct PlatformedEntries { /// file gets wrapped in `#if canImport(Darwin)` and the manifest's /// reference to it is gated too. var typeIsAppleOnly: Bool = false + /// When true, the type is unavailable on the iOS family (iOS, + /// tvOS, watchOS, visionOS) but exists on macOS / Linux / Windows + /// / Android. The whole per-type file gets wrapped in + /// `#if !os(iOS) && !os(tvOS) && !os(watchOS) && !os(visionOS)`. + /// Mutually exclusive with `typeIsAppleOnly`. + var typeIsNonIOSOnly: Bool = false var isEmpty: Bool { crossPlatform.isEmpty && appleOnly.isEmpty } } @@ -2345,6 +2622,36 @@ func renderPerTypeFile( """ } + if entries.typeIsNonIOSOnly { + // Available on macOS / Linux / Windows / Android but not on + // the iOS family — emit the dict under the non-iOS guard and + // a `[:]` stub elsewhere so the manifest's reference still + // resolves on every platform. + let dictName = staticLetName(for: typeName) + let allEntries = (entries.crossPlatform + entries.appleOnly) + .joined(separator: "\n") + let body = allEntries.isEmpty ? " // (no entries)" : allEntries + return """ + \(autogenBanner)import Foundation + import ShellKit + #if canImport(FoundationNetworking) + import FoundationNetworking + #endif + + #if \(nonIOSGuardCondition) + extension \(namespace) { + nonisolated(unsafe) static let \(dictName): [String: Bridge] = [ + \(body) + ] + } + #else + extension \(namespace) { + nonisolated(unsafe) static let \(dictName): [String: Bridge] = [:] + } + #endif + + """ + } let dictName = staticLetName(for: typeName) if entries.appleOnly.isEmpty { // Pure cross-platform dict — emit the literal form directly. @@ -2468,6 +2775,7 @@ func groupedByType(_ entries: [EmitEntry]) -> [(String, PlatformedEntries)] { switch entry.platform { case .crossPlatform: current.crossPlatform.append(entry.code) case .appleOnly: current.appleOnly.append(entry.code) + case .nonIOSOnly: current.crossPlatform.append(entry.code) } bodies[name] = current } @@ -2477,6 +2785,13 @@ func groupedByType(_ entries: [EmitEntry]) -> [(String, PlatformedEntries)] { for name in order where appleOnlyTypes.contains(name) { bodies[name]?.typeIsAppleOnly = true } + // Same for the non-iOS-family wrap. Entries are folded into + // `crossPlatform` above (the per-type file uses a single dict + // literal under the file-level guard), so `appleOnly` stays + // empty and the renderer takes the literal-dict path. + for name in order where nonIOSOnlyTypes.contains(name) { + bodies[name]?.typeIsNonIOSOnly = true + } return order.map { ($0, bodies[$0]!) } } @@ -2491,6 +2806,8 @@ func runtimeBodies(_ entries: [EmitEntry]) -> [String] { return entry.code case .appleOnly: return "#if canImport(Darwin)\n\(entry.code)\n#endif" + case .nonIOSOnly: + return "#if \(nonIOSGuardCondition)\n\(entry.code)\n#endif" } } } diff --git a/Sources/SwiftScriptInterpreter/API/HostHooks.swift b/Sources/SwiftScriptInterpreter/API/HostHooks.swift index 5c41d44..404b784 100644 --- a/Sources/SwiftScriptInterpreter/API/HostHooks.swift +++ b/Sources/SwiftScriptInterpreter/API/HostHooks.swift @@ -79,6 +79,33 @@ public func authorizeURL( } } +// MARK: Subprocess deny + +/// Thrown by every `Process` bridge entry when a sandbox is bound. +/// `Foundation.Process` spawns a real OS subprocess that escapes +/// every host gate (path, network, identity), so the policy is +/// "denied entirely whenever a sandbox is configured". Embedders +/// that want subprocess execution under a sandbox must register +/// SwiftBash's virtual-process table instead. +public struct ProcessSandboxDenied: Error, CustomStringConvertible { + public let reason: String + public init(reason: String = "Process is denied when a sandbox is active") { + self.reason = reason + } + public var description: String { reason } +} + +/// Throw ``ProcessSandboxDenied`` when a sandbox is bound on the +/// current shell. Generated `Process(...)` bridges call this before +/// touching any Foundation API. Returns silently in the standalone +/// passthrough case (no sandbox configured). +@inlinable +public func denyProcessIfSandboxed() throws { + if ShellKit.Shell.current.sandbox != nil { + throw ProcessSandboxDenied() + } +} + // MARK: Identity /// Synthetic user-name override — script-side `ProcessInfo @@ -157,9 +184,18 @@ extension ShellKit.NetworkConfig { @usableFromInline func checkAllowed(url: URL, method: String) throws { if dangerouslyAllowFullInternetAccess { return } - // Method gate. + // Method gate. Unknown verbs (LINK, UNLINK, custom WebDAV, …) + // must be rejected outright — falling back to `.GET` would + // silently grant a method the embedder never approved, since + // a request with `httpMethod = "FOO"` would be evaluated + // against GET permissions while the actual request method + // stayed `FOO`. let normalised = method.uppercased() - let knownMethod = HTTPMethod(rawValue: normalised) ?? .GET + guard let knownMethod = HTTPMethod(rawValue: normalised) else { + throw NetworkAccessDenied( + url: url, + reason: "HTTP method \(normalised) not supported by network gate") + } if !allowedMethods.contains(knownMethod) { throw NetworkAccessDenied( url: url, diff --git a/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+Bundle.swift b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+Bundle.swift new file mode 100644 index 0000000..afb03b8 --- /dev/null +++ b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+Bundle.swift @@ -0,0 +1,233 @@ +// AUTO-GENERATED by BridgeGeneratorTool. Do not edit by hand. +// Regenerate with: bash Tools/regen-foundation-bridge.sh +import Foundation + import ShellKit +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +extension FoundationBridges { + nonisolated(unsafe) static let bundle: [String: Bridge] = { + var d: [String: Bridge] = [ + "static let Bundle.main": .staticValue(boxOpaque(Bundle.main, typeName: "Bundle")), + "func Bundle.load()": .method { receiver, args in + guard args.count == 0 else { + throw RuntimeError.invalid("Bundle.load: expected 0 argument(s), got \(args.count)") + } + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + return .bool(recv.load()) + }, + "var Bundle.isLoaded: Bool": .computed { receiver in + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + return .bool(recv.isLoaded) + }, + "func Bundle.preflight()": .method { receiver, args in + guard args.count == 0 else { + throw RuntimeError.invalid("Bundle.preflight: expected 0 argument(s), got \(args.count)") + } + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + do { + try recv.preflight() + return .void + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + }, + "func Bundle.loadAndReturnError()": .method { receiver, args in + guard args.count == 0 else { + throw RuntimeError.invalid("Bundle.loadAndReturnError: expected 0 argument(s), got \(args.count)") + } + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + do { + try recv.loadAndReturnError() + return .void + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + }, + "var Bundle.bundleURL: URL": .computed { receiver in + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + return boxOpaque(recv.bundleURL, typeName: "URL") + }, + "var Bundle.resourceURL: URL?": .computed { receiver in + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + if let _v = recv.resourceURL { + return .optional(boxOpaque(_v, typeName: "URL")) + } + return .optional(nil) + }, + "var Bundle.executableURL: URL?": .computed { receiver in + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + if let _v = recv.executableURL { + return .optional(boxOpaque(_v, typeName: "URL")) + } + return .optional(nil) + }, + "var Bundle.privateFrameworksURL: URL?": .computed { receiver in + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + if let _v = recv.privateFrameworksURL { + return .optional(boxOpaque(_v, typeName: "URL")) + } + return .optional(nil) + }, + "var Bundle.sharedFrameworksURL: URL?": .computed { receiver in + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + if let _v = recv.sharedFrameworksURL { + return .optional(boxOpaque(_v, typeName: "URL")) + } + return .optional(nil) + }, + "var Bundle.sharedSupportURL: URL?": .computed { receiver in + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + if let _v = recv.sharedSupportURL { + return .optional(boxOpaque(_v, typeName: "URL")) + } + return .optional(nil) + }, + "var Bundle.builtInPlugInsURL: URL?": .computed { receiver in + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + if let _v = recv.builtInPlugInsURL { + return .optional(boxOpaque(_v, typeName: "URL")) + } + return .optional(nil) + }, + "var Bundle.appStoreReceiptURL: URL?": .computed { receiver in + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + if let _v = recv.appStoreReceiptURL { + return .optional(boxOpaque(_v, typeName: "URL")) + } + return .optional(nil) + }, + "var Bundle.bundlePath: String": .computed { receiver in + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + return .string(recv.bundlePath) + }, + "var Bundle.resourcePath: String?": .computed { receiver in + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + if let _v = recv.resourcePath { + return .optional(.string(_v)) + } + return .optional(nil) + }, + "var Bundle.executablePath: String?": .computed { receiver in + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + if let _v = recv.executablePath { + return .optional(.string(_v)) + } + return .optional(nil) + }, + "var Bundle.privateFrameworksPath: String?": .computed { receiver in + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + if let _v = recv.privateFrameworksPath { + return .optional(.string(_v)) + } + return .optional(nil) + }, + "var Bundle.sharedFrameworksPath: String?": .computed { receiver in + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + if let _v = recv.sharedFrameworksPath { + return .optional(.string(_v)) + } + return .optional(nil) + }, + "var Bundle.sharedSupportPath: String?": .computed { receiver in + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + if let _v = recv.sharedSupportPath { + return .optional(.string(_v)) + } + return .optional(nil) + }, + "var Bundle.builtInPlugInsPath: String?": .computed { receiver in + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + if let _v = recv.builtInPlugInsPath { + return .optional(.string(_v)) + } + return .optional(nil) + }, + "var Bundle.bundleIdentifier: String?": .computed { receiver in + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + if let _v = recv.bundleIdentifier { + return .optional(.string(_v)) + } + return .optional(nil) + }, + "var Bundle.developmentLocalization: String?": .computed { receiver in + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + if let _v = recv.developmentLocalization { + return .optional(.string(_v)) + } + return .optional(nil) + }, + "init Bundle(path:)": .`init` { args in + guard args.count == 1 else { + throw RuntimeError.invalid("init Bundle(path:): expected 1 argument(s), got \(args.count)") + } + let arg0 = try unboxString(args[0]) + do { + try await authorizePath(arg0, for: .read) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + if let _v = await Bundle(path: arg0) { + return .optional(boxOpaque(_v, typeName: "Bundle")) + } + return .optional(nil) + }, + "init Bundle(url:)": .`init` { args in + guard args.count == 1 else { + throw RuntimeError.invalid("init Bundle(url:): expected 1 argument(s), got \(args.count)") + } + let arg0 = try unboxOpaque(args[0], as: URL.self, typeName: "URL") + do { + try await authorizePath(arg0, for: .read) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + if let _v = await Bundle(url: arg0) { + return .optional(boxOpaque(_v, typeName: "Bundle")) + } + return .optional(nil) + }, + "init Bundle(identifier:)": .`init` { args in + guard args.count == 1 else { + throw RuntimeError.invalid("init Bundle(identifier:): expected 1 argument(s), got \(args.count)") + } + if let _v = Bundle(identifier: try unboxString(args[0])) { + return .optional(boxOpaque(_v, typeName: "Bundle")) + } + return .optional(nil) + }, + "func Bundle.url()": .method { receiver, args in + guard args.count == 1 else { + throw RuntimeError.invalid("Bundle.url: expected 1 argument(s), got \(args.count)") + } + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + if let _v = recv.url(forAuxiliaryExecutable: try unboxString(args[0])) { + return .optional(boxOpaque(_v, typeName: "URL")) + } + return .optional(nil) + }, + "func Bundle.path()": .method { receiver, args in + guard args.count == 1 else { + throw RuntimeError.invalid("Bundle.path: expected 1 argument(s), got \(args.count)") + } + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + if let _v = recv.path(forAuxiliaryExecutable: try unboxString(args[0])) { + return .optional(.string(_v)) + } + return .optional(nil) + }, + ] + #if canImport(Darwin) + d["func Bundle.unload()"] = .method { receiver, args in + guard args.count == 0 else { + throw RuntimeError.invalid("Bundle.unload: expected 0 argument(s), got \(args.count)") + } + let recv: Bundle = try unboxOpaque(receiver, as: Bundle.self, typeName: "Bundle") + return .bool(recv.unload()) + } + d["static let Bundle.didLoadNotification"] = .staticValue(boxOpaque(Bundle.didLoadNotification, typeName: "NSNotification.Name")) + #endif + return d + }() +} diff --git a/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+FileHandle.swift b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+FileHandle.swift new file mode 100644 index 0000000..f6a424f --- /dev/null +++ b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+FileHandle.swift @@ -0,0 +1,180 @@ +// AUTO-GENERATED by BridgeGeneratorTool. Do not edit by hand. +// Regenerate with: bash Tools/regen-foundation-bridge.sh +import Foundation +import ShellKit +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +extension FoundationBridges { + nonisolated(unsafe) static let fileHandle: [String: Bridge] = [ + "func FileHandle.readToEnd()": .method { receiver, args in + guard args.count == 0 else { + throw RuntimeError.invalid("FileHandle.readToEnd: expected 0 argument(s), got \(args.count)") + } + let recv: FileHandle = try unboxOpaque(receiver, as: FileHandle.self, typeName: "FileHandle") + do { + if let _v = try recv.readToEnd() { + return .optional(boxOpaque(_v, typeName: "Data")) + } + return .optional(nil) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + }, + "var FileHandle.availableData: Data": .computed { receiver in + let recv: FileHandle = try unboxOpaque(receiver, as: FileHandle.self, typeName: "FileHandle") + return boxOpaque(recv.availableData, typeName: "Data") + }, + "func FileHandle.synchronize()": .method { receiver, args in + guard args.count == 0 else { + throw RuntimeError.invalid("FileHandle.synchronize: expected 0 argument(s), got \(args.count)") + } + let recv: FileHandle = try unboxOpaque(receiver, as: FileHandle.self, typeName: "FileHandle") + do { + try recv.synchronize() + return .void + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + }, + "func FileHandle.close()": .method { receiver, args in + guard args.count == 0 else { + throw RuntimeError.invalid("FileHandle.close: expected 0 argument(s), got \(args.count)") + } + let recv: FileHandle = try unboxOpaque(receiver, as: FileHandle.self, typeName: "FileHandle") + do { + try recv.close() + return .void + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + }, + "static let FileHandle.standardInput": .staticValue(boxOpaque(FileHandle.standardInput, typeName: "FileHandle")), + "static let FileHandle.standardOutput": .staticValue(boxOpaque(FileHandle.standardOutput, typeName: "FileHandle")), + "static let FileHandle.standardError": .staticValue(boxOpaque(FileHandle.standardError, typeName: "FileHandle")), + "static let FileHandle.nullDevice": .staticValue(boxOpaque(FileHandle.nullDevice, typeName: "FileHandle")), + "func FileHandle.readDataToEndOfFile()": .method { receiver, args in + guard args.count == 0 else { + throw RuntimeError.invalid("FileHandle.readDataToEndOfFile: expected 0 argument(s), got \(args.count)") + } + let recv: FileHandle = try unboxOpaque(receiver, as: FileHandle.self, typeName: "FileHandle") + return boxOpaque(recv.readDataToEndOfFile(), typeName: "Data") + }, + "static let FileHandle.readCompletionNotification": .staticValue(boxOpaque(FileHandle.readCompletionNotification, typeName: "NSNotification.Name")), + "func FileHandle.read()": .method { receiver, args in + guard args.count == 1 else { + throw RuntimeError.invalid("FileHandle.read: expected 1 argument(s), got \(args.count)") + } + let recv: FileHandle = try unboxOpaque(receiver, as: FileHandle.self, typeName: "FileHandle") + do { + if let _v = try recv.read(upToCount: try unboxInt(args[0])) { + return .optional(boxOpaque(_v, typeName: "Data")) + } + return .optional(nil) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + }, + "init FileHandle(forReadingAtPath:)": .`init` { args in + guard args.count == 1 else { + throw RuntimeError.invalid("init FileHandle(forReadingAtPath:): expected 1 argument(s), got \(args.count)") + } + let arg0 = try unboxString(args[0]) + do { + try await authorizePath(arg0, for: .read) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + if let _v = await FileHandle(forReadingAtPath: arg0) { + return .optional(boxOpaque(_v, typeName: "FileHandle")) + } + return .optional(nil) + }, + "init FileHandle(forWritingAtPath:)": .`init` { args in + guard args.count == 1 else { + throw RuntimeError.invalid("init FileHandle(forWritingAtPath:): expected 1 argument(s), got \(args.count)") + } + let arg0 = try unboxString(args[0]) + do { + try await authorizePath(arg0, for: .write) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + if let _v = await FileHandle(forWritingAtPath: arg0) { + return .optional(boxOpaque(_v, typeName: "FileHandle")) + } + return .optional(nil) + }, + "init FileHandle(forUpdatingAtPath:)": .`init` { args in + guard args.count == 1 else { + throw RuntimeError.invalid("init FileHandle(forUpdatingAtPath:): expected 1 argument(s), got \(args.count)") + } + let arg0 = try unboxString(args[0]) + do { + try await authorizePath(arg0, for: .write) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + if let _v = await FileHandle(forUpdatingAtPath: arg0) { + return .optional(boxOpaque(_v, typeName: "FileHandle")) + } + return .optional(nil) + }, + "init FileHandle(forReadingFrom:)": .`init` { args in + guard args.count == 1 else { + throw RuntimeError.invalid("init FileHandle(forReadingFrom:): expected 1 argument(s), got \(args.count)") + } + let arg0 = try unboxOpaque(args[0], as: URL.self, typeName: "URL") + do { + try await authorizePath(arg0, for: .read) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + do { + return boxOpaque(try await FileHandle(forReadingFrom: arg0), typeName: "FileHandle") + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + }, + "init FileHandle(forWritingTo:)": .`init` { args in + guard args.count == 1 else { + throw RuntimeError.invalid("init FileHandle(forWritingTo:): expected 1 argument(s), got \(args.count)") + } + let arg0 = try unboxOpaque(args[0], as: URL.self, typeName: "URL") + do { + try await authorizePath(arg0, for: .write) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + do { + return boxOpaque(try await FileHandle(forWritingTo: arg0), typeName: "FileHandle") + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + }, + "init FileHandle(forUpdating:)": .`init` { args in + guard args.count == 1 else { + throw RuntimeError.invalid("init FileHandle(forUpdating:): expected 1 argument(s), got \(args.count)") + } + let arg0 = try unboxOpaque(args[0], as: URL.self, typeName: "URL") + do { + try await authorizePath(arg0, for: .write) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + do { + return boxOpaque(try await FileHandle(forUpdating: arg0), typeName: "FileHandle") + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + }, + "func FileHandle.readData()": .method { receiver, args in + guard args.count == 1 else { + throw RuntimeError.invalid("FileHandle.readData: expected 1 argument(s), got \(args.count)") + } + let recv: FileHandle = try unboxOpaque(receiver, as: FileHandle.self, typeName: "FileHandle") + return boxOpaque(recv.readData(ofLength: try unboxInt(args[0])), typeName: "Data") + }, + ] +} diff --git a/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+FileManager.swift b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+FileManager.swift index 9d39121..a1b44a5 100644 --- a/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+FileManager.swift +++ b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+FileManager.swift @@ -169,8 +169,14 @@ extension FoundationBridges { } catch { throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) } + let arg1 = try unboxOpaque(args[1], as: URL.self, typeName: "URL") do { - try await recv.createSymbolicLink(at: arg0, withDestinationURL: try unboxOpaque(args[1], as: URL.self, typeName: "URL")) + try await authorizePath(arg1, for: .write) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + do { + try await recv.createSymbolicLink(at: arg0, withDestinationURL: arg1) return .void } catch { throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) @@ -259,7 +265,13 @@ extension FoundationBridges { } catch { throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) } - return .bool(await recv.contentsEqual(atPath: arg0, andPath: try unboxString(args[1]))) + let arg1 = try unboxString(args[1]) + do { + try await authorizePath(arg1, for: .read) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + return .bool(await recv.contentsEqual(atPath: arg0, andPath: arg1)) }, "func FileManager.createDirectory()": .method { receiver, args in guard args.count == 2 else { @@ -351,8 +363,20 @@ extension FoundationBridges { throw RuntimeError.invalid("FileManager.setUbiquitous: expected 3 argument(s), got \(args.count)") } let recv: FileManager = try unboxOpaque(receiver, as: FileManager.self, typeName: "FileManager") + let arg1 = try unboxOpaque(args[1], as: URL.self, typeName: "URL") + do { + try await authorizePath(arg1, for: .write) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + let arg2 = try unboxOpaque(args[2], as: URL.self, typeName: "URL") + do { + try await authorizePath(arg2, for: .write) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } do { - try recv.setUbiquitous(try unboxBool(args[0]), itemAt: try unboxOpaque(args[1], as: URL.self, typeName: "URL"), destinationURL: try unboxOpaque(args[2], as: URL.self, typeName: "URL")) + try await recv.setUbiquitous(try unboxBool(args[0]), itemAt: arg1, destinationURL: arg2) return .void } catch { throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) diff --git a/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+FileWrapper.swift b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+FileWrapper.swift new file mode 100644 index 0000000..5660e6c --- /dev/null +++ b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+FileWrapper.swift @@ -0,0 +1,157 @@ +// AUTO-GENERATED by BridgeGeneratorTool. Do not edit by hand. +// Regenerate with: bash Tools/regen-foundation-bridge.sh +import Foundation +import ShellKit +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +#if canImport(Darwin) +extension FoundationBridges { + nonisolated(unsafe) static let fileWrapper: [String: Bridge] = [ + "var FileWrapper.isDirectory: Bool": .computed { receiver in + let recv: FileWrapper = try unboxOpaque(receiver, as: FileWrapper.self, typeName: "FileWrapper") + return .bool(recv.isDirectory) + }, + "var FileWrapper.isRegularFile: Bool": .computed { receiver in + let recv: FileWrapper = try unboxOpaque(receiver, as: FileWrapper.self, typeName: "FileWrapper") + return .bool(recv.isRegularFile) + }, + "var FileWrapper.isSymbolicLink: Bool": .computed { receiver in + let recv: FileWrapper = try unboxOpaque(receiver, as: FileWrapper.self, typeName: "FileWrapper") + return .bool(recv.isSymbolicLink) + }, + "var FileWrapper.preferredFilename: String?": .computed { receiver in + let recv: FileWrapper = try unboxOpaque(receiver, as: FileWrapper.self, typeName: "FileWrapper") + if let _v = recv.preferredFilename { + return .optional(.string(_v)) + } + return .optional(nil) + }, + "var FileWrapper.filename: String?": .computed { receiver in + let recv: FileWrapper = try unboxOpaque(receiver, as: FileWrapper.self, typeName: "FileWrapper") + if let _v = recv.filename { + return .optional(.string(_v)) + } + return .optional(nil) + }, + "var FileWrapper.serializedRepresentation: Data?": .computed { receiver in + let recv: FileWrapper = try unboxOpaque(receiver, as: FileWrapper.self, typeName: "FileWrapper") + if let _v = recv.serializedRepresentation { + return .optional(boxOpaque(_v, typeName: "Data")) + } + return .optional(nil) + }, + "var FileWrapper.regularFileContents: Data?": .computed { receiver in + let recv: FileWrapper = try unboxOpaque(receiver, as: FileWrapper.self, typeName: "FileWrapper") + if let _v = recv.regularFileContents { + return .optional(boxOpaque(_v, typeName: "Data")) + } + return .optional(nil) + }, + "var FileWrapper.symbolicLinkDestinationURL: URL?": .computed { receiver in + let recv: FileWrapper = try unboxOpaque(receiver, as: FileWrapper.self, typeName: "FileWrapper") + if let _v = recv.symbolicLinkDestinationURL { + return .optional(boxOpaque(_v, typeName: "URL")) + } + return .optional(nil) + }, + "init FileWrapper(regularFileWithContents:)": .`init` { args in + guard args.count == 1 else { + throw RuntimeError.invalid("init FileWrapper(regularFileWithContents:): expected 1 argument(s), got \(args.count)") + } + return boxOpaque(FileWrapper(regularFileWithContents: try unboxOpaque(args[0], as: Data.self, typeName: "Data")), typeName: "FileWrapper") + }, + "init FileWrapper(symbolicLinkWithDestinationURL:)": .`init` { args in + guard args.count == 1 else { + throw RuntimeError.invalid("init FileWrapper(symbolicLinkWithDestinationURL:): expected 1 argument(s), got \(args.count)") + } + return boxOpaque(FileWrapper(symbolicLinkWithDestinationURL: try unboxOpaque(args[0], as: URL.self, typeName: "URL")), typeName: "FileWrapper") + }, + "init FileWrapper(serializedRepresentation:)": .`init` { args in + guard args.count == 1 else { + throw RuntimeError.invalid("init FileWrapper(serializedRepresentation:): expected 1 argument(s), got \(args.count)") + } + if let _v = FileWrapper(serializedRepresentation: try unboxOpaque(args[0], as: Data.self, typeName: "Data")) { + return .optional(boxOpaque(_v, typeName: "FileWrapper")) + } + return .optional(nil) + }, + "func FileWrapper.matchesContents()": .method { receiver, args in + guard args.count == 1 else { + throw RuntimeError.invalid("FileWrapper.matchesContents: expected 1 argument(s), got \(args.count)") + } + let recv: FileWrapper = try unboxOpaque(receiver, as: FileWrapper.self, typeName: "FileWrapper") + let arg0 = try unboxOpaque(args[0], as: URL.self, typeName: "URL") + do { + try await authorizePath(arg0, for: .read) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + return .bool(await recv.matchesContents(of: arg0)) + }, + "func FileWrapper.addFileWrapper()": .method { receiver, args in + guard args.count == 1 else { + throw RuntimeError.invalid("FileWrapper.addFileWrapper: expected 1 argument(s), got \(args.count)") + } + let recv: FileWrapper = try unboxOpaque(receiver, as: FileWrapper.self, typeName: "FileWrapper") + return .string(recv.addFileWrapper(try unboxOpaque(args[0], as: FileWrapper.self, typeName: "FileWrapper"))) + }, + "func FileWrapper.keyForChildFileWrapper()": .method { receiver, args in + guard args.count == 1 else { + throw RuntimeError.invalid("FileWrapper.keyForChildFileWrapper: expected 1 argument(s), got \(args.count)") + } + let recv: FileWrapper = try unboxOpaque(receiver, as: FileWrapper.self, typeName: "FileWrapper") + if let _v = recv.keyForChildFileWrapper(try unboxOpaque(args[0], as: FileWrapper.self, typeName: "FileWrapper")) { + return .optional(.string(_v)) + } + return .optional(nil) + }, + "init FileWrapper(url:options:)": .`init` { args in + guard args.count == 2 else { + throw RuntimeError.invalid("init FileWrapper(url:options:): expected 2 argument(s), got \(args.count)") + } + let arg0 = try unboxOpaque(args[0], as: URL.self, typeName: "URL") + do { + try await authorizePath(arg0, for: .read) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + do { + return boxOpaque(try await FileWrapper(url: arg0, options: try unboxOpaque(args[1], as: FileWrapper.ReadingOptions.self, typeName: "FileWrapper.ReadingOptions")), typeName: "FileWrapper") + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + }, + "func FileWrapper.read()": .method { receiver, args in + guard args.count == 2 else { + throw RuntimeError.invalid("FileWrapper.read: expected 2 argument(s), got \(args.count)") + } + let recv: FileWrapper = try unboxOpaque(receiver, as: FileWrapper.self, typeName: "FileWrapper") + let arg0 = try unboxOpaque(args[0], as: URL.self, typeName: "URL") + do { + try await authorizePath(arg0, for: .read) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + do { + try await recv.read(from: arg0, options: try unboxOpaque(args[1], as: FileWrapper.ReadingOptions.self, typeName: "FileWrapper.ReadingOptions")) + return .void + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + }, + "func FileWrapper.addRegularFile()": .method { receiver, args in + guard args.count == 2 else { + throw RuntimeError.invalid("FileWrapper.addRegularFile: expected 2 argument(s), got \(args.count)") + } + let recv: FileWrapper = try unboxOpaque(receiver, as: FileWrapper.self, typeName: "FileWrapper") + return .string(recv.addRegularFile(withContents: try unboxOpaque(args[0], as: Data.self, typeName: "Data"), preferredFilename: try unboxString(args[1]))) + }, + ] +} +#else +extension FoundationBridges { + nonisolated(unsafe) static let fileWrapper: [String: Bridge] = [:] +} +#endif diff --git a/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+InputStream.swift b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+InputStream.swift new file mode 100644 index 0000000..01452bb --- /dev/null +++ b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+InputStream.swift @@ -0,0 +1,52 @@ +// AUTO-GENERATED by BridgeGeneratorTool. Do not edit by hand. +// Regenerate with: bash Tools/regen-foundation-bridge.sh +import Foundation +import ShellKit +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +extension FoundationBridges { + nonisolated(unsafe) static let inputStream: [String: Bridge] = [ + "var InputStream.hasBytesAvailable: Bool": .computed { receiver in + let recv: InputStream = try unboxOpaque(receiver, as: InputStream.self, typeName: "InputStream") + return .bool(recv.hasBytesAvailable) + }, + "init InputStream(data:)": .`init` { args in + guard args.count == 1 else { + throw RuntimeError.invalid("init InputStream(data:): expected 1 argument(s), got \(args.count)") + } + return boxOpaque(InputStream(data: try unboxOpaque(args[0], as: Data.self, typeName: "Data")), typeName: "InputStream") + }, + "init InputStream(url:)": .`init` { args in + guard args.count == 1 else { + throw RuntimeError.invalid("init InputStream(url:): expected 1 argument(s), got \(args.count)") + } + let arg0 = try unboxOpaque(args[0], as: URL.self, typeName: "URL") + do { + try await authorizePath(arg0, for: .read) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + if let _v = await InputStream(url: arg0) { + return .optional(boxOpaque(_v, typeName: "InputStream")) + } + return .optional(nil) + }, + "init InputStream(fileAtPath:)": .`init` { args in + guard args.count == 1 else { + throw RuntimeError.invalid("init InputStream(fileAtPath:): expected 1 argument(s), got \(args.count)") + } + let arg0 = try unboxString(args[0]) + do { + try await authorizePath(arg0, for: .read) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + if let _v = await InputStream(fileAtPath: arg0) { + return .optional(boxOpaque(_v, typeName: "InputStream")) + } + return .optional(nil) + }, + ] +} diff --git a/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+NSExceptionName.swift b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+NSExceptionName.swift index b415859..d56e453 100644 --- a/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+NSExceptionName.swift +++ b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+NSExceptionName.swift @@ -45,14 +45,14 @@ extension FoundationBridges { d["static let NSExceptionName.portReceiveException"] = .staticValue(boxOpaque(NSExceptionName.portReceiveException, typeName: "NSExceptionName")) d["static let NSExceptionName.oldStyleException"] = .staticValue(boxOpaque(NSExceptionName.oldStyleException, typeName: "NSExceptionName")) d["static let NSExceptionName.inconsistentArchiveException"] = .staticValue(boxOpaque(NSExceptionName.inconsistentArchiveException, typeName: "NSExceptionName")) + d["static let NSExceptionName.characterConversionException"] = .staticValue(boxOpaque(NSExceptionName.characterConversionException, typeName: "NSExceptionName")) + d["static let NSExceptionName.parseErrorException"] = .staticValue(boxOpaque(NSExceptionName.parseErrorException, typeName: "NSExceptionName")) d["static let NSExceptionName.invocationOperationVoidResultException"] = .staticValue(boxOpaque(NSExceptionName.invocationOperationVoidResultException, typeName: "NSExceptionName")) d["static let NSExceptionName.invocationOperationCancelledException"] = .staticValue(boxOpaque(NSExceptionName.invocationOperationCancelledException, typeName: "NSExceptionName")) d["var NSExceptionName.hashValue: Int"] = .computed { receiver in let recv: NSExceptionName = try unboxOpaque(receiver, as: NSExceptionName.self, typeName: "NSExceptionName") return .int(recv.hashValue) } - d["static let NSExceptionName.characterConversionException"] = .staticValue(boxOpaque(NSExceptionName.characterConversionException, typeName: "NSExceptionName")) - d["static let NSExceptionName.parseErrorException"] = .staticValue(boxOpaque(NSExceptionName.parseErrorException, typeName: "NSExceptionName")) d["static let NSExceptionName.undefinedKeyException"] = .staticValue(boxOpaque(NSExceptionName.undefinedKeyException, typeName: "NSExceptionName")) #endif return d diff --git a/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+NSNotificationName.swift b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+NSNotificationName.swift index bff3149..1847c4c 100644 --- a/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+NSNotificationName.swift +++ b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+NSNotificationName.swift @@ -10,10 +10,10 @@ extension FoundationBridges { nonisolated(unsafe) static let nSNotificationName: [String: Bridge] = { var d: [String: Bridge] = [ "static let NSNotification.Name.NSCalendarDayChanged": .staticValue(boxOpaque(NSNotification.Name.NSCalendarDayChanged, typeName: "NSNotification.Name")), - "static let NSNotification.Name.NSSystemTimeZoneDidChange": .staticValue(boxOpaque(NSNotification.Name.NSSystemTimeZoneDidChange, typeName: "NSNotification.Name")), "static let NSNotification.Name.NSWillBecomeMultiThreaded": .staticValue(boxOpaque(NSNotification.Name.NSWillBecomeMultiThreaded, typeName: "NSNotification.Name")), "static let NSNotification.Name.NSDidBecomeSingleThreaded": .staticValue(boxOpaque(NSNotification.Name.NSDidBecomeSingleThreaded, typeName: "NSNotification.Name")), "static let NSNotification.Name.NSThreadWillExit": .staticValue(boxOpaque(NSNotification.Name.NSThreadWillExit, typeName: "NSNotification.Name")), + "static let NSNotification.Name.NSSystemTimeZoneDidChange": .staticValue(boxOpaque(NSNotification.Name.NSSystemTimeZoneDidChange, typeName: "NSNotification.Name")), "init NSNotification.Name(_:)": .`init` { args in guard args.count == 1 else { throw RuntimeError.invalid("init NSNotification.Name(_:): expected 1 argument(s), got \(args.count)") @@ -31,11 +31,17 @@ extension FoundationBridges { d["static let NSNotification.Name.NSFileHandleReadToEndOfFileCompletion"] = .staticValue(boxOpaque(NSNotification.Name.NSFileHandleReadToEndOfFileCompletion, typeName: "NSNotification.Name")) d["static let NSNotification.Name.NSFileHandleConnectionAccepted"] = .staticValue(boxOpaque(NSNotification.Name.NSFileHandleConnectionAccepted, typeName: "NSNotification.Name")) d["static let NSNotification.Name.NSFileHandleDataAvailable"] = .staticValue(boxOpaque(NSNotification.Name.NSFileHandleDataAvailable, typeName: "NSNotification.Name")) + d["static let NSNotification.Name.NSMetadataQueryDidStartGathering"] = .staticValue(boxOpaque(NSNotification.Name.NSMetadataQueryDidStartGathering, typeName: "NSNotification.Name")) + d["static let NSNotification.Name.NSMetadataQueryGatheringProgress"] = .staticValue(boxOpaque(NSNotification.Name.NSMetadataQueryGatheringProgress, typeName: "NSNotification.Name")) + d["static let NSNotification.Name.NSMetadataQueryDidFinishGathering"] = .staticValue(boxOpaque(NSNotification.Name.NSMetadataQueryDidFinishGathering, typeName: "NSNotification.Name")) + d["static let NSNotification.Name.NSMetadataQueryDidUpdate"] = .staticValue(boxOpaque(NSNotification.Name.NSMetadataQueryDidUpdate, typeName: "NSNotification.Name")) d["static let NSNotification.Name.NSProcessInfoPowerStateDidChange"] = .staticValue(boxOpaque(NSNotification.Name.NSProcessInfoPowerStateDidChange, typeName: "NSNotification.Name")) d["var NSNotification.Name.hashValue: Int"] = .computed { receiver in let recv: NSNotification.Name = try unboxOpaque(receiver, as: NSNotification.Name.self, typeName: "NSNotification.Name") return .int(recv.hashValue) } + d["static let NSNotification.Name.NSUbiquityIdentityDidChange"] = .staticValue(boxOpaque(NSNotification.Name.NSUbiquityIdentityDidChange, typeName: "NSNotification.Name")) + d["static let NSNotification.Name.NSHTTPCookieManagerCookiesChanged"] = .staticValue(boxOpaque(NSNotification.Name.NSHTTPCookieManagerCookiesChanged, typeName: "NSNotification.Name")) d["static let NSNotification.Name.NSUndoManagerCheckpoint"] = .staticValue(boxOpaque(NSNotification.Name.NSUndoManagerCheckpoint, typeName: "NSNotification.Name")) d["static let NSNotification.Name.NSUndoManagerWillUndoChange"] = .staticValue(boxOpaque(NSNotification.Name.NSUndoManagerWillUndoChange, typeName: "NSNotification.Name")) d["static let NSNotification.Name.NSUndoManagerWillRedoChange"] = .staticValue(boxOpaque(NSNotification.Name.NSUndoManagerWillRedoChange, typeName: "NSNotification.Name")) @@ -44,12 +50,6 @@ extension FoundationBridges { d["static let NSNotification.Name.NSUndoManagerDidOpenUndoGroup"] = .staticValue(boxOpaque(NSNotification.Name.NSUndoManagerDidOpenUndoGroup, typeName: "NSNotification.Name")) d["static let NSNotification.Name.NSUndoManagerWillCloseUndoGroup"] = .staticValue(boxOpaque(NSNotification.Name.NSUndoManagerWillCloseUndoGroup, typeName: "NSNotification.Name")) d["static let NSNotification.Name.NSUndoManagerDidCloseUndoGroup"] = .staticValue(boxOpaque(NSNotification.Name.NSUndoManagerDidCloseUndoGroup, typeName: "NSNotification.Name")) - d["static let NSNotification.Name.NSUbiquityIdentityDidChange"] = .staticValue(boxOpaque(NSNotification.Name.NSUbiquityIdentityDidChange, typeName: "NSNotification.Name")) - d["static let NSNotification.Name.NSMetadataQueryDidStartGathering"] = .staticValue(boxOpaque(NSNotification.Name.NSMetadataQueryDidStartGathering, typeName: "NSNotification.Name")) - d["static let NSNotification.Name.NSMetadataQueryGatheringProgress"] = .staticValue(boxOpaque(NSNotification.Name.NSMetadataQueryGatheringProgress, typeName: "NSNotification.Name")) - d["static let NSNotification.Name.NSMetadataQueryDidFinishGathering"] = .staticValue(boxOpaque(NSNotification.Name.NSMetadataQueryDidFinishGathering, typeName: "NSNotification.Name")) - d["static let NSNotification.Name.NSMetadataQueryDidUpdate"] = .staticValue(boxOpaque(NSNotification.Name.NSMetadataQueryDidUpdate, typeName: "NSNotification.Name")) - d["static let NSNotification.Name.NSHTTPCookieManagerCookiesChanged"] = .staticValue(boxOpaque(NSNotification.Name.NSHTTPCookieManagerCookiesChanged, typeName: "NSNotification.Name")) d["static let NSNotification.Name.NSSystemClockDidChange"] = .staticValue(boxOpaque(NSNotification.Name.NSSystemClockDidChange, typeName: "NSNotification.Name")) #endif return d diff --git a/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+OutputStream.swift b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+OutputStream.swift new file mode 100644 index 0000000..6f18e22 --- /dev/null +++ b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+OutputStream.swift @@ -0,0 +1,52 @@ +// AUTO-GENERATED by BridgeGeneratorTool. Do not edit by hand. +// Regenerate with: bash Tools/regen-foundation-bridge.sh +import Foundation +import ShellKit +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +extension FoundationBridges { + nonisolated(unsafe) static let outputStream: [String: Bridge] = [ + "var OutputStream.hasSpaceAvailable: Bool": .computed { receiver in + let recv: OutputStream = try unboxOpaque(receiver, as: OutputStream.self, typeName: "OutputStream") + return .bool(recv.hasSpaceAvailable) + }, + "static func OutputStream.toMemory()": .staticMethod { args in + guard args.count == 0 else { + throw RuntimeError.invalid("OutputStream.toMemory: expected 0 argument(s), got \(args.count)") + } + return boxOpaque(OutputStream.toMemory(), typeName: "OutputStream") + }, + "init OutputStream(url:append:)": .`init` { args in + guard args.count == 2 else { + throw RuntimeError.invalid("init OutputStream(url:append:): expected 2 argument(s), got \(args.count)") + } + let arg0 = try unboxOpaque(args[0], as: URL.self, typeName: "URL") + do { + try await authorizePath(arg0, for: .write) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + if let _v = await OutputStream(url: arg0, append: try unboxBool(args[1])) { + return .optional(boxOpaque(_v, typeName: "OutputStream")) + } + return .optional(nil) + }, + "init OutputStream(toFileAtPath:append:)": .`init` { args in + guard args.count == 2 else { + throw RuntimeError.invalid("init OutputStream(toFileAtPath:append:): expected 2 argument(s), got \(args.count)") + } + let arg0 = try unboxString(args[0]) + do { + try await authorizePath(arg0, for: .write) + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + if let _v = await OutputStream(toFileAtPath: arg0, append: try unboxBool(args[1])) { + return .optional(boxOpaque(_v, typeName: "OutputStream")) + } + return .optional(nil) + }, + ] +} diff --git a/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+Process.swift b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+Process.swift new file mode 100644 index 0000000..5f738ef --- /dev/null +++ b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+Process.swift @@ -0,0 +1,134 @@ +// AUTO-GENERATED by BridgeGeneratorTool. Do not edit by hand. +// Regenerate with: bash Tools/regen-foundation-bridge.sh +import Foundation +import ShellKit +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +#if !os(iOS) && !os(tvOS) && !os(watchOS) && !os(visionOS) +extension FoundationBridges { + nonisolated(unsafe) static let process: [String: Bridge] = [ + "init Process()": .`init` { args in + guard args.count == 0 else { + throw RuntimeError.invalid("init Process(): expected 0 argument(s), got \(args.count)") + } + do { + try denyProcessIfSandboxed() + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + return boxOpaque(Process(), typeName: "Process") + }, + "var Process.executableURL: URL?": .computed { receiver in + let recv: Process = try unboxOpaque(receiver, as: Process.self, typeName: "Process") + do { + try denyProcessIfSandboxed() + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + if let _v = recv.executableURL { + return .optional(boxOpaque(_v, typeName: "URL")) + } + return .optional(nil) + }, + "var Process.currentDirectoryURL: URL?": .computed { receiver in + let recv: Process = try unboxOpaque(receiver, as: Process.self, typeName: "Process") + do { + try denyProcessIfSandboxed() + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + if let _v = recv.currentDirectoryURL { + return .optional(boxOpaque(_v, typeName: "URL")) + } + return .optional(nil) + }, + "func Process.run()": .method { receiver, args in + guard args.count == 0 else { + throw RuntimeError.invalid("Process.run: expected 0 argument(s), got \(args.count)") + } + let recv: Process = try unboxOpaque(receiver, as: Process.self, typeName: "Process") + do { + try denyProcessIfSandboxed() + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + do { + try recv.run() + return .void + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + }, + "func Process.suspend()": .method { receiver, args in + guard args.count == 0 else { + throw RuntimeError.invalid("Process.suspend: expected 0 argument(s), got \(args.count)") + } + let recv: Process = try unboxOpaque(receiver, as: Process.self, typeName: "Process") + do { + try denyProcessIfSandboxed() + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + return .bool(recv.suspend()) + }, + "func Process.resume()": .method { receiver, args in + guard args.count == 0 else { + throw RuntimeError.invalid("Process.resume: expected 0 argument(s), got \(args.count)") + } + let recv: Process = try unboxOpaque(receiver, as: Process.self, typeName: "Process") + do { + try denyProcessIfSandboxed() + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + return .bool(recv.resume()) + }, + "var Process.isRunning: Bool": .computed { receiver in + let recv: Process = try unboxOpaque(receiver, as: Process.self, typeName: "Process") + do { + try denyProcessIfSandboxed() + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + return .bool(recv.isRunning) + }, + "var Process.launchPath: String?": .computed { receiver in + let recv: Process = try unboxOpaque(receiver, as: Process.self, typeName: "Process") + do { + try denyProcessIfSandboxed() + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + if let _v = recv.launchPath { + return .optional(.string(_v)) + } + return .optional(nil) + }, + "var Process.currentDirectoryPath: String": .computed { receiver in + let recv: Process = try unboxOpaque(receiver, as: Process.self, typeName: "Process") + do { + try denyProcessIfSandboxed() + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + return .string(recv.currentDirectoryPath) + }, + "set var Process.currentDirectoryPath: String": .setter { receiver, newValue in + do { + try denyProcessIfSandboxed() + } catch { + throw UserThrowSignal(value: .opaque(typeName: "Error", value: error)) + } + let recv: Process = try unboxOpaque(receiver, as: Process.self, typeName: "Process") + recv.currentDirectoryPath = try unboxString(newValue) + }, + "static let Process.didTerminateNotification": .staticValue(boxOpaque(Process.didTerminateNotification, typeName: "NSNotification.Name")), + ] +} +#else +extension FoundationBridges { + nonisolated(unsafe) static let process: [String: Bridge] = [:] +} +#endif diff --git a/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+URLRequest.swift b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+URLRequest.swift index 856e6e5..5668990 100644 --- a/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+URLRequest.swift +++ b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+URLRequest.swift @@ -45,6 +45,13 @@ extension FoundationBridges { } return .optional(nil) }, + "var URLRequest.httpBodyStream: InputStream?": .computed { receiver in + let recv: URLRequest = try unboxOpaque(receiver, as: URLRequest.self, typeName: "URLRequest") + if let _v = recv.httpBodyStream { + return .optional(boxOpaque(_v, typeName: "InputStream")) + } + return .optional(nil) + }, "var URLRequest.httpShouldHandleCookies: Bool": .computed { receiver in let recv: URLRequest = try unboxOpaque(receiver, as: URLRequest.self, typeName: "URLRequest") return .bool(recv.httpShouldHandleCookies) diff --git a/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+URLResource.swift b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+URLResource.swift index 427046f..2bbe108 100644 --- a/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+URLResource.swift +++ b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges+URLResource.swift @@ -9,6 +9,10 @@ import FoundationNetworking #if canImport(Darwin) extension FoundationBridges { nonisolated(unsafe) static let uRLResource: [String: Bridge] = [ + "var URLResource.bundle: Bundle": .computed { receiver in + let recv: URLResource = try unboxOpaque(receiver, as: URLResource.self, typeName: "URLResource") + return boxOpaque(recv.bundle, typeName: "Bundle") + }, "var URLResource.name: String": .computed { receiver in let recv: URLResource = try unboxOpaque(receiver, as: URLResource.self, typeName: "URLResource") return .string(recv.name) diff --git a/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges.swift b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges.swift index b779910..da5aef1 100644 --- a/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges.swift +++ b/Sources/SwiftScriptInterpreter/Modules/FoundationBridge/FoundationBridges.swift @@ -16,6 +16,7 @@ enum FoundationBridges { nonisolated(unsafe) static let all: [String: Bridge] = [ FoundationBridges.runLoopSchedulerTimeType, FoundationBridges.uRLParseStrategy, + FoundationBridges.fileHandle, FoundationBridges.characterSet, FoundationBridges.machError, FoundationBridges.personNameComponents, @@ -103,53 +104,57 @@ enum FoundationBridges { FoundationBridges.personNameComponentsAttributedStyle, FoundationBridges.personNameComponentsParseStrategy, FoundationBridges.dateComponentsFormatStyle, - FoundationBridges.nSLinguisticTag, - FoundationBridges.nSLinguisticTagScheme, - FoundationBridges.nSLinguisticTaggerOptions, + FoundationBridges.uRLSession, FoundationBridges.nSExceptionName, FoundationBridges.nSNotificationName, + FoundationBridges.inlinePresentationIntent, + FoundationBridges.nSAttributedStringFormattingContextKey, + FoundationBridges.nSAttributedStringEnumerationOptions, + FoundationBridges.nSAttributedStringKey, FoundationBridges.nSCalendarIdentifier, FoundationBridges.nSCalendarUnit, FoundationBridges.nSCalendarOptions, - FoundationBridges.fileWrapperReadingOptions, - FoundationBridges.fileWrapperWritingOptions, FoundationBridges.personNameComponentsFormatterOptions, FoundationBridges.nSPointerFunctionsOptions, + FoundationBridges.bundle, + FoundationBridges.nSItemProviderFileOptions, FoundationBridges.hTTPCookiePropertyKey, FoundationBridges.hTTPCookieStringPolicy, + FoundationBridges.uRLFileProtection, + FoundationBridges.uRLFileResourceType, + FoundationBridges.uRLResourceKey, + FoundationBridges.uRLThumbnailDictionaryItem, + FoundationBridges.uRLUbiquitousItemDownloadingStatus, + FoundationBridges.uRLUbiquitousSharedItemPermissions, + FoundationBridges.uRLUbiquitousSharedItemRole, + FoundationBridges.nSURLBookmarkCreationOptions, + FoundationBridges.nSURLBookmarkResolutionOptions, + FoundationBridges.nSBinarySearchingOptions, FoundationBridges.processInfo, FoundationBridges.processInfoActivityOptions, - FoundationBridges.nSBinarySearchingOptions, - FoundationBridges.nSXPCConnectionOptions, FoundationBridges.measurementFormatterUnitOptions, - FoundationBridges.nSComparisonPredicateOptions, - FoundationBridges.nSTextCheckingKey, - FoundationBridges.byteCountFormatterUnits, + FoundationBridges.nSFileVersionAddingOptions, + FoundationBridges.nSFileVersionReplacingOptions, + FoundationBridges.nSValueTransformerName, + FoundationBridges.nSFileCoordinatorReadingOptions, + FoundationBridges.nSFileCoordinatorWritingOptions, FoundationBridges.nSRegularExpressionOptions, FoundationBridges.nSRegularExpressionMatchingOptions, FoundationBridges.nSRegularExpressionMatchingFlags, - FoundationBridges.hTTPURLResponse, - FoundationBridges.uRLResponse, - FoundationBridges.netServiceOptions, + FoundationBridges.stringEncodingDetectionOptionsKey, + FoundationBridges.stringTransform, + FoundationBridges.nSStringCompareOptions, + FoundationBridges.nSStringEncodingConversionOptions, + FoundationBridges.nSStringEnumerationOptions, FoundationBridges.jSONSerializationReadingOptions, FoundationBridges.jSONSerializationWritingOptions, FoundationBridges.nSKeyValueChangeKey, FoundationBridges.nSKeyValueObservingOptions, - FoundationBridges.streamNetworkServiceTypeValue, - FoundationBridges.streamSOCKSProxyConfiguration, - FoundationBridges.streamSOCKSProxyVersion, - FoundationBridges.streamSocketSecurityLevel, - FoundationBridges.streamPropertyKey, - FoundationBridges.streamEvent, FoundationBridges.nSDataReadingOptions, FoundationBridges.nSDataWritingOptions, FoundationBridges.nSDataSearchOptions, FoundationBridges.nSDataBase64EncodingOptions, FoundationBridges.nSDataBase64DecodingOptions, - FoundationBridges.dateComponentsFormatterZeroFormattingBehavior, - FoundationBridges.progressKind, - FoundationBridges.progressUserInfoKey, - FoundationBridges.progressFileOperationKind, FoundationBridges.fileAttributeKey, FoundationBridges.fileAttributeType, FoundationBridges.fileManager, @@ -158,42 +163,43 @@ enum FoundationBridges { FoundationBridges.fileManagerVolumeEnumerationOptions, FoundationBridges.fileManagerDirectoryEnumerationOptions, FoundationBridges.fileManagerItemReplacementOptions, - FoundationBridges.uRLSession, + FoundationBridges.nSLinguisticTag, + FoundationBridges.nSLinguisticTagScheme, + FoundationBridges.nSLinguisticTaggerOptions, FoundationBridges.nSOrderedCollectionDifferenceCalculationOptions, - FoundationBridges.inlinePresentationIntent, - FoundationBridges.nSAttributedStringFormattingContextKey, - FoundationBridges.nSAttributedStringEnumerationOptions, - FoundationBridges.nSAttributedStringKey, + FoundationBridges.process, FoundationBridges.iSO8601DateFormatterOptions, - FoundationBridges.nSItemProviderFileOptions, - FoundationBridges.nSFileVersionAddingOptions, - FoundationBridges.nSFileVersionReplacingOptions, + FoundationBridges.fileWrapper, + FoundationBridges.fileWrapperReadingOptions, + FoundationBridges.fileWrapperWritingOptions, FoundationBridges.nSMachPortOptions, FoundationBridges.propertyListSerializationMutabilityOptions, - FoundationBridges.uRLFileProtection, - FoundationBridges.uRLFileResourceType, - FoundationBridges.uRLResourceKey, - FoundationBridges.uRLThumbnailDictionaryItem, - FoundationBridges.uRLUbiquitousItemDownloadingStatus, - FoundationBridges.uRLUbiquitousSharedItemPermissions, - FoundationBridges.uRLUbiquitousSharedItemRole, - FoundationBridges.nSURLBookmarkCreationOptions, - FoundationBridges.nSURLBookmarkResolutionOptions, + FoundationBridges.nSXPCConnectionOptions, FoundationBridges.nSEnumerationOptions, FoundationBridges.nSSortOptions, FoundationBridges.runLoopMode, - FoundationBridges.nSValueTransformerName, - FoundationBridges.nSFileCoordinatorReadingOptions, - FoundationBridges.nSFileCoordinatorWritingOptions, + FoundationBridges.nSComparisonPredicateOptions, FoundationBridges.notificationQueueNotificationCoalescing, FoundationBridges.fileManagerSearchPathDomainMask, FoundationBridges.nSLocaleKey, - FoundationBridges.stringEncodingDetectionOptionsKey, - FoundationBridges.stringTransform, - FoundationBridges.nSStringCompareOptions, - FoundationBridges.nSStringEncodingConversionOptions, - FoundationBridges.nSStringEnumerationOptions, + FoundationBridges.byteCountFormatterUnits, + FoundationBridges.nSTextCheckingKey, + FoundationBridges.netServiceOptions, + FoundationBridges.hTTPURLResponse, + FoundationBridges.uRLResponse, + FoundationBridges.inputStream, + FoundationBridges.outputStream, + FoundationBridges.streamNetworkServiceTypeValue, + FoundationBridges.streamSOCKSProxyConfiguration, + FoundationBridges.streamSOCKSProxyVersion, + FoundationBridges.streamSocketSecurityLevel, + FoundationBridges.streamPropertyKey, + FoundationBridges.streamEvent, FoundationBridges.nSKeyValueOperator, + FoundationBridges.dateComponentsFormatterZeroFormattingBehavior, + FoundationBridges.progressKind, + FoundationBridges.progressUserInfoKey, + FoundationBridges.progressFileOperationKind, FoundationBridges.duration, FoundationBridges.durationTimeFormatStyle, FoundationBridges.durationUnitsFormatStyle, @@ -219,15 +225,6 @@ enum FoundationBridges { extension FoundationModule { func registerGenerated(into i: Interpreter) { for (k, v) in FoundationBridges.all { i.bridges[k] = v } -#if canImport(Darwin) - i.registerGlobal(name: "NSHostByteOrder") { args in - guard args.count == 0 else { - throw RuntimeError.invalid("NSHostByteOrder: expected 0 argument(s), got \(args.count)") - } - return .int(NSHostByteOrder()) - } -#endif - #if canImport(Darwin) i.registerGlobal(name: "NSLogPageSize") { args in guard args.count == 0 else { @@ -244,6 +241,15 @@ extension FoundationModule { return .int(NSPageSize()) } +#if canImport(Darwin) + i.registerGlobal(name: "NSHostByteOrder") { args in + guard args.count == 0 else { + throw RuntimeError.invalid("NSHostByteOrder: expected 0 argument(s), got \(args.count)") + } + return .int(NSHostByteOrder()) + } +#endif + i.registerGlobal(name: "NSFullUserName") { args in guard args.count == 0 else { throw RuntimeError.invalid("NSFullUserName: expected 0 argument(s), got \(args.count)") @@ -350,81 +356,61 @@ extension FoundationModule { } } -#if canImport(Darwin) - i.registerComparator(on: "URL.ParseStrategy") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? URL.ParseStrategy, - case .opaque(_, let b) = rhs, let lb = b as? URL.ParseStrategy - else { throw RuntimeError.invalid("URL.ParseStrategy comparison: bad payloads") } + i.registerComparator(on: "JSONEncoder.OutputFormatting") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? JSONEncoder.OutputFormatting, + case .opaque(_, let b) = rhs, let lb = b as? JSONEncoder.OutputFormatting + else { throw RuntimeError.invalid("JSONEncoder.OutputFormatting comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif #if canImport(Darwin) - i.registerComparator(on: "AttributedString") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? AttributedString, - case .opaque(_, let b) = rhs, let lb = b as? AttributedString - else { throw RuntimeError.invalid("AttributedString comparison: bad payloads") } + i.registerComparator(on: "URLResource") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? URLResource, + case .opaque(_, let b) = rhs, let lb = b as? URLResource + else { throw RuntimeError.invalid("URLResource comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "NotificationQueue.NotificationCoalescing") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NotificationQueue.NotificationCoalescing, - case .opaque(_, let b) = rhs, let lb = b as? NotificationQueue.NotificationCoalescing - else { throw RuntimeError.invalid("NotificationQueue.NotificationCoalescing comparison: bad payloads") } - return la == lb ? 0 : -1 - } - - i.registerComparator(on: "Date") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Date, - case .opaque(_, let b) = rhs, let lb = b as? Date - else { throw RuntimeError.invalid("Date comparison: bad payloads") } - return la < lb ? -1 : (la > lb ? 1 : 0) - } - -#if canImport(Darwin) - i.registerComparator(on: "AttributedString.AttributeInvalidationCondition") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? AttributedString.AttributeInvalidationCondition, - case .opaque(_, let b) = rhs, let lb = b as? AttributedString.AttributeInvalidationCondition - else { throw RuntimeError.invalid("AttributedString.AttributeInvalidationCondition comparison: bad payloads") } + i.registerComparator(on: "UUID") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? UUID, + case .opaque(_, let b) = rhs, let lb = b as? UUID + else { throw RuntimeError.invalid("UUID comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif - i.registerComparator(on: "NSRegularExpression.MatchingFlags") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSRegularExpression.MatchingFlags, - case .opaque(_, let b) = rhs, let lb = b as? NSRegularExpression.MatchingFlags - else { throw RuntimeError.invalid("NSRegularExpression.MatchingFlags comparison: bad payloads") } + i.registerComparator(on: "NSCalendar.Options") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSCalendar.Options, + case .opaque(_, let b) = rhs, let lb = b as? NSCalendar.Options + else { throw RuntimeError.invalid("NSCalendar.Options comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "FileManager.VolumeEnumerationOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? FileManager.VolumeEnumerationOptions, - case .opaque(_, let b) = rhs, let lb = b as? FileManager.VolumeEnumerationOptions - else { throw RuntimeError.invalid("FileManager.VolumeEnumerationOptions comparison: bad payloads") } - return la == lb ? 0 : -1 + i.registerComparator(on: "DateInterval") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? DateInterval, + case .opaque(_, let b) = rhs, let lb = b as? DateInterval + else { throw RuntimeError.invalid("DateInterval comparison: bad payloads") } + return la < lb ? -1 : (la > lb ? 1 : 0) } -#if canImport(Darwin) - i.registerComparator(on: "URLResponse") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? URLResponse, - case .opaque(_, let b) = rhs, let lb = b as? URLResponse - else { throw RuntimeError.invalid("URLResponse comparison: bad payloads") } + i.registerComparator(on: "Morphology.CustomPronoun") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Morphology.CustomPronoun, + case .opaque(_, let b) = rhs, let lb = b as? Morphology.CustomPronoun + else { throw RuntimeError.invalid("Morphology.CustomPronoun comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif - i.registerComparator(on: "Date.ComponentsFormatStyle") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Date.ComponentsFormatStyle, - case .opaque(_, let b) = rhs, let lb = b as? Date.ComponentsFormatStyle - else { throw RuntimeError.invalid("Date.ComponentsFormatStyle comparison: bad payloads") } + i.registerComparator(on: "Locale.LanguageCode") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Locale.LanguageCode, + case .opaque(_, let b) = rhs, let lb = b as? Locale.LanguageCode + else { throw RuntimeError.invalid("Locale.LanguageCode comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "POSIXError") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? POSIXError, - case .opaque(_, let b) = rhs, let lb = b as? POSIXError - else { throw RuntimeError.invalid("POSIXError comparison: bad payloads") } + i.registerComparator(on: "Date.FormatString") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Date.FormatString, + case .opaque(_, let b) = rhs, let lb = b as? Date.FormatString + else { throw RuntimeError.invalid("Date.FormatString comparison: bad payloads") } return la == lb ? 0 : -1 } @@ -435,601 +421,569 @@ extension FoundationModule { return la == lb ? 0 : -1 } - i.registerComparator(on: "Locale.Region") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Locale.Region, - case .opaque(_, let b) = rhs, let lb = b as? Locale.Region - else { throw RuntimeError.invalid("Locale.Region comparison: bad payloads") } + i.registerComparator(on: "CocoaError") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? CocoaError, + case .opaque(_, let b) = rhs, let lb = b as? CocoaError + else { throw RuntimeError.invalid("CocoaError comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "FileManager.DirectoryEnumerationOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? FileManager.DirectoryEnumerationOptions, - case .opaque(_, let b) = rhs, let lb = b as? FileManager.DirectoryEnumerationOptions - else { throw RuntimeError.invalid("FileManager.DirectoryEnumerationOptions comparison: bad payloads") } + i.registerComparator(on: "Date.VerbatimFormatStyle") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Date.VerbatimFormatStyle, + case .opaque(_, let b) = rhs, let lb = b as? Date.VerbatimFormatStyle + else { throw RuntimeError.invalid("Date.VerbatimFormatStyle comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "Progress.FileOperationKind") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Progress.FileOperationKind, - case .opaque(_, let b) = rhs, let lb = b as? Progress.FileOperationKind - else { throw RuntimeError.invalid("Progress.FileOperationKind comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "PersonNameComponents.AttributedStyle") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? PersonNameComponents.AttributedStyle, + case .opaque(_, let b) = rhs, let lb = b as? PersonNameComponents.AttributedStyle + else { throw RuntimeError.invalid("PersonNameComponents.AttributedStyle comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif - i.registerComparator(on: "ByteCountFormatStyle") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? ByteCountFormatStyle, - case .opaque(_, let b) = rhs, let lb = b as? ByteCountFormatStyle - else { throw RuntimeError.invalid("ByteCountFormatStyle comparison: bad payloads") } + i.registerComparator(on: "NumberFormatStyleConfiguration.Grouping") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NumberFormatStyleConfiguration.Grouping, + case .opaque(_, let b) = rhs, let lb = b as? NumberFormatStyleConfiguration.Grouping + else { throw RuntimeError.invalid("NumberFormatStyleConfiguration.Grouping comparison: bad payloads") } return la == lb ? 0 : -1 } -#if canImport(Darwin) - i.registerComparator(on: "NSLinguisticTagScheme") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSLinguisticTagScheme, - case .opaque(_, let b) = rhs, let lb = b as? NSLinguisticTagScheme - else { throw RuntimeError.invalid("NSLinguisticTagScheme comparison: bad payloads") } + i.registerComparator(on: "FileProtectionType") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? FileProtectionType, + case .opaque(_, let b) = rhs, let lb = b as? FileProtectionType + else { throw RuntimeError.invalid("FileProtectionType comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif - i.registerComparator(on: "StreamNetworkServiceTypeValue") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? StreamNetworkServiceTypeValue, - case .opaque(_, let b) = rhs, let lb = b as? StreamNetworkServiceTypeValue - else { throw RuntimeError.invalid("StreamNetworkServiceTypeValue comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "PersonNameComponentsFormatter.Options") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? PersonNameComponentsFormatter.Options, + case .opaque(_, let b) = rhs, let lb = b as? PersonNameComponentsFormatter.Options + else { throw RuntimeError.invalid("PersonNameComponentsFormatter.Options comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif - i.registerComparator(on: "Stream.PropertyKey") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Stream.PropertyKey, - case .opaque(_, let b) = rhs, let lb = b as? Stream.PropertyKey - else { throw RuntimeError.invalid("Stream.PropertyKey comparison: bad payloads") } - return la == lb ? 0 : -1 - } - - i.registerComparator(on: "ProgressUserInfoKey") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? ProgressUserInfoKey, - case .opaque(_, let b) = rhs, let lb = b as? ProgressUserInfoKey - else { throw RuntimeError.invalid("ProgressUserInfoKey comparison: bad payloads") } - return la == lb ? 0 : -1 - } - - i.registerComparator(on: "Locale.Subdivision") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Locale.Subdivision, - case .opaque(_, let b) = rhs, let lb = b as? Locale.Subdivision - else { throw RuntimeError.invalid("Locale.Subdivision comparison: bad payloads") } + i.registerComparator(on: "URLError") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? URLError, + case .opaque(_, let b) = rhs, let lb = b as? URLError + else { throw RuntimeError.invalid("URLError comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "Locale.Components") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Locale.Components, - case .opaque(_, let b) = rhs, let lb = b as? Locale.Components - else { throw RuntimeError.invalid("Locale.Components comparison: bad payloads") } + i.registerComparator(on: "StringTransform") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? StringTransform, + case .opaque(_, let b) = rhs, let lb = b as? StringTransform + else { throw RuntimeError.invalid("StringTransform comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "URLFileProtection") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? URLFileProtection, - case .opaque(_, let b) = rhs, let lb = b as? URLFileProtection - else { throw RuntimeError.invalid("URLFileProtection comparison: bad payloads") } + i.registerComparator(on: "NSURL.BookmarkCreationOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSURL.BookmarkCreationOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSURL.BookmarkCreationOptions + else { throw RuntimeError.invalid("NSURL.BookmarkCreationOptions comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "FileAttributeType") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? FileAttributeType, - case .opaque(_, let b) = rhs, let lb = b as? FileAttributeType - else { throw RuntimeError.invalid("FileAttributeType comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "URLSession") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? URLSession, + case .opaque(_, let b) = rhs, let lb = b as? URLSession + else { throw RuntimeError.invalid("URLSession comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif - i.registerComparator(on: "TimeZone") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? TimeZone, - case .opaque(_, let b) = rhs, let lb = b as? TimeZone - else { throw RuntimeError.invalid("TimeZone comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "Bundle") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Bundle, + case .opaque(_, let b) = rhs, let lb = b as? Bundle + else { throw RuntimeError.invalid("Bundle comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif - i.registerComparator(on: "StreamSOCKSProxyVersion") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? StreamSOCKSProxyVersion, - case .opaque(_, let b) = rhs, let lb = b as? StreamSOCKSProxyVersion - else { throw RuntimeError.invalid("StreamSOCKSProxyVersion comparison: bad payloads") } + i.registerComparator(on: "Date.RelativeFormatStyle") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Date.RelativeFormatStyle, + case .opaque(_, let b) = rhs, let lb = b as? Date.RelativeFormatStyle + else { throw RuntimeError.invalid("Date.RelativeFormatStyle comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "ProcessInfo") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? ProcessInfo, - case .opaque(_, let b) = rhs, let lb = b as? ProcessInfo - else { throw RuntimeError.invalid("ProcessInfo comparison: bad payloads") } + i.registerComparator(on: "NSFileProviderServiceName") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSFileProviderServiceName, + case .opaque(_, let b) = rhs, let lb = b as? NSFileProviderServiceName + else { throw RuntimeError.invalid("NSFileProviderServiceName comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "URL") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? URL, - case .opaque(_, let b) = rhs, let lb = b as? URL - else { throw RuntimeError.invalid("URL comparison: bad payloads") } + i.registerComparator(on: "Date.AttributedStyle") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Date.AttributedStyle, + case .opaque(_, let b) = rhs, let lb = b as? Date.AttributedStyle + else { throw RuntimeError.invalid("Date.AttributedStyle comparison: bad payloads") } return la == lb ? 0 : -1 } -#if canImport(Darwin) - i.registerComparator(on: "URL.FormatStyle") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? URL.FormatStyle, - case .opaque(_, let b) = rhs, let lb = b as? URL.FormatStyle - else { throw RuntimeError.invalid("URL.FormatStyle comparison: bad payloads") } + i.registerComparator(on: "NumberFormatStyleConfiguration.DecimalSeparatorDisplayStrategy") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NumberFormatStyleConfiguration.DecimalSeparatorDisplayStrategy, + case .opaque(_, let b) = rhs, let lb = b as? NumberFormatStyleConfiguration.DecimalSeparatorDisplayStrategy + else { throw RuntimeError.invalid("NumberFormatStyleConfiguration.DecimalSeparatorDisplayStrategy comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif -#if canImport(Darwin) - i.registerComparator(on: "URLThumbnailDictionaryItem") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? URLThumbnailDictionaryItem, - case .opaque(_, let b) = rhs, let lb = b as? URLThumbnailDictionaryItem - else { throw RuntimeError.invalid("URLThumbnailDictionaryItem comparison: bad payloads") } + i.registerComparator(on: "URLComponents") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? URLComponents, + case .opaque(_, let b) = rhs, let lb = b as? URLComponents + else { throw RuntimeError.invalid("URLComponents comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif - i.registerComparator(on: "IndexPath") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? IndexPath, - case .opaque(_, let b) = rhs, let lb = b as? IndexPath - else { throw RuntimeError.invalid("IndexPath comparison: bad payloads") } - return la < lb ? -1 : (la > lb ? 1 : 0) + i.registerComparator(on: "RunLoop.Mode") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? RunLoop.Mode, + case .opaque(_, let b) = rhs, let lb = b as? RunLoop.Mode + else { throw RuntimeError.invalid("RunLoop.Mode comparison: bad payloads") } + return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "AttributedString.MarkdownSourcePosition") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? AttributedString.MarkdownSourcePosition, - case .opaque(_, let b) = rhs, let lb = b as? AttributedString.MarkdownSourcePosition - else { throw RuntimeError.invalid("AttributedString.MarkdownSourcePosition comparison: bad payloads") } + i.registerComparator(on: "FileWrapper") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? FileWrapper, + case .opaque(_, let b) = rhs, let lb = b as? FileWrapper + else { throw RuntimeError.invalid("FileWrapper comparison: bad payloads") } return la == lb ? 0 : -1 } #endif #if canImport(Darwin) - i.registerComparator(on: "URLSession") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? URLSession, - case .opaque(_, let b) = rhs, let lb = b as? URLSession - else { throw RuntimeError.invalid("URLSession comparison: bad payloads") } + i.registerComparator(on: "NSFileVersion.ReplacingOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSFileVersion.ReplacingOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSFileVersion.ReplacingOptions + else { throw RuntimeError.invalid("NSFileVersion.ReplacingOptions comparison: bad payloads") } return la == lb ? 0 : -1 } #endif -#if canImport(Darwin) - i.registerComparator(on: "NetService.Options") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NetService.Options, - case .opaque(_, let b) = rhs, let lb = b as? NetService.Options - else { throw RuntimeError.invalid("NetService.Options comparison: bad payloads") } + i.registerComparator(on: "CurrencyFormatStyleConfiguration.SignDisplayStrategy") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? CurrencyFormatStyleConfiguration.SignDisplayStrategy, + case .opaque(_, let b) = rhs, let lb = b as? CurrencyFormatStyleConfiguration.SignDisplayStrategy + else { throw RuntimeError.invalid("CurrencyFormatStyleConfiguration.SignDisplayStrategy comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif - i.registerComparator(on: "FileAttributeKey") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? FileAttributeKey, - case .opaque(_, let b) = rhs, let lb = b as? FileAttributeKey - else { throw RuntimeError.invalid("FileAttributeKey comparison: bad payloads") } + i.registerComparator(on: "NSRegularExpression.MatchingFlags") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSRegularExpression.MatchingFlags, + case .opaque(_, let b) = rhs, let lb = b as? NSRegularExpression.MatchingFlags + else { throw RuntimeError.invalid("NSRegularExpression.MatchingFlags comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "Calendar") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Calendar, - case .opaque(_, let b) = rhs, let lb = b as? Calendar - else { throw RuntimeError.invalid("Calendar comparison: bad payloads") } + i.registerComparator(on: "PropertyListSerialization.MutabilityOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? PropertyListSerialization.MutabilityOptions, + case .opaque(_, let b) = rhs, let lb = b as? PropertyListSerialization.MutabilityOptions + else { throw RuntimeError.invalid("PropertyListSerialization.MutabilityOptions comparison: bad payloads") } return la == lb ? 0 : -1 } -#if canImport(Darwin) - i.registerComparator(on: "NSValueTransformerName") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSValueTransformerName, - case .opaque(_, let b) = rhs, let lb = b as? NSValueTransformerName - else { throw RuntimeError.invalid("NSValueTransformerName comparison: bad payloads") } + i.registerComparator(on: "Locale.Collation") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Locale.Collation, + case .opaque(_, let b) = rhs, let lb = b as? Locale.Collation + else { throw RuntimeError.invalid("Locale.Collation comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif - i.registerComparator(on: "NumberFormatStyleConfiguration.Notation") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NumberFormatStyleConfiguration.Notation, - case .opaque(_, let b) = rhs, let lb = b as? NumberFormatStyleConfiguration.Notation - else { throw RuntimeError.invalid("NumberFormatStyleConfiguration.Notation comparison: bad payloads") } + i.registerComparator(on: "JSONSerialization.ReadingOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? JSONSerialization.ReadingOptions, + case .opaque(_, let b) = rhs, let lb = b as? JSONSerialization.ReadingOptions + else { throw RuntimeError.invalid("JSONSerialization.ReadingOptions comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "NumberFormatStyleConfiguration.SignDisplayStrategy") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NumberFormatStyleConfiguration.SignDisplayStrategy, - case .opaque(_, let b) = rhs, let lb = b as? NumberFormatStyleConfiguration.SignDisplayStrategy - else { throw RuntimeError.invalid("NumberFormatStyleConfiguration.SignDisplayStrategy comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "HTTPURLResponse") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? HTTPURLResponse, + case .opaque(_, let b) = rhs, let lb = b as? HTTPURLResponse + else { throw RuntimeError.invalid("HTTPURLResponse comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif - i.registerComparator(on: "StringStyle") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? StringStyle, - case .opaque(_, let b) = rhs, let lb = b as? StringStyle - else { throw RuntimeError.invalid("StringStyle comparison: bad payloads") } + i.registerComparator(on: "FileManager.ItemReplacementOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? FileManager.ItemReplacementOptions, + case .opaque(_, let b) = rhs, let lb = b as? FileManager.ItemReplacementOptions + else { throw RuntimeError.invalid("FileManager.ItemReplacementOptions comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "DateComponentsFormatter.ZeroFormattingBehavior") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? DateComponentsFormatter.ZeroFormattingBehavior, - case .opaque(_, let b) = rhs, let lb = b as? DateComponentsFormatter.ZeroFormattingBehavior - else { throw RuntimeError.invalid("DateComponentsFormatter.ZeroFormattingBehavior comparison: bad payloads") } + i.registerComparator(on: "NSKeyValueOperator") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSKeyValueOperator, + case .opaque(_, let b) = rhs, let lb = b as? NSKeyValueOperator + else { throw RuntimeError.invalid("NSKeyValueOperator comparison: bad payloads") } return la == lb ? 0 : -1 } #endif -#if canImport(Darwin) - i.registerComparator(on: "PersonNameComponentsFormatter.Options") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? PersonNameComponentsFormatter.Options, - case .opaque(_, let b) = rhs, let lb = b as? PersonNameComponentsFormatter.Options - else { throw RuntimeError.invalid("PersonNameComponentsFormatter.Options comparison: bad payloads") } + i.registerComparator(on: "NSLocale.Key") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSLocale.Key, + case .opaque(_, let b) = rhs, let lb = b as? NSLocale.Key + else { throw RuntimeError.invalid("NSLocale.Key comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif - i.registerComparator(on: "ISO8601DateFormatter.Options") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? ISO8601DateFormatter.Options, - case .opaque(_, let b) = rhs, let lb = b as? ISO8601DateFormatter.Options - else { throw RuntimeError.invalid("ISO8601DateFormatter.Options comparison: bad payloads") } + i.registerComparator(on: "Locale.Script") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Locale.Script, + case .opaque(_, let b) = rhs, let lb = b as? Locale.Script + else { throw RuntimeError.invalid("Locale.Script comparison: bad payloads") } return la == lb ? 0 : -1 } -#if canImport(Darwin) - i.registerComparator(on: "NSMachPort.Options") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSMachPort.Options, - case .opaque(_, let b) = rhs, let lb = b as? NSMachPort.Options - else { throw RuntimeError.invalid("NSMachPort.Options comparison: bad payloads") } + i.registerComparator(on: "NSAttributedString.Key") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSAttributedString.Key, + case .opaque(_, let b) = rhs, let lb = b as? NSAttributedString.Key + else { throw RuntimeError.invalid("NSAttributedString.Key comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif - i.registerComparator(on: "URLRequest") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? URLRequest, - case .opaque(_, let b) = rhs, let lb = b as? URLRequest - else { throw RuntimeError.invalid("URLRequest comparison: bad payloads") } + i.registerComparator(on: "StreamNetworkServiceTypeValue") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? StreamNetworkServiceTypeValue, + case .opaque(_, let b) = rhs, let lb = b as? StreamNetworkServiceTypeValue + else { throw RuntimeError.invalid("StreamNetworkServiceTypeValue comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "JSONEncoder.OutputFormatting") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? JSONEncoder.OutputFormatting, - case .opaque(_, let b) = rhs, let lb = b as? JSONEncoder.OutputFormatting - else { throw RuntimeError.invalid("JSONEncoder.OutputFormatting comparison: bad payloads") } + i.registerComparator(on: "NSCalendar.Unit") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSCalendar.Unit, + case .opaque(_, let b) = rhs, let lb = b as? NSCalendar.Unit + else { throw RuntimeError.invalid("NSCalendar.Unit comparison: bad payloads") } return la == lb ? 0 : -1 } -#if canImport(Darwin) - i.registerComparator(on: "NSLinguisticTag") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSLinguisticTag, - case .opaque(_, let b) = rhs, let lb = b as? NSLinguisticTag - else { throw RuntimeError.invalid("NSLinguisticTag comparison: bad payloads") } + i.registerComparator(on: "NSSortOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSSortOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSSortOptions + else { throw RuntimeError.invalid("NSSortOptions comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif #if canImport(Darwin) - i.registerComparator(on: "NSFileProviderServiceName") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSFileProviderServiceName, - case .opaque(_, let b) = rhs, let lb = b as? NSFileProviderServiceName - else { throw RuntimeError.invalid("NSFileProviderServiceName comparison: bad payloads") } + i.registerComparator(on: "PresentationIntent.TableColumn") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? PresentationIntent.TableColumn, + case .opaque(_, let b) = rhs, let lb = b as? PresentationIntent.TableColumn + else { throw RuntimeError.invalid("PresentationIntent.TableColumn comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "Locale.Currency") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Locale.Currency, - case .opaque(_, let b) = rhs, let lb = b as? Locale.Currency - else { throw RuntimeError.invalid("Locale.Currency comparison: bad payloads") } - return la == lb ? 0 : -1 - } - - i.registerComparator(on: "JSONSerialization.ReadingOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? JSONSerialization.ReadingOptions, - case .opaque(_, let b) = rhs, let lb = b as? JSONSerialization.ReadingOptions - else { throw RuntimeError.invalid("JSONSerialization.ReadingOptions comparison: bad payloads") } + i.registerComparator(on: "CurrencyFormatStyleConfiguration.Presentation") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? CurrencyFormatStyleConfiguration.Presentation, + case .opaque(_, let b) = rhs, let lb = b as? CurrencyFormatStyleConfiguration.Presentation + else { throw RuntimeError.invalid("CurrencyFormatStyleConfiguration.Presentation comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "URLFileResourceType") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? URLFileResourceType, - case .opaque(_, let b) = rhs, let lb = b as? URLFileResourceType - else { throw RuntimeError.invalid("URLFileResourceType comparison: bad payloads") } - return la == lb ? 0 : -1 + i.registerComparator(on: "Date") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Date, + case .opaque(_, let b) = rhs, let lb = b as? Date + else { throw RuntimeError.invalid("Date comparison: bad payloads") } + return la < lb ? -1 : (la > lb ? 1 : 0) } - i.registerComparator(on: "Locale.Collation") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Locale.Collation, - case .opaque(_, let b) = rhs, let lb = b as? Locale.Collation - else { throw RuntimeError.invalid("Locale.Collation comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "PersonNameComponents.ParseStrategy") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? PersonNameComponents.ParseStrategy, + case .opaque(_, let b) = rhs, let lb = b as? PersonNameComponents.ParseStrategy + else { throw RuntimeError.invalid("PersonNameComponents.ParseStrategy comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif #if canImport(Darwin) - i.registerComparator(on: "NSURL.BookmarkCreationOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSURL.BookmarkCreationOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSURL.BookmarkCreationOptions - else { throw RuntimeError.invalid("NSURL.BookmarkCreationOptions comparison: bad payloads") } + i.registerComparator(on: "URLThumbnailDictionaryItem") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? URLThumbnailDictionaryItem, + case .opaque(_, let b) = rhs, let lb = b as? URLThumbnailDictionaryItem + else { throw RuntimeError.invalid("URLThumbnailDictionaryItem comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "Decimal") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Decimal, - case .opaque(_, let b) = rhs, let lb = b as? Decimal - else { throw RuntimeError.invalid("Decimal comparison: bad payloads") } - return la < lb ? -1 : (la > lb ? 1 : 0) - } - #if canImport(Darwin) - i.registerComparator(on: "NSAttributedStringFormattingContextKey") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSAttributedStringFormattingContextKey, - case .opaque(_, let b) = rhs, let lb = b as? NSAttributedStringFormattingContextKey - else { throw RuntimeError.invalid("NSAttributedStringFormattingContextKey comparison: bad payloads") } + i.registerComparator(on: "AttributedString.FormattingOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? AttributedString.FormattingOptions, + case .opaque(_, let b) = rhs, let lb = b as? AttributedString.FormattingOptions + else { throw RuntimeError.invalid("AttributedString.FormattingOptions comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "NSAttributedString.Key") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSAttributedString.Key, - case .opaque(_, let b) = rhs, let lb = b as? NSAttributedString.Key - else { throw RuntimeError.invalid("NSAttributedString.Key comparison: bad payloads") } + i.registerComparator(on: "IndexSet.Index") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? IndexSet.Index, + case .opaque(_, let b) = rhs, let lb = b as? IndexSet.Index + else { throw RuntimeError.invalid("IndexSet.Index comparison: bad payloads") } + return la < lb ? -1 : (la > lb ? 1 : 0) + } + + i.registerComparator(on: "Stream.PropertyKey") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Stream.PropertyKey, + case .opaque(_, let b) = rhs, let lb = b as? Stream.PropertyKey + else { throw RuntimeError.invalid("Stream.PropertyKey comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "HTTPCookieStringPolicy") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? HTTPCookieStringPolicy, - case .opaque(_, let b) = rhs, let lb = b as? HTTPCookieStringPolicy - else { throw RuntimeError.invalid("HTTPCookieStringPolicy comparison: bad payloads") } + i.registerComparator(on: "NSLinguisticTagScheme") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSLinguisticTagScheme, + case .opaque(_, let b) = rhs, let lb = b as? NSLinguisticTagScheme + else { throw RuntimeError.invalid("NSLinguisticTagScheme comparison: bad payloads") } return la == lb ? 0 : -1 } #endif -#if canImport(Darwin) - i.registerComparator(on: "StringEncodingDetectionOptionsKey") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? StringEncodingDetectionOptionsKey, - case .opaque(_, let b) = rhs, let lb = b as? StringEncodingDetectionOptionsKey - else { throw RuntimeError.invalid("StringEncodingDetectionOptionsKey comparison: bad payloads") } + i.registerComparator(on: "NSAttributedString.EnumerationOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSAttributedString.EnumerationOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSAttributedString.EnumerationOptions + else { throw RuntimeError.invalid("NSAttributedString.EnumerationOptions comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif #if canImport(Darwin) - i.registerComparator(on: "AttributedSubstring") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? AttributedSubstring, - case .opaque(_, let b) = rhs, let lb = b as? AttributedSubstring - else { throw RuntimeError.invalid("AttributedSubstring comparison: bad payloads") } + i.registerComparator(on: "NSMachPort.Options") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSMachPort.Options, + case .opaque(_, let b) = rhs, let lb = b as? NSMachPort.Options + else { throw RuntimeError.invalid("NSMachPort.Options comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "CharacterSet") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? CharacterSet, - case .opaque(_, let b) = rhs, let lb = b as? CharacterSet - else { throw RuntimeError.invalid("CharacterSet comparison: bad payloads") } + i.registerComparator(on: "Locale") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Locale, + case .opaque(_, let b) = rhs, let lb = b as? Locale + else { throw RuntimeError.invalid("Locale comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "NSRegularExpression.MatchingOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSRegularExpression.MatchingOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSRegularExpression.MatchingOptions - else { throw RuntimeError.invalid("NSRegularExpression.MatchingOptions comparison: bad payloads") } + i.registerComparator(on: "NSExceptionName") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSExceptionName, + case .opaque(_, let b) = rhs, let lb = b as? NSExceptionName + else { throw RuntimeError.invalid("NSExceptionName comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "NumberFormatStyleConfiguration.Precision") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NumberFormatStyleConfiguration.Precision, - case .opaque(_, let b) = rhs, let lb = b as? NumberFormatStyleConfiguration.Precision - else { throw RuntimeError.invalid("NumberFormatStyleConfiguration.Precision comparison: bad payloads") } + i.registerComparator(on: "NSTextCheckingKey") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSTextCheckingKey, + case .opaque(_, let b) = rhs, let lb = b as? NSTextCheckingKey + else { throw RuntimeError.invalid("NSTextCheckingKey comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "Date.AttributedStyle") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Date.AttributedStyle, - case .opaque(_, let b) = rhs, let lb = b as? Date.AttributedStyle - else { throw RuntimeError.invalid("Date.AttributedStyle comparison: bad payloads") } + i.registerComparator(on: "FileManager.VolumeEnumerationOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? FileManager.VolumeEnumerationOptions, + case .opaque(_, let b) = rhs, let lb = b as? FileManager.VolumeEnumerationOptions + else { throw RuntimeError.invalid("FileManager.VolumeEnumerationOptions comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "NSCalendar.Unit") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSCalendar.Unit, - case .opaque(_, let b) = rhs, let lb = b as? NSCalendar.Unit - else { throw RuntimeError.invalid("NSCalendar.Unit comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "NSValueTransformerName") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSValueTransformerName, + case .opaque(_, let b) = rhs, let lb = b as? NSValueTransformerName + else { throw RuntimeError.invalid("NSValueTransformerName comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif #if canImport(Darwin) - i.registerComparator(on: "AttributedString.Runs") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? AttributedString.Runs, - case .opaque(_, let b) = rhs, let lb = b as? AttributedString.Runs - else { throw RuntimeError.invalid("AttributedString.Runs comparison: bad payloads") } + i.registerComparator(on: "FileWrapper.WritingOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? FileWrapper.WritingOptions, + case .opaque(_, let b) = rhs, let lb = b as? FileWrapper.WritingOptions + else { throw RuntimeError.invalid("FileWrapper.WritingOptions comparison: bad payloads") } return la == lb ? 0 : -1 } #endif -#if canImport(Darwin) - i.registerComparator(on: "NSComparisonPredicate.Options") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSComparisonPredicate.Options, - case .opaque(_, let b) = rhs, let lb = b as? NSComparisonPredicate.Options - else { throw RuntimeError.invalid("NSComparisonPredicate.Options comparison: bad payloads") } + i.registerComparator(on: "ByteCountFormatter.Units") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? ByteCountFormatter.Units, + case .opaque(_, let b) = rhs, let lb = b as? ByteCountFormatter.Units + else { throw RuntimeError.invalid("ByteCountFormatter.Units comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif - i.registerComparator(on: "NSRegularExpression.Options") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSRegularExpression.Options, - case .opaque(_, let b) = rhs, let lb = b as? NSRegularExpression.Options - else { throw RuntimeError.invalid("NSRegularExpression.Options comparison: bad payloads") } + i.registerComparator(on: "HTTPCookiePropertyKey") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? HTTPCookiePropertyKey, + case .opaque(_, let b) = rhs, let lb = b as? HTTPCookiePropertyKey + else { throw RuntimeError.invalid("HTTPCookiePropertyKey comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "NSFileCoordinator.ReadingOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSFileCoordinator.ReadingOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSFileCoordinator.ReadingOptions - else { throw RuntimeError.invalid("NSFileCoordinator.ReadingOptions comparison: bad payloads") } + i.registerComparator(on: "MeasurementFormatter.UnitOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? MeasurementFormatter.UnitOptions, + case .opaque(_, let b) = rhs, let lb = b as? MeasurementFormatter.UnitOptions + else { throw RuntimeError.invalid("MeasurementFormatter.UnitOptions comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "URLResourceKey") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? URLResourceKey, - case .opaque(_, let b) = rhs, let lb = b as? URLResourceKey - else { throw RuntimeError.invalid("URLResourceKey comparison: bad payloads") } + i.registerComparator(on: "Date.IntervalFormatStyle") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Date.IntervalFormatStyle, + case .opaque(_, let b) = rhs, let lb = b as? Date.IntervalFormatStyle + else { throw RuntimeError.invalid("Date.IntervalFormatStyle comparison: bad payloads") } return la == lb ? 0 : -1 } -#if canImport(Darwin) - i.registerComparator(on: "NSPointerFunctions.Options") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSPointerFunctions.Options, - case .opaque(_, let b) = rhs, let lb = b as? NSPointerFunctions.Options - else { throw RuntimeError.invalid("NSPointerFunctions.Options comparison: bad payloads") } + i.registerComparator(on: "JSONSerialization.WritingOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? JSONSerialization.WritingOptions, + case .opaque(_, let b) = rhs, let lb = b as? JSONSerialization.WritingOptions + else { throw RuntimeError.invalid("JSONSerialization.WritingOptions comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif #if canImport(Darwin) - i.registerComparator(on: "ErrorUserInfoKey") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? ErrorUserInfoKey, - case .opaque(_, let b) = rhs, let lb = b as? ErrorUserInfoKey - else { throw RuntimeError.invalid("ErrorUserInfoKey comparison: bad payloads") } + i.registerComparator(on: "NSData.ReadingOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSData.ReadingOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSData.ReadingOptions + else { throw RuntimeError.invalid("NSData.ReadingOptions comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "CurrencyFormatStyleConfiguration.SignDisplayStrategy") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? CurrencyFormatStyleConfiguration.SignDisplayStrategy, - case .opaque(_, let b) = rhs, let lb = b as? CurrencyFormatStyleConfiguration.SignDisplayStrategy - else { throw RuntimeError.invalid("CurrencyFormatStyleConfiguration.SignDisplayStrategy comparison: bad payloads") } + i.registerComparator(on: "FormatStyleCapitalizationContext") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? FormatStyleCapitalizationContext, + case .opaque(_, let b) = rhs, let lb = b as? FormatStyleCapitalizationContext + else { throw RuntimeError.invalid("FormatStyleCapitalizationContext comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "NSFileVersion.AddingOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSFileVersion.AddingOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSFileVersion.AddingOptions - else { throw RuntimeError.invalid("NSFileVersion.AddingOptions comparison: bad payloads") } + i.registerComparator(on: "FileHandle") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? FileHandle, + case .opaque(_, let b) = rhs, let lb = b as? FileHandle + else { throw RuntimeError.invalid("FileHandle comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "UUID") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? UUID, - case .opaque(_, let b) = rhs, let lb = b as? UUID - else { throw RuntimeError.invalid("UUID comparison: bad payloads") } + i.registerComparator(on: "ByteCountFormatStyle.Attributed") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? ByteCountFormatStyle.Attributed, + case .opaque(_, let b) = rhs, let lb = b as? ByteCountFormatStyle.Attributed + else { throw RuntimeError.invalid("ByteCountFormatStyle.Attributed comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "FileManager.ItemReplacementOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? FileManager.ItemReplacementOptions, - case .opaque(_, let b) = rhs, let lb = b as? FileManager.ItemReplacementOptions - else { throw RuntimeError.invalid("FileManager.ItemReplacementOptions comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "NSKeyValueObservingOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSKeyValueObservingOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSKeyValueObservingOptions + else { throw RuntimeError.invalid("NSKeyValueObservingOptions comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif - i.registerComparator(on: "Notification") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Notification, - case .opaque(_, let b) = rhs, let lb = b as? Notification - else { throw RuntimeError.invalid("Notification comparison: bad payloads") } + i.registerComparator(on: "FileAttributeKey") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? FileAttributeKey, + case .opaque(_, let b) = rhs, let lb = b as? FileAttributeKey + else { throw RuntimeError.invalid("FileAttributeKey comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "NSOrderedCollectionDifferenceCalculationOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSOrderedCollectionDifferenceCalculationOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSOrderedCollectionDifferenceCalculationOptions - else { throw RuntimeError.invalid("NSOrderedCollectionDifferenceCalculationOptions comparison: bad payloads") } + i.registerComparator(on: "NSData.SearchOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSData.SearchOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSData.SearchOptions + else { throw RuntimeError.invalid("NSData.SearchOptions comparison: bad payloads") } return la == lb ? 0 : -1 } #endif #if canImport(Darwin) - i.registerComparator(on: "URLResource") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? URLResource, - case .opaque(_, let b) = rhs, let lb = b as? URLResource - else { throw RuntimeError.invalid("URLResource comparison: bad payloads") } + i.registerComparator(on: "NSString.CompareOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSString.CompareOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSString.CompareOptions + else { throw RuntimeError.invalid("NSString.CompareOptions comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "Locale.Language") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Locale.Language, - case .opaque(_, let b) = rhs, let lb = b as? Locale.Language - else { throw RuntimeError.invalid("Locale.Language comparison: bad payloads") } - return la == lb ? 0 : -1 - } - - i.registerComparator(on: "Locale.Script") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Locale.Script, - case .opaque(_, let b) = rhs, let lb = b as? Locale.Script - else { throw RuntimeError.invalid("Locale.Script comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "StringEncodingDetectionOptionsKey") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? StringEncodingDetectionOptionsKey, + case .opaque(_, let b) = rhs, let lb = b as? StringEncodingDetectionOptionsKey + else { throw RuntimeError.invalid("StringEncodingDetectionOptionsKey comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif #if canImport(Darwin) - i.registerComparator(on: "AttributedString.FormattingOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? AttributedString.FormattingOptions, - case .opaque(_, let b) = rhs, let lb = b as? AttributedString.FormattingOptions - else { throw RuntimeError.invalid("AttributedString.FormattingOptions comparison: bad payloads") } + i.registerComparator(on: "NSLinguisticTag") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSLinguisticTag, + case .opaque(_, let b) = rhs, let lb = b as? NSLinguisticTag + else { throw RuntimeError.invalid("NSLinguisticTag comparison: bad payloads") } return la == lb ? 0 : -1 } #endif #if canImport(Darwin) - i.registerComparator(on: "NSData.WritingOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSData.WritingOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSData.WritingOptions - else { throw RuntimeError.invalid("NSData.WritingOptions comparison: bad payloads") } + i.registerComparator(on: "DateComponentsFormatter.ZeroFormattingBehavior") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? DateComponentsFormatter.ZeroFormattingBehavior, + case .opaque(_, let b) = rhs, let lb = b as? DateComponentsFormatter.ZeroFormattingBehavior + else { throw RuntimeError.invalid("DateComponentsFormatter.ZeroFormattingBehavior comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "NumberFormatStyleConfiguration.DecimalSeparatorDisplayStrategy") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NumberFormatStyleConfiguration.DecimalSeparatorDisplayStrategy, - case .opaque(_, let b) = rhs, let lb = b as? NumberFormatStyleConfiguration.DecimalSeparatorDisplayStrategy - else { throw RuntimeError.invalid("NumberFormatStyleConfiguration.DecimalSeparatorDisplayStrategy comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "ErrorUserInfoKey") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? ErrorUserInfoKey, + case .opaque(_, let b) = rhs, let lb = b as? ErrorUserInfoKey + else { throw RuntimeError.invalid("ErrorUserInfoKey comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif #if canImport(Darwin) - i.registerComparator(on: "NSKeyValueObservingOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSKeyValueObservingOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSKeyValueObservingOptions - else { throw RuntimeError.invalid("NSKeyValueObservingOptions comparison: bad payloads") } + i.registerComparator(on: "NSKeyValueChangeKey") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSKeyValueChangeKey, + case .opaque(_, let b) = rhs, let lb = b as? NSKeyValueChangeKey + else { throw RuntimeError.invalid("NSKeyValueChangeKey comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "JSONSerialization.WritingOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? JSONSerialization.WritingOptions, - case .opaque(_, let b) = rhs, let lb = b as? JSONSerialization.WritingOptions - else { throw RuntimeError.invalid("JSONSerialization.WritingOptions comparison: bad payloads") } + i.registerComparator(on: "IndexSet.RangeView") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? IndexSet.RangeView, + case .opaque(_, let b) = rhs, let lb = b as? IndexSet.RangeView + else { throw RuntimeError.invalid("IndexSet.RangeView comparison: bad payloads") } return la == lb ? 0 : -1 } -#if canImport(Darwin) - i.registerComparator(on: "NSKeyValueOperator") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSKeyValueOperator, - case .opaque(_, let b) = rhs, let lb = b as? NSKeyValueOperator - else { throw RuntimeError.invalid("NSKeyValueOperator comparison: bad payloads") } + i.registerComparator(on: "NumberFormatStyleConfiguration.SignDisplayStrategy") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NumberFormatStyleConfiguration.SignDisplayStrategy, + case .opaque(_, let b) = rhs, let lb = b as? NumberFormatStyleConfiguration.SignDisplayStrategy + else { throw RuntimeError.invalid("NumberFormatStyleConfiguration.SignDisplayStrategy comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif - i.registerComparator(on: "StreamSocketSecurityLevel") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? StreamSocketSecurityLevel, - case .opaque(_, let b) = rhs, let lb = b as? StreamSocketSecurityLevel - else { throw RuntimeError.invalid("StreamSocketSecurityLevel comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "FileWrapper.ReadingOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? FileWrapper.ReadingOptions, + case .opaque(_, let b) = rhs, let lb = b as? FileWrapper.ReadingOptions + else { throw RuntimeError.invalid("FileWrapper.ReadingOptions comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif -#if canImport(Darwin) - i.registerComparator(on: "URLUbiquitousItemDownloadingStatus") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? URLUbiquitousItemDownloadingStatus, - case .opaque(_, let b) = rhs, let lb = b as? URLUbiquitousItemDownloadingStatus - else { throw RuntimeError.invalid("URLUbiquitousItemDownloadingStatus comparison: bad payloads") } + i.registerComparator(on: "NSString.EnumerationOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSString.EnumerationOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSString.EnumerationOptions + else { throw RuntimeError.invalid("NSString.EnumerationOptions comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif i.registerComparator(on: "NSNotification.Name") { lhs, rhs in guard case .opaque(_, let a) = lhs, let la = a as? NSNotification.Name, @@ -1038,13 +992,52 @@ extension FoundationModule { return la == lb ? 0 : -1 } - i.registerComparator(on: "NSLocale.Key") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSLocale.Key, - case .opaque(_, let b) = rhs, let lb = b as? NSLocale.Key - else { throw RuntimeError.invalid("NSLocale.Key comparison: bad payloads") } + i.registerComparator(on: "URLResourceKey") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? URLResourceKey, + case .opaque(_, let b) = rhs, let lb = b as? URLResourceKey + else { throw RuntimeError.invalid("URLResourceKey comparison: bad payloads") } + return la == lb ? 0 : -1 + } + + i.registerComparator(on: "NumberFormatStyleConfiguration.Notation") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NumberFormatStyleConfiguration.Notation, + case .opaque(_, let b) = rhs, let lb = b as? NumberFormatStyleConfiguration.Notation + else { throw RuntimeError.invalid("NumberFormatStyleConfiguration.Notation comparison: bad payloads") } + return la == lb ? 0 : -1 + } + +#if canImport(Darwin) + i.registerComparator(on: "NSOrderedCollectionDifferenceCalculationOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSOrderedCollectionDifferenceCalculationOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSOrderedCollectionDifferenceCalculationOptions + else { throw RuntimeError.invalid("NSOrderedCollectionDifferenceCalculationOptions comparison: bad payloads") } + return la == lb ? 0 : -1 + } +#endif + + i.registerComparator(on: "StreamSOCKSProxyConfiguration") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? StreamSOCKSProxyConfiguration, + case .opaque(_, let b) = rhs, let lb = b as? StreamSOCKSProxyConfiguration + else { throw RuntimeError.invalid("StreamSOCKSProxyConfiguration comparison: bad payloads") } return la == lb ? 0 : -1 } + i.registerComparator(on: "Locale.Variant") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Locale.Variant, + case .opaque(_, let b) = rhs, let lb = b as? Locale.Variant + else { throw RuntimeError.invalid("Locale.Variant comparison: bad payloads") } + return la == lb ? 0 : -1 + } + +#if canImport(Darwin) + i.registerComparator(on: "URLUbiquitousSharedItemPermissions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? URLUbiquitousSharedItemPermissions, + case .opaque(_, let b) = rhs, let lb = b as? URLUbiquitousSharedItemPermissions + else { throw RuntimeError.invalid("URLUbiquitousSharedItemPermissions comparison: bad payloads") } + return la == lb ? 0 : -1 + } +#endif + i.registerComparator(on: "URLQueryItem") { lhs, rhs in guard case .opaque(_, let a) = lhs, let la = a as? URLQueryItem, case .opaque(_, let b) = rhs, let lb = b as? URLQueryItem @@ -1052,444 +1045,495 @@ extension FoundationModule { return la == lb ? 0 : -1 } - i.registerComparator(on: "HTTPCookiePropertyKey") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? HTTPCookiePropertyKey, - case .opaque(_, let b) = rhs, let lb = b as? HTTPCookiePropertyKey - else { throw RuntimeError.invalid("HTTPCookiePropertyKey comparison: bad payloads") } + i.registerComparator(on: "Notification") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Notification, + case .opaque(_, let b) = rhs, let lb = b as? Notification + else { throw RuntimeError.invalid("Notification comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "NSString.EncodingConversionOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSString.EncodingConversionOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSString.EncodingConversionOptions - else { throw RuntimeError.invalid("NSString.EncodingConversionOptions comparison: bad payloads") } - return la == lb ? 0 : -1 + i.registerComparator(on: "Decimal") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Decimal, + case .opaque(_, let b) = rhs, let lb = b as? Decimal + else { throw RuntimeError.invalid("Decimal comparison: bad payloads") } + return la < lb ? -1 : (la > lb ? 1 : 0) } - i.registerComparator(on: "Date.FormatString") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Date.FormatString, - case .opaque(_, let b) = rhs, let lb = b as? Date.FormatString - else { throw RuntimeError.invalid("Date.FormatString comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "FileManager") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? FileManager, + case .opaque(_, let b) = rhs, let lb = b as? FileManager + else { throw RuntimeError.invalid("FileManager comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif #if canImport(Darwin) - i.registerComparator(on: "FileWrapper.WritingOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? FileWrapper.WritingOptions, - case .opaque(_, let b) = rhs, let lb = b as? FileWrapper.WritingOptions - else { throw RuntimeError.invalid("FileWrapper.WritingOptions comparison: bad payloads") } + i.registerComparator(on: "ProcessInfo") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? ProcessInfo, + case .opaque(_, let b) = rhs, let lb = b as? ProcessInfo + else { throw RuntimeError.invalid("ProcessInfo comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "Locale.Variant") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Locale.Variant, - case .opaque(_, let b) = rhs, let lb = b as? Locale.Variant - else { throw RuntimeError.invalid("Locale.Variant comparison: bad payloads") } + i.registerComparator(on: "CocoaError.Code") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? CocoaError.Code, + case .opaque(_, let b) = rhs, let lb = b as? CocoaError.Code + else { throw RuntimeError.invalid("CocoaError.Code comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "IndexSet") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? IndexSet, - case .opaque(_, let b) = rhs, let lb = b as? IndexSet - else { throw RuntimeError.invalid("IndexSet comparison: bad payloads") } + i.registerComparator(on: "NSRegularExpression.Options") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSRegularExpression.Options, + case .opaque(_, let b) = rhs, let lb = b as? NSRegularExpression.Options + else { throw RuntimeError.invalid("NSRegularExpression.Options comparison: bad payloads") } + return la == lb ? 0 : -1 + } + + i.registerComparator(on: "POSIXError") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? POSIXError, + case .opaque(_, let b) = rhs, let lb = b as? POSIXError + else { throw RuntimeError.invalid("POSIXError comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "ProcessInfo.ActivityOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? ProcessInfo.ActivityOptions, - case .opaque(_, let b) = rhs, let lb = b as? ProcessInfo.ActivityOptions - else { throw RuntimeError.invalid("ProcessInfo.ActivityOptions comparison: bad payloads") } + i.registerComparator(on: "NSFileCoordinator.ReadingOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSFileCoordinator.ReadingOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSFileCoordinator.ReadingOptions + else { throw RuntimeError.invalid("NSFileCoordinator.ReadingOptions comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "Locale") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Locale, - case .opaque(_, let b) = rhs, let lb = b as? Locale - else { throw RuntimeError.invalid("Locale comparison: bad payloads") } + i.registerComparator(on: "DateComponents") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? DateComponents, + case .opaque(_, let b) = rhs, let lb = b as? DateComponents + else { throw RuntimeError.invalid("DateComponents comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "URLError") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? URLError, - case .opaque(_, let b) = rhs, let lb = b as? URLError - else { throw RuntimeError.invalid("URLError comparison: bad payloads") } - return la == lb ? 0 : -1 +#if canImport(Darwin) + i.registerComparator(on: "AttributedString.Index") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? AttributedString.Index, + case .opaque(_, let b) = rhs, let lb = b as? AttributedString.Index + else { throw RuntimeError.invalid("AttributedString.Index comparison: bad payloads") } + return la < lb ? -1 : (la > lb ? 1 : 0) } +#endif - i.registerComparator(on: "ByteCountFormatter.Units") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? ByteCountFormatter.Units, - case .opaque(_, let b) = rhs, let lb = b as? ByteCountFormatter.Units - else { throw RuntimeError.invalid("ByteCountFormatter.Units comparison: bad payloads") } + i.registerComparator(on: "ProgressUserInfoKey") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? ProgressUserInfoKey, + case .opaque(_, let b) = rhs, let lb = b as? ProgressUserInfoKey + else { throw RuntimeError.invalid("ProgressUserInfoKey comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "Morphology") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Morphology, - case .opaque(_, let b) = rhs, let lb = b as? Morphology - else { throw RuntimeError.invalid("Morphology comparison: bad payloads") } + i.registerComparator(on: "ByteCountFormatStyle") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? ByteCountFormatStyle, + case .opaque(_, let b) = rhs, let lb = b as? ByteCountFormatStyle + else { throw RuntimeError.invalid("ByteCountFormatStyle comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "DateInterval") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? DateInterval, - case .opaque(_, let b) = rhs, let lb = b as? DateInterval - else { throw RuntimeError.invalid("DateInterval comparison: bad payloads") } - return la < lb ? -1 : (la > lb ? 1 : 0) + i.registerComparator(on: "Locale.Region") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Locale.Region, + case .opaque(_, let b) = rhs, let lb = b as? Locale.Region + else { throw RuntimeError.invalid("Locale.Region comparison: bad payloads") } + return la == lb ? 0 : -1 } - i.registerComparator(on: "DescriptiveNumberFormatConfiguration.Presentation") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? DescriptiveNumberFormatConfiguration.Presentation, - case .opaque(_, let b) = rhs, let lb = b as? DescriptiveNumberFormatConfiguration.Presentation - else { throw RuntimeError.invalid("DescriptiveNumberFormatConfiguration.Presentation comparison: bad payloads") } + i.registerComparator(on: "NSCalendar.Identifier") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSCalendar.Identifier, + case .opaque(_, let b) = rhs, let lb = b as? NSCalendar.Identifier + else { throw RuntimeError.invalid("NSCalendar.Identifier comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "NSData.ReadingOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSData.ReadingOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSData.ReadingOptions - else { throw RuntimeError.invalid("NSData.ReadingOptions comparison: bad payloads") } + i.registerComparator(on: "NSURL.BookmarkResolutionOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSURL.BookmarkResolutionOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSURL.BookmarkResolutionOptions + else { throw RuntimeError.invalid("NSURL.BookmarkResolutionOptions comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "ByteCountFormatStyle.Attributed") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? ByteCountFormatStyle.Attributed, - case .opaque(_, let b) = rhs, let lb = b as? ByteCountFormatStyle.Attributed - else { throw RuntimeError.invalid("ByteCountFormatStyle.Attributed comparison: bad payloads") } + i.registerComparator(on: "IndexSet") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? IndexSet, + case .opaque(_, let b) = rhs, let lb = b as? IndexSet + else { throw RuntimeError.invalid("IndexSet comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "StreamSOCKSProxyConfiguration") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? StreamSOCKSProxyConfiguration, - case .opaque(_, let b) = rhs, let lb = b as? StreamSOCKSProxyConfiguration - else { throw RuntimeError.invalid("StreamSOCKSProxyConfiguration comparison: bad payloads") } + i.registerComparator(on: "FileAttributeType") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? FileAttributeType, + case .opaque(_, let b) = rhs, let lb = b as? FileAttributeType + else { throw RuntimeError.invalid("FileAttributeType comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "NSData.Base64DecodingOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSData.Base64DecodingOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSData.Base64DecodingOptions - else { throw RuntimeError.invalid("NSData.Base64DecodingOptions comparison: bad payloads") } + i.registerComparator(on: "InputStream") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? InputStream, + case .opaque(_, let b) = rhs, let lb = b as? InputStream + else { throw RuntimeError.invalid("InputStream comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "URLComponents") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? URLComponents, - case .opaque(_, let b) = rhs, let lb = b as? URLComponents - else { throw RuntimeError.invalid("URLComponents comparison: bad payloads") } + i.registerComparator(on: "Stream.Event") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Stream.Event, + case .opaque(_, let b) = rhs, let lb = b as? Stream.Event + else { throw RuntimeError.invalid("Stream.Event comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "StringTransform") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? StringTransform, - case .opaque(_, let b) = rhs, let lb = b as? StringTransform - else { throw RuntimeError.invalid("StringTransform comparison: bad payloads") } + i.registerComparator(on: "NSString.EncodingConversionOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSString.EncodingConversionOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSString.EncodingConversionOptions + else { throw RuntimeError.invalid("NSString.EncodingConversionOptions comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "NSString.EnumerationOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSString.EnumerationOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSString.EnumerationOptions - else { throw RuntimeError.invalid("NSString.EnumerationOptions comparison: bad payloads") } + i.registerComparator(on: "ByteCountFormatStyle.Units") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? ByteCountFormatStyle.Units, + case .opaque(_, let b) = rhs, let lb = b as? ByteCountFormatStyle.Units + else { throw RuntimeError.invalid("ByteCountFormatStyle.Units comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "URLError.Code") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? URLError.Code, - case .opaque(_, let b) = rhs, let lb = b as? URLError.Code - else { throw RuntimeError.invalid("URLError.Code comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "InlinePresentationIntent") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? InlinePresentationIntent, + case .opaque(_, let b) = rhs, let lb = b as? InlinePresentationIntent + else { throw RuntimeError.invalid("InlinePresentationIntent comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif #if canImport(Darwin) - i.registerComparator(on: "NSFileCoordinator.WritingOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSFileCoordinator.WritingOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSFileCoordinator.WritingOptions - else { throw RuntimeError.invalid("NSFileCoordinator.WritingOptions comparison: bad payloads") } + i.registerComparator(on: "AttributedString.MarkdownSourcePosition") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? AttributedString.MarkdownSourcePosition, + case .opaque(_, let b) = rhs, let lb = b as? AttributedString.MarkdownSourcePosition + else { throw RuntimeError.invalid("AttributedString.MarkdownSourcePosition comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "Data") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Data, - case .opaque(_, let b) = rhs, let lb = b as? Data - else { throw RuntimeError.invalid("Data comparison: bad payloads") } + i.registerComparator(on: "Locale.Currency") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Locale.Currency, + case .opaque(_, let b) = rhs, let lb = b as? Locale.Currency + else { throw RuntimeError.invalid("Locale.Currency comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "NSString.CompareOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSString.CompareOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSString.CompareOptions - else { throw RuntimeError.invalid("NSString.CompareOptions comparison: bad payloads") } + i.registerComparator(on: "NSLinguisticTagger.Options") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSLinguisticTagger.Options, + case .opaque(_, let b) = rhs, let lb = b as? NSLinguisticTagger.Options + else { throw RuntimeError.invalid("NSLinguisticTagger.Options comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "NSEnumerationOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSEnumerationOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSEnumerationOptions - else { throw RuntimeError.invalid("NSEnumerationOptions comparison: bad payloads") } + i.registerComparator(on: "Date.ParseStrategy") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Date.ParseStrategy, + case .opaque(_, let b) = rhs, let lb = b as? Date.ParseStrategy + else { throw RuntimeError.invalid("Date.ParseStrategy comparison: bad payloads") } + return la == lb ? 0 : -1 + } + +#if canImport(Darwin) + i.registerComparator(on: "MachError") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? MachError, + case .opaque(_, let b) = rhs, let lb = b as? MachError + else { throw RuntimeError.invalid("MachError comparison: bad payloads") } + return la == lb ? 0 : -1 + } +#endif + + i.registerComparator(on: "TimeZone") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? TimeZone, + case .opaque(_, let b) = rhs, let lb = b as? TimeZone + else { throw RuntimeError.invalid("TimeZone comparison: bad payloads") } + return la == lb ? 0 : -1 + } + + i.registerComparator(on: "StringStyle") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? StringStyle, + case .opaque(_, let b) = rhs, let lb = b as? StringStyle + else { throw RuntimeError.invalid("StringStyle comparison: bad payloads") } + return la == lb ? 0 : -1 + } + + i.registerComparator(on: "NSBinarySearchingOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSBinarySearchingOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSBinarySearchingOptions + else { throw RuntimeError.invalid("NSBinarySearchingOptions comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "NSData.SearchOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSData.SearchOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSData.SearchOptions - else { throw RuntimeError.invalid("NSData.SearchOptions comparison: bad payloads") } + i.registerComparator(on: "URL.FormatStyle") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? URL.FormatStyle, + case .opaque(_, let b) = rhs, let lb = b as? URL.FormatStyle + else { throw RuntimeError.invalid("URL.FormatStyle comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "IndexSet.Index") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? IndexSet.Index, - case .opaque(_, let b) = rhs, let lb = b as? IndexSet.Index - else { throw RuntimeError.invalid("IndexSet.Index comparison: bad payloads") } - return la < lb ? -1 : (la > lb ? 1 : 0) - } - - i.registerComparator(on: "Morphology.CustomPronoun") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Morphology.CustomPronoun, - case .opaque(_, let b) = rhs, let lb = b as? Morphology.CustomPronoun - else { throw RuntimeError.invalid("Morphology.CustomPronoun comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "NSData.Base64DecodingOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSData.Base64DecodingOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSData.Base64DecodingOptions + else { throw RuntimeError.invalid("NSData.Base64DecodingOptions comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif #if canImport(Darwin) - i.registerComparator(on: "LocalizedStringResource") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? LocalizedStringResource, - case .opaque(_, let b) = rhs, let lb = b as? LocalizedStringResource - else { throw RuntimeError.invalid("LocalizedStringResource comparison: bad payloads") } + i.registerComparator(on: "AttributedString.Runs") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? AttributedString.Runs, + case .opaque(_, let b) = rhs, let lb = b as? AttributedString.Runs + else { throw RuntimeError.invalid("AttributedString.Runs comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "ProgressKind") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? ProgressKind, - case .opaque(_, let b) = rhs, let lb = b as? ProgressKind - else { throw RuntimeError.invalid("ProgressKind comparison: bad payloads") } +#if !os(iOS) && !os(tvOS) && !os(watchOS) && !os(visionOS) + i.registerComparator(on: "Process") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Process, + case .opaque(_, let b) = rhs, let lb = b as? Process + else { throw RuntimeError.invalid("Process comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif - i.registerComparator(on: "CocoaError.Code") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? CocoaError.Code, - case .opaque(_, let b) = rhs, let lb = b as? CocoaError.Code - else { throw RuntimeError.invalid("CocoaError.Code comparison: bad payloads") } + i.registerComparator(on: "DescriptiveNumberFormatConfiguration.Presentation") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? DescriptiveNumberFormatConfiguration.Presentation, + case .opaque(_, let b) = rhs, let lb = b as? DescriptiveNumberFormatConfiguration.Presentation + else { throw RuntimeError.invalid("DescriptiveNumberFormatConfiguration.Presentation comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "NSLinguisticTagger.Options") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSLinguisticTagger.Options, - case .opaque(_, let b) = rhs, let lb = b as? NSLinguisticTagger.Options - else { throw RuntimeError.invalid("NSLinguisticTagger.Options comparison: bad payloads") } + i.registerComparator(on: "AttributedSubstring") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? AttributedSubstring, + case .opaque(_, let b) = rhs, let lb = b as? AttributedSubstring + else { throw RuntimeError.invalid("AttributedSubstring comparison: bad payloads") } return la == lb ? 0 : -1 } #endif #if canImport(Darwin) - i.registerComparator(on: "InlinePresentationIntent") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? InlinePresentationIntent, - case .opaque(_, let b) = rhs, let lb = b as? InlinePresentationIntent - else { throw RuntimeError.invalid("InlinePresentationIntent comparison: bad payloads") } + i.registerComparator(on: "OutputStream") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? OutputStream, + case .opaque(_, let b) = rhs, let lb = b as? OutputStream + else { throw RuntimeError.invalid("OutputStream comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "DateComponents") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? DateComponents, - case .opaque(_, let b) = rhs, let lb = b as? DateComponents - else { throw RuntimeError.invalid("DateComponents comparison: bad payloads") } + i.registerComparator(on: "AttributeContainer") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? AttributeContainer, + case .opaque(_, let b) = rhs, let lb = b as? AttributeContainer + else { throw RuntimeError.invalid("AttributeContainer comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "RunLoop.Mode") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? RunLoop.Mode, - case .opaque(_, let b) = rhs, let lb = b as? RunLoop.Mode - else { throw RuntimeError.invalid("RunLoop.Mode comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "AttributedString") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? AttributedString, + case .opaque(_, let b) = rhs, let lb = b as? AttributedString + else { throw RuntimeError.invalid("AttributedString comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif - i.registerComparator(on: "Date.VerbatimFormatStyle") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Date.VerbatimFormatStyle, - case .opaque(_, let b) = rhs, let lb = b as? Date.VerbatimFormatStyle - else { throw RuntimeError.invalid("Date.VerbatimFormatStyle comparison: bad payloads") } + i.registerComparator(on: "URL") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? URL, + case .opaque(_, let b) = rhs, let lb = b as? URL + else { throw RuntimeError.invalid("URL comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "PresentationIntent") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? PresentationIntent, - case .opaque(_, let b) = rhs, let lb = b as? PresentationIntent - else { throw RuntimeError.invalid("PresentationIntent comparison: bad payloads") } + i.registerComparator(on: "NetService.Options") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NetService.Options, + case .opaque(_, let b) = rhs, let lb = b as? NetService.Options + else { throw RuntimeError.invalid("NetService.Options comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "NSSortOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSSortOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSSortOptions - else { throw RuntimeError.invalid("NSSortOptions comparison: bad payloads") } + i.registerComparator(on: "URLFileResourceType") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? URLFileResourceType, + case .opaque(_, let b) = rhs, let lb = b as? URLFileResourceType + else { throw RuntimeError.invalid("URLFileResourceType comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "FileManager") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? FileManager, - case .opaque(_, let b) = rhs, let lb = b as? FileManager - else { throw RuntimeError.invalid("FileManager comparison: bad payloads") } + i.registerComparator(on: "PersonNameComponents.FormatStyle") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? PersonNameComponents.FormatStyle, + case .opaque(_, let b) = rhs, let lb = b as? PersonNameComponents.FormatStyle + else { throw RuntimeError.invalid("PersonNameComponents.FormatStyle comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "NSTextCheckingKey") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSTextCheckingKey, - case .opaque(_, let b) = rhs, let lb = b as? NSTextCheckingKey - else { throw RuntimeError.invalid("NSTextCheckingKey comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "NSData.Base64EncodingOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSData.Base64EncodingOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSData.Base64EncodingOptions + else { throw RuntimeError.invalid("NSData.Base64EncodingOptions comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif - i.registerComparator(on: "FileProtectionType") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? FileProtectionType, - case .opaque(_, let b) = rhs, let lb = b as? FileProtectionType - else { throw RuntimeError.invalid("FileProtectionType comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "LocalizedStringResource") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? LocalizedStringResource, + case .opaque(_, let b) = rhs, let lb = b as? LocalizedStringResource + else { throw RuntimeError.invalid("LocalizedStringResource comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif - i.registerComparator(on: "NSCalendar.Identifier") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSCalendar.Identifier, - case .opaque(_, let b) = rhs, let lb = b as? NSCalendar.Identifier - else { throw RuntimeError.invalid("NSCalendar.Identifier comparison: bad payloads") } + i.registerComparator(on: "Data") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Data, + case .opaque(_, let b) = rhs, let lb = b as? Data + else { throw RuntimeError.invalid("Data comparison: bad payloads") } return la == lb ? 0 : -1 } -#if canImport(Darwin) - i.registerComparator(on: "URLUbiquitousSharedItemRole") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? URLUbiquitousSharedItemRole, - case .opaque(_, let b) = rhs, let lb = b as? URLUbiquitousSharedItemRole - else { throw RuntimeError.invalid("URLUbiquitousSharedItemRole comparison: bad payloads") } + i.registerComparator(on: "NumberFormatStyleConfiguration.Precision") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NumberFormatStyleConfiguration.Precision, + case .opaque(_, let b) = rhs, let lb = b as? NumberFormatStyleConfiguration.Precision + else { throw RuntimeError.invalid("NumberFormatStyleConfiguration.Precision comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif - i.registerComparator(on: "NSTextCheckingResult.CheckingType") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSTextCheckingResult.CheckingType, - case .opaque(_, let b) = rhs, let lb = b as? NSTextCheckingResult.CheckingType - else { throw RuntimeError.invalid("NSTextCheckingResult.CheckingType comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "NSXPCConnection.Options") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSXPCConnection.Options, + case .opaque(_, let b) = rhs, let lb = b as? NSXPCConnection.Options + else { throw RuntimeError.invalid("NSXPCConnection.Options comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif - i.registerComparator(on: "ByteCountFormatStyle.Units") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? ByteCountFormatStyle.Units, - case .opaque(_, let b) = rhs, let lb = b as? ByteCountFormatStyle.Units - else { throw RuntimeError.invalid("ByteCountFormatStyle.Units comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "ProcessInfo.ActivityOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? ProcessInfo.ActivityOptions, + case .opaque(_, let b) = rhs, let lb = b as? ProcessInfo.ActivityOptions + else { throw RuntimeError.invalid("ProcessInfo.ActivityOptions comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif - i.registerComparator(on: "PropertyListSerialization.MutabilityOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? PropertyListSerialization.MutabilityOptions, - case .opaque(_, let b) = rhs, let lb = b as? PropertyListSerialization.MutabilityOptions - else { throw RuntimeError.invalid("PropertyListSerialization.MutabilityOptions comparison: bad payloads") } + i.registerComparator(on: "Date.FormatStyle") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Date.FormatStyle, + case .opaque(_, let b) = rhs, let lb = b as? Date.FormatStyle + else { throw RuntimeError.invalid("Date.FormatStyle comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "Locale.LanguageCode") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Locale.LanguageCode, - case .opaque(_, let b) = rhs, let lb = b as? Locale.LanguageCode - else { throw RuntimeError.invalid("Locale.LanguageCode comparison: bad payloads") } + i.registerComparator(on: "Date.ComponentsFormatStyle") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Date.ComponentsFormatStyle, + case .opaque(_, let b) = rhs, let lb = b as? Date.ComponentsFormatStyle + else { throw RuntimeError.invalid("Date.ComponentsFormatStyle comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "PersonNameComponents.FormatStyle") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? PersonNameComponents.FormatStyle, - case .opaque(_, let b) = rhs, let lb = b as? PersonNameComponents.FormatStyle - else { throw RuntimeError.invalid("PersonNameComponents.FormatStyle comparison: bad payloads") } + i.registerComparator(on: "NSAttributedStringFormattingContextKey") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSAttributedStringFormattingContextKey, + case .opaque(_, let b) = rhs, let lb = b as? NSAttributedStringFormattingContextKey + else { throw RuntimeError.invalid("NSAttributedStringFormattingContextKey comparison: bad payloads") } return la == lb ? 0 : -1 } #endif + i.registerComparator(on: "Locale.Language") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Locale.Language, + case .opaque(_, let b) = rhs, let lb = b as? Locale.Language + else { throw RuntimeError.invalid("Locale.Language comparison: bad payloads") } + return la == lb ? 0 : -1 + } + #if canImport(Darwin) - i.registerComparator(on: "PresentationIntent.TableColumn") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? PresentationIntent.TableColumn, - case .opaque(_, let b) = rhs, let lb = b as? PresentationIntent.TableColumn - else { throw RuntimeError.invalid("PresentationIntent.TableColumn comparison: bad payloads") } + i.registerComparator(on: "URLResponse") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? URLResponse, + case .opaque(_, let b) = rhs, let lb = b as? URLResponse + else { throw RuntimeError.invalid("URLResponse comparison: bad payloads") } return la == lb ? 0 : -1 } #endif #if canImport(Darwin) - i.registerComparator(on: "PersonNameComponents.ParseStrategy") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? PersonNameComponents.ParseStrategy, - case .opaque(_, let b) = rhs, let lb = b as? PersonNameComponents.ParseStrategy - else { throw RuntimeError.invalid("PersonNameComponents.ParseStrategy comparison: bad payloads") } + i.registerComparator(on: "NSFileCoordinator.WritingOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSFileCoordinator.WritingOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSFileCoordinator.WritingOptions + else { throw RuntimeError.invalid("NSFileCoordinator.WritingOptions comparison: bad payloads") } return la == lb ? 0 : -1 } #endif #if canImport(Darwin) - i.registerComparator(on: "NSKeyValueChangeKey") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSKeyValueChangeKey, - case .opaque(_, let b) = rhs, let lb = b as? NSKeyValueChangeKey - else { throw RuntimeError.invalid("NSKeyValueChangeKey comparison: bad payloads") } + i.registerComparator(on: "PresentationIntent") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? PresentationIntent, + case .opaque(_, let b) = rhs, let lb = b as? PresentationIntent + else { throw RuntimeError.invalid("PresentationIntent comparison: bad payloads") } return la == lb ? 0 : -1 } #endif #if canImport(Darwin) - i.registerComparator(on: "NSURL.BookmarkResolutionOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSURL.BookmarkResolutionOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSURL.BookmarkResolutionOptions - else { throw RuntimeError.invalid("NSURL.BookmarkResolutionOptions comparison: bad payloads") } + i.registerComparator(on: "URLUbiquitousSharedItemRole") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? URLUbiquitousSharedItemRole, + case .opaque(_, let b) = rhs, let lb = b as? URLUbiquitousSharedItemRole + else { throw RuntimeError.invalid("URLUbiquitousSharedItemRole comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "FileManager.SearchPathDomainMask") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? FileManager.SearchPathDomainMask, - case .opaque(_, let b) = rhs, let lb = b as? FileManager.SearchPathDomainMask - else { throw RuntimeError.invalid("FileManager.SearchPathDomainMask comparison: bad payloads") } + i.registerComparator(on: "Progress.FileOperationKind") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Progress.FileOperationKind, + case .opaque(_, let b) = rhs, let lb = b as? Progress.FileOperationKind + else { throw RuntimeError.invalid("Progress.FileOperationKind comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "IndexSet.RangeView") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? IndexSet.RangeView, - case .opaque(_, let b) = rhs, let lb = b as? IndexSet.RangeView - else { throw RuntimeError.invalid("IndexSet.RangeView comparison: bad payloads") } + i.registerComparator(on: "StreamSOCKSProxyVersion") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? StreamSOCKSProxyVersion, + case .opaque(_, let b) = rhs, let lb = b as? StreamSOCKSProxyVersion + else { throw RuntimeError.invalid("StreamSOCKSProxyVersion comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "CurrencyFormatStyleConfiguration.Presentation") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? CurrencyFormatStyleConfiguration.Presentation, - case .opaque(_, let b) = rhs, let lb = b as? CurrencyFormatStyleConfiguration.Presentation - else { throw RuntimeError.invalid("CurrencyFormatStyleConfiguration.Presentation comparison: bad payloads") } + i.registerComparator(on: "URLError.Code") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? URLError.Code, + case .opaque(_, let b) = rhs, let lb = b as? URLError.Code + else { throw RuntimeError.invalid("URLError.Code comparison: bad payloads") } return la == lb ? 0 : -1 } -#if canImport(Darwin) - i.registerComparator(on: "AttributedString.Index") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? AttributedString.Index, - case .opaque(_, let b) = rhs, let lb = b as? AttributedString.Index - else { throw RuntimeError.invalid("AttributedString.Index comparison: bad payloads") } - return la < lb ? -1 : (la > lb ? 1 : 0) + i.registerComparator(on: "Locale.Components") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Locale.Components, + case .opaque(_, let b) = rhs, let lb = b as? Locale.Components + else { throw RuntimeError.invalid("Locale.Components comparison: bad payloads") } + return la == lb ? 0 : -1 } -#endif -#if canImport(Darwin) - i.registerComparator(on: "FileWrapper.ReadingOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? FileWrapper.ReadingOptions, - case .opaque(_, let b) = rhs, let lb = b as? FileWrapper.ReadingOptions - else { throw RuntimeError.invalid("FileWrapper.ReadingOptions comparison: bad payloads") } + i.registerComparator(on: "Locale.Subdivision") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Locale.Subdivision, + case .opaque(_, let b) = rhs, let lb = b as? Locale.Subdivision + else { throw RuntimeError.invalid("Locale.Subdivision comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif i.registerComparator(on: "Date.ISO8601FormatStyle") { lhs, rhs in guard case .opaque(_, let a) = lhs, let la = a as? Date.ISO8601FormatStyle, @@ -1498,42 +1542,65 @@ extension FoundationModule { return la == lb ? 0 : -1 } - i.registerComparator(on: "Date.ParseStrategy") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Date.ParseStrategy, - case .opaque(_, let b) = rhs, let lb = b as? Date.ParseStrategy - else { throw RuntimeError.invalid("Date.ParseStrategy comparison: bad payloads") } + i.registerComparator(on: "PersonNameComponents") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? PersonNameComponents, + case .opaque(_, let b) = rhs, let lb = b as? PersonNameComponents + else { throw RuntimeError.invalid("PersonNameComponents comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "AttributeContainer") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? AttributeContainer, - case .opaque(_, let b) = rhs, let lb = b as? AttributeContainer - else { throw RuntimeError.invalid("AttributeContainer comparison: bad payloads") } + i.registerComparator(on: "NSEnumerationOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSEnumerationOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSEnumerationOptions + else { throw RuntimeError.invalid("NSEnumerationOptions comparison: bad payloads") } return la == lb ? 0 : -1 } + i.registerComparator(on: "IndexPath") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? IndexPath, + case .opaque(_, let b) = rhs, let lb = b as? IndexPath + else { throw RuntimeError.invalid("IndexPath comparison: bad payloads") } + return la < lb ? -1 : (la > lb ? 1 : 0) + } + #if canImport(Darwin) - i.registerComparator(on: "MachError") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? MachError, - case .opaque(_, let b) = rhs, let lb = b as? MachError - else { throw RuntimeError.invalid("MachError comparison: bad payloads") } + i.registerComparator(on: "AttributedString.AttributeInvalidationCondition") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? AttributedString.AttributeInvalidationCondition, + case .opaque(_, let b) = rhs, let lb = b as? AttributedString.AttributeInvalidationCondition + else { throw RuntimeError.invalid("AttributedString.AttributeInvalidationCondition comparison: bad payloads") } return la == lb ? 0 : -1 } #endif + i.registerComparator(on: "CharacterSet") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? CharacterSet, + case .opaque(_, let b) = rhs, let lb = b as? CharacterSet + else { throw RuntimeError.invalid("CharacterSet comparison: bad payloads") } + return la == lb ? 0 : -1 + } + #if canImport(Darwin) - i.registerComparator(on: "AttributedString.InterpolationOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? AttributedString.InterpolationOptions, - case .opaque(_, let b) = rhs, let lb = b as? AttributedString.InterpolationOptions - else { throw RuntimeError.invalid("AttributedString.InterpolationOptions comparison: bad payloads") } + i.registerComparator(on: "NSItemProviderFileOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSItemProviderFileOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSItemProviderFileOptions + else { throw RuntimeError.invalid("NSItemProviderFileOptions comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "Date.IntervalFormatStyle") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Date.IntervalFormatStyle, - case .opaque(_, let b) = rhs, let lb = b as? Date.IntervalFormatStyle - else { throw RuntimeError.invalid("Date.IntervalFormatStyle comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "NSData.WritingOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSData.WritingOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSData.WritingOptions + else { throw RuntimeError.invalid("NSData.WritingOptions comparison: bad payloads") } + return la == lb ? 0 : -1 + } +#endif + + i.registerComparator(on: "NotificationQueue.NotificationCoalescing") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NotificationQueue.NotificationCoalescing, + case .opaque(_, let b) = rhs, let lb = b as? NotificationQueue.NotificationCoalescing + else { throw RuntimeError.invalid("NotificationQueue.NotificationCoalescing comparison: bad payloads") } return la == lb ? 0 : -1 } @@ -1544,160 +1611,153 @@ extension FoundationModule { return la == lb ? 0 : -1 } - i.registerComparator(on: "Date.FormatStyle") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Date.FormatStyle, - case .opaque(_, let b) = rhs, let lb = b as? Date.FormatStyle - else { throw RuntimeError.invalid("Date.FormatStyle comparison: bad payloads") } + i.registerComparator(on: "ISO8601DateFormatter.Options") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? ISO8601DateFormatter.Options, + case .opaque(_, let b) = rhs, let lb = b as? ISO8601DateFormatter.Options + else { throw RuntimeError.invalid("ISO8601DateFormatter.Options comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "Stream.Event") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Stream.Event, - case .opaque(_, let b) = rhs, let lb = b as? Stream.Event - else { throw RuntimeError.invalid("Stream.Event comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "NSComparisonPredicate.Options") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSComparisonPredicate.Options, + case .opaque(_, let b) = rhs, let lb = b as? NSComparisonPredicate.Options + else { throw RuntimeError.invalid("NSComparisonPredicate.Options comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif #if canImport(Darwin) - i.registerComparator(on: "NSItemProviderFileOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSItemProviderFileOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSItemProviderFileOptions - else { throw RuntimeError.invalid("NSItemProviderFileOptions comparison: bad payloads") } + i.registerComparator(on: "NSFileVersion.AddingOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSFileVersion.AddingOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSFileVersion.AddingOptions + else { throw RuntimeError.invalid("NSFileVersion.AddingOptions comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "NSBinarySearchingOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSBinarySearchingOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSBinarySearchingOptions - else { throw RuntimeError.invalid("NSBinarySearchingOptions comparison: bad payloads") } + i.registerComparator(on: "StreamSocketSecurityLevel") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? StreamSocketSecurityLevel, + case .opaque(_, let b) = rhs, let lb = b as? StreamSocketSecurityLevel + else { throw RuntimeError.invalid("StreamSocketSecurityLevel comparison: bad payloads") } return la == lb ? 0 : -1 } -#if canImport(Darwin) - i.registerComparator(on: "URLUbiquitousSharedItemPermissions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? URLUbiquitousSharedItemPermissions, - case .opaque(_, let b) = rhs, let lb = b as? URLUbiquitousSharedItemPermissions - else { throw RuntimeError.invalid("URLUbiquitousSharedItemPermissions comparison: bad payloads") } + i.registerComparator(on: "ProgressKind") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? ProgressKind, + case .opaque(_, let b) = rhs, let lb = b as? ProgressKind + else { throw RuntimeError.invalid("ProgressKind comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif #if canImport(Darwin) - i.registerComparator(on: "PresentationIntent.IntentType") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? PresentationIntent.IntentType, - case .opaque(_, let b) = rhs, let lb = b as? PresentationIntent.IntentType - else { throw RuntimeError.invalid("PresentationIntent.IntentType comparison: bad payloads") } + i.registerComparator(on: "NSPointerFunctions.Options") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSPointerFunctions.Options, + case .opaque(_, let b) = rhs, let lb = b as? NSPointerFunctions.Options + else { throw RuntimeError.invalid("NSPointerFunctions.Options comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "FormatStyleCapitalizationContext") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? FormatStyleCapitalizationContext, - case .opaque(_, let b) = rhs, let lb = b as? FormatStyleCapitalizationContext - else { throw RuntimeError.invalid("FormatStyleCapitalizationContext comparison: bad payloads") } + i.registerComparator(on: "NSRegularExpression.MatchingOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSRegularExpression.MatchingOptions, + case .opaque(_, let b) = rhs, let lb = b as? NSRegularExpression.MatchingOptions + else { throw RuntimeError.invalid("NSRegularExpression.MatchingOptions comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "NSFileVersion.ReplacingOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSFileVersion.ReplacingOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSFileVersion.ReplacingOptions - else { throw RuntimeError.invalid("NSFileVersion.ReplacingOptions comparison: bad payloads") } + i.registerComparator(on: "URLUbiquitousItemDownloadingStatus") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? URLUbiquitousItemDownloadingStatus, + case .opaque(_, let b) = rhs, let lb = b as? URLUbiquitousItemDownloadingStatus + else { throw RuntimeError.invalid("URLUbiquitousItemDownloadingStatus comparison: bad payloads") } return la == lb ? 0 : -1 } #endif #if canImport(Darwin) - i.registerComparator(on: "NSXPCConnection.Options") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSXPCConnection.Options, - case .opaque(_, let b) = rhs, let lb = b as? NSXPCConnection.Options - else { throw RuntimeError.invalid("NSXPCConnection.Options comparison: bad payloads") } + i.registerComparator(on: "URLFileProtection") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? URLFileProtection, + case .opaque(_, let b) = rhs, let lb = b as? URLFileProtection + else { throw RuntimeError.invalid("URLFileProtection comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "NSExceptionName") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSExceptionName, - case .opaque(_, let b) = rhs, let lb = b as? NSExceptionName - else { throw RuntimeError.invalid("NSExceptionName comparison: bad payloads") } - return la == lb ? 0 : -1 - } - - i.registerComparator(on: "NSAttributedString.EnumerationOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSAttributedString.EnumerationOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSAttributedString.EnumerationOptions - else { throw RuntimeError.invalid("NSAttributedString.EnumerationOptions comparison: bad payloads") } + i.registerComparator(on: "FileManager.SearchPathDomainMask") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? FileManager.SearchPathDomainMask, + case .opaque(_, let b) = rhs, let lb = b as? FileManager.SearchPathDomainMask + else { throw RuntimeError.invalid("FileManager.SearchPathDomainMask comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "NumberFormatStyleConfiguration.Grouping") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NumberFormatStyleConfiguration.Grouping, - case .opaque(_, let b) = rhs, let lb = b as? NumberFormatStyleConfiguration.Grouping - else { throw RuntimeError.invalid("NumberFormatStyleConfiguration.Grouping comparison: bad payloads") } + i.registerComparator(on: "FileManager.DirectoryEnumerationOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? FileManager.DirectoryEnumerationOptions, + case .opaque(_, let b) = rhs, let lb = b as? FileManager.DirectoryEnumerationOptions + else { throw RuntimeError.invalid("FileManager.DirectoryEnumerationOptions comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "Date.RelativeFormatStyle") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Date.RelativeFormatStyle, - case .opaque(_, let b) = rhs, let lb = b as? Date.RelativeFormatStyle - else { throw RuntimeError.invalid("Date.RelativeFormatStyle comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "PresentationIntent.IntentType") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? PresentationIntent.IntentType, + case .opaque(_, let b) = rhs, let lb = b as? PresentationIntent.IntentType + else { throw RuntimeError.invalid("PresentationIntent.IntentType comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif #if canImport(Darwin) - i.registerComparator(on: "MeasurementFormatter.UnitOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? MeasurementFormatter.UnitOptions, - case .opaque(_, let b) = rhs, let lb = b as? MeasurementFormatter.UnitOptions - else { throw RuntimeError.invalid("MeasurementFormatter.UnitOptions comparison: bad payloads") } + i.registerComparator(on: "HTTPCookieStringPolicy") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? HTTPCookieStringPolicy, + case .opaque(_, let b) = rhs, let lb = b as? HTTPCookieStringPolicy + else { throw RuntimeError.invalid("HTTPCookieStringPolicy comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "PersonNameComponents") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? PersonNameComponents, - case .opaque(_, let b) = rhs, let lb = b as? PersonNameComponents - else { throw RuntimeError.invalid("PersonNameComponents comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "AttributedString.InterpolationOptions") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? AttributedString.InterpolationOptions, + case .opaque(_, let b) = rhs, let lb = b as? AttributedString.InterpolationOptions + else { throw RuntimeError.invalid("AttributedString.InterpolationOptions comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif -#if canImport(Darwin) - i.registerComparator(on: "NSData.Base64EncodingOptions") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSData.Base64EncodingOptions, - case .opaque(_, let b) = rhs, let lb = b as? NSData.Base64EncodingOptions - else { throw RuntimeError.invalid("NSData.Base64EncodingOptions comparison: bad payloads") } + i.registerComparator(on: "URLRequest") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? URLRequest, + case .opaque(_, let b) = rhs, let lb = b as? URLRequest + else { throw RuntimeError.invalid("URLRequest comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif -#if canImport(Darwin) - i.registerComparator(on: "HTTPURLResponse") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? HTTPURLResponse, - case .opaque(_, let b) = rhs, let lb = b as? HTTPURLResponse - else { throw RuntimeError.invalid("HTTPURLResponse comparison: bad payloads") } + i.registerComparator(on: "Calendar") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Calendar, + case .opaque(_, let b) = rhs, let lb = b as? Calendar + else { throw RuntimeError.invalid("Calendar comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif - i.registerComparator(on: "NSCalendar.Options") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NSCalendar.Options, - case .opaque(_, let b) = rhs, let lb = b as? NSCalendar.Options - else { throw RuntimeError.invalid("NSCalendar.Options comparison: bad payloads") } + i.registerComparator(on: "Morphology") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Morphology, + case .opaque(_, let b) = rhs, let lb = b as? Morphology + else { throw RuntimeError.invalid("Morphology comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "CocoaError") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? CocoaError, - case .opaque(_, let b) = rhs, let lb = b as? CocoaError - else { throw RuntimeError.invalid("CocoaError comparison: bad payloads") } + i.registerComparator(on: "NSTextCheckingResult.CheckingType") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NSTextCheckingResult.CheckingType, + case .opaque(_, let b) = rhs, let lb = b as? NSTextCheckingResult.CheckingType + else { throw RuntimeError.invalid("NSTextCheckingResult.CheckingType comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "PersonNameComponents.AttributedStyle") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? PersonNameComponents.AttributedStyle, - case .opaque(_, let b) = rhs, let lb = b as? PersonNameComponents.AttributedStyle - else { throw RuntimeError.invalid("PersonNameComponents.AttributedStyle comparison: bad payloads") } + i.registerComparator(on: "URL.ParseStrategy") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? URL.ParseStrategy, + case .opaque(_, let b) = rhs, let lb = b as? URL.ParseStrategy + else { throw RuntimeError.invalid("URL.ParseStrategy comparison: bad payloads") } return la == lb ? 0 : -1 } #endif diff --git a/Sources/SwiftScriptInterpreter/Modules/StdlibBridge/StdlibBridges.swift b/Sources/SwiftScriptInterpreter/Modules/StdlibBridge/StdlibBridges.swift index 5c83dc6..aa01eb1 100644 --- a/Sources/SwiftScriptInterpreter/Modules/StdlibBridge/StdlibBridges.swift +++ b/Sources/SwiftScriptInterpreter/Modules/StdlibBridge/StdlibBridges.swift @@ -30,141 +30,141 @@ enum StdlibBridges { extension Interpreter { func registerGeneratedStdlib(into i: Interpreter) { for (k, v) in StdlibBridges.all { i.bridges[k] = v } - i.registerComparator(on: "TaskPriority") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? TaskPriority, - case .opaque(_, let b) = rhs, let lb = b as? TaskPriority - else { throw RuntimeError.invalid("TaskPriority comparison: bad payloads") } + i.registerComparator(on: "ObjectIdentifier") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? ObjectIdentifier, + case .opaque(_, let b) = rhs, let lb = b as? ObjectIdentifier + else { throw RuntimeError.invalid("ObjectIdentifier comparison: bad payloads") } return la < lb ? -1 : (la > lb ? 1 : 0) } #if canImport(Darwin) - i.registerComparator(on: "AnyIndex") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? AnyIndex, - case .opaque(_, let b) = rhs, let lb = b as? AnyIndex - else { throw RuntimeError.invalid("AnyIndex comparison: bad payloads") } + i.registerComparator(on: "Unicode.CanonicalCombiningClass") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Unicode.CanonicalCombiningClass, + case .opaque(_, let b) = rhs, let lb = b as? Unicode.CanonicalCombiningClass + else { throw RuntimeError.invalid("Unicode.CanonicalCombiningClass comparison: bad payloads") } return la < lb ? -1 : (la > lb ? 1 : 0) } #endif -#if canImport(Darwin) - i.registerComparator(on: "NotificationCenter.Publisher") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? NotificationCenter.Publisher, - case .opaque(_, let b) = rhs, let lb = b as? NotificationCenter.Publisher - else { throw RuntimeError.invalid("NotificationCenter.Publisher comparison: bad payloads") } + i.registerComparator(on: "Duration.TimeFormatStyle") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Duration.TimeFormatStyle, + case .opaque(_, let b) = rhs, let lb = b as? Duration.TimeFormatStyle + else { throw RuntimeError.invalid("Duration.TimeFormatStyle comparison: bad payloads") } return la == lb ? 0 : -1 } -#endif - i.registerComparator(on: "UnsafeCurrentTask") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? UnsafeCurrentTask, - case .opaque(_, let b) = rhs, let lb = b as? UnsafeCurrentTask - else { throw RuntimeError.invalid("UnsafeCurrentTask comparison: bad payloads") } + i.registerComparator(on: "String.Encoding") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? String.Encoding, + case .opaque(_, let b) = rhs, let lb = b as? String.Encoding + else { throw RuntimeError.invalid("String.Encoding comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "OpaquePointer") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? OpaquePointer, - case .opaque(_, let b) = rhs, let lb = b as? OpaquePointer - else { throw RuntimeError.invalid("OpaquePointer comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "CodingUserInfoKey") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? CodingUserInfoKey, + case .opaque(_, let b) = rhs, let lb = b as? CodingUserInfoKey + else { throw RuntimeError.invalid("CodingUserInfoKey comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif -#if canImport(Darwin) - i.registerComparator(on: "RunLoop.SchedulerTimeType") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? RunLoop.SchedulerTimeType, - case .opaque(_, let b) = rhs, let lb = b as? RunLoop.SchedulerTimeType - else { throw RuntimeError.invalid("RunLoop.SchedulerTimeType comparison: bad payloads") } + i.registerComparator(on: "UnsafeRawPointer") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? UnsafeRawPointer, + case .opaque(_, let b) = rhs, let lb = b as? UnsafeRawPointer + else { throw RuntimeError.invalid("UnsafeRawPointer comparison: bad payloads") } return la < lb ? -1 : (la > lb ? 1 : 0) } -#endif #if canImport(Darwin) - i.registerComparator(on: "Duration") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Duration, - case .opaque(_, let b) = rhs, let lb = b as? Duration - else { throw RuntimeError.invalid("Duration comparison: bad payloads") } + i.registerComparator(on: "SuspendingClock.Instant") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? SuspendingClock.Instant, + case .opaque(_, let b) = rhs, let lb = b as? SuspendingClock.Instant + else { throw RuntimeError.invalid("SuspendingClock.Instant comparison: bad payloads") } return la < lb ? -1 : (la > lb ? 1 : 0) } #endif - i.registerComparator(on: "String.StandardComparator") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? String.StandardComparator, - case .opaque(_, let b) = rhs, let lb = b as? String.StandardComparator - else { throw RuntimeError.invalid("String.StandardComparator comparison: bad payloads") } +#if canImport(Darwin) + i.registerComparator(on: "NotificationCenter.Publisher") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? NotificationCenter.Publisher, + case .opaque(_, let b) = rhs, let lb = b as? NotificationCenter.Publisher + else { throw RuntimeError.invalid("NotificationCenter.Publisher comparison: bad payloads") } return la == lb ? 0 : -1 } +#endif #if canImport(Darwin) - i.registerComparator(on: "ContinuousClock.Instant") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? ContinuousClock.Instant, - case .opaque(_, let b) = rhs, let lb = b as? ContinuousClock.Instant - else { throw RuntimeError.invalid("ContinuousClock.Instant comparison: bad payloads") } + i.registerComparator(on: "OperationQueue.SchedulerTimeType") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? OperationQueue.SchedulerTimeType, + case .opaque(_, let b) = rhs, let lb = b as? OperationQueue.SchedulerTimeType + else { throw RuntimeError.invalid("OperationQueue.SchedulerTimeType comparison: bad payloads") } return la < lb ? -1 : (la > lb ? 1 : 0) } #endif #if canImport(Darwin) - i.registerComparator(on: "Unicode.CanonicalCombiningClass") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Unicode.CanonicalCombiningClass, - case .opaque(_, let b) = rhs, let lb = b as? Unicode.CanonicalCombiningClass - else { throw RuntimeError.invalid("Unicode.CanonicalCombiningClass comparison: bad payloads") } + i.registerComparator(on: "AnyIndex") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? AnyIndex, + case .opaque(_, let b) = rhs, let lb = b as? AnyIndex + else { throw RuntimeError.invalid("AnyIndex comparison: bad payloads") } return la < lb ? -1 : (la > lb ? 1 : 0) } #endif #if canImport(Darwin) - i.registerComparator(on: "String.LocalizationValue") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? String.LocalizationValue, - case .opaque(_, let b) = rhs, let lb = b as? String.LocalizationValue - else { throw RuntimeError.invalid("String.LocalizationValue comparison: bad payloads") } + i.registerComparator(on: "RegexSemanticLevel") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? RegexSemanticLevel, + case .opaque(_, let b) = rhs, let lb = b as? RegexSemanticLevel + else { throw RuntimeError.invalid("RegexSemanticLevel comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "Duration.UnitsFormatStyle") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Duration.UnitsFormatStyle, - case .opaque(_, let b) = rhs, let lb = b as? Duration.UnitsFormatStyle - else { throw RuntimeError.invalid("Duration.UnitsFormatStyle comparison: bad payloads") } - return la == lb ? 0 : -1 - } - #if canImport(Darwin) - i.registerComparator(on: "RegexSemanticLevel") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? RegexSemanticLevel, - case .opaque(_, let b) = rhs, let lb = b as? RegexSemanticLevel - else { throw RuntimeError.invalid("RegexSemanticLevel comparison: bad payloads") } + i.registerComparator(on: "RegexRepetitionBehavior") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? RegexRepetitionBehavior, + case .opaque(_, let b) = rhs, let lb = b as? RegexRepetitionBehavior + else { throw RuntimeError.invalid("RegexRepetitionBehavior comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "String.Encoding") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? String.Encoding, - case .opaque(_, let b) = rhs, let lb = b as? String.Encoding - else { throw RuntimeError.invalid("String.Encoding comparison: bad payloads") } + i.registerComparator(on: "String.StandardComparator") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? String.StandardComparator, + case .opaque(_, let b) = rhs, let lb = b as? String.StandardComparator + else { throw RuntimeError.invalid("String.StandardComparator comparison: bad payloads") } return la == lb ? 0 : -1 } - i.registerComparator(on: "Duration.TimeFormatStyle") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Duration.TimeFormatStyle, - case .opaque(_, let b) = rhs, let lb = b as? Duration.TimeFormatStyle - else { throw RuntimeError.invalid("Duration.TimeFormatStyle comparison: bad payloads") } + i.registerComparator(on: "String.Index") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? String.Index, + case .opaque(_, let b) = rhs, let lb = b as? String.Index + else { throw RuntimeError.invalid("String.Index comparison: bad payloads") } + return la < lb ? -1 : (la > lb ? 1 : 0) + } + + i.registerComparator(on: "OpaquePointer") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? OpaquePointer, + case .opaque(_, let b) = rhs, let lb = b as? OpaquePointer + else { throw RuntimeError.invalid("OpaquePointer comparison: bad payloads") } return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "SuspendingClock.Instant") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? SuspendingClock.Instant, - case .opaque(_, let b) = rhs, let lb = b as? SuspendingClock.Instant - else { throw RuntimeError.invalid("SuspendingClock.Instant comparison: bad payloads") } + i.registerComparator(on: "Duration") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Duration, + case .opaque(_, let b) = rhs, let lb = b as? Duration + else { throw RuntimeError.invalid("Duration comparison: bad payloads") } return la < lb ? -1 : (la > lb ? 1 : 0) } #endif - i.registerComparator(on: "UnsafeMutableRawPointer") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? UnsafeMutableRawPointer, - case .opaque(_, let b) = rhs, let lb = b as? UnsafeMutableRawPointer - else { throw RuntimeError.invalid("UnsafeMutableRawPointer comparison: bad payloads") } - return la < lb ? -1 : (la > lb ? 1 : 0) + i.registerComparator(on: "Duration.UnitsFormatStyle") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Duration.UnitsFormatStyle, + case .opaque(_, let b) = rhs, let lb = b as? Duration.UnitsFormatStyle + else { throw RuntimeError.invalid("Duration.UnitsFormatStyle comparison: bad payloads") } + return la == lb ? 0 : -1 } i.registerComparator(on: "String.Comparator") { lhs, rhs in @@ -174,68 +174,68 @@ extension Interpreter { return la == lb ? 0 : -1 } - i.registerComparator(on: "Decimal.FormatStyle") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? Decimal.FormatStyle, - case .opaque(_, let b) = rhs, let lb = b as? Decimal.FormatStyle - else { throw RuntimeError.invalid("Decimal.FormatStyle comparison: bad payloads") } - return la == lb ? 0 : -1 + i.registerComparator(on: "UnsafeMutableRawPointer") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? UnsafeMutableRawPointer, + case .opaque(_, let b) = rhs, let lb = b as? UnsafeMutableRawPointer + else { throw RuntimeError.invalid("UnsafeMutableRawPointer comparison: bad payloads") } + return la < lb ? -1 : (la > lb ? 1 : 0) + } + + i.registerComparator(on: "TaskPriority") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? TaskPriority, + case .opaque(_, let b) = rhs, let lb = b as? TaskPriority + else { throw RuntimeError.invalid("TaskPriority comparison: bad payloads") } + return la < lb ? -1 : (la > lb ? 1 : 0) } #if canImport(Darwin) - i.registerComparator(on: "CodingUserInfoKey") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? CodingUserInfoKey, - case .opaque(_, let b) = rhs, let lb = b as? CodingUserInfoKey - else { throw RuntimeError.invalid("CodingUserInfoKey comparison: bad payloads") } + i.registerComparator(on: "RegexWordBoundaryKind") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? RegexWordBoundaryKind, + case .opaque(_, let b) = rhs, let lb = b as? RegexWordBoundaryKind + else { throw RuntimeError.invalid("RegexWordBoundaryKind comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - i.registerComparator(on: "ObjectIdentifier") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? ObjectIdentifier, - case .opaque(_, let b) = rhs, let lb = b as? ObjectIdentifier - else { throw RuntimeError.invalid("ObjectIdentifier comparison: bad payloads") } - return la < lb ? -1 : (la > lb ? 1 : 0) + i.registerComparator(on: "UnsafeCurrentTask") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? UnsafeCurrentTask, + case .opaque(_, let b) = rhs, let lb = b as? UnsafeCurrentTask + else { throw RuntimeError.invalid("UnsafeCurrentTask comparison: bad payloads") } + return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "OperationQueue.SchedulerTimeType") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? OperationQueue.SchedulerTimeType, - case .opaque(_, let b) = rhs, let lb = b as? OperationQueue.SchedulerTimeType - else { throw RuntimeError.invalid("OperationQueue.SchedulerTimeType comparison: bad payloads") } + i.registerComparator(on: "RunLoop.SchedulerTimeType") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? RunLoop.SchedulerTimeType, + case .opaque(_, let b) = rhs, let lb = b as? RunLoop.SchedulerTimeType + else { throw RuntimeError.invalid("RunLoop.SchedulerTimeType comparison: bad payloads") } return la < lb ? -1 : (la > lb ? 1 : 0) } #endif - i.registerComparator(on: "String.Index") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? String.Index, - case .opaque(_, let b) = rhs, let lb = b as? String.Index - else { throw RuntimeError.invalid("String.Index comparison: bad payloads") } - return la < lb ? -1 : (la > lb ? 1 : 0) + i.registerComparator(on: "Decimal.FormatStyle") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? Decimal.FormatStyle, + case .opaque(_, let b) = rhs, let lb = b as? Decimal.FormatStyle + else { throw RuntimeError.invalid("Decimal.FormatStyle comparison: bad payloads") } + return la == lb ? 0 : -1 } #if canImport(Darwin) - i.registerComparator(on: "RegexRepetitionBehavior") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? RegexRepetitionBehavior, - case .opaque(_, let b) = rhs, let lb = b as? RegexRepetitionBehavior - else { throw RuntimeError.invalid("RegexRepetitionBehavior comparison: bad payloads") } - return la == lb ? 0 : -1 + i.registerComparator(on: "ContinuousClock.Instant") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? ContinuousClock.Instant, + case .opaque(_, let b) = rhs, let lb = b as? ContinuousClock.Instant + else { throw RuntimeError.invalid("ContinuousClock.Instant comparison: bad payloads") } + return la < lb ? -1 : (la > lb ? 1 : 0) } #endif #if canImport(Darwin) - i.registerComparator(on: "RegexWordBoundaryKind") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? RegexWordBoundaryKind, - case .opaque(_, let b) = rhs, let lb = b as? RegexWordBoundaryKind - else { throw RuntimeError.invalid("RegexWordBoundaryKind comparison: bad payloads") } + i.registerComparator(on: "String.LocalizationValue") { lhs, rhs in + guard case .opaque(_, let a) = lhs, let la = a as? String.LocalizationValue, + case .opaque(_, let b) = rhs, let lb = b as? String.LocalizationValue + else { throw RuntimeError.invalid("String.LocalizationValue comparison: bad payloads") } return la == lb ? 0 : -1 } #endif - - i.registerComparator(on: "UnsafeRawPointer") { lhs, rhs in - guard case .opaque(_, let a) = lhs, let la = a as? UnsafeRawPointer, - case .opaque(_, let b) = rhs, let lb = b as? UnsafeRawPointer - else { throw RuntimeError.invalid("UnsafeRawPointer comparison: bad payloads") } - return la < lb ? -1 : (la > lb ? 1 : 0) - } } } diff --git a/Tests/SwiftScriptInterpreterTests/ShellKitIntegrationTests.swift b/Tests/SwiftScriptInterpreterTests/ShellKitIntegrationTests.swift index e893f00..a2a49e0 100644 --- a/Tests/SwiftScriptInterpreterTests/ShellKitIntegrationTests.swift +++ b/Tests/SwiftScriptInterpreterTests/ShellKitIntegrationTests.swift @@ -221,6 +221,346 @@ struct ShellKitIntegrationTests { #expect(r == .bool(true)) } + // MARK: sandbox — FileHandle path inits + + @Test func sandboxBlocksFileHandleReadingAtPathOutsideRoot() async throws { + // FileHandle(forReadingAtPath:) is the canonical "open a file" + // door outside FileManager. Without the new gate it bypassed + // the sandbox entirely. + let root = NSTemporaryDirectory() + + "swiftscript-sandbox-\(UUID().uuidString)" + try FileManager.default.createDirectory( + atPath: root, withIntermediateDirectories: true) + defer { try? FileManager.default.removeItem(atPath: root) } + let shell = TestShell( + sandbox: .rooted(at: URL(fileURLWithPath: root), + allowedHosts: [])) + var caughtError: Error? + await shell.shellKit.withCurrent { + let interp = Interpreter() + do { + _ = try await interp.eval(#""" + import Foundation + FileHandle(forReadingAtPath: "/etc/passwd") + """#) + } catch { + caughtError = error + } + } + #expect(caughtError != nil) + if let signal = caughtError as? UserThrowSignal, + case .opaque(_, let payload) = signal.value, + payload is ShellKit.Sandbox.Denial + { + // ok + } else { + Issue.record("expected Sandbox.Denial, got \(caughtError as Any)") + } + } + + @Test func sandboxBlocksFileHandleWritingAtPathOutsideRoot() async throws { + // The forWritingAtPath / forUpdatingAtPath inits gate as + // `.write` so a sandbox that allows read but not write also + // denies them. Validates the read-vs-write intent split. + let root = NSTemporaryDirectory() + + "swiftscript-sandbox-\(UUID().uuidString)" + try FileManager.default.createDirectory( + atPath: root, withIntermediateDirectories: true) + defer { try? FileManager.default.removeItem(atPath: root) } + let shell = TestShell( + sandbox: .rooted(at: URL(fileURLWithPath: root), + allowedHosts: [])) + var caughtError: Error? + await shell.shellKit.withCurrent { + let interp = Interpreter() + do { + _ = try await interp.eval(#""" + import Foundation + FileHandle(forWritingAtPath: "/etc/passwd") + """#) + } catch { + caughtError = error + } + } + #expect(caughtError != nil) + if let signal = caughtError as? UserThrowSignal, + case .opaque(_, let payload) = signal.value, + payload is ShellKit.Sandbox.Denial + { + // ok + } else { + Issue.record("expected Sandbox.Denial, got \(caughtError as Any)") + } + } + + @Test func sandboxAllowsFileHandleReadingInsideRoot() async throws { + let root = NSTemporaryDirectory() + + "swiftscript-sandbox-\(UUID().uuidString)" + try FileManager.default.createDirectory( + atPath: root, withIntermediateDirectories: true) + defer { try? FileManager.default.removeItem(atPath: root) } + let sentinel = root + "/marker" + try "hello".write(toFile: sentinel, atomically: true, encoding: .utf8) + let shell = TestShell( + sandbox: .rooted(at: URL(fileURLWithPath: root), + allowedHosts: [])) + let escaped = sentinel.replacingOccurrences(of: "\\", with: "\\\\") + try await shell.shellKit.withCurrent { + let interp = Interpreter() + // The init returns an Optional; presence in the + // result confirms the gate let it through and the open + // succeeded. + let r = try await interp.eval(#""" + import Foundation + let h = FileHandle(forReadingAtPath: "\#(escaped)") + h != nil + """#) + #expect(r == .bool(true)) + } + } + + // MARK: sandbox — Bundle path init + + @Test func sandboxBlocksBundlePathOutsideRoot() async throws { + // Bundle(path:) opens a bundle root the script later reads + // resources from. The gate fires at construction so a + // pathological root (`/etc`) is denied before the script can + // call .url(forResource:withExtension:). + let root = NSTemporaryDirectory() + + "swiftscript-sandbox-\(UUID().uuidString)" + try FileManager.default.createDirectory( + atPath: root, withIntermediateDirectories: true) + defer { try? FileManager.default.removeItem(atPath: root) } + let shell = TestShell( + sandbox: .rooted(at: URL(fileURLWithPath: root), + allowedHosts: [])) + var caughtError: Error? + await shell.shellKit.withCurrent { + let interp = Interpreter() + do { + _ = try await interp.eval(#""" + import Foundation + Bundle(path: "/etc") + """#) + } catch { + caughtError = error + } + } + #expect(caughtError != nil) + if let signal = caughtError as? UserThrowSignal, + case .opaque(_, let payload) = signal.value, + payload is ShellKit.Sandbox.Denial + { + // ok + } else { + Issue.record("expected Sandbox.Denial, got \(caughtError as Any)") + } + } + + // MARK: sandbox — InputStream / OutputStream path inits + + @Test func sandboxBlocksOutputStreamWriteOutsideRoot() async throws { + let root = NSTemporaryDirectory() + + "swiftscript-sandbox-\(UUID().uuidString)" + try FileManager.default.createDirectory( + atPath: root, withIntermediateDirectories: true) + defer { try? FileManager.default.removeItem(atPath: root) } + let shell = TestShell( + sandbox: .rooted(at: URL(fileURLWithPath: root), + allowedHosts: [])) + var caughtError: Error? + await shell.shellKit.withCurrent { + let interp = Interpreter() + do { + _ = try await interp.eval(#""" + import Foundation + OutputStream(toFileAtPath: "/etc/secrets", append: false) + """#) + } catch { + caughtError = error + } + } + #expect(caughtError != nil) + if let signal = caughtError as? UserThrowSignal, + case .opaque(_, let payload) = signal.value, + payload is ShellKit.Sandbox.Denial + { + // ok + } else { + Issue.record("expected Sandbox.Denial, got \(caughtError as Any)") + } + } + + // MARK: sandbox — FileWrapper URL methods + + // `Foundation.FileWrapper` is only bridged on Darwin (the type + // is `@available(*, unavailable)` on swift-corelibs-foundation), + // so this test only runs there. + #if canImport(Darwin) + @Test func sandboxBlocksFileWrapperMatchesContentsOutsideRoot() async throws { + // FileWrapper.matchesContents(of:) reads filesystem state at + // the supplied URL to decide if the wrapper still matches. The + // `of:` label isn't in the generic urlLabelsRead set (too + // collision-prone across Foundation), so the FileWrapper + // receiver branch positionally gates index 0. Without that + // gate, a script could construct an in-memory FileWrapper and + // probe arbitrary host paths via matchesContents. + let root = NSTemporaryDirectory() + + "swiftscript-sandbox-\(UUID().uuidString)" + try FileManager.default.createDirectory( + atPath: root, withIntermediateDirectories: true) + defer { try? FileManager.default.removeItem(atPath: root) } + let shell = TestShell( + sandbox: .rooted(at: URL(fileURLWithPath: root), + allowedHosts: [])) + var caughtError: Error? + await shell.shellKit.withCurrent { + let interp = Interpreter() + do { + _ = try await interp.eval(#""" + import Foundation + let w = FileWrapper(regularFileWithContents: Data()) + w.matchesContents(of: URL(fileURLWithPath: "/etc/passwd")) + """#) + } catch { + caughtError = error + } + } + #expect(caughtError != nil) + if let signal = caughtError as? UserThrowSignal, + case .opaque(_, let payload) = signal.value, + payload is ShellKit.Sandbox.Denial + { + // ok + } else { + Issue.record("expected Sandbox.Denial, got \(caughtError as Any)") + } + } + #endif + + // MARK: sandbox — Process deny + + // `Foundation.Process` is unavailable on the iOS family (iOS, + // tvOS, watchOS, visionOS), so these tests only run where the + // type exists. + #if !os(iOS) && !os(tvOS) && !os(watchOS) && !os(visionOS) + @Test func sandboxDeniesProcessConstructionEntirely() async throws { + // Foundation.Process spawns a real OS subprocess that escapes + // every host gate, so the policy is "denied entirely whenever + // a sandbox is bound". Even constructing a Process — without + // calling .run() — has to fail so the script can't capture the + // instance and pass it around. + let root = NSTemporaryDirectory() + + "swiftscript-sandbox-\(UUID().uuidString)" + try FileManager.default.createDirectory( + atPath: root, withIntermediateDirectories: true) + defer { try? FileManager.default.removeItem(atPath: root) } + let shell = TestShell( + sandbox: .rooted(at: URL(fileURLWithPath: root), + allowedHosts: [])) + var caughtError: Error? + await shell.shellKit.withCurrent { + let interp = Interpreter() + do { + _ = try await interp.eval(#""" + import Foundation + Process() + """#) + } catch { + caughtError = error + } + } + #expect(caughtError != nil) + if let signal = caughtError as? UserThrowSignal, + case .opaque(_, let payload) = signal.value, + payload is ProcessSandboxDenied + { + // ok + } else { + Issue.record("expected ProcessSandboxDenied, got \(caughtError as Any)") + } + } + + @Test func processConstructionAllowedWithoutSandbox() async throws { + // Without a bound sandbox the deny check is a no-op, so the + // standalone `swift-script` CLI behaves as before. Construct + // a Process and check it boxes — we don't `.run()` it because + // CI environments shouldn't fork test-time subprocesses. + let shell = TestShell() // no sandbox + try await shell.shellKit.withCurrent { + let interp = Interpreter() + let r = try await interp.eval(#""" + import Foundation + let p = Process() + p.isRunning + """#) + #expect(r == .bool(false)) + } + } + #endif + + // MARK: network — URLRequest variants gate + + @Test func networkConfigBlocksURLSessionDataForRequestOffAllowList() async throws { + // URLSession.data(for: URLRequest) was the headline hole the + // generalised gate closes — the request-bearing overload now + // pulls URL+method out of the URLRequest and runs them through + // `authorizeURL` the same as the bare-URL overload. + let net = NetworkConfig( + allowedURLPrefixes: [AllowedURLEntry("https://allowed.example.com")], + allowedMethods: [.GET]) + let shell = TestShell(networkConfig: net) + var caughtError: Error? + await shell.shellKit.withCurrent { + let interp = Interpreter() + do { + _ = try await interp.eval(#""" + import Foundation + let url = URL(string: "https://denied.example.com/secret")! + let req = URLRequest(url: url, timeoutInterval: 30.0) + try await URLSession.shared.upload(for: req, fromFile: url) + """#) + } catch { + caughtError = error + } + } + #expect(caughtError != nil) + if let signal = caughtError as? UserThrowSignal, + case .opaque(_, let payload) = signal.value, + payload is NetworkConfig.NetworkAccessDenied + { + // ok + } else { + Issue.record( + "expected NetworkAccessDenied, got \(caughtError as Any)") + } + } + + @Test func networkConfigRejectsUnknownHTTPMethod() throws { + // Earlier `NetworkConfig.checkAllowed` fell back to `.GET` + // when `HTTPMethod(rawValue:)` returned nil, so a request + // with `httpMethod = "FOO"` would be evaluated against GET + // permissions and could pass when only GET was allowed — + // even though the actual method stayed `FOO`. The fix is in + // the helper itself; URLRequest's `httpMethod` setter isn't + // bridged (it's a struct, the bridge generator only emits + // setters for class-typed receivers), so this is a direct + // unit test on the gate rather than through a script. + let net = NetworkConfig( + allowedURLPrefixes: [AllowedURLEntry("https://allowed.example.com")], + allowedMethods: [.GET, .POST, .PUT, .DELETE, .HEAD, .PATCH, .OPTIONS]) + let url = URL(string: "https://allowed.example.com/x")! + do { + try net.checkAllowed(url: url, method: "FOO") + Issue.record("expected NetworkAccessDenied for unknown method") + } catch let denial as NetworkConfig.NetworkAccessDenied { + #expect(denial.reason.contains("FOO not supported"), + "got: \(denial.reason)") + } catch { + Issue.record("expected NetworkAccessDenied, got \(error)") + } + } + // MARK: identity @Test func processInfoUserNameReadsHostInfo() async throws {