···2233let charset = "234567abcdefghijklmnopqrstuvwxyz"
4455-let encode (n : int64) : t =
66- let rec encode ~tid n =
55+let tid_regexp =
66+ Re.Pcre.regexp "[234567abcdefghij][234567abcdefghijklmnopqrstuvwxyz]{12}"
77+88+let is_valid (s : string) : bool =
99+ match String.length s with
1010+ | 13 when Re.execp tid_regexp s ->
1111+ true
1212+ | _ ->
1313+ false
1414+1515+let ensure_valid (tid : t) : unit =
1616+ if String.length tid <> 13 then
1717+ raise
1818+ (Invalid_argument
1919+ (Format.sprintf "invalid tid length %d: %s" (String.length tid) tid) )
2020+ else if not (Re.execp tid_regexp tid) then
2121+ raise (Invalid_argument (Format.sprintf "invalid tid format: %s" tid))
2222+2323+let _encode (n : int64) : t =
2424+ let rec _encode ~tid n =
725 match n with
826 | 0L ->
927 tid
1028 | n ->
1111- encode
2929+ _encode
1230 ~tid:(String.make 1 charset.[Int64.to_int (Int64.rem n 32L)] ^ tid)
1331 (Int64.unsigned_div n 32L)
1432 in
1515- encode ~tid:"" n
3333+ _encode ~tid:"" n
16341717-let decode (s : t) : int64 =
1818- let rec decode ~(n : int64) (s : string) =
3535+let _decode (s : t) : int64 =
3636+ let rec _decode ~(n : int64) (s : string) =
1937 match s with
2038 | s when String.length s > 0 ->
2139 let c = s.[0] in
2240 let cs = String.sub s 1 (String.length s - 1) in
2323- decode
4141+ _decode
2442 ~n:
2543 (Int64.add (Int64.mul n 32L)
2644 (Int64.of_int (String.index charset c)) )
···2846 | _ ->
2947 n
3048 in
3131- decode ~n:0L s
4949+ _decode ~n:0L s
5050+5151+let of_timestamp_us (timestamp : int64) ~(clockid : int) : t =
5252+ if timestamp < 0L || timestamp >= Int64.shift_left 1L 53 then
5353+ raise (Invalid_argument "timestamp must be within range [0, 2^53)") ;
5454+ if clockid < 0 || clockid > 1023 then
5555+ raise (Invalid_argument "clockid must be within range [0, 1023]") ;
5656+ let rec pad str len =
5757+ if String.length str >= len then str else pad ("2" ^ str) len
5858+ in
5959+ pad (_encode timestamp) 11 ^ pad (_encode @@ Int64.of_int clockid) 2
6060+6161+let of_timestamp_ms (timestamp : int64) ~(clockid : int) : t =
6262+ of_timestamp_us (Int64.mul timestamp 1000L) ~clockid
6363+6464+let to_timestamp_us (tid : t) : int64 * int =
6565+ ensure_valid tid ;
6666+ let timestamp = _decode (String.sub tid 0 11) in
6767+ let clockid = Int64.to_int @@ _decode (String.sub tid 11 2) in
6868+ (timestamp, clockid)
6969+7070+let to_timestamp_ms (tid : t) : int64 * int =
7171+ ensure_valid tid ;
7272+ let timestamp = _decode (String.sub tid 0 11) in
7373+ let clockid = Int64.to_int @@ _decode (String.sub tid 11 2) in
7474+ (Int64.div timestamp 1000L, clockid)
32753376let now () : t =
3434- Mtime_clock.now_ns () |> Int64.unsigned_div 1_000_000L |> encode
7777+ Mtime_clock.now_ns () |> Int64.unsigned_div 1_000L
7878+ |> of_timestamp_us ~clockid:(Random.int_in_range ~min:0 ~max:1023)
35793636-let of_string (s : string) : t =
3737- match String.length s with
3838- | 13
3939- when Str.string_match
4040- (Str.regexp
4141- "/^[234567abcdefghij][234567abcdefghijklmnopqrstuvwxyz]{12}$/" )
4242- s 0 ->
4343- s
4444- | _ ->
4545- raise (Invalid_argument (Format.sprintf "invalid tid: %s" s))
8080+let of_string (s : string) : t = ensure_valid s ; s
46814782let to_string (s : t) : string = s
4883
+13-9
mist/lib/util.ml
···88 let zeros' =
99 zeros
1010 +
1111- if byte = 0x0 then 4
1212- else if byte < 0x04 then 3
1313- else if byte < 0x10 then 2
1414- else if byte < 0x40 then 1
1111+ if byte = 0 then 4
1212+ else if byte < 4 then 3
1313+ else if byte < 16 then 2
1414+ else if byte < 64 then 1
1515 else 0
1616 in
1717- if byte = 0x0 then loop (idx + 1) zeros' else zeros'
1717+ if byte = 0 then loop (idx + 1) zeros' else zeros'
1818 in
1919 loop 0 0
2020···2626 in
2727 loop 0
28282929-let valid_key_char_regex = Str.regexp "^[a-zA-Z0-9_~\\-:.]*$"
2929+let shared_prefix (a : string) (b : string) : string =
3030+ let len = shared_prefix_length a b in
3131+ String.sub a 0 len
3232+3333+let valid_key_char_regex = Re.Pcre.regexp "^[a-zA-Z0-9_~\\-:.]*$"
30343135let is_valid_mst_key (key : string) : bool =
3236 match String.split_on_char '/' key with
3337 | [coll; rkey]
3438 when String.length key <= 1024
3539 && coll <> "" && rkey <> ""
3636- && Str.string_match valid_key_char_regex coll 0
3737- && Str.string_match valid_key_char_regex rkey 0 ->
4040+ && Re.execp valid_key_char_regex coll
4141+ && Re.execp valid_key_char_regex rkey ->
3842 true
3943 | _ ->
4044 false
41454246let ensure_valid_key (key : string) : unit =
4343- if not (is_valid_mst_key key) then raise (Invalid_argument "Invalid MST key")
4747+ if not (is_valid_mst_key key) then raise (Invalid_argument "invalid mst key")