Thank you everyone for the answers!
Right, I have only ascii/utf8 encodings and was thinking only about them. I think that is and will be the only need for my use-cases.
I was looking at this as one of possible methods for custom struct. However, even if I implement ExpressibleByStringLiteral for InlineArray or any custom struct or class I couldn't find better way rather than fail that at runtime:
struct InlineString<let count: Int>: ExpressibleByStringLiteral {
init(stringLiteral value: StringLiteralType) {
precondition(value.count <= count, "Expected at most \(count) characters in inline string literal, but got \(value.count)")
// ...
}
}
At some point I was thinking if I could use where constraint for count in string literal but that seems also available only on runtime. But would be fun if some const values could be a part of where statement like below:
protocol StringLiteralProtocol {
associatedtype Element
static var count: Int { get } // or `associatedValue let count: Int { get }`
}
struct InlineString<let count: Int>: ExpressibleByStringLiteral {
init<StringLiteral: StringLiteralProtocol>(
_ value: StringLiteral
) where StringLiteral.count <= Self.count,
StringLiteral.Element: UTF8Char {
// ...
}
...
Using direct array literal is a one of approaches that works for internal use-cases and code-gens. Though that looks a bit scary when exposed as end-user API.
So, yeah, macro is probably the way to do it.
One of the approaches was to make a free-standing macro that would infer the size:
@freestanding(expression)
public macro fixedString<let count: Int>(_ string: String, size: Int = count) -> InlineArray<count, UInt8> =
#externalMacro(module: "PluginTypeMacros", type: "FixedStringMacro")
message.setFixedSizeByteArray(#fixedString("123")) // cannot get `size` parameter from expression
Unfortunately, I could not extract nor default argument, nor return type which is a macro limitation as far as I understood from the other threads.
Instead explicit size works:
message.setFixedSizeByteArray(#fixedString("123", size: 4)) // padded string with zeros
message.setFixedSizeByteArray(#fixedString("12345", size: 4)) // error -> "Expected '4' elements in inline array literal, but got '5'"
Probably macro is a good compromise for current use-cases. However, if I could write some of generic constrains instead for custom structures, it would be much much nicer.
So, I wonder if there are any features planned in one of these directions?