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

Add first-class support for completely custom chunk parsing #26

Open
stefan-baumann opened this issue Feb 23, 2022 · 1 comment
Open
Assignees

Comments

@stefan-baumann
Copy link
Owner

Currently, completely custom parsing of chunks is not really well-supported. Parsing individual fields with custom methods is already a fully supported first-class API, but classes are missing. An official, easy way to do this would be useful.

Implementing this kind of behaviour is already possible using only official public APIs, but that requires wrapping the actual contents in a custom struct or other similar workarounds. See e.g. https://github.com/stefan-baumann/ManiaPlanetSharp/blob/c9e84b463ea980645e26974b23c3361142205887/src/ManiaPlanetSharp/GameBox/Parsing/Chunks/Replay/ReplayMainChunk.cs

@stefan-baumann
Copy link
Owner Author

stefan-baumann commented Feb 23, 2022

Implementation plan

My current plan for how to tackle this in the best possible way is to easily allow the creation of custom ChunkParser<TChunk> instances. This would probably look like this:

public class TestChunk
    : Chunk
{
    // Some custom fields
}

[CustomChunkParser]
public class TestChunkParser
    : ChunkParser<CustomChunk>
{
    public override CustomChunk Parse(GameBoxReader reader, uint chunkId)
    {
        // Parse
        return new CustomChunk();
    }

    // Tuples of (chunkId, skippable)
    public override List<Tuple<uint, bool>> ParseableIds => new List<Tuple<uint, bool>>() { Tuple.Create(0x0000000, true) };
}

These chunk parsers would then be registered as all chunk parsers were usually registered.

Official "unofficial" way to write code that works now and can easily be adapted to the official API later

For now, until this is officially supported, it's possible to implement the same feature with some small workarounds, which can easily be adapted to the final official API later on with minimal changes:

public class TestChunk
    : Chunk
{
    // Some custom fields
}

public class TestChunkParser
    : PregeneratedChunkParser<CustomChunk>
{
    public override CustomChunk Parse(GameBoxReader reader, uint chunkId)
    {
        // Parse
        return new CustomChunk();
    }

    // Tuples of (chunkId, skippable)
    public override List<Tuple<uint, bool>> ParseableIds => new List<Tuple<uint, bool>>() { Tuple.Create(0x0000000, true) };
}

// Put this code somewhere and run it to register the custom parser
// Keep in mind this misuses private APIs that are not officially supported in this way
// It should however work reliably at least until the official feature for custom chunk parsers is released
((Dictionary<uint, IChunkParser<Chunk>>)typeof(ParserFactory).GetField("chunkParsersByID", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null)).Add(chunkId, new TestChunkParser());
((HashSet<uint>)typeof(ParserFactory).GetField("chunkIds", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null)).Add(chunkId);

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

No branches or pull requests

1 participant