The proposal itself looks good and it's definitely a +1, as someone who has and is still working on a IDN library which accepts any bytes and needs to perform some unicode operations such as checking for or converting to NFC, and performing Puny-code operations.
Two notes:
/// Calls the given closure with a buffer of `Element`s,
/// which are *not* necessarily NUL-terminated.
@inlinable
public func withCharacterData<R, Failure>(
_ body: (Span<Element>) throws(Failure) -> R
) throws(Failure) -> R
Sounds to me these kinds of with... functions can instead be some vars?
I don't know if there is an actual blocker but I'd assume it's possible to provide some variables instead. Similar to Requirements for IP address and port APIs - #32 by MahdiBM.
public var characterData: Span<Element> {
@_lifetime(borrow self)
get {
let pointer = UnsafeRawPointer(Builtin.addressOfBorrow(self.whatever))
let span = unsafe Span<UInt8>(_unsafeStart: pointer, byteCount: self.elementCount)
return unsafe _overrideLifetime(span, borrowing: self)
}
}
While It's not really a shortcoming of this proposal, I still would like to see considerations or at least awareness regarding the hopefully upcoming "bag of bytes" types.
Similar to this comment and the related to the discussion [Discussion] Bag of Bytes Types - #25 by MahdiBM.
Essentially, I'd like to see at least escape hatches for not having to copy memory around.
For example if you get some data from C, there should be some possibly unsafe way to pass that data to UncheckedString without copying the data.
Also this'll be helpful in other contexts like with SwiftNIO which passes data to you via its own ByteBuffer type.
This one should hopefully not be needed anymore in some future version of Swift where we have the bag of bytes types. It'll need to be enabled via NIO's ByteBuffer being able to freely transform itself to OurNewBagOfBytes (very possible IMO) and UncheckedString being able to accept and take care of that OurNewBagOfBytes without copies or such (Depends on the impl).
Looking at the proposal, I'd say a OurNewBagOfBytes should not be a big deal for UncheckedString as UncheckedString can just add an enum case that accepts it.
However, we'll need UncheckedString to not become frozen before then.