Hello friends!
I love Embedded Swift, but its lack of a mutable String-like type is a difficult limitation. So, I made a TinyString as a way to do some basic text manipulation for the ASCII character set.
The Problem
String manipulation is a common use case — even on embedded systems. But Swift’s String type is not available on Embedded Swift because it contains all the megabytes of Unicode goodness required for complete text handling of an OS.
Requirements:
- Be Swifty
- Safe
- Aggressively lightweight
- Work great with C-strings
- Work great with Swift
String - Work with many — hopefully all — supported Swift platforms
- Zero runtime dependencies
Find TinyString on Swift Package Index
https://swiftpackageindex.com/mcritz/TinyString
Use Cases
Parsing/building small ASCII strings at runtime - JSON fields, BLE tokens, sensor labels, LVGL UI, logging values, etc.
TinyString Pros
- Swift superpowers
- Ergonomic, expressive, and safe
ByteArray!? I barely knew her!TinyStringprovides a nice,String-like type for low-level textSpansupport for bounds-checked safety- An optional throwing-strict init that validates input
- Comes with useful protocols and extensions, and you can add your own
- Ergonomic, expressive, and safe
- Can construct text at runtime
- Unlike
StaticString, which is only for compile-time literals var name: TinyString = "Wai Yin"- Note:
TinyStringisExpressibleByStringLiteral
- Note:
- Unlike
- Designed for Embedded Swift, Swift Wasm, AND all other platforms
- ≈56 KB release build for the entire package, BUT my project use-cases build to ≈1 KB. Unlike
Stringwhich is too large for embedded platforms TinyStringdoes not import Foundation- Designed to work safely with C-string
name.withCString { some_c_func($0) }let cStringValue = sensor.value // UnsafePointer<CChar>
let sensorValue = TinyString(cString: cStringValue) // replaces non-ASCII Chars with `?`
// Or require a valid C string
guard let confirmedValue = try? TinyString(strict: cStringValue) else { return } // disallows non-ASCII values
- ≈56 KB release build for the entire package, BUT my project use-cases build to ≈1 KB. Unlike
- Has
String-y features- Interpolation
var greeting: TinyString = "Hello, \(name)!" - Mutation
greeting.append("\n Welcome to Embedded Swift")greeting += "!"
- Collection/Equatable/Hashable
greeting.hasPrefix("Hello")greeting.contains(name)name.isAllLetters- and so on…
- Interpolation
- Works well with
Stringon other platformslet stringGreeting = String(greeting)let stringName: String = name.description // TinyString is CustomStringConvertible// On Apple platform to TinyString
let bleCommand: String = bluetoothCommand(for: stringName)
let command = TinyString(bleCommand)
TinyString Limitations
- ASCII only
- Full Release build: ≈56 KB (Embedded) / ≈169 KB (Wasm)
- Note: release builds for your project will prune unused code. Actual compiled overhead may be much smaller.
TinyString’s internal storage is a heap-allocated object — know your tradeoffs!- Use
InlineTinyStringfor stack-allocation
- Use
- Doesn’t support
StringProtocol
