95 lines
2.2 KiB
Swift
95 lines
2.2 KiB
Swift
|
|
//
|
||
|
|
// XPCConvertible.swift
|
||
|
|
// kordophone2
|
||
|
|
//
|
||
|
|
// Created by James Magahern on 8/24/25.
|
||
|
|
//
|
||
|
|
|
||
|
|
import Foundation
|
||
|
|
import XPC
|
||
|
|
|
||
|
|
protocol XPCConvertible
|
||
|
|
{
|
||
|
|
static func fromXPC(_ value: xpc_object_t) -> Self?
|
||
|
|
}
|
||
|
|
|
||
|
|
extension String: XPCConvertible
|
||
|
|
{
|
||
|
|
static func fromXPC(_ value: xpc_object_t) -> String? {
|
||
|
|
guard xpc_get_type(value) == XPC_TYPE_STRING, let cstr = xpc_string_get_string_ptr(value) else {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
return String(cString: cstr)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
extension Int: XPCConvertible
|
||
|
|
{
|
||
|
|
static func fromXPC(_ value: xpc_object_t) -> Int? {
|
||
|
|
switch xpc_get_type(value) {
|
||
|
|
case XPC_TYPE_INT64:
|
||
|
|
return Int(xpc_int64_get_value(value))
|
||
|
|
case XPC_TYPE_UINT64:
|
||
|
|
return Int(xpc_uint64_get_value(value))
|
||
|
|
case XPC_TYPE_STRING:
|
||
|
|
if let cstr = xpc_string_get_string_ptr(value) {
|
||
|
|
return Int(String(cString: cstr))
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
extension Date: XPCConvertible
|
||
|
|
{
|
||
|
|
static func fromXPC(_ value: xpc_object_t) -> Date? {
|
||
|
|
// Accept seconds since epoch as int/uint or string
|
||
|
|
if let seconds: Int = Int.fromXPC(value) {
|
||
|
|
return Date(timeIntervalSince1970: TimeInterval(seconds))
|
||
|
|
}
|
||
|
|
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
extension Array: XPCConvertible where Element: XPCConvertible
|
||
|
|
{
|
||
|
|
static func fromXPC(_ value: xpc_object_t) -> [Element]? {
|
||
|
|
guard xpc_get_type(value) == XPC_TYPE_ARRAY else {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
var result: [Element] = []
|
||
|
|
xpc_array_apply(value) { _, item in
|
||
|
|
if let element = Element.fromXPC(item) {
|
||
|
|
result.append(element)
|
||
|
|
}
|
||
|
|
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
extension xpc_object_t
|
||
|
|
{
|
||
|
|
func get<T: XPCConvertible>(_ key: String) -> T? {
|
||
|
|
var raw: xpc_object_t?
|
||
|
|
key.withCString { cKey in
|
||
|
|
raw = xpc_dictionary_get_value(self, cKey)
|
||
|
|
}
|
||
|
|
|
||
|
|
guard let value = raw else { return nil }
|
||
|
|
return T.fromXPC(value)
|
||
|
|
}
|
||
|
|
|
||
|
|
subscript<T: XPCConvertible>(key: String) -> T? {
|
||
|
|
return get(key)
|
||
|
|
}
|
||
|
|
}
|