-
Notifications
You must be signed in to change notification settings - Fork 2
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
Work with strings, expose module functor #3
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice, that was fast, thanks! looks good to me except for the stream/buffer stuff that i'm not sure about (see inline)
src/vlq.ml
Outdated
then base64.[digit] | ||
else failwith (Printf.sprintf "Must be between 0 and 63: %d" digit) | ||
let char_of_int digit = | ||
match digit >= 0, digit < String.length base64 with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm sure it doesn't really matter, but is this as efficient as an if
? it won't short circuit, and i wouldn't be surprised if it actually allocates tuples, especially in JS
|
||
let decode = | ||
let rec helper (acc, shift) stream = | ||
let decode value = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the problem with taking a string is that we don't know how many characters the VLQ is. with a stream, we consume characters until we read a complete VLQ, which mutates the stream so it's ready to read the next one. given a sourcemap segment as a string like "AKgBiB", how do we split it into ("A", "K", "gB", "iB") to decode it into (0, 5, 16, 17)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. Thinking in this case, if encode
receives an int
and not an int Stream.t
, then decode
should work when composed with encode (and vice-versa):
decode (encode x) = x
encode (decode y) = y
Mathematically, there is an isomorphism because both functions are bijective, like string_of_int
and int_of_string
.
This would be an issue where the sourcemap module would be responsible at all (but, for optimizations, we could expose functions with streams and buffers. I'll implement it.
|
||
(* Encodes `value` as a VLQ and writes it to `buf` *) | ||
let encode buf value = | ||
let encode value = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
writing to a buffer was actually a significant perf win for us, so I'd like to leave the ability to do that even if we also expose a string
API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree! The source map implementation for string_of_mappings
writes the encoded value to the result, buffer
to buffer
.
This pull-request does:
string -> int
andint -> string
instead of mutable buffers and streamsocamldoc
comments on.mli
Discussion
Currently, the implementation is bound to string (or string like value) as encoded value because the VLQ implementation (not the Base64 one) was using specifically
char
for encoding.To make it more modular, the correct way would be having the module parameter from
Make
as being also anEnum
and aMonoid
.For example:
So, for strings,
elt = char
,t = string
, for char streamselt = char
,t = elt Stream.t
and so on.