Metaplasia is a library that offers users the ability to do a few fun things with their types and objects in Zig, such as:
- Easy reflection
- Interfaces
- Compile-time and run-time (and hybrid)!
- Type merging
- Type generation
- Interfaces are important and make sure that your code obeys a standard implementation such that it can be swapped out with another bit without needing to re-write everything, thus increasing modularity! But they also serve an important role as sanity checks for your code!
// A simple reader interface
const IReader =
Blank()
.And(IsInType(FindFieldAs("buffer", []u8))
.And(IsInType(FindFunctionAs("read_fn", fn([]u8, []u8) []u8));
// "grant" returns the type defined below at compile-time if and only if it implements IReader
const custom_reader_type = IReader.Grant(
struct {
buffer: []u8,
pub fn read_fn(path: []u8, options: []u8) []u8 {
// ...
}
});
- Ever wanted to have a reader and a writer in one package, having those written already, but did not want to write this mixed type by hand? Type merging is the solution! Simply pass two types as
// Naive type-merging
const writer_type = struct { ... };
const reader_type = struct { ... };
// Obtain a writer and reader combined type
const writer_reader_type = InferAndMerge([_]type {writer_type, reader_type});
// Safe type-merging
const safe_writer_type = IWriter.Grant(struct { ... });
const safe_reader_type = IReader.Grant(struct { ... });
// This type matches both interfaces, because the original types matched them, if not, we'd get a compile error explaining the situation!
// This type can be used as both a writer and a reader, swap freely!
const safe_writer_reader_type = InferAndMerge([_]type {safe_writer_type, safe_reader_type});
- Now think of a game, where you would have a lot of types, and you would want to re-use them to build more advanced, complex types based off of the original ones. Or, what about procedural types?
// Some base type that's going to be used in a lot of places
const entity_type = InferAndMerge([_]type {health_type, damage_type, identity_type, ...});
// A new player type that 'extends' the entity type. Inheritance, but without all the fuss!
const player_type = InferAndMerge([_]type {entity_type, physics_type, chat_type, ... });
// ...
// insert example for procedural types
};
Below is the status of current features. Blank means not implemented.
- Reflection (#2)
- Interfaces (#5)
- Type merging
- Type generation