Add 'osx/' from commit '46755a07ef2e7aa9852d74c30e2c12f9fe8f2278'
git-subtree-dir: osx git-subtree-mainline:034026e88agit-subtree-split:46755a07ef
This commit is contained in:
138
osx/kordophone2/XPC/XPCConvertible.swift
Normal file
138
osx/kordophone2/XPC/XPCConvertible.swift
Normal file
@@ -0,0 +1,138 @@
|
||||
//
|
||||
// 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 getObject(_ key: String) -> xpc_object_t? {
|
||||
var raw: xpc_object_t?
|
||||
key.withCString { cKey in
|
||||
raw = xpc_dictionary_get_value(self, cKey)
|
||||
}
|
||||
|
||||
return raw
|
||||
}
|
||||
|
||||
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) }
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user