Big +1 to the proposal from me.
Here's one use case I'd like to highlight. With the example repository I've been able to implement a compile-time conversion from string literals to arrays of bytes. This seems like a reasonable solution for environments where String
type with Unicode handling is too heavyweight. Here's the example code for MacroExamplesPlugin
.
import SwiftSyntax
import _SwiftSyntaxMacros
public struct UTF8ArrayMacro: ExpressionMacro {
public static func expansion(
of macro: MacroExpansionExprSyntax, in context: inout MacroExpansionContext
) throws -> ExprSyntax {
guard let firstElement = macro.argumentList.first,
let stringLiteral = firstElement.expression
.as(StringLiteralExprSyntax.self),
stringLiteral.segments.count == 1,
case let .stringSegment(messageString)? = stringLiteral.segments.first
else {
throw CustomError.message("#utf8 macro requires a string literal")
}
return "\(raw: messageString.syntaxTextBytes)"
}
}
Then in MacroExamplesLib
:
public macro utf8(_ string: String) -> [UInt8] = MacroExamplesPlugin.UTF8ArrayMacro
And at the place of use:
_ = #utf8("Hello, world!").withUnsafeBytes {
fputs($0.baseAddress, stdout)
}
When dead code elimination becomes advanced enough to strip out unused Unicode tables on platforms where everything is linked statically, this would allow producing binaries as small as those you can get with Rust or C. Of course, there are downsides to this approach, as you're losing interpolation and other niceties of String
. But for applications where binary size is a top priority, this is still a big improvement.