···11module Config = Configurator.V1
2233-let pre407 = {ocaml|external unsafe_set_uint16 : bytes -> int -> int -> unit = "%caml_string_set16u" [@@noalloc]|ocaml}
44-let standard = {ocaml|external unsafe_set_uint16 : bytes -> int -> int -> unit = "%caml_bytes_set16u" [@@noalloc]|ocaml}
33+let pre407 =
44+ {ocaml|external unsafe_set_uint16 : bytes -> int -> int -> unit = "%caml_string_set16u" [@@noalloc]|ocaml}
5566-type t =
77- { major : int
88- ; minor : int
99- ; patch : int option
1010- ; extra : string option }
66+let standard =
77+ {ocaml|external unsafe_set_uint16 : bytes -> int -> int -> unit = "%caml_bytes_set16u" [@@noalloc]|ocaml}
1181212-let v ?patch ?extra major minor = { major; minor; patch; extra; }
99+type t = { major : int; minor : int; patch : int option; extra : string option }
1010+1111+let v ?patch ?extra major minor = { major; minor; patch; extra }
13121413let parse s =
1515- try Scanf.sscanf s "%d.%d.%d+%s" (fun major minor patch extra -> v ~patch ~extra major minor)
1616- with End_of_file | Scanf.Scan_failure _ ->
1717- ( try Scanf.sscanf s "%d.%d+%s" (fun major minor extra -> v ~extra major minor)
1414+ try
1515+ Scanf.sscanf s "%d.%d.%d+%s" (fun major minor patch extra ->
1616+ v ~patch ~extra major minor)
1717+ with End_of_file | Scanf.Scan_failure _ -> (
1818+ try
1919+ Scanf.sscanf s "%d.%d+%s" (fun major minor extra -> v ~extra major minor)
2020+ with End_of_file | Scanf.Scan_failure _ -> (
2121+ try
2222+ Scanf.sscanf s "%d.%d.%d" (fun major minor patch ->
2323+ v ~patch major minor)
1824 with End_of_file | Scanf.Scan_failure _ ->
1919- ( try Scanf.sscanf s "%d.%d.%d" (fun major minor patch -> v ~patch major minor)
2020- with End_of_file | Scanf.Scan_failure _ ->
2121- Scanf.sscanf s "%d.%d" (fun major minor -> v major minor) ) )
2525+ Scanf.sscanf s "%d.%d" (fun major minor -> v major minor)))
22262323-let ( >|= ) x f = match x with
2424- | Some x -> Some (f x )
2525- | None -> None
2727+let ( >|= ) x f = match x with Some x -> Some (f x) | None -> None
26282729let ocaml_cp ~src ~dst =
2830 let ic = open_in src in
2931 let oc = open_out dst in
3032 let bf = Bytes.create 0x1000 in
3131- let rec go () = match input ic bf 0 (Bytes.length bf) with
3333+ let rec go () =
3434+ match input ic bf 0 (Bytes.length bf) with
3235 | 0 -> ()
3333- | len -> output oc bf 0 len ; go ()
3636+ | len ->
3737+ output oc bf 0 len ;
3838+ go ()
3439 | exception End_of_file -> () in
3535- go () ; close_in ic ; close_out oc
3636-;;
4040+ go () ;
4141+ close_in ic ;
4242+ close_out oc
37433844let () =
3945 Config.main ~name:"config-base64" @@ fun t ->
4046 match Config.ocaml_config_var t "version" >|= parse with
4147 | Some version ->
4242- let dst = "unsafe.ml" in
4848+ let dst = "unsafe.ml" in
43494444- if (version.major, version.minor) >= (4, 7)
4545- then ocaml_cp ~src:"unsafe_stable.ml" ~dst
4646- else ocaml_cp ~src:"unsafe_pre407.ml" ~dst
5050+ if (version.major, version.minor) >= (4, 7)
5151+ then ocaml_cp ~src:"unsafe_stable.ml" ~dst
5252+ else ocaml_cp ~src:"unsafe_pre407.ml" ~dst
4753 | None -> Config.die "OCaml version is not available"
4854 | exception exn -> Config.die "Got an exception: %s" (Printexc.to_string exn)
···11open Crowbar
2233exception Encode_error of string
44+45exception Decode_error of string
5667(** Pretty printers *)
···910 Printexc.register_printer (function
1011 | Encode_error err -> Some (Fmt.strf "(Encoding error: %s)" err)
1112 | Decode_error err -> Some (Fmt.strf "(Decoding error: %s)" err)
1212- | _ -> None )
1313+ | _ -> None)
13141415let pp_chr =
1516 let escaped = function ' ' .. '~' as c -> String.make 1 c | _ -> "." in
1617 Fmt.using escaped Fmt.string
17181818-let pp_scalar : type buffer.
1919+let pp_scalar :
2020+ type buffer.
1921 get:(buffer -> int -> char) -> length:(buffer -> int) -> buffer Fmt.t =
2022 fun ~get ~length ppf b ->
2123 let l = length b in
···2325 Fmt.pf ppf "%08x: " (i * 16) ;
2426 let j = ref 0 in
2527 while !j < 16 do
2626- if (i * 16) + !j < l then
2727- Fmt.pf ppf "%02x" (Char.code @@ get b ((i * 16) + !j))
2828+ if (i * 16) + !j < l
2929+ then Fmt.pf ppf "%02x" (Char.code @@ get b ((i * 16) + !j))
2830 else Fmt.pf ppf " " ;
2931 if !j mod 2 <> 0 then Fmt.pf ppf " " ;
3032 incr j
···3234 Fmt.pf ppf " " ;
3335 j := 0 ;
3436 while !j < 16 do
3535- if (i * 16) + !j < l then Fmt.pf ppf "%a" pp_chr (get b ((i * 16) + !j))
3737+ if (i * 16) + !j < l
3838+ then Fmt.pf ppf "%a" pp_chr (get b ((i * 16) + !j))
3639 else Fmt.pf ppf " " ;
3740 incr j
3841 done ;
···4649let check_encode str =
4750 let subs = Astring.String.cuts ~sep:"\r\n" str in
4851 let check str =
4949- if String.length str > 78 then
5050- raise (Encode_error "too long string returned")
5151- in
5252- List.iter check subs ; str
5252+ if String.length str > 78
5353+ then raise (Encode_error "too long string returned") in
5454+ List.iter check subs ;
5555+ str
53565457let encode input =
5558 let buf = Buffer.create 80 in
···5760 String.iter
5861 (fun c ->
5962 let ret = Base64_rfc2045.encode encoder (`Char c) in
6060- match ret with `Ok -> () | _ -> assert false )
6363+ match ret with `Ok -> () | _ -> assert false)
6164 (* XXX(dinosaure): [`Partial] can never occur. *)
6265 input ;
6366 let encode = Base64_rfc2045.encode encoder `End in
···6871let decode input =
6972 let decoder = Base64_rfc2045.decoder (`String input) in
7073 let rec go acc =
7171- if Base64_rfc2045.decoder_dangerous decoder then
7272- raise (Decode_error "Dangerous input") ;
7474+ if Base64_rfc2045.decoder_dangerous decoder
7575+ then raise (Decode_error "Dangerous input") ;
7376 match Base64_rfc2045.decode decoder with
7477 | `End -> List.rev acc
7578 | `Flush output -> go (output :: acc)
7679 | `Malformed _ -> raise (Decode_error "Malformed")
7780 | `Wrong_padding -> raise (Decode_error "Wrong padding")
7878- | _ -> (* XXX(dinosaure): [`Await] can never occur. *) assert false
7979- in
8181+ | _ -> (* XXX(dinosaure): [`Await] can never occur. *) assert false in
8082 String.concat "" (go [])
81838284(** String generators *)
···8486let bytes_fixed_range : string gen = dynamic_bind (range 78) bytes_fixed
85878688let char_from_alpha alpha : string gen =
8787- map [range (String.length alpha)] (fun i -> alpha.[i] |> String.make 1)
8989+ map [ range (String.length alpha) ] (fun i -> alpha.[i] |> String.make 1)
88908991let string_from_alpha n =
9092 let acc = const "" in
···9395 | 0 -> acc
9496 | n ->
9597 add_char_from_alpha alpha
9696- (concat_gen_list (const "") [acc; char_from_alpha alpha])
9797- (n - 1)
9898- in
9898+ (concat_gen_list (const "") [ acc; char_from_alpha alpha ])
9999+ (n - 1) in
99100 add_char_from_alpha alpha acc n
100101101102let random_string_from_alpha n = dynamic_bind (range n) string_from_alpha
···106107let set_canonic str =
107108 let l = String.length str in
108109 let to_drop = l * 6 mod 8 in
109109- if
110110- to_drop = 6
111111- (* XXX(clecat): Case when we need to drop 6 bits which means a whole letter *)
110110+ if to_drop = 6
111111+ (* XXX(clecat): Case when we need to drop 6 bits which means a whole letter *)
112112 then String.sub str 0 (l - 1)
113113- else if
114114- to_drop <> 0
115115- (* XXX(clecat): Case when we need to drop 2 or 4 bits: we apply a mask droping the bits *)
113113+ else if to_drop <> 0
114114+ (* XXX(clecat): Case when we need to drop 2 or 4 bits: we apply a mask droping the bits *)
116115 then (
117116 let buf = Bytes.of_string str in
118117 let value =
119119- String.index Base64_rfc2045.default_alphabet (Bytes.get buf (l - 1))
120120- in
118118+ String.index Base64_rfc2045.default_alphabet (Bytes.get buf (l - 1)) in
121119 let canonic =
122120 Base64_rfc2045.default_alphabet.[value land lnot ((1 lsl to_drop) - 1)]
123121 in
124122 Bytes.set buf (l - 1) canonic ;
125125- Bytes.unsafe_to_string buf )
123123+ Bytes.unsafe_to_string buf)
126124 else str
127125128126let add_padding str =
···140138141139let d2e inputs end_input =
142140 let end_input = add_padding end_input in
143143- let inputs = inputs @ [end_input] in
141141+ let inputs = inputs @ [ end_input ] in
144142 let input =
145143 List.fold_left
146144 (fun acc s -> if String.length s <> 0 then acc ^ "\r\n" ^ s else acc)
147147- (List.hd inputs) (List.tl inputs)
148148- in
145145+ (List.hd inputs) (List.tl inputs) in
149146 let decode = decode input in
150147 let encode = encode decode in
151148 check_eq ~pp ~cmp:String.compare ~eq:String.equal input encode
152149153150let () =
154151 register_printer () ;
155155- add_test ~name:"rfc2045: encode -> decode" [list bytes_fixed_range] e2d ;
152152+ add_test ~name:"rfc2045: encode -> decode" [ list bytes_fixed_range ] e2d ;
156153 add_test ~name:"rfc2045: decode -> encode"
157157- [list (string_from_alpha 76); random_string_from_alpha 76]
154154+ [ list (string_from_alpha 76); random_string_from_alpha 76 ]
158155 d2e
+80-65
fuzz/fuzz_rfc4648.ml
···44 let escaped = function ' ' .. '~' as c -> String.make 1 c | _ -> "." in
55 Fmt.using escaped Fmt.string
6677-let pp_scalar : type buffer.
77+let pp_scalar :
88+ type buffer.
89 get:(buffer -> int -> char) -> length:(buffer -> int) -> buffer Fmt.t =
910 fun ~get ~length ppf b ->
1011 let l = length b in
···1213 Fmt.pf ppf "%08x: " (i * 16) ;
1314 let j = ref 0 in
1415 while !j < 16 do
1515- if (i * 16) + !j < l then
1616- Fmt.pf ppf "%02x" (Char.code @@ get b ((i * 16) + !j))
1616+ if (i * 16) + !j < l
1717+ then Fmt.pf ppf "%02x" (Char.code @@ get b ((i * 16) + !j))
1718 else Fmt.pf ppf " " ;
1819 if !j mod 2 <> 0 then Fmt.pf ppf " " ;
1920 incr j
···2122 Fmt.pf ppf " " ;
2223 j := 0 ;
2324 while !j < 16 do
2424- if (i * 16) + !j < l then Fmt.pf ppf "%a" pp_chr (get b ((i * 16) + !j))
2525+ if (i * 16) + !j < l
2626+ then Fmt.pf ppf "%a" pp_chr (get b ((i * 16) + !j))
2527 else Fmt.pf ppf " " ;
2628 incr j
2729 done ;
···30323133let pp = pp_scalar ~get:String.get ~length:String.length
32343333-let (<.>) f g x = f (g x)
3535+let ( <.> ) f g x = f (g x)
34363537let char_from_alphabet alphabet : string gen =
3636- map [ range 64 ] (String.make 1 <.> Char.chr <.> Array.unsafe_get (Base64.alphabet alphabet))
3838+ map [ range 64 ]
3939+ (String.make 1 <.> Char.chr <.> Array.unsafe_get (Base64.alphabet alphabet))
37403841let random_string_from_alphabet alphabet len : string gen =
3942 let rec add_char_from_alphabet acc = function
4040- | 0 -> acc
4141- | n ->
4242- add_char_from_alphabet
4343- (concat_gen_list (const "") [ acc ; char_from_alphabet alphabet ])
4444- (n - 1) in
4343+ | 0 -> acc
4444+ | n ->
4545+ add_char_from_alphabet
4646+ (concat_gen_list (const "") [ acc; char_from_alphabet alphabet ])
4747+ (n - 1) in
4548 add_char_from_alphabet (const "") len
46494750let random_string_from_alphabet ~max alphabet =
4848- dynamic_bind (range max)
4949- @@ fun real_len ->
5050- dynamic_bind (random_string_from_alphabet alphabet real_len)
5151- @@ fun input ->
5252- if real_len <= 1 then const (input, 0, real_len)
5353- else dynamic_bind (range (real_len / 2))
5454- @@ fun off -> map [ range (real_len - off) ] (fun len -> (input, off, len))
5151+ dynamic_bind (range max) @@ fun real_len ->
5252+ dynamic_bind (random_string_from_alphabet alphabet real_len) @@ fun input ->
5353+ if real_len <= 1
5454+ then const (input, 0, real_len)
5555+ else
5656+ dynamic_bind (range (real_len / 2)) @@ fun off ->
5757+ map [ range (real_len - off) ] (fun len -> (input, off, len))
55585659let encode_and_decode (input, off, len) =
5760 match Base64.encode ~pad:true ~off ~len input with
5861 | Error (`Msg err) -> fail err
5962 | Ok result ->
6060- match Base64.decode ~pad:true result with
6161- | Error (`Msg err) -> fail err
6262- | Ok result ->
6363- check_eq ~pp ~cmp:String.compare ~eq:String.equal result (String.sub input off len)
6363+ match Base64.decode ~pad:true result with
6464+ | Error (`Msg err) -> fail err
6565+ | Ok result ->
6666+ check_eq ~pp ~cmp:String.compare ~eq:String.equal result
6767+ (String.sub input off len)
64686569let decode_and_encode (input, off, len) =
6670 match Base64.decode ~pad:true ~off ~len input with
6767- | Error (`Msg err) ->
6868- fail err
7171+ | Error (`Msg err) -> fail err
6972 | Ok result ->
7070- match Base64.encode ~pad:true result with
7171- | Error (`Msg err) -> fail err
7272- | Ok result ->
7373- check_eq ~pp:Fmt.string ~cmp:String.compare ~eq:String.equal result (String.sub input off len)
7373+ match Base64.encode ~pad:true result with
7474+ | Error (`Msg err) -> fail err
7575+ | Ok result ->
7676+ check_eq ~pp:Fmt.string ~cmp:String.compare ~eq:String.equal result
7777+ (String.sub input off len)
74787575-let (//) x y =
7979+let ( // ) x y =
7680 if y < 1 then raise Division_by_zero ;
7781 if x > 0 then 1 + ((x - 1) / y) else 0
7878-[@@inline]
8282+ [@@inline]
79838084let canonic alphabet =
8185 let dmap = Array.make 256 (-1) in
8282- Array.iteri (fun i x -> Array.set dmap x i) (Base64.alphabet alphabet) ;
8686+ Array.iteri (fun i x -> dmap.(x) <- i) (Base64.alphabet alphabet) ;
8387 fun (input, off, len) ->
8488 let real_len = String.length input in
8589 let input_len = len in
8686- let normalized_len = (input_len // 4) * 4 in
8787- if normalized_len = input_len then (input, off, input_len)
8888- else if normalized_len - input_len = 3 then (input, off, input_len - 1)
8989- else begin
9090+ let normalized_len = input_len // 4 * 4 in
9191+ if normalized_len = input_len
9292+ then (input, off, input_len)
9393+ else if normalized_len - input_len = 3
9494+ then (input, off, input_len - 1)
9595+ else
9096 let remainder_len = normalized_len - input_len in
9191- let last = String.get input (off + input_len - 1) in
9797+ let last = input.[off + input_len - 1] in
9298 let output = Bytes.make (max real_len (off + normalized_len)) '=' in
93999494- Bytes.blit_string input 0 output 0 (off + input_len);
100100+ Bytes.blit_string input 0 output 0 (off + input_len) ;
95101 if off + normalized_len < real_len
9696- then Bytes.blit_string input (off + normalized_len) output (off + normalized_len) (real_len - (off + normalized_len)) ;
102102+ then
103103+ Bytes.blit_string input (off + normalized_len) output
104104+ (off + normalized_len)
105105+ (real_len - (off + normalized_len)) ;
971069898- let mask = match remainder_len with
9999- | 1 -> 0x3c
100100- | 2 -> 0x30
101101- | _ -> assert false in
102102- let decoded = Array.get dmap (Char.code last) in
103103- let canonic = (decoded land mask) in
104104- let encoded = Array.get (Base64.alphabet alphabet) canonic in
107107+ let mask =
108108+ match remainder_len with 1 -> 0x3c | 2 -> 0x30 | _ -> assert false in
109109+ let decoded = dmap.(Char.code last) in
110110+ let canonic = decoded land mask in
111111+ let encoded = (Base64.alphabet alphabet).(canonic) in
105112 Bytes.set output (off + input_len - 1) (Char.chr encoded) ;
106113 (Bytes.unsafe_to_string output, off, normalized_len)
107107- end
108114109115let isomorphism0 (input, off, len) =
110116 (* x0 = decode(input) && x1 = decode(encode(x0)) && x0 = x1 *)
111117 match Base64.decode ~pad:false ~off ~len input with
112112- | Error (`Msg err) ->
113113- fail err
114114- | Ok result0 ->
118118+ | Error (`Msg err) -> fail err
119119+ | Ok result0 -> (
115120 let result1 = Base64.encode_exn result0 in
116121 match Base64.decode ~pad:true result1 with
117117- | Error (`Msg err) ->
118118- fail err
122122+ | Error (`Msg err) -> fail err
119123 | Ok result2 ->
120120- check_eq ~pp ~cmp:String.compare ~eq:String.equal result0 result2
124124+ check_eq ~pp ~cmp:String.compare ~eq:String.equal result0 result2)
121125122126let isomorphism1 (input, off, len) =
123127 let result0 = Base64.encode_exn ~off ~len input in
···125129 | Error (`Msg err) -> fail err
126130 | Ok result1 ->
127131 let result2 = Base64.encode_exn result1 in
128128- check_eq ~pp:Fmt.string ~cmp:String.compare ~eq:String.equal result0 result2
132132+ check_eq ~pp:Fmt.string ~cmp:String.compare ~eq:String.equal result0
133133+ result2
129134130135let bytes_and_range : (string * int * int) gen =
131131- dynamic_bind bytes
132132- @@ fun t ->
136136+ dynamic_bind bytes @@ fun t ->
133137 let real_length = String.length t in
134138 if real_length <= 1
135139 then const (t, 0, real_length)
136136- else dynamic_bind (range (real_length / 2))
137137- @@ fun off ->
140140+ else
141141+ dynamic_bind (range (real_length / 2)) @@ fun off ->
138142 map [ range (real_length - off) ] (fun len -> (t, off, len))
139143140144let range_of_max max : (int * int) gen =
141141- dynamic_bind (range (max / 2))
142142- @@ fun off -> map [ range (max - off) ] (fun len -> (off, len))
145145+ dynamic_bind (range (max / 2)) @@ fun off ->
146146+ map [ range (max - off) ] (fun len -> (off, len))
143147144148let failf fmt = Fmt.kstrf fail fmt
145149146150let no_exception pad off len input =
147147- try let _ = Base64.decode ?pad ?off ?len ~alphabet:Base64.default_alphabet input in ()
151151+ try
152152+ let _ =
153153+ Base64.decode ?pad ?off ?len ~alphabet:Base64.default_alphabet input in
154154+ ()
148155 with exn -> failf "decode fails with: %s." (Printexc.to_string exn)
149156150157let () =
151151- add_test ~name:"rfc4648: encode -> decode" [ bytes_and_range ] encode_and_decode ;
152152- add_test ~name:"rfc4648: decode -> encode" [ random_string_from_alphabet ~max:1000 Base64.default_alphabet ] (decode_and_encode <.> canonic Base64.default_alphabet) ;
153153- add_test ~name:"rfc4648: x = decode(encode(x))" [ random_string_from_alphabet ~max:1000 Base64.default_alphabet ] isomorphism0 ;
154154- add_test ~name:"rfc4648: x = encode(decode(x))" [ bytes_and_range ] isomorphism1 ;
155155- add_test ~name:"rfc4648: no exception leak" [ option bool; option int; option int; bytes ] no_exception
158158+ add_test ~name:"rfc4648: encode -> decode" [ bytes_and_range ]
159159+ encode_and_decode ;
160160+ add_test ~name:"rfc4648: decode -> encode"
161161+ [ random_string_from_alphabet ~max:1000 Base64.default_alphabet ]
162162+ (decode_and_encode <.> canonic Base64.default_alphabet) ;
163163+ add_test ~name:"rfc4648: x = decode(encode(x))"
164164+ [ random_string_from_alphabet ~max:1000 Base64.default_alphabet ]
165165+ isomorphism0 ;
166166+ add_test ~name:"rfc4648: x = encode(decode(x))" [ bytes_and_range ]
167167+ isomorphism1 ;
168168+ add_test ~name:"rfc4648: no exception leak"
169169+ [ option bool; option int; option int; bytes ]
170170+ no_exception
+182-155
src/base64.ml
···1919 *
2020 *)
21212222-type alphabet =
2323- { emap : int array
2424- ; dmap : int array }
2222+type alphabet = { emap : int array; dmap : int array }
25232624type sub = string * int * int
27252828-let (//) x y =
2626+let ( // ) x y =
2927 if y < 1 then raise Division_by_zero ;
3028 if x > 0 then 1 + ((x - 1) / y) else 0
3131-[@@inline]
2929+ [@@inline]
32303331let unsafe_get_uint8 t off = Char.code (String.unsafe_get t off)
3232+3433let unsafe_set_uint8 t off v = Bytes.unsafe_set t off (Char.chr v)
3434+3535let unsafe_set_uint16 = Unsafe.unsafe_set_uint16
36363737-external unsafe_get_uint16 : string -> int -> int = "%caml_string_get16u" [@@noalloc]
3737+external unsafe_get_uint16 : string -> int -> int = "%caml_string_get16u"
3838+ [@@noalloc]
3939+3840external swap16 : int -> int = "%bswap16" [@@noalloc]
39414040-let none = (-1)
4242+let none = -1
41434244(* We mostly want to have an optional array for [dmap] (e.g. [int option
4345 array]). So we consider the [none] value as [-1]. *)
44464547let make_alphabet alphabet =
4646- if String.length alphabet <> 64 then invalid_arg "Length of alphabet must be 64" ;
4747- if String.contains alphabet '=' then invalid_arg "Alphabet can not contain padding character" ;
4848- let emap = Array.init (String.length alphabet) (fun i -> Char.code (String.get alphabet i)) in
4848+ if String.length alphabet <> 64
4949+ then invalid_arg "Length of alphabet must be 64" ;
5050+ if String.contains alphabet '='
5151+ then invalid_arg "Alphabet can not contain padding character" ;
5252+ let emap =
5353+ Array.init (String.length alphabet) (fun i -> Char.code alphabet.[i]) in
4954 let dmap = Array.make 256 none in
5050- String.iteri (fun idx chr -> Array.set dmap (Char.code chr) idx) alphabet ;
5151- { emap; dmap; }
5555+ String.iteri (fun idx chr -> dmap.(Char.code chr) <- idx) alphabet ;
5656+ { emap; dmap }
52575358let length_alphabet { emap; _ } = Array.length emap
5959+5460let alphabet { emap; _ } = emap
55615656-let default_alphabet = make_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
5757-let uri_safe_alphabet = make_alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
6262+let default_alphabet =
6363+ make_alphabet
6464+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
6565+6666+let uri_safe_alphabet =
6767+ make_alphabet
6868+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
58695970let unsafe_set_be_uint16 =
6071 if Sys.big_endian
···6576 can raise and avoid appearance of unknown exceptions like an ex-nihilo
6677 magic rabbit (or magic money?). *)
6778exception Out_of_bounds
7979+6880exception Too_much_input
69817082let get_uint8 t off =
···7688let error_msgf fmt = Format.ksprintf (fun err -> Error (`Msg err)) fmt
77897890let encode_sub pad { emap; _ } ?(off = 0) ?len input =
7979- let len = match len with
8080- | Some len -> len
8181- | None -> String.length input - off in
9191+ let len =
9292+ match len with Some len -> len | None -> String.length input - off in
82938394 if len < 0 || off < 0 || off > String.length input - len
8495 then error_msgf "Invalid bounds"
8596 else
8686- let n = len in
8787- let n' = n // 3 * 4 in
8888- let res = Bytes.create n' in
9797+ let n = len in
9898+ let n' = n // 3 * 4 in
9999+ let res = Bytes.create n' in
891009090- let emap i = Array.unsafe_get emap i in
101101+ let emap i = Array.unsafe_get emap i in
911029292- let emit b1 b2 b3 i =
9393- unsafe_set_be_uint16 res i
9494- ((emap (b1 lsr 2 land 0x3f) lsl 8)
9595- lor (emap ((b1 lsl 4) lor (b2 lsr 4) land 0x3f))) ;
9696- unsafe_set_be_uint16 res (i + 2)
9797- ((emap ((b2 lsl 2) lor (b3 lsr 6) land 0x3f) lsl 8)
9898- lor (emap (b3 land 0x3f))) in
103103+ let emit b1 b2 b3 i =
104104+ unsafe_set_be_uint16 res i
105105+ ((emap ((b1 lsr 2) land 0x3f) lsl 8)
106106+ lor emap ((b1 lsl 4) lor (b2 lsr 4) land 0x3f)) ;
107107+ unsafe_set_be_uint16 res (i + 2)
108108+ ((emap ((b2 lsl 2) lor (b3 lsr 6) land 0x3f) lsl 8)
109109+ lor emap (b3 land 0x3f)) in
110110+111111+ let rec enc j i =
112112+ if i = n
113113+ then ()
114114+ else if i = n - 1
115115+ then emit (unsafe_get_uint8 input (off + i)) 0 0 j
116116+ else if i = n - 2
117117+ then
118118+ emit
119119+ (unsafe_get_uint8 input (off + i))
120120+ (unsafe_get_uint8 input (off + i + 1))
121121+ 0 j
122122+ else (
123123+ emit
124124+ (unsafe_get_uint8 input (off + i))
125125+ (unsafe_get_uint8 input (off + i + 1))
126126+ (unsafe_get_uint8 input (off + i + 2))
127127+ j ;
128128+ enc (j + 4) (i + 3)) in
99129100100- let rec enc j i =
101101- if i = n then ()
102102- else if i = n - 1
103103- then emit (unsafe_get_uint8 input (off + i)) 0 0 j
104104- else if i = n - 2
105105- then emit (unsafe_get_uint8 input (off + i)) (unsafe_get_uint8 input (off + i + 1)) 0 j
106106- else
107107- (emit
108108- (unsafe_get_uint8 input (off + i))
109109- (unsafe_get_uint8 input (off + i + 1))
110110- (unsafe_get_uint8 input (off + i + 2))
111111- j ;
112112- enc (j + 4) (i + 3)) in
130130+ let rec unsafe_fix = function
131131+ | 0 -> ()
132132+ | i ->
133133+ unsafe_set_uint8 res (n' - i) padding ;
134134+ unsafe_fix (i - 1) in
113135114114- let rec unsafe_fix = function
115115- | 0 -> ()
116116- | i -> unsafe_set_uint8 res (n' - i) padding ; unsafe_fix (i - 1) in
136136+ enc 0 0 ;
117137118118- enc 0 0 ;
138138+ let pad_to_write = (3 - (n mod 3)) mod 3 in
119139120120- let pad_to_write = ((3 - n mod 3) mod 3) in
140140+ if pad
141141+ then (
142142+ unsafe_fix pad_to_write ;
143143+ Ok (Bytes.unsafe_to_string res, 0, n'))
144144+ else Ok (Bytes.unsafe_to_string res, 0, n' - pad_to_write)
121145122122- if pad
123123- then begin unsafe_fix pad_to_write ; Ok (Bytes.unsafe_to_string res, 0, n') end
124124- else Ok (Bytes.unsafe_to_string res, 0, (n' - pad_to_write))
125146(* [pad = false], we don't want to write them. *)
126147127148let encode ?(pad = true) ?(alphabet = default_alphabet) ?off ?len input =
···143164 | Error (`Msg err) -> invalid_arg err
144165145166let decode_sub ?(pad = true) { dmap; _ } ?(off = 0) ?len input =
146146- let len = match len with
147147- | Some len -> len
148148- | None -> String.length input - off in
167167+ let len =
168168+ match len with Some len -> len | None -> String.length input - off in
149169150170 if len < 0 || off < 0 || off > String.length input - len
151171 then error_msgf "Invalid bounds"
152172 else
173173+ let n = len // 4 * 4 in
174174+ let n' = n // 4 * 3 in
175175+ let res = Bytes.create n' in
176176+ let invalid_pad_overflow = pad in
153177154154- let n = (len // 4) * 4 in
155155- let n' = (n // 4) * 3 in
156156- let res = Bytes.create n' in
157157- let invalid_pad_overflow = pad in
178178+ let get_uint8_or_padding =
179179+ if pad
180180+ then (fun t i ->
181181+ if i >= len then raise Out_of_bounds ;
182182+ get_uint8 t (off + i))
183183+ else
184184+ fun t i ->
185185+ try if i < len then get_uint8 t (off + i) else padding
186186+ with Out_of_bounds -> padding in
158187159159- let get_uint8_or_padding =
160160- if pad then (fun t i -> if i >= len then raise Out_of_bounds ; get_uint8 t (off + i) )
161161- else (fun t i -> try if i < len then get_uint8 t (off + i) else padding with Out_of_bounds -> padding ) in
188188+ let set_be_uint16 t off v =
189189+ (* can not write 2 bytes. *)
190190+ if off < 0 || off + 1 > Bytes.length t
191191+ then () (* can not write 1 byte but can write 1 byte *)
192192+ else if off < 0 || off + 2 > Bytes.length t
193193+ then unsafe_set_uint8 t off (v lsr 8) (* can write 2 bytes. *)
194194+ else unsafe_set_be_uint16 t off v in
162195163163- let set_be_uint16 t off v =
164164- (* can not write 2 bytes. *)
165165- if off < 0 || off + 1 > Bytes.length t then ()
166166- (* can not write 1 byte but can write 1 byte *)
167167- else if off < 0 || off + 2 > Bytes.length t then unsafe_set_uint8 t off (v lsr 8)
168168- (* can write 2 bytes. *)
169169- else unsafe_set_be_uint16 t off v in
196196+ let set_uint8 t off v =
197197+ if off < 0 || off >= Bytes.length t then () else unsafe_set_uint8 t off v
198198+ in
170199171171- let set_uint8 t off v =
172172- if off < 0 || off >= Bytes.length t then ()
173173- else unsafe_set_uint8 t off v in
200200+ let emit a b c d j =
201201+ let x = (a lsl 18) lor (b lsl 12) lor (c lsl 6) lor d in
202202+ set_be_uint16 res j (x lsr 8) ;
203203+ set_uint8 res (j + 2) (x land 0xff) in
174204175175- let emit a b c d j =
176176- let x = (a lsl 18) lor (b lsl 12) lor (c lsl 6) lor d in
177177- set_be_uint16 res j (x lsr 8) ;
178178- set_uint8 res (j + 2) (x land 0xff) in
205205+ let dmap i =
206206+ let x = Array.unsafe_get dmap i in
207207+ if x = none then raise Not_found ;
208208+ x in
179209180180- let dmap i =
181181- let x = Array.unsafe_get dmap i in
182182- if x = none then raise Not_found ; x in
183183-184184- let only_padding pad idx =
185185-186186- (* because we round length of [res] to the upper bound of how many
187187- characters we should have from [input], we got at this stage only padding
188188- characters and we need to delete them, so for each [====], we delete 3
189189- bytes. *)
190190-191191- let pad = ref (pad + 3) in
192192- let idx = ref idx in
210210+ let only_padding pad idx =
211211+ (* because we round length of [res] to the upper bound of how many
212212+ characters we should have from [input], we got at this stage only padding
213213+ characters and we need to delete them, so for each [====], we delete 3
214214+ bytes. *)
215215+ let pad = ref (pad + 3) in
216216+ let idx = ref idx in
193217194194- while !idx + 4 < len do
195195- (* use [unsafe_get_uint16] instead [unsafe_get_uint32] to avoid allocation
196196- of [int32]. Of course, [3d3d3d3d] is [====]. *)
197197- if unsafe_get_uint16 input (off + !idx) <> 0x3d3d
198198- || unsafe_get_uint16 input (off + !idx + 2) <> 0x3d3d
199199- then raise Not_found ;
200200- (* We got something bad, should be a valid character according to
201201- [alphabet] but outside the scope. *)
218218+ while !idx + 4 < len do
219219+ (* use [unsafe_get_uint16] instead [unsafe_get_uint32] to avoid allocation
220220+ of [int32]. Of course, [3d3d3d3d] is [====]. *)
221221+ if unsafe_get_uint16 input (off + !idx) <> 0x3d3d
222222+ || unsafe_get_uint16 input (off + !idx + 2) <> 0x3d3d
223223+ then raise Not_found ;
202224203203- idx := !idx + 4 ;
204204- pad := !pad + 3 ;
205205- done ;
206206- while !idx < len do
207207- if unsafe_get_uint8 input (off + !idx) <> padding
208208- then raise Not_found ;
225225+ (* We got something bad, should be a valid character according to
226226+ [alphabet] but outside the scope. *)
227227+ idx := !idx + 4 ;
228228+ pad := !pad + 3
229229+ done ;
230230+ while !idx < len do
231231+ if unsafe_get_uint8 input (off + !idx) <> padding then raise Not_found ;
209232210210- incr idx ;
211211- done ; !pad in
233233+ incr idx
234234+ done ;
235235+ !pad in
212236213213- let rec dec j i =
214214- if i = n then 0
215215- else begin
216216- let (d, pad) =
217217- let x = get_uint8_or_padding input (i + 3) in
218218- try (dmap x, 0) with Not_found when x = padding -> (0, 1) in
219219- (* [Not_found] iff [x ∉ alphabet and x <> '='] can leak. *)
220220- let (c, pad) =
221221- let x = get_uint8_or_padding input (i + 2) in
222222- try (dmap x, pad) with Not_found when x = padding && pad = 1 -> (0, 2) in
223223- (* [Not_found] iff [x ∉ alphabet and x <> '='] can leak. *)
224224- let (b, pad) =
225225- let x = get_uint8_or_padding input (i + 1) in
226226- try (dmap x, pad) with Not_found when x = padding && pad = 2 -> (0, 3) in
227227- (* [Not_found] iff [x ∉ alphabet and x <> '='] can leak. *)
228228- let (a, pad) =
229229- let x = get_uint8_or_padding input i in
230230- try (dmap x, pad) with Not_found when x = padding && pad = 3 -> (0, 4) in
231231- (* [Not_found] iff [x ∉ alphabet and x <> '='] can leak. *)
237237+ let rec dec j i =
238238+ if i = n
239239+ then 0
240240+ else
241241+ let d, pad =
242242+ let x = get_uint8_or_padding input (i + 3) in
243243+ try (dmap x, 0) with Not_found when x = padding -> (0, 1) in
244244+ (* [Not_found] iff [x ∉ alphabet and x <> '='] can leak. *)
245245+ let c, pad =
246246+ let x = get_uint8_or_padding input (i + 2) in
247247+ try (dmap x, pad)
248248+ with Not_found when x = padding && pad = 1 -> (0, 2) in
249249+ (* [Not_found] iff [x ∉ alphabet and x <> '='] can leak. *)
250250+ let b, pad =
251251+ let x = get_uint8_or_padding input (i + 1) in
252252+ try (dmap x, pad)
253253+ with Not_found when x = padding && pad = 2 -> (0, 3) in
254254+ (* [Not_found] iff [x ∉ alphabet and x <> '='] can leak. *)
255255+ let a, pad =
256256+ let x = get_uint8_or_padding input i in
257257+ try (dmap x, pad)
258258+ with Not_found when x = padding && pad = 3 -> (0, 4) in
232259233233- emit a b c d j ;
260260+ (* [Not_found] iff [x ∉ alphabet and x <> '='] can leak. *)
261261+ emit a b c d j ;
234262235235- if i + 4 = n
236236- (* end of input in anyway *)
237237- then match pad with
238238- | 0 ->
239239- 0
240240- | 4 ->
241241- (* assert (invalid_pad_overflow = false) ; *)
242242- 3
243243- (* [get_uint8] lies and if we get [4], that mean we got one or more (at
244244- most 4) padding character. In this situation, because we round length
245245- of [res] (see [n // 4]), we need to delete 3 bytes. *)
246246- | pad ->
247247- pad
248248- else match pad with
249249- | 0 -> dec (j + 3) (i + 4)
250250- | 4 ->
251251- (* assert (invalid_pad_overflow = false) ; *)
252252- only_padding 3 (i + 4)
253253- (* Same situation than above but we should get only more padding
254254- characters then. *)
255255- | pad ->
256256- if invalid_pad_overflow = true then raise Too_much_input ;
257257- only_padding pad (i + 4) end in
263263+ if i + 4 = n (* end of input in anyway *)
264264+ then
265265+ match pad with
266266+ | 0 -> 0
267267+ | 4 ->
268268+ (* assert (invalid_pad_overflow = false) ; *)
269269+ 3
270270+ (* [get_uint8] lies and if we get [4], that mean we got one or more (at
271271+ most 4) padding character. In this situation, because we round length
272272+ of [res] (see [n // 4]), we need to delete 3 bytes. *)
273273+ | pad -> pad
274274+ else
275275+ match pad with
276276+ | 0 -> dec (j + 3) (i + 4)
277277+ | 4 ->
278278+ (* assert (invalid_pad_overflow = false) ; *)
279279+ only_padding 3 (i + 4)
280280+ (* Same situation than above but we should get only more padding
281281+ characters then. *)
282282+ | pad ->
283283+ if invalid_pad_overflow = true then raise Too_much_input ;
284284+ only_padding pad (i + 4) in
258285259259- match dec 0 0 with
260260- | 0 -> Ok (Bytes.unsafe_to_string res, 0, n')
261261- | pad -> Ok (Bytes.unsafe_to_string res, 0, (n' - pad))
262262- | exception Out_of_bounds -> error_msgf "Wrong padding"
263263- (* appear only when [pad = true] and when length of input is not a multiple of 4. *)
264264- | exception Not_found ->
265265- (* appear when one character of [input] ∉ [alphabet] and this character <> '=' *)
266266- error_msgf "Malformed input"
267267- | exception Too_much_input ->
268268- error_msgf "Too much input"
286286+ match dec 0 0 with
287287+ | 0 -> Ok (Bytes.unsafe_to_string res, 0, n')
288288+ | pad -> Ok (Bytes.unsafe_to_string res, 0, n' - pad)
289289+ | exception Out_of_bounds ->
290290+ error_msgf "Wrong padding"
291291+ (* appear only when [pad = true] and when length of input is not a multiple of 4. *)
292292+ | exception Not_found ->
293293+ (* appear when one character of [input] ∉ [alphabet] and this character <> '=' *)
294294+ error_msgf "Malformed input"
295295+ | exception Too_much_input -> error_msgf "Too much input"
269296270297let decode ?pad ?(alphabet = default_alphabet) ?off ?len input =
271298 match decode_sub ?pad alphabet ?off ?len input with
+40-13
src/base64.mli
···4848val alphabet : alphabet -> int array
4949(** Returns the alphabet. *)
50505151-val decode_exn : ?pad:bool -> ?alphabet:alphabet -> ?off:int -> ?len:int -> string -> string
5252-(** [decode_exn ?off ?len s] decodes [len] bytes (defaults to [String.length s -
5353- off]) of the string [s] starting from [off] (defaults to [0]) that is encoded
5454- in Base64 format. Will leave trailing NULLs on the string, padding it out to
5555- a multiple of 3 characters. [alphabet] defaults to {!default_alphabet}. [pad
5656- = true] specifies to check if [s] is padded or not, otherwise, it raises an
5757- exception.
5151+val decode_exn :
5252+ ?pad:bool -> ?alphabet:alphabet -> ?off:int -> ?len:int -> string -> string
5353+(** [decode_exn ?off ?len s] decodes [len] bytes (defaults to
5454+ [String.length s - off]) of the string [s] starting from [off] (defaults to
5555+ [0]) that is encoded in Base64 format. Will leave trailing NULLs on the
5656+ string, padding it out to a multiple of 3 characters. [alphabet] defaults to
5757+ {!default_alphabet}. [pad = true] specifies to check if [s] is padded or
5858+ not, otherwise, it raises an exception.
58595960 Decoder can fail when character of [s] is not a part of [alphabet] or is not
6061 [padding] character. If input is not padded correctly, decoder does the
···62636364 @raise if Invalid_argument [s] is not a valid Base64 string. *)
64656565-val decode_sub : ?pad:bool -> ?alphabet:alphabet -> ?off:int -> ?len:int -> string -> (sub, [> `Msg of string ]) result
6666+val decode_sub :
6767+ ?pad:bool ->
6868+ ?alphabet:alphabet ->
6969+ ?off:int ->
7070+ ?len:int ->
7171+ string ->
7272+ (sub, [> `Msg of string ]) result
6673(** Same as {!decode_exn} but it returns a result type instead to raise an
6774 exception. Then, it returns a {!sub} string. Decoded input [(str, off, len)]
6875 will starting to [off] and will have [len] bytes - by this way, we ensure to
6976 allocate only one time result. *)
70777171-val decode : ?pad:bool -> ?alphabet:alphabet -> ?off:int -> ?len:int -> string -> (string, [> `Msg of string ]) result
7272-(** Same as {!decode_exn}, but returns an explicit error message {!result} if it fails. *)
7878+val decode :
7979+ ?pad:bool ->
8080+ ?alphabet:alphabet ->
8181+ ?off:int ->
8282+ ?len:int ->
8383+ string ->
8484+ (string, [> `Msg of string ]) result
8585+(** Same as {!decode_exn}, but returns an explicit error message {!result} if it
8686+ fails. *)
73877474-val encode : ?pad:bool -> ?alphabet:alphabet -> ?off:int -> ?len:int -> string -> (string, [> `Msg of string]) result
8888+val encode :
8989+ ?pad:bool ->
9090+ ?alphabet:alphabet ->
9191+ ?off:int ->
9292+ ?len:int ->
9393+ string ->
9494+ (string, [> `Msg of string ]) result
7595(** [encode s] encodes the string [s] into base64. If [pad] is false, no
7696 trailing padding is added. [pad] defaults to [true], and [alphabet] to
7797 {!default_alphabet}.
···83103 trailing padding is added. [pad] defaults to [true], and [alphabet] to
84104 {!default_alphabet}. *)
851058686-val encode_sub : ?pad:bool -> ?alphabet:alphabet -> ?off:int -> ?len:int -> string -> (sub, [> `Msg of string]) result
106106+val encode_sub :
107107+ ?pad:bool ->
108108+ ?alphabet:alphabet ->
109109+ ?off:int ->
110110+ ?len:int ->
111111+ string ->
112112+ (sub, [> `Msg of string ]) result
87113(** Same as {!encode} but return a {!sub}-string instead a plain result. By this
88114 way, we ensure to allocate only one time result. *)
891159090-val encode_exn : ?pad:bool -> ?alphabet:alphabet -> ?off:int -> ?len:int -> string -> string
116116+val encode_exn :
117117+ ?pad:bool -> ?alphabet:alphabet -> ?off:int -> ?len:int -> string -> string
91118(** Same as {!encode} but raises an invalid argument exception if we retrieve an
92119 error. *)
+161-135
src/base64_rfc2045.ml
···1919 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
20202121let io_buffer_size = 65536
2222+2223let invalid_arg fmt = Format.ksprintf (fun s -> invalid_arg s) fmt
23242425let invalid_bounds off len =
2526 invalid_arg "Invalid bounds (off: %d, len: %d)" off len
26272727-let malformed chr =
2828- `Malformed (String.make 1 chr)
2828+let malformed chr = `Malformed (String.make 1 chr)
29293030let unsafe_byte source off pos = Bytes.unsafe_get source (off + pos)
3131+3132let unsafe_blit = Bytes.unsafe_blit
3333+3234let unsafe_chr = Char.unsafe_chr
3535+3336let unsafe_set_chr source off chr = Bytes.unsafe_set source off chr
34373535-type state = {quantum: int; size: int; buffer: Bytes.t}
3838+type state = { quantum : int; size : int; buffer : Bytes.t }
3939+4040+let continue state (quantum, size) = `Continue { state with quantum; size }
36413737-let continue state (quantum, size) = `Continue {state with quantum; size}
3838-let flush state = `Flush {state with quantum= 0; size= 0}
4242+let flush state = `Flush { state with quantum = 0; size = 0 }
39434044let table =
4145 "\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\062\255\255\255\063\052\053\054\055\056\057\058\059\060\061\255\255\255\255\255\255\255\000\001\002\003\004\005\006\007\008\009\010\011\012\013\014\015\016\017\018\019\020\021\022\023\024\025\255\255\255\255\255\255\026\027\028\029\030\031\032\033\034\035\036\037\038\039\040\041\042\043\044\045\046\047\048\049\050\051\255\255\255\255\255"
42464343-let r_repr ({quantum; size; _} as state) chr =
4747+let r_repr ({ quantum; size; _ } as state) chr =
4448 (* assert (0 <= off && 0 <= len && off + len <= String.length source); *)
4549 (* assert (len >= 1); *)
4650 let code = Char.code table.[Char.code chr] in
···5660 flush state
5761 | _ -> malformed chr
58625959-type src = [`Channel of in_channel | `String of string | `Manual]
6363+type src = [ `Channel of in_channel | `String of string | `Manual ]
60646165type decode =
6262- [`Await | `End | `Wrong_padding | `Malformed of string | `Flush of string]
6666+ [ `Await | `End | `Wrong_padding | `Malformed of string | `Flush of string ]
63676468type input =
6565- [`Line_break | `Wsp | `Padding | `Malformed of string | `Flush of state]
6969+ [ `Line_break | `Wsp | `Padding | `Malformed of string | `Flush of state ]
66706767-type decoder =
6868- { src: src
6969- ; mutable i: Bytes.t
7070- ; mutable i_off: int
7171- ; mutable i_pos: int
7272- ; mutable i_len: int
7373- ; mutable s: state
7474- ; mutable padding: int
7575- ; mutable unsafe: bool
7676- ; mutable byte_count: int
7777- ; mutable limit_count: int
7878- ; mutable pp: decoder -> input -> decode
7979- ; mutable k: decoder -> decode }
7171+type decoder = {
7272+ src : src;
7373+ mutable i : Bytes.t;
7474+ mutable i_off : int;
7575+ mutable i_pos : int;
7676+ mutable i_len : int;
7777+ mutable s : state;
7878+ mutable padding : int;
7979+ mutable unsafe : bool;
8080+ mutable byte_count : int;
8181+ mutable limit_count : int;
8282+ mutable pp : decoder -> input -> decode;
8383+ mutable k : decoder -> decode;
8484+}
80858186let i_rem decoder = decoder.i_len - decoder.i_pos + 1
8287···8792 decoder.i_len <- min_int
88938994let src decoder source off len =
9090- if off < 0 || len < 0 || off + len > Bytes.length source then
9191- invalid_bounds off len
9292- else if len = 0 then end_of_input decoder
9595+ if off < 0 || len < 0 || off + len > Bytes.length source
9696+ then invalid_bounds off len
9797+ else if len = 0
9898+ then end_of_input decoder
9399 else (
94100 decoder.i <- source ;
95101 decoder.i_off <- off ;
96102 decoder.i_pos <- 0 ;
9797- decoder.i_len <- len - 1 )
103103+ decoder.i_len <- len - 1)
9810499105let refill k decoder =
100106 match decoder.src with
101107 | `Manual ->
102108 decoder.k <- k ;
103109 `Await
104104- | `String _ -> end_of_input decoder ; k decoder
110110+ | `String _ ->
111111+ end_of_input decoder ;
112112+ k decoder
105113 | `Channel ic ->
106114 let len = input ic decoder.i 0 (Bytes.length decoder.i) in
107115 src decoder decoder.i 0 len ;
108116 k decoder
109117110118let dangerous decoder v = decoder.unsafe <- v
119119+111120let reset decoder = decoder.limit_count <- 0
112121113122let ret k v byte_count decoder =
···117126 if decoder.limit_count > 78 then dangerous decoder true ;
118127 decoder.pp decoder v
119128120120-type flush_and_malformed = [`Flush of state | `Malformed of string]
129129+type flush_and_malformed = [ `Flush of state | `Malformed of string ]
121130122122-let padding {size; _} padding =
131131+let padding { size; _ } padding =
123132 match (size, padding) with
124133 | 0, 0 -> true
125134 | 1, _ -> false
···127136 | 3, 1 -> true
128137 | _ -> false
129138130130-let t_flush {quantum; size; buffer} =
139139+let t_flush { quantum; size; buffer } =
131140 match size with
132132- | 0 | 1 -> `Flush {quantum; size; buffer= Bytes.empty}
141141+ | 0 | 1 -> `Flush { quantum; size; buffer = Bytes.empty }
133142 | 2 ->
134143 let quantum = quantum lsr 4 in
135144 `Flush
136136- { quantum
137137- ; size
138138- ; buffer= Bytes.make 1 (unsafe_chr (quantum land 255)) }
145145+ { quantum; size; buffer = Bytes.make 1 (unsafe_chr (quantum land 255)) }
139146 | 3 ->
140147 let quantum = quantum lsr 2 in
141148 unsafe_set_chr buffer 0 (unsafe_chr ((quantum lsr 8) land 255)) ;
142149 unsafe_set_chr buffer 1 (unsafe_chr (quantum land 255)) ;
143143- `Flush {quantum; size; buffer= Bytes.sub buffer 0 2}
144144- | _ -> assert false (* this branch is impossible, size can only ever be in the range [0..3]. *)
150150+ `Flush { quantum; size; buffer = Bytes.sub buffer 0 2 }
151151+ | _ -> assert false
152152+153153+(* this branch is impossible, size can only ever be in the range [0..3]. *)
145154146155let wrong_padding decoder =
147156 let k _ = `End in
148148- decoder.k <- k ; `Wrong_padding
157157+ decoder.k <- k ;
158158+ `Wrong_padding
149159150160let rec t_decode_base64 chr decoder =
151151- if decoder.padding = 0 then
161161+ if decoder.padding = 0
162162+ then
152163 let rec go pos = function
153164 | `Continue state ->
154165 if decoder.i_len - (decoder.i_pos + pos) + 1 > 0
155166 then (
156167 match unsafe_byte decoder.i decoder.i_off (decoder.i_pos + pos) with
157157- | ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '+' | '/') as chr -> go (succ pos) (r_repr state chr)
168168+ | ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '+' | '/') as chr ->
169169+ go (succ pos) (r_repr state chr)
158170 | '=' ->
159171 decoder.padding <- decoder.padding + 1 ;
160172 decoder.i_pos <- decoder.i_pos + pos + 1 ;
161173 decoder.s <- state ;
162162- ret decode_base64 `Padding (pos+1) decoder
174174+ ret decode_base64 `Padding (pos + 1) decoder
163175 | ' ' | '\t' ->
164176 decoder.i_pos <- decoder.i_pos + pos + 1 ;
165177 decoder.s <- state ;
···171183 | chr ->
172184 decoder.i_pos <- decoder.i_pos + pos + 1 ;
173185 decoder.s <- state ;
174174- ret decode_base64 (malformed chr) (pos+1) decoder
175175- ) else (
186186+ ret decode_base64 (malformed chr) (pos + 1) decoder)
187187+ else (
176188 decoder.i_pos <- decoder.i_pos + pos ;
177189 decoder.byte_count <- decoder.byte_count + pos ;
178190 decoder.limit_count <- decoder.limit_count + pos ;
179191 decoder.s <- state ;
180180- refill decode_base64 decoder )
192192+ refill decode_base64 decoder)
181193 | #flush_and_malformed as v ->
182194 decoder.i_pos <- decoder.i_pos + pos ;
183183- ret decode_base64 v pos decoder
184184- in
195195+ ret decode_base64 v pos decoder in
185196 go 1 (r_repr decoder.s chr)
186197 else (
187198 decoder.i_pos <- decoder.i_pos + 1 ;
···189200190201and decode_base64_lf_after_cr decoder =
191202 let rem = i_rem decoder in
192192- if rem < 0 then
193193- ret decode_base64 (malformed '\r') 1 decoder
194194- else if rem = 0 then refill decode_base64_lf_after_cr decoder
203203+ if rem < 0
204204+ then ret decode_base64 (malformed '\r') 1 decoder
205205+ else if rem = 0
206206+ then refill decode_base64_lf_after_cr decoder
195207 else
196208 match unsafe_byte decoder.i decoder.i_off decoder.i_pos with
197209 | '\n' ->
198198- decoder.i_pos <- decoder.i_pos + 1 ;
199199- ret decode_base64 `Line_break 2 decoder
200200- | _ ->
201201- ret decode_base64 (malformed '\r') 1 decoder
210210+ decoder.i_pos <- decoder.i_pos + 1 ;
211211+ ret decode_base64 `Line_break 2 decoder
212212+ | _ -> ret decode_base64 (malformed '\r') 1 decoder
202213203214and decode_base64 decoder =
204215 let rem = i_rem decoder in
205205- if rem <= 0 then
206206- if rem < 0 then
216216+ if rem <= 0
217217+ then
218218+ if rem < 0
219219+ then
207220 ret
208221 (fun decoder ->
209209- if padding decoder.s decoder.padding then `End else wrong_padding decoder )
222222+ if padding decoder.s decoder.padding
223223+ then `End
224224+ else wrong_padding decoder)
210225 (t_flush decoder.s) 0 decoder
211226 else refill decode_base64 decoder
212227 else
···228243 ret decode_base64 (malformed chr) 1 decoder
229244230245let pp_base64 decoder = function
231231- | `Line_break -> reset decoder ; decoder.k decoder
246246+ | `Line_break ->
247247+ reset decoder ;
248248+ decoder.k decoder
232249 | `Wsp | `Padding -> decoder.k decoder
233250 | `Flush state ->
234251 decoder.s <- state ;
···242259 match src with
243260 | `Manual -> (Bytes.empty, 0, 1, 0)
244261 | `Channel _ -> (Bytes.create io_buffer_size, 0, 1, 0)
245245- | `String s -> (Bytes.unsafe_of_string s, 0, 0, String.length s - 1)
246246- in
247247- { src
248248- ; i_off
249249- ; i_pos
250250- ; i_len
251251- ; i
252252- ; s= {quantum= 0; size= 0; buffer= Bytes.create 3}
253253- ; padding= 0
254254- ; unsafe= false
255255- ; byte_count= 0
256256- ; limit_count= 0
257257- ; pp
258258- ; k }
262262+ | `String s -> (Bytes.unsafe_of_string s, 0, 0, String.length s - 1) in
263263+ {
264264+ src;
265265+ i_off;
266266+ i_pos;
267267+ i_len;
268268+ i;
269269+ s = { quantum = 0; size = 0; buffer = Bytes.create 3 };
270270+ padding = 0;
271271+ unsafe = false;
272272+ byte_count = 0;
273273+ limit_count = 0;
274274+ pp;
275275+ k;
276276+ }
259277260278let decode decoder = decoder.k decoder
279279+261280let decoder_byte_count decoder = decoder.byte_count
281281+262282let decoder_src decoder = decoder.src
283283+263284let decoder_dangerous decoder = decoder.unsafe
264285265286(* / *)
266287267288let invalid_encode () = invalid_arg "Expected `Await encode"
268289269269-type dst = [`Channel of out_channel | `Buffer of Buffer.t | `Manual]
270270-type encode = [`Await | `End | `Char of char]
290290+type dst = [ `Channel of out_channel | `Buffer of Buffer.t | `Manual ]
271291272272-type encoder =
273273- { dst: dst
274274- ; mutable o: Bytes.t
275275- ; mutable o_off: int
276276- ; mutable o_pos: int
277277- ; mutable o_len: int
278278- ; mutable c_col: int
279279- ; i: Bytes.t
280280- ; mutable s: int
281281- ; t: Bytes.t
282282- ; mutable t_pos: int
283283- ; mutable t_len: int
284284- ; mutable k: encoder -> encode -> [`Ok | `Partial] }
292292+type encode = [ `Await | `End | `Char of char ]
293293+294294+type encoder = {
295295+ dst : dst;
296296+ mutable o : Bytes.t;
297297+ mutable o_off : int;
298298+ mutable o_pos : int;
299299+ mutable o_len : int;
300300+ mutable c_col : int;
301301+ i : Bytes.t;
302302+ mutable s : int;
303303+ t : Bytes.t;
304304+ mutable t_pos : int;
305305+ mutable t_len : int;
306306+ mutable k : encoder -> encode -> [ `Ok | `Partial ];
307307+}
285308286309let o_rem encoder = encoder.o_len - encoder.o_pos + 1
287310288311let dst encoder source off len =
289289- if off < 0 || len < 0 || off + len > Bytes.length source then
290290- invalid_bounds off len ;
312312+ if off < 0 || len < 0 || off + len > Bytes.length source
313313+ then invalid_bounds off len ;
291314 encoder.o <- source ;
292315 encoder.o_off <- off ;
293316 encoder.o_pos <- 0 ;
···322345 let blit encoder len =
323346 unsafe_blit encoder.t encoder.t_pos encoder.o encoder.o_pos len ;
324347 encoder.o_pos <- encoder.o_pos + len ;
325325- encoder.t_pos <- encoder.t_pos + len
326326- in
348348+ encoder.t_pos <- encoder.t_pos + len in
327349 let rem = o_rem encoder in
328350 let len = encoder.t_len - encoder.t_pos + 1 in
329329- if rem < len then (
351351+ if rem < len
352352+ then (
330353 blit encoder rem ;
331331- flush (t_flush k) encoder )
332332- else ( blit encoder len ; k encoder )
354354+ flush (t_flush k) encoder)
355355+ else (
356356+ blit encoder len ;
357357+ k encoder)
333358334359let rec encode_line_break k encoder =
335360 let rem = o_rem encoder in
336361 let s, j, k =
337337- if rem < 2 then (
362362+ if rem < 2
363363+ then (
338364 t_range encoder 2 ;
339339- (encoder.t, 0, t_flush k) )
365365+ (encoder.t, 0, t_flush k))
340366 else
341367 let j = encoder.o_pos in
342368 encoder.o_pos <- encoder.o_pos + 2 ;
343343- (encoder.o, encoder.o_off + j, k)
344344- in
369369+ (encoder.o, encoder.o_off + j, k) in
345370 unsafe_set_chr s j '\r' ;
346371 unsafe_set_chr s (j + 1) '\n' ;
347372 encoder.c_col <- 0 ;
348373 k encoder
349374350375and encode_char chr k (encoder : encoder) =
351351- if encoder.s >= 2 then (
352352- let a, b, c =
353353- (unsafe_byte encoder.i 0 0, unsafe_byte encoder.i 0 1, chr)
354354- in
376376+ if encoder.s >= 2
377377+ then (
378378+ let a, b, c = (unsafe_byte encoder.i 0 0, unsafe_byte encoder.i 0 1, chr) in
355379 encoder.s <- 0 ;
356380 let quantum = (Char.code a lsl 16) + (Char.code b lsl 8) + Char.code c in
357381 let a = quantum lsr 18 in
···360384 let d = quantum land 63 in
361385 let rem = o_rem encoder in
362386 let s, j, k =
363363- if rem < 4 then (
387387+ if rem < 4
388388+ then (
364389 t_range encoder 4 ;
365365- (encoder.t, 0, t_flush (k 4)) )
390390+ (encoder.t, 0, t_flush (k 4)))
366391 else
367392 let j = encoder.o_pos in
368393 encoder.o_pos <- encoder.o_pos + 4 ;
369369- (encoder.o, encoder.o_off + j, k 4)
370370- in
394394+ (encoder.o, encoder.o_off + j, k 4) in
371395 unsafe_set_chr s j default_alphabet.[a] ;
372396 unsafe_set_chr s (j + 1) default_alphabet.[b] ;
373397 unsafe_set_chr s (j + 2) default_alphabet.[c] ;
374398 unsafe_set_chr s (j + 3) default_alphabet.[d] ;
375375- flush k encoder )
399399+ flush k encoder)
376400 else (
377401 unsafe_set_chr encoder.i encoder.s chr ;
378402 encoder.s <- encoder.s + 1 ;
379379- k 0 encoder )
403403+ k 0 encoder)
380404381405and encode_trailing k encoder =
382406 match encoder.s with
···389413 let d = quantum land 63 in
390414 let rem = o_rem encoder in
391415 let s, j, k =
392392- if rem < 4 then (
416416+ if rem < 4
417417+ then (
393418 t_range encoder 4 ;
394394- (encoder.t, 0, t_flush (k 4)) )
419419+ (encoder.t, 0, t_flush (k 4)))
395420 else
396421 let j = encoder.o_pos in
397422 encoder.o_pos <- encoder.o_pos + 4 ;
398398- (encoder.o, encoder.o_off + j, k 4)
399399- in
423423+ (encoder.o, encoder.o_off + j, k 4) in
400424 unsafe_set_chr s j default_alphabet.[b] ;
401425 unsafe_set_chr s (j + 1) default_alphabet.[c] ;
402426 unsafe_set_chr s (j + 2) default_alphabet.[d] ;
···410434 let d = quantum land 63 in
411435 let rem = o_rem encoder in
412436 let s, j, k =
413413- if rem < 4 then (
437437+ if rem < 4
438438+ then (
414439 t_range encoder 4 ;
415415- (encoder.t, 0, t_flush (k 4)) )
440440+ (encoder.t, 0, t_flush (k 4)))
416441 else
417442 let j = encoder.o_pos in
418443 encoder.o_pos <- encoder.o_pos + 4 ;
419419- (encoder.o, encoder.o_off + j, k 4)
420420- in
444444+ (encoder.o, encoder.o_off + j, k 4) in
421445 unsafe_set_chr s j default_alphabet.[c] ;
422446 unsafe_set_chr s (j + 1) default_alphabet.[d] ;
423447 unsafe_set_chr s (j + 2) '=' ;
···430454 let k col_count encoder =
431455 encoder.c_col <- encoder.c_col + col_count ;
432456 encoder.k <- encode_base64 ;
433433- `Ok
434434- in
457457+ `Ok in
435458 match v with
436459 | `Await -> k 0 encoder
437460 | `End ->
438438- if encoder.c_col = 76 then
439439- encode_line_break (fun encoder -> encode_base64 encoder v) encoder
461461+ if encoder.c_col = 76
462462+ then encode_line_break (fun encoder -> encode_base64 encoder v) encoder
440463 else encode_trailing k encoder
441464 | `Char chr ->
442465 let rem = o_rem encoder in
443443- if rem < 1 then flush (fun encoder -> encode_base64 encoder v) encoder
444444- else if encoder.c_col = 76 then
445445- encode_line_break (fun encoder -> encode_base64 encoder v) encoder
466466+ if rem < 1
467467+ then flush (fun encoder -> encode_base64 encoder v) encoder
468468+ else if encoder.c_col = 76
469469+ then encode_line_break (fun encoder -> encode_base64 encoder v) encoder
446470 else encode_char chr k encoder
447471448472let encoder dst =
···450474 match dst with
451475 | `Manual -> (Bytes.empty, 1, 0, 0)
452476 | `Buffer _ | `Channel _ ->
453453- (Bytes.create io_buffer_size, 0, 0, io_buffer_size - 1)
454454- in
455455- { dst
456456- ; o_off
457457- ; o_pos
458458- ; o_len
459459- ; o
460460- ; t= Bytes.create 4
461461- ; t_pos= 1
462462- ; t_len= 0
463463- ; c_col= 0
464464- ; i= Bytes.create 3
465465- ; s= 0
466466- ; k= encode_base64 }
477477+ (Bytes.create io_buffer_size, 0, 0, io_buffer_size - 1) in
478478+ {
479479+ dst;
480480+ o_off;
481481+ o_pos;
482482+ o_len;
483483+ o;
484484+ t = Bytes.create 4;
485485+ t_pos = 1;
486486+ t_len = 0;
487487+ c_col = 0;
488488+ i = Bytes.create 3;
489489+ s = 0;
490490+ k = encode_base64;
491491+ }
467492468493let encode encoder = encoder.k encoder
494494+469495let encoder_dst encoder = encoder.dst
+9-9
src/base64_rfc2045.mli
···2020val default_alphabet : string
2121(** A 64-character string specifying the regular Base64 alphabet. *)
22222323-(** The type for decoders. *)
2423type decoder
2424+(** The type for decoders. *)
25252626+type src = [ `Manual | `Channel of in_channel | `String of string ]
2627(** The type for input sources. With a [`Manual] source the client must provide
2728 input with {!src}. *)
2828-type src = [`Manual | `Channel of in_channel | `String of string]
29293030type decode =
3131- [`Await | `End | `Flush of string | `Malformed of string | `Wrong_padding]
3131+ [ `Await | `End | `Flush of string | `Malformed of string | `Wrong_padding ]
32323333val src : decoder -> Bytes.t -> int -> int -> unit
3434(** [src d s j l] provides [d] with [l] bytes to read, starting at [j] in [s].
···6666 still continue to decode even if [decoder_dangerous d] returns [true].
6767 Nothing grow automatically internally in this state. *)
68686969+type dst = [ `Channel of out_channel | `Buffer of Buffer.t | `Manual ]
6970(** The type for output destinations. With a [`Manual] destination the client
7071 must provide output storage with {!dst}. *)
7171-type dst = [`Channel of out_channel | `Buffer of Buffer.t | `Manual]
72727373-type encode = [`Await | `End | `Char of char]
7373+type encode = [ `Await | `End | `Char of char ]
74747575+type encoder
7576(** The type for Base64 (RFC2045) encoder. *)
7676-type encoder
77777878val encoder : dst -> encoder
7979(** [encoder dst] is an encoder for Base64 (RFC2045) that outputs to [dst]. *)
80808181-val encode : encoder -> encode -> [`Ok | `Partial]
8181+val encode : encoder -> encode -> [ `Ok | `Partial ]
8282(** [encode e v]: is {ul {- [`Partial] iff [e] has a [`Manual] destination and
8383 needs more output storage. The client must use {!dst} to provide a new
8484 buffer and then call {!encode} with [`Await] until [`Ok] is returned.} {-
···9999val dst : encoder -> Bytes.t -> int -> int -> unit
100100(** [dst e s j l] provides [e] with [l] bytes to write, starting at [j] in [s].
101101 This byte range is written by calls to {!encode} with [e] until [`Partial]
102102- is returned. Use {!dst_rem} to know the remaining number of non-written
103103- free bytes in [s]. *)
102102+ is returned. Use {!dst_rem} to know the remaining number of non-written free
103103+ bytes in [s]. *)
104104105105val dst_rem : encoder -> int
106106(** [dst_rem e] is the remaining number of non-written, free bytes in the last
···11-external unsafe_set_uint16 : bytes -> int -> int -> unit = "%caml_string_set16u" [@@noalloc]
11+external unsafe_set_uint16 : bytes -> int -> int -> unit = "%caml_string_set16u"
22+ [@@noalloc]
+2-1
src/unsafe_stable.ml
···11-external unsafe_set_uint16 : bytes -> int -> int -> unit = "%caml_bytes_set16u" [@@noalloc]
11+external unsafe_set_uint16 : bytes -> int -> int -> unit = "%caml_bytes_set16u"
22+ [@@noalloc]