Source file bytesrw_hex.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
let strf = Printf.sprintf
let to_binary_string' h =
let hex_value s i = match s.[i] with
| '0' .. '9' as c -> Char.code c - 0x30
| 'A' .. 'F' as c -> 10 + (Char.code c - 0x41)
| 'a' .. 'f' as c -> 10 + (Char.code c - 0x61)
| c -> failwith (strf "%d: %C is not an ASCII hexadecimal digit" i c)
in
match String.length h with
| len when len mod 2 <> 0 -> failwith "Missing final hex digit"
| len ->
let rec loop max s i h k = match i > max with
| true -> Bytes.unsafe_to_string s
| false ->
let hi = hex_value h k and lo = hex_value h (k + 1) in
Bytes.set s i (Char.chr @@ (hi lsl 4) lor lo);
loop max s (i + 1) h (k + 2)
in
let s_len = len / 2 in
let s = Bytes.create s_len in
loop (s_len - 1) s 0 h 0
let err_len ~exp ~fnd =
strf "Expected %d ASCII hexadecimal digits but found %d characters" exp fnd
let to_binary_string ?length hex =
try match length with
| None -> Ok (to_binary_string' hex)
| Some len ->
let exp = len * 2 in
let fnd = String.length hex in
if exp <> fnd then failwith (err_len ~exp ~fnd) else
Ok (to_binary_string' hex)
with
| Failure e -> Error e
let pp_binary_string ppf s =
for i = 0 to String.length s - 1
do Format.fprintf ppf "%02x" (Char.code (s.[i])) done
let of_binary_string s = Format.asprintf "%a" pp_binary_string s
let check_binary_string_length ~length s =
let len = String.length s in
if len = length then Ok s else
Error (strf "Expected %d bytes but found %d" length len)