This wouldn't require any bitwise operations to store/retrieve fields, assuming they are all byte-aligned.
> While looking all this up, I found Justin Fagnani’s article Composite Map Keys in JavaScript with Bitsets, which is mostly unrelated to what I’m doing here
In fact, the author specifically wants his records to be mutable, which precludes using them as Set or Map keys (at least at the same time).
So immutable bigints seem like sort of the wrong tool for the job: changing any single field requires creating a completely new number (and while in theory a compiler might be able to optimize away the copy, in practice I doubt this happens).
Also, there's no great story for getting a large byte blob into or out of a BigInt, short of converting it all to ASCII hex and back. I ran into that limitation when attempting to use BigInts for arbitrary-precision arithmetic.
For simple data storage, I'd rather just use a Uint32Array and split/merge bits over element boundaries as appropriate.
* I don't use bit or byte boundaries. If I need to store a field with 11 possible values, I go (n*11) + value. You'd think that would be a performance bottleneck, but it turns out major browsers are hella fast at this, at least when handling the amount of data in one Kyudosudoku undo item, which isn't a lot. The obvious downside is that you can't index into the data, you can only decode the whole thing, but I always want to decode a whole undo item at a time anyway.
* The main goal was for the representation to be as compact as possible so as to fill up as little of the user's localStorage as possible. Using hexadecimal for this is a massive waste. So I try to use the entire range of Unicode characters that are 16 bits in UTF-16 (that's the BMP minus surrogates, but to be safe I avoid the C0 control characters too). (I reserve the space character so that I can concatenate the entire undo history into a single string and still split it apart later without having to decode all of it.) This means I essentially encode the BigInt in base-63453. Again, dividing and moduloing huge numbers by 63453 seems like a performance nightmare, but it looks like modern browsers handle it fine, as the undo/redo feature is perfectly usable.
So app state -> bigint -> bytearray -> compressed bytearray -> bigint -> packed utf16 string.
Probably it would but help much
dleeftink•4mo ago
[0]: https://github.com/zandaqo/structurae