Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatic parsing / serialization #42

Open
dhensby opened this issue Sep 26, 2022 · 0 comments
Open

Automatic parsing / serialization #42

dhensby opened this issue Sep 26, 2022 · 0 comments

Comments

@dhensby
Copy link

dhensby commented Sep 26, 2022

Problem description

When dealing with headers, it's hard for a generic library to know what the serialization for an arbitrary header is going to be.

If we wish to normalise an arbitrary header without knowing it's serialization (is it a dictionary, a list, or an item?) then to parse the header reliably becomes somewhat tedious.

Further to this, serialisation becomes tricky as well. Any parser that is implemented by this libary's consumer to attempt to parse the fields in a generic way must somehow keep hold of the type that was successfully parsed and, likewise, how to re-serialize it (if needed). Serializing the values of a dictionary are more complex still as there's no concrete way to know if the item in the Map is itself an Item or and InnerList. (edit: there is an isInnerList type guard which is useful for this purpose).

The lack of concrete typing of the returned values from the parsers make inference harder as well. If the returned types were first-class classes that we could perform instanceof checks on or similar, then inferring the type once parsed in a generic manner would be easier, including the serialization of any sub items that were returned.

Proposed solution

Implementing concrete classes would facilitate a more generic parsing / serialization approach to the data that an application deals with.

For example:

interface StructuredField {
  serialize(): string;
  toString(): string; // just an alias of serialize()
}

class Dictionary {
    private readonly parsed: DictType;
    private readonly raw: string;
    constructor(input: string) {
        this.raw = input;
        this.parsed = parseDictionary(input);
    }

    toString(): string {
        return this.serialize();
    }

    serialize(): string {
        return serializeDictionary(this.parsed);
    }

    has(key: string): boolean {
        return this.parsed.has(key);
    }

    get(key: string): StructuredField {
        return this.parsed.get(key);
    }
}

With this kind of concrete implementation we can then perform some more generic parsing/serialization of dictionaries.

const dict = new Dictionary('a=1, b=2;x=1;y=2, c=(a   b    c), d');
console.log(dict.has('a')); // true
console.log(dict.has('e')); // false
console.log(dict.get('b').serialize()); // 2;x=1;y=2
console.log(dict.get('c').serialize()); // (a b c)

Above the consumer doesn't need to know anything about the items in the dictionary to serialize them, we can also see that this could extend to a more generic parser that returns the appropriate class for the structured field, and then can be acted on appropriately.

The existing parseDictionary() and similar functions effectively become factories for the respective classes (mostly for backwards compatability) and then we could introduce a generic parseHeader()/parseField() function that could follow the guidance of the spec in terms of parsing structured fields

Use case

I'm working on HTTP Message Signing, which requires parsing of structured headers in a generic way. It's not feasible for the signer/verifier logic to know exactly what type of structured header we (should) be parsing, there's also a need to be able to serialize headers or items in dictionaries, without having to know ahead of time what the type of item we are dealing with.

How does this sound as an approach?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant