I would really like an encoder/decoder for Roc that uses a more efficient representation than JSON. I would like to use this e.g. in basic-webserver to cache data in memory between requests. JSON doesn't map very well 1-1 with Roc's types and could be way more efficient.
I started implementing get : U64, value -> Task value [NotFound] where value implements Decoding
but realised that the platform needs access to a decoder to do that.
So I've been doing some research to explore ways to implement this in Roc. Any tips or pointers would be most appreciated. I'm not sure it's possible to do this well using pure Roc at the moment, but interested to explore this further.
Take an F64
for example, I can encode this to bytes using Num.toStr
. Then to convert back using Str.toF64
. For example we could do this.
f64ToBytes : F64 -> List U8
f64ToBytes = \f64 ->
f64
|> Num.toStr
|> Str.toUtf8
f64FromBytes : List U8 -> F64
f64FromBytes = \bytes ->
bytes
|> Str.fromUtf8
|> Result.try Str.toF64
|> Result.withDefault 0f64
I don't love this idea... because it isn't very efficient. For example f64ToBytes 123.42345234 == [49, 50, 51, 46, 52, 50, 51, 52, 53, 50, 51, 52] : List U8
which is far more bytes than I think we actually need to represent this number.
For example IEEE 754 double precision floats is a 64-bit encoding, so maybe we could have toRaw : F64 -> (U8,U8,U8,U8,U8,U8,U8,U8)
? Or maybe a builtin to expose the sign, exponent and significand?
yeah I like the idea of having a way to encode and decode every number type to/from raw bytes—with endianness specified explicitly instead of inferred based on the target (I think we talked about this somewhere on Zulip although I don't remember where :sweat_smile:)
10 messages were moved from this topic to #ideas > builtin serialization format by Richard Feldman.
Last updated: Jul 05 2025 at 12:14 UTC