let to_string lines = let cell_to_string cell = if Js.String.includes "\"" cell then "\"" ^ (Js.String.replaceByRe [%re "/\"/g"] "\"\"" cell) ^ "\"" else cell in let line_to_string line = line |> Js.Array.map cell_to_string |> Js.Array.joinWith "," in lines |> Js.Array.map line_to_string |> Js.Array.joinWith "\n" let parse str = let lines = [| |] in let current_line = ref [| |] in let current_cell = ref "" in let in_quote = ref false in let i = ref 0 in let l = Js.String.length str in let () = while !i < l do let cc = Js.String.get str !i in let nc = Js.String.get str (!i + 1) in let () = if !in_quote && cc == "\"" && nc == "\"" then let () = current_cell := !current_cell ^ cc in i := !i + 1 else if cc == "\"" then in_quote := not !in_quote else if not !in_quote && cc == "," then let _ = Js.Array.push !current_cell !current_line in current_cell := "" else if not !in_quote && ((cc == "\r" && nc == "\n") || cc == "\n" || cc == "\r") then let _ = Js.Array.push !current_cell !current_line in let _ = Js.Array.push !current_line lines in let _ = current_line := [| |] in current_cell := "" else current_cell := !current_cell ^ cc in i := !i + 1 done in let _ = if Js.String.length !current_cell > 0 then let _ = Js.Array.push !current_cell !current_line in () else () in let _ = if Js.Array.length !current_line > 0 then let _ = Js.Array.push !current_line lines in () else () in lines let to_dicts lines = let res = [| |] in let () = if Js.Array.length lines > 0 then let header = Js.Array.unsafe_get lines 0 in for i = 1 to Js.Array.length lines - 1 do let line = Js.Array.unsafe_get lines i in let dict = Js.Dict.empty() in let () = Js.Array.forEachi (fun key j -> Js.Dict.set dict key (Js.Array.unsafe_get line j)) header in ignore (Js.Array.push dict res) done in res