Sure, something like following:
Data
An embedded-defined Data type should be the central byte container, similar to Data in regular Swift.
It is used to build and parse binary structures, move data between layers, and serve as the base for higher-level features like JSON and Base64.
Example: building a binary packet
var packet = Data()
packet.append(0xA1) // message type
packet.append(UInt16(48), endian: .little) // payload length
packet.append(contentsOf: "OK".utf8)
packet.append(0x0D)
packet.append(0x0A)
// out (hex): A1 30 00 4F 4B 0D 0A
Example: reading from a buffer
let type = packet.readUInt8(at: 0)
let length = packet.readUInt16(at: 1, endian: .little)
let text = packet.slice(from: 3, count: 2)
// out:
// type = 0xA1
// length = 48
// text = [0x4F, 0x4B]
String helpers
Text handling is common even in low-level code. A few well-chosen helpers remove a lot of boilerplate.
UTF-8 encoding
let message = "SWD OK ✅"
let bytes = Data(message.utf8)
// out (hex): 53 57 44 20 4F 4B 20 E2 9C 85
Base64
let raw = Data([0x01, 0x02, 0xFF])
let encoded = raw.base64EncodedString()
// out: "AQL/"
let decoded = Data(base64Encoded: encoded)
// out (hex): 01 02 FF
JSON Encoding and Decoding
JSON support can follow the same concepts and naming used in Swift (Encodable, Decodable, JSONEncoder, JSONDecoder), but implemented in a way that is explicit and deterministic.
Encoding example
struct Telemetry: Encodable {
let temperature: Int
let ok: Bool
}
let telemetry = Telemetry(temperature: 23, ok: true)
let encoder = JSONEncoder()
if let data = encoder.encode(telemetry) {
// out: {"temperature":23,"ok":true}
process(data)
} else {
// encoding error
}
Decoding example
let input = data // JSON bytes coming from somewhere
let decoder = JSONDecoder()
if let decoded = decoder.decode(Telemetry.self, from: input) {
// decoded.temperature == 23
// decoded.ok == true
} else {
// decoding error
}
Timer
The core defines abstract types like Timer , but the actual time source often depends on hardware such as timers.
This means time support may vary across MCUs and architectures, which can reduce true multi-platform portability.
Timer represents a monotonic point in time and is mainly used to measure elapsed time.
let start = Timer.now()
// ... do work ...
let elapsed = Timer.now() - start
// out: elapsed = 12ms (example)
Date
Date represents an instant in time and does not depend on the MCU or RTC. It is a value type that typically stores a timestamp relative to a fixed epoch. The hardware dependency exists in how the current time is obtained. Date.now is a convenience API whose implementation may rely on RTC or some real world time source.
// Current instant
let now = Date.now
// Basic arithmetic
let inOneHour = now.addingTimeInterval(3600)
// String formatting (Swift-like)
let isoText = DateFormatter.iso8601.string(from: now)
// "2026-02-04T19:12:03Z"
let shortText = DateFormatter("yyyy-MM-dd").string(from: now)
// "2026-02-04"
// Parsing
let parsed = DateFormatter.iso8601.date(from: "2026-02-04T19:12:03Z")
// Comparison
if now > parsed {
// ...
}
Because of this, while the Date type itself is portable, the behavior and accuracy of Date.now can vary across platforms and MCUs, depending on available hardware support.
Calendar
Calendar implementation.
URL and URLComponents
Lightweight URL parsing and construction using familiar Swift APIs.
var c = URLComponents()
c.scheme = "http"
c.host = "example.com"
c.port = 8080
c.path = "/api/status"
c.queryItems = [
URLQueryItem(name: "id", value: "42"),
URLQueryItem(name: "mode", value: "fast")
]
let url = URL(components: c)
// out: http://example.com:8080/api/status?id=42&mode=fast
What can be built on top of this core
With a clean Data type, JSON support, string helpers, collection utilities, and clear time abstractions, higher-level libraries become easier to build.
Examples include:
- HTTP helpers
- JSON-RPC layers
- Structured logging
- Binary framing and message schemas
- Telemetry and sensor pipelines
All of these can be layered on top of the core, without coupling the core itself to hardware.
General Direction
The overall goal is a small, pure-Swift Foundation-like core, independent from hardware and architecture-specific details.
Some features — especially time and date — may require architecture- or MCU-specific implementations underneath. That risk is real and unavoidable, and it does reduce how “universal” those features can be.
By keeping hardware concerns outside the core and limiting the core to clear abstractions, Embedded Swift Foundation can remain mostly portable across MCUs, while still allowing more complete behavior when the hardware supports it.
This keeps the foundation stable, understandable, and reusable, even as different targets provide different capabilities underneath it.