Private
Public Access
1
0
Files
Kordophone/osx/kordophone2/XPC/XPCConvertible.swift

139 lines
3.3 KiB
Swift
Raw Normal View History

2025-08-24 16:24:21 -07:00
//
// 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
{
2025-08-24 18:54:50 -07:00
func getObject(_ key: String) -> xpc_object_t? {
var raw: xpc_object_t?
key.withCString { cKey in
raw = xpc_dictionary_get_value(self, cKey)
}
return raw
}
2025-08-24 16:24:21 -07:00
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)
}
2025-08-24 18:54:50 -07:00
subscript<T: XPCConvertible>(key: String) -> T? { return get(key) }
var isDictionary: Bool { xpc_get_type(self) == XPC_TYPE_DICTIONARY }
var isArray: Bool { xpc_get_type(self) == XPC_TYPE_ARRAY }
}
// MARK: - Dictionary wrapper
struct XPCDictionary
{
let raw: xpc_object_t
init?(_ value: xpc_object_t) {
guard xpc_get_type(value) == XPC_TYPE_DICTIONARY else { return nil }
self.raw = value
}
func object(_ key: String) -> xpc_object_t? {
var rawValue: xpc_object_t?
key.withCString { cKey in
rawValue = xpc_dictionary_get_value(raw, cKey)
}
return rawValue
}
func get<T: XPCConvertible>(_ key: String) -> T? {
guard let value = object(key) else { return nil }
return T.fromXPC(value)
}
subscript<T: XPCConvertible>(_ key: String) -> T? { return get(key) }
}
extension XPCDictionary
{
static func wrap(_ value: xpc_object_t) -> XPCDictionary? {
return XPCDictionary(value)
2025-08-24 16:24:21 -07:00
}
}