Skip to content

Feature Request: Make ParserSpan copying initializer public #58

Description

@TwirlySeal

This internal ParserSpan initializer for a copy of another instance would be useful for speculative/transactional parsing where it is ambiguous what kind of structure is being parsed until later in the data, and the parser must make a guess with the ability to commit the state change if successful or discard it if invalid.

@inlinable
@_lifetime(copy other)
init(copying other: borrowing ParserSpan) {
self._bytes = other._bytes
self._lowerBound = other._lowerBound
self._upperBound = other._upperBound
}

Here is an example where this would be useful, using the RawSpan initializer with the bytes property of another ParserSpan as a workaround for the current API.

import BinaryParsing

struct RetType {
    let customMods: [CustomMod]
    
    init(span: inout ParserSpan) throws {
        // It is not known how many custom modifiers there are,
        // so a copy of the span is made to try parsing one and the state change
        // is committed if successful
        var customMods = [CustomMod]()
        while true {
            var copySpan = ParserSpan(span.bytes)
            guard let customMod = try CustomMod(span: &copySpan) else {
                break
            }
            customMods.append(customMod)
            span = copySpan
        }
        self.customMods = customMods
    }
}

An alternative would be to add 'peeking' equivalents for each of the parsing initializers (integers, strings, arrays, etc.), but the copying approach has the benefit of reuse for eager parsing code both in the implementation of this library and for its users, as an initializer accepting a ParserSpan can be given either a primary instance or a copy. Committing the state change by assigning the copy span to the primary span is also simpler than seeking by a relative offset equal to the size of what was parsed, which would be needed for peeking APIs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions