Source file uvarint.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
(* Simple variable length integers *)
let max_varint_len_64 = 10

(* Uses the go-lang implementation: https://golang.org/src/encoding/binary/varint.go *)
type t = int

let byte t = t lor 0x80

let put_uvarint buff v =
  let i = ref 0 in
  let x = ref v in
  while !x >= 0x80 do
    Cstruct.set_uint8 buff !i (byte !x);
    x := !x asr 7;
    incr i
  done;
  Cstruct.set_uint8 buff !i !x;
  !i + 1

let encode t =
  let buff = Cstruct.create max_varint_len_64 in
  let bytes_written = put_uvarint buff t in
  Cstruct.sub buff 0 bytes_written

let decode buff =
  let x = ref 0 in
  let s = ref 0 in
  let rec loop i =
    if i >= max_varint_len_64 then (!x, i)
    else
      let b = Cstruct.get_uint8 buff i in
      if b < 0x80 then
        if i == max_varint_len_64 - 1 && b > 1 then (!x, i)
        else (!x lor (b lsl !s), i)
      else (
        x := !x lor ((b land 0x7f) lsl !s);
        s := !s + 7;
        loop (i + 1))
  in
  let r, i = loop 0 in
  (r, i + 1)

let unsafe_get_uint8 t off = Char.code (String.unsafe_get t off)

let decode_string (buff : string) =
  let x = ref 0 in
  let s = ref 0 in
  let rec loop i =
    if i >= max_varint_len_64 then (!x, i)
    else
      let b = unsafe_get_uint8 buff i in
      if b < 0x80 then
        if i == max_varint_len_64 - 1 && b > 1 then (!x, i)
        else (!x lor (b lsl !s), i)
      else (
        x := !x lor ((b land 0x7f) lsl !s);
        s := !s + 7;
        loop (i + 1))
  in
  let r, i = loop 0 in
  (r, i + 1)