I wanted to use this library in my project, but ran into an issue: I have a "dynamic value" type that can hold arbitrary data. Encoding it to messagepack is no problem, but decoding is an issue, since I don't know ahead of time what the type will be.
The DataReader class provides a low-level api, which is too low-level for my liking - you have understand the messagepack format to use it effectively, not to mention that misusing it can "corrupt" the data stream (for example, calling getFloat64 when the next entry is a string will just read the marker and some of the string bytes as a float value without any checks, leaving the "cursor" in the middle of the string (or past it if the string is short), which will make all subsequent readings give complete nonsence).
The Decoder class on the other hand provides a more high-level API, but I cannot use it, since I don't know what the format will be before-hand. Therefore, I need a "mid-level" API that would read "complete non-deep entries" with possibility to query what kind of entry it is. That way, it is impossible to "completely corrupt" the data stream, but the user is still responsible for reading "deep structures" (array and map) themself - this api will only tell them that the next entry is "map of length N" for example.
Here is an example usage from current (first proof of concept) implementation:
export function decodeDynValue(data: DataReader): DynValue {
const entryReader = new EntryReader(data);
const entry = entryReader.nextEntry()!;
if (entry.isInt(false)) {
return DynValue.number(entry.readInt() as f64);
}
if (entry.isUint(false)) {
return DynValue.number(entry.readUint() as f64);
}
if (entry.isFloat()) {
return DynValue.number(entry.readFloat());
}
if (entry.isMapLength() && entry.readMapLength() == 1) {
const tag = entryReader.nextEntry()!.tryReadString().get("Get map tag");
// throw new Error("what is the tag?" + tag);
if (tag == "SlimeAmount") {
const entry = entryReader.nextEntry()!;
const abi = entry.tryReadInt().get("Get slime amount");
return DynValue.slimeAmount(slimeAmountFromAbi(abi));
}
throw new Error("Unknown map tag: " + tag);
}
throw new Error("Unknown entry: " + entry.toString());
}
There are many things that need resolving before I would consider this production-ready. The whole "every method has two variants" with optional results idea would probably need scrapping, since it's not really idiomatic in AS as far as I know. Also I didn't implement lower-bytes numbers as separate types, instead, the user can read a Uint64 and test themself if it's an u8 or not.
In the end, this is more of an idea than an PR, but I would be interested in hearing whether you would add something like this to the library if it was a little bit more polished. Also, I couldn't get tests running, so it's not really tested, besides the 2 or 3 types that I actually used in my code.
I wanted to use this library in my project, but ran into an issue: I have a "dynamic value" type that can hold arbitrary data. Encoding it to messagepack is no problem, but decoding is an issue, since I don't know ahead of time what the type will be.
The
DataReader
class provides a low-level api, which is too low-level for my liking - you have understand the messagepack format to use it effectively, not to mention that misusing it can "corrupt" the data stream (for example, callinggetFloat64
when the next entry is a string will just read the marker and some of the string bytes as a float value without any checks, leaving the "cursor" in the middle of the string (or past it if the string is short), which will make all subsequent readings give complete nonsence).The
Decoder
class on the other hand provides a more high-level API, but I cannot use it, since I don't know what the format will be before-hand. Therefore, I need a "mid-level" API that would read "complete non-deep entries" with possibility to query what kind of entry it is. That way, it is impossible to "completely corrupt" the data stream, but the user is still responsible for reading "deep structures" (array and map) themself - this api will only tell them that the next entry is "map of length N" for example.Here is an example usage from current (first proof of concept) implementation:
There are many things that need resolving before I would consider this production-ready. The whole "every method has two variants" with optional results idea would probably need scrapping, since it's not really idiomatic in AS as far as I know. Also I didn't implement lower-bytes numbers as separate types, instead, the user can read a Uint64 and test themself if it's an u8 or not.
In the end, this is more of an idea than an PR, but I would be interested in hearing whether you would add something like this to the library if it was a little bit more polished. Also, I couldn't get tests running, so it's not really tested, besides the 2 or 3 types that I actually used in my code.