Skip to content

Instantly share code, notes, and snippets.

View EricRabil's full-sized avatar
🤕
abusing the swift runtime

Eric Rabil EricRabil

🤕
abusing the swift runtime
View GitHub Profile
@EricRabil
EricRabil / OSLogPropertyWrapper.swift
Last active December 14, 2022 20:58
Property wrappers providing access to shared logs identified by StaticStrings
import Foundation
import OSLog
extension StaticString: Hashable {
public static func == (lhs: StaticString, rhs: StaticString) -> Bool {
if lhs.hasPointerRepresentation || rhs.hasPointerRepresentation {
guard lhs.hasPointerRepresentation && rhs.hasPointerRepresentation else {
return false
}
return strcmp(lhs.utf8Start, rhs.utf8Start) == 0
import ERWeakLink
@objc protocol SZExtractorDelegate: NSObjectProtocol {
@objc(setExtractionProgress:) func progress(changedTo percent: Double)
@objc(extractionCompleteAtArchivePath:) func extraction(completedAt archivePath: String)
@objc(extractionEnteredPassThroughMode) func extractionEnteredPassThroughMode()
}
typealias SZExtractorPrepCompletion = @convention(block) (UInt64, NSError?) -> ()
typealias SZExtractorStreamCompletion = @convention(block) (NSError?, Bool) -> ()
@EricRabil
EricRabil / DispatchQueue+Current.swift
Created April 27, 2022 16:29
Get current dispatch queue in Swift
extension DispatchQueue {
private static let dispatch_get_current_queue = dlsym(dlopen(nil, RTLD_GLOBAL), "dispatch_get_current_queue")
static var current: DispatchQueue {
dispatch_get_current_queue.map {
unsafeBitCast($0, to: (@convention(c) () -> Unmanaged<DispatchQueue>).self)().takeUnretainedValue()
} ?? .global(qos: .background)
}
}
@EricRabil
EricRabil / XCTHarness.swift
Last active August 1, 2024 08:32
XCTest doing absolutely nothing? Lack of documentation driving you insane? Avoiding a DTS ticket? Here's a Swift class that forcibly bootstraps XCTest when running inside of a test host and XCTest is not starting itself.
public class XCTHarness {
private typealias XCTestMainType = @convention(c) (_ something: AnyObject?) -> ()
private static func dlsymcast<T>(_ handle: UnsafeMutableRawPointer!, _ symbol: UnsafePointer<CChar>) -> T! {
dlsym(handle, symbol).map {
if T.self is AnyObject.Type {
return $0 as! T
} else {
return unsafeBitCast($0, to: T.self)
}
@EricRabil
EricRabil / main.swift
Created March 3, 2022 19:52
Example of Swift Combine CurrentValueSubject
//
// main.swift
//
// Created by Eric Rabil on 3/3/22.
//
import Foundation
import Combine
let foo = CurrentValueSubject<String, Never>("bar")
@_transparent private func CFDictionaryGetValue(_ dictionary: CFDictionary, _ key: CFString) -> UnsafeRawPointer? {
CFDictionaryGetValue(dictionary, Unmanaged.passUnretained(key).toOpaque())
}
@_transparent private func CFDictionaryUnwrap(_ type: CFTypeRef) -> CFDictionary? {
guard CFGetTypeID(type) == CFDictionaryGetTypeID() else {
return nil
}
return unsafeBitCast(type, to: CFDictionary.self)
}
@EricRabil
EricRabil / Hasher+Seedable.swift
Created November 14, 2021 18:12
Seed a Hasher at runtime instead of through an environment variable
extension Hasher {
static func randomSeed() -> [UInt8] {
Array(unsafeUninitializedCapacity: 32) { pointer, initializedCount in
for i in 0..<32 {
pointer[i] = UInt8(arc4random())
}
initializedCount = 32
}
}
@EricRabil
EricRabil / objc-internals-minimal.h
Created October 14, 2021 23:53
Minimal derivative of objc internal headers for interacting with the runtime
#include <atomic>
#include <cstddef> // for nullptr_t
#include <stdint.h>
#include <assert.h>
#include <iterator>
#include <functional>
// MARK: - Defines
#if __LP64__
@EricRabil
EricRabil / recovery-mode.sh
Last active August 31, 2021 16:59
Things I run on Macs when I get started
# sip
csrutil disable
csrutil authenticated-root disable
@EricRabil
EricRabil / withZip.swift
Created August 29, 2021 04:11
my head hurts
/**
Accepts three functions, where the sole argument of the first two functions is a closure which each accept some ephemeral value and return some value.
The third function accepts two parameters, the first parameter being the parameter of function A, and the second belonging to B. It's combinant value is returned.
- Parameter sourceA: The first function to zip
- Parameter sourceB: The second function to zip
- Parameter combiner: The third function to receive the argument of both A and B
- Returns: The return value
*/
@discardableResult