Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 17 additions & 8 deletions proposals/0498-runtime-demangle.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ We propose to introduce two `demangle` functions in the `Runtime` module:
A simple demangle method, returning an optional `String`:

```swift
public func demangle(_ mangledName: String) -> String?
public func demangle(_ mangledName: String) throws(DemanglingError) -> String
```

The demangling function supports all valid Swift symbols. Valid Swift 5.0 and later symbols begin with `$s` (preceded by an optional platform-specific prefix).
Expand All @@ -42,30 +42,39 @@ And an overload which accepts an `UTF8Span` into which the demangled string can
public func demangle(
_ mangledName: borrowing UTF8Span,
into output: inout OutputSpan<UTF8.CodeUnit>
) -> DemanglingResult
) throws(DemanglingError)

public enum DemanglingResult: Equatable {
case success
case failed
case truncated(Int)
/// Error thrown to indicate failure to demangle a Swift symbol.
public enum DemanglingError: Error {
/// Demangling resulted in truncating the result. The payload value is the
/// number of bytes necessary for a full demangle.
case truncated(requiredBufferSize: Int)

/// The passed Swift mangled symbol was invalid.
case invalidSymbol
}
```

The span accepting API is necessary for performance sensitive use-cases, which attempt to demangle symbols in process, before displaying or sending them for further processing. In those use-cases it is common to have a known maximum buffer size into which we are willing to write the demangled representation.

The output from this API is an `OutputSpan` of `UTF8.CodeUnit`s, and it may not necessarily be well-formed UTF8, because of the potential of truncation happening between two code units which would render the UTF8 invalid.

If the demangled representation does not fit the preallocated buffer, the demangle method will return `truncated(actualSize)` such that developers can determine by how much the buffer might need to be increased to handle the complete demangling.
If the demangled representation does not fit the preallocated buffer, the demangle method will throw `DemanglingError.truncated(requiredBufferSize: Int)` such that developers can determine by how much the buffer might need to be increased to handle the complete demangling.

To construct an `UTF8Span` or valid `String` from the `OutputSpan` you can do the following:

```swift
var demangledOutputSpan: OutputSpan<UTF8.CodeUnit> = ...

if demangle("$sSG", into: &demangledOutputSpan) == .success {
do {
try demangle("$sSG", into: &demangledOutputSpan)
let utf8 = try UTF8Span(validating: demangledOutputSpan.span)
let demangledString = String(copying: utf8)
print(demangledString) // Swift.RandomNumberGenerator
} catch DemanglingError.truncated(let requiredBufferSize) {
// Handle truncation - need a buffer of size requiredBufferSize
} catch {
// Handle invalid symbol
}
```

Expand Down
Loading