package bytesrw
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(*--------------------------------------------------------------------------- Copyright (c) 2024 The bytesrw programmers. All rights reserved. SPDX-License-Identifier: ISC ---------------------------------------------------------------------------*) (* Binary strings *) let strf = Printf.sprintf let to_binary_string' h = (* raises Failure *) 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)