Swift 6.4 migration and exhancements (#1)

This PR contains the work done to update the library and the attached example project to use the Swift 6.4 computer as a minimum supported version and also, to use the latest features introduced in it.

Reviewed-on: #1
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
This commit was merged in pull request #1.
This commit is contained in:
2026-09-18 13:15:08 +00:00
committed by javier
parent d0a561b91f
commit c5037dd716
105 changed files with 1390 additions and 1397 deletions
+13 -63
View File
@@ -1,79 +1,29 @@
internal import CPlaydate
/// Internal C-string helpers shared by the wrappers.
///
/// The conversions are implemented manually (rather than with
/// `String(cString:)` / `withCString`) so the module stays within the
/// Embedded Swift subset used for device builds.
/// C-string helpers. Strings passed to C use `withCString`, which doesn't copy.
extension String {
/// Creates a string by copying a null-terminated UTF-8 C string.
init(playdateCString pointer: UnsafePointer<CChar>) {
var count = 0
while pointer[count] != 0 { count += 1 }
let bytes = UnsafeRawBufferPointer(start: pointer, count: count)
self = String(decoding: bytes, as: UTF8.self)
}
/// Creates a string from a nullable C string, or `nil` if the pointer is null.
/// `nil` if `pointer` is null.
init?(playdateCString pointer: UnsafePointer<CChar>?) {
guard let pointer else { return nil }
self.init(playdateCString: pointer)
self.init(cString: pointer)
}
/// Calls `body` with a temporary null-terminated UTF-8 copy of the
/// string. The copy lives on the stack for short strings, so calling
/// this in the update loop does not churn the heap.
func withPlaydateCString<Result>(_ body: (UnsafePointer<CChar>) -> Result) -> Result {
let count = utf8.count
return withUnsafeTemporaryAllocation(of: CChar.self, capacity: count + 1) { buffer in
var index = 0
for byte in utf8 {
buffer[index] = CChar(bitPattern: byte)
index += 1
}
buffer[count] = 0
return body(buffer.baseAddress.unsafelyUnwrapped)
}
}
/// Calls `body` with a temporary buffer of the string's UTF-8 bytes (not
/// null-terminated) and its length, for the `(const void*, size_t)` text
/// APIs. Stack-allocated for short strings.
func withPlaydateUTF8<Result>(_ body: (UnsafeRawPointer, Int) -> Result) -> Result {
let count = utf8.count
return withUnsafeTemporaryAllocation(of: UInt8.self, capacity: count + 1) { buffer in
var index = 0
for byte in utf8 {
buffer[index] = byte
index += 1
}
return body(UnsafeRawPointer(buffer.baseAddress.unsafelyUnwrapped), count)
}
}
/// Copies the string into a newly allocated null-terminated C string.
/// The caller owns the memory and must free it with `deallocate()`.
/// New null-terminated copy; the caller frees it with `deallocate()`.
func copiedPlaydateCString() -> UnsafeMutablePointer<CChar> {
let count = utf8.count
let buffer = UnsafeMutablePointer<CChar>.allocate(capacity: count + 1)
var index = 0
for byte in utf8 {
buffer[index] = CChar(bitPattern: byte)
index += 1
withCString { cString in
let count = utf8.count + 1
let buffer = UnsafeMutablePointer<CChar>.allocate(capacity: count)
buffer.initialize(from: cString, count: count)
return buffer
}
buffer[count] = 0
return buffer
}
}
#if hasFeature(Embedded) && !os(macOS)
/// The Embedded Swift runtime allocates through `posix_memalign(3)`, which
/// the Playdate device C library does not provide. Memory comes from
/// `malloc`, which the SDK's setup code routes to the firmware allocator.
/// The pointer is later released with plain `free`, so it cannot be offset
/// to adjust alignment; the firmware allocator's natural alignment has to
/// satisfy the request, which the precondition asserts.
@_cdecl("posix_memalign")
/// `posix_memalign(3)` for the Embedded Swift runtime; the device C library lacks it.
/// Uses `malloc` (the firmware allocator). Freed with plain `free`, so no alignment offset:
/// the precondition checks `malloc`'s alignment suffices. Traps on failure; else returns 0.
@c(posix_memalign)
public func posix_memalign(
_ memptr: UnsafeMutablePointer<UnsafeMutableRawPointer?>,
_ alignment: Int,