···55555656(* {1 Crash safety: arbitrary bytes never cause a crash} *)
57575858-let test_no_crash_on_arbitrary_input bytes =
5858+let test_no_crash_arbitrary bytes =
5959 (* Decoding arbitrary bytes should either succeed or return Error,
6060 never crash *)
6161 ignore (Csvt.decode_string int_codec bytes);
···222222 ( "csvt",
223223 [
224224 test_case "no crash on arbitrary" [ bytes ]
225225- test_no_crash_on_arbitrary_input;
225225+ test_no_crash_arbitrary;
226226 test_case "int roundtrip" [ int ] test_int_roundtrip;
227227 test_case "float roundtrip" [ float ] test_float_roundtrip;
228228 test_case "bool roundtrip" [ bool ] test_bool_roundtrip;
+6-6
lib/csvt.ml
···272272273273 The paper's [mem] combinator, adapted for CSV. *)
274274275275-let get_col name t = Row.(obj Fun.id |> col name t ~enc:Fun.id |> finish)
275275+let col name t = Row.(obj Fun.id |> col name t ~enc:Fun.id |> finish)
276276277277(* {1 Update support} *)
278278279279-let find_col_by_name header name =
279279+let col_by_name header name =
280280 let name = String.trim name in
281281 let n = Array.length header in
282282 let rec go i =
···287287 go 0
288288289289let update_col name codec f header row =
290290- let idx = find_col_by_name header name in
290290+ let idx = col_by_name header name in
291291 if idx < 0 then Error (Missing_column name)
292292 else if idx >= Array.length row then
293293 Error
···303303 Ok result
304304305305let delete_col name header row =
306306- let idx = find_col_by_name header name in
306306+ let idx = col_by_name header name in
307307 if idx < 0 then (header, row)
308308 else
309309 let n = Array.length header in
···330330 r_dec : ('a, 'a) dec_fun;
331331}
332332333333-let find_col header name =
333333+let resolve_col header name =
334334 let name = String.trim name in
335335 let n = Array.length header in
336336 let rec go i =
···349349 if i >= n then Ok { r_indices = indices; r_mems = mems; r_dec = m.dec }
350350 else
351351 let (Mem_dec mm) = mems.(i) in
352352- let idx = find_col header mm.name in
352352+ let idx = resolve_col header mm.name in
353353 indices.(i) <- idx;
354354 if idx < 0 && Option.is_none mm.dec_absent then
355355 Error (Missing_column mm.name)
+4-4
lib/csvt.mli
···7777 [false]. *)
78787979val nullable_float : float t
8080-(** Like {!float} but treats ["NULL"] and empty strings as [nan]. *)
8080+(** [nullable_float] is like {!float} but treats ["NULL"] and empty strings as [nan]. *)
81818282val nullable_int : int t
8383-(** Like {!int} but treats ["NULL"] and empty strings as [-1]. *)
8383+(** [nullable_int] is like {!int} but treats ["NULL"] and empty strings as [-1]. *)
84848585val option : 'a t -> 'a option t
8686(** [option t] treats ["NULL"] and empty strings as [None], otherwise decodes
···104104105105(** {1:query Query} *)
106106107107-val get_col : string -> 'a t -> 'a t
108108-(** [get_col name t] creates a single-column row codec that extracts column
107107+val col : string -> 'a t -> 'a t
108108+(** [col name t] creates a single-column row codec that extracts column
109109 [name] decoded with [t]. Useful for projecting a single column from a CSV
110110 file without defining a full row type. *)
111111
+5-5
test/test_csvt.ml
···646646647647let test_get_col_int () =
648648 let csv = "id,name,score,active\n1,alice,95.5,true\n2,bob,87.3,false\n" in
649649- let id_codec = Csvt.get_col "id" Csvt.int in
649649+ let id_codec = Csvt.col "id" Csvt.int in
650650 match Csvt.decode_string id_codec csv with
651651 | Error e -> Alcotest.failf "get_col id: %s" (Csvt.error_to_string e)
652652 | Ok ids -> Alcotest.(check (list int)) "ids" [ 1; 2 ] ids
653653654654let test_get_col_string () =
655655 let csv = "id,name,score,active\n1,alice,95.5,true\n2,bob,87.3,false\n" in
656656- let name_codec = Csvt.get_col "name" Csvt.string in
656656+ let name_codec = Csvt.col "name" Csvt.string in
657657 match Csvt.decode_string name_codec csv with
658658 | Error e -> Alcotest.failf "get_col name: %s" (Csvt.error_to_string e)
659659 | Ok names -> Alcotest.(check (list string)) "names" [ "alice"; "bob" ] names
660660661661let test_get_col_missing () =
662662 let csv = "id,name\n1,alice\n" in
663663- let score_codec = Csvt.get_col "score" Csvt.float in
663663+ let score_codec = Csvt.col "score" Csvt.float in
664664 match Csvt.decode_string score_codec csv with
665665 | Ok _ -> Alcotest.fail "expected error for missing column"
666666 | Error (Csvt.Missing_column "score") -> ()
667667 | Error e -> Alcotest.failf "unexpected error: %s" (Csvt.error_to_string e)
668668669669let test_get_col_encode () =
670670- let codec = Csvt.get_col "v" Csvt.int in
670670+ let codec = Csvt.col "v" Csvt.int in
671671 let h = Csvt.Private.encode_header codec in
672672 Alcotest.(check (array string)) "header" [| "v" |] h;
673673 let row = Csvt.Private.encode_row codec 42 in
674674 Alcotest.(check (array string)) "row" [| "42" |] row
675675676676let test_get_col_col_names () =
677677- let codec = Csvt.get_col "score" Csvt.float in
677677+ let codec = Csvt.col "score" Csvt.float in
678678 Alcotest.(check (list string)) "col_names" [ "score" ] (Csvt.col_names codec);
679679 Alcotest.(check int) "col_count" 1 (Csvt.col_count codec)
680680