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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
module Option = GapiOption
module Infix = struct
let ( |> ) x f = f x
let ( -| ) f g x = f (g x)
let ( |- ) f g x = g (f x)
end
open Infix
let is_weak_etag etag =
if String.length etag > 2 then String.sub etag 0 2 = "W/" else false
let etag_option etag = match etag with "" -> None | v -> Some v
let merge_query_string parameters url =
let neturl = Neturl.parse_url url in
let fields =
try
Netencoding.Url.dest_url_encoded_parameters
(Neturl.url_query ~encoded:true neturl)
with Not_found -> []
in
let query_string =
Netencoding.Url.mk_url_encoded_parameters (fields @ parameters)
in
let new_neturl = Neturl.modify_url ~encoded:true ~query:query_string neturl in
Neturl.string_of_url new_neturl
let add_path_to_url ?(encoded = true) path_to_add url =
let neturl = Neturl.parse_url url in
let base_path =
if List.length path_to_add > 0 && List.hd path_to_add = "" then
[]
else
let base_path =
Neturl.url_path neturl |> List.filter (fun p -> p <> "")
in
"" :: base_path
in
let path_to_add_encoded =
List.map
(fun p ->
if encoded && (String.contains p '#' || String.contains p '/') then
Netencoding.Url.encode p
else p)
path_to_add
in
let new_path = base_path @ path_to_add_encoded in
let new_neturl = Neturl.modify_url ~encoded ~path:new_path neturl in
Neturl.string_of_url new_neturl
let string_after_char c s =
let last_position = String.rindex s c in
Str.string_after s (last_position + 1)
let string_before_char c s =
try
let first_occurrence = String.index s c in
Str.string_before s first_occurrence
with Not_found -> s
let divide_string s c =
try
let i = String.index s c in
let len = String.length s in
let j = i + 1 in
(String.sub s 0 i, String.sub s j (len - j))
with Invalid_argument _ -> ("", s)
let strip_string s =
let leading_trailing_whitespace =
Str.regexp "\\(^[ \t\r\n]+\\|[ \t\r\n]+$\\)"
in
Str.global_replace leading_trailing_whitespace "" s
let string_starts_with s prefix =
let prefix_len = String.length prefix in
if prefix_len > String.length s then false
else
let start = String.sub s 0 prefix_len in
String.compare start prefix == 0
let string_ends_with s suffix =
let len = String.length s in
let suffix_len = String.length suffix in
if suffix_len > len then false
else
let ending = String.sub s (len - suffix_len) suffix_len in
String.compare ending suffix == 0
let wait_exponential_backoff n =
let seconds = 1 lsl n in
let milliseconds = Random.float 1.0 in
let wait_time = float_of_int seconds +. milliseconds in
Unix.select [] [] [] wait_time |> ignore
class bigarray_rec_out_channel buffer =
object
val mutable pos = 0
method output b offset len =
Netsys_mem.blit_bytes_to_memory b offset buffer pos len;
pos <- pos + len;
len
method flush () = ()
method close_out () = ()
end
class bigarray_out_obj_channel buffer =
Netchannels.out_obj_channel_delegation
(Netchannels.lift_out ~buffered:false
(`Rec (new bigarray_rec_out_channel buffer)))
class bigarray_rec_in_channel buffer =
object
val dim = Bigarray.Array1.dim buffer
val mutable pos = 0
method input b offset len =
let input_bytes l =
Netsys_mem.blit_memory_to_bytes buffer pos b offset l;
pos <- pos + l;
l
in
if pos >= dim then raise End_of_file
else if pos + len > dim then input_bytes (dim - pos)
else input_bytes len
method close_in () = ()
end
class bigarray_in_obj_channel buffer =
Netchannels.in_obj_channel_delegation
(Netchannels.lift_in ~buffered:false
(`Rec (new bigarray_rec_in_channel buffer)))
let option_map_default f default v = Option.(map f v |> value ~default)
let () = Random.self_init ()