[@@@opam eio_main progress] let progress_source report (Eio.Resource.T (v, bindings) : _ Eio.Flow.source) = let module X = (val (Eio.Resource.get bindings Eio.Flow.Pi.Source)) in let module V = struct include X let single_read v bufs = let r = X.single_read v bufs in report (Int64.of_int r); r end in Eio.Resource.T (v, Eio.Flow.Pi.source (module V)) let load path = Eio.Path.with_open_in path @@ fun flow -> let size = Eio.File.size flow in Progress.with_reporter (Progress.counter ?message:(Option.map snd @@ Eio.Path.split path) (Optint.Int63.to_int64 size)) @@ fun r -> let flow = progress_source r flow in try if Optint.Int63.(compare size (of_int Sys.max_string_length)) = 1 then raise @@ Eio.Fs.err File_too_large; let buf = Cstruct.create (Optint.Int63.to_int size) in let rec loop buf got = match Eio.Flow.single_read flow buf with | n -> loop (Cstruct.shift buf n) (n + got) | exception End_of_file -> got in let got = loop buf 0 in Cstruct.to_string ~len:got buf with Eio.Exn.Io _ as ex -> let bt = Printexc.get_raw_backtrace () in Eio.Exn.reraise_with_context ex bt "loading %a" Eio.Path.pp path let () = Eio_main.run @@ fun env -> let s = load Eio.Path.(env#fs / Sys.argv.(1)) in ignore s