+6
-3
bin/mlgpx_cli.ml
+6
-3
bin/mlgpx_cli.ml
···
3
3
open Cmdliner
4
4
open Gpx
5
5
6
+
let ( / ) = Eio.Path.( / )
7
+
6
8
(* Terminal and formatting setup *)
7
9
let setup_fmt style_renderer =
8
10
Fmt_tty.setup_std_outputs ?style_renderer ();
···
67
69
log_info "Reading GPX file: %a" (bold_style Fmt.string) input_file;
68
70
69
71
(* Read input GPX *)
70
-
let gpx = Gpx_eio.read ~fs input_file in
72
+
let gpx = Gpx_eio.read (fs / input_file) in
71
73
72
74
if verbose then
73
75
log_info "Found %d waypoints and %d existing tracks"
···
140
142
log_info "Writing output to: %a" (bold_style Fmt.string) output_file;
141
143
142
144
(* Write output GPX *)
143
-
Gpx_eio.write ~fs output_file output_gpx;
145
+
Gpx_eio.write (fs / output_file) output_gpx;
144
146
145
147
if verbose then (
146
148
Fmt.pf Format.std_formatter "%a\n" (success_style Fmt.string) "Conversion completed successfully!";
···
215
217
if verbose then
216
218
log_info "Analyzing GPX file: %a" (bold_style Fmt.string) input_file;
217
219
218
-
let gpx = Gpx_eio.read ~fs input_file in
220
+
let gpx = Gpx_eio.read (fs / input_file) in
219
221
220
222
(* Header *)
221
223
Fmt.pf Format.std_formatter "%a\n" (bold_style Fmt.string) "GPX File Information";
···
255
257
let duration_span = Ptime.diff stop_time start_time in
256
258
match Ptime.Span.to_int_s duration_span with
257
259
| Some seconds ->
260
+
let ( / ) = Int.div in
258
261
let days = seconds / 86400 in
259
262
let hours = (seconds mod 86400) / 3600 in
260
263
let minutes = (seconds mod 3600) / 60 in
+3
-3
lib/gpx_eio/gpx_eio.ml
+3
-3
lib/gpx_eio/gpx_eio.ml
···
3
3
module IO = Gpx_io
4
4
5
5
(** Read and parse GPX file *)
6
-
let read ?(validate=false) ~fs path = IO.read_file ~validate ~fs path
6
+
let read ?(validate=false) path = IO.read_file ~validate path
7
7
8
8
(** Write GPX to file *)
9
-
let write ?(validate=false) ~fs path gpx = IO.write_file ~validate ~fs path gpx
9
+
let write ?(validate=false) path gpx = IO.write_file ~validate path gpx
10
10
11
11
(** Write GPX to file with backup *)
12
-
let write_with_backup ?(validate=false) ~fs path gpx = IO.write_file_with_backup ~validate ~fs path gpx
12
+
let write_with_backup ?(validate=false) path gpx = IO.write_file_with_backup ~validate path gpx
13
13
14
14
(** Read GPX from Eio source *)
15
15
let from_source ?(validate=false) source = IO.read_source ~validate source
+7
-10
lib/gpx_eio/gpx_eio.mli
+7
-10
lib/gpx_eio/gpx_eio.mli
···
38
38
These functions provide simple file I/O with the filesystem from {!Eio.Stdenv.fs}. *)
39
39
40
40
(** Read and parse GPX file.
41
-
@param fs Filesystem capability
42
41
@param path File path to read
43
42
@param ?validate Optional validation flag (default: false)
44
43
@return GPX document
45
44
@raises Gpx.Gpx_error on read or parse failure *)
46
-
val read : ?validate:bool -> fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> string -> Gpx.t
45
+
val read : ?validate:bool -> _ Eio.Path.t -> Gpx.t
47
46
48
47
(** Write GPX to file.
49
-
@param fs Filesystem capability
50
48
@param path File path to write
51
49
@param gpx GPX document to write
52
50
@param ?validate Optional validation flag (default: false)
53
51
@raises Gpx.Gpx_error on write failure *)
54
-
val write : ?validate:bool -> fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> string -> Gpx.t -> unit
52
+
val write : ?validate:bool -> _ Eio.Path.t -> Gpx.t -> unit
55
53
56
54
(** Write GPX to file with automatic backup.
57
-
@param fs Filesystem capability
58
55
@param path File path to write
59
56
@param gpx GPX document to write
60
57
@param ?validate Optional validation flag (default: false)
61
-
@return Backup file path (empty if no backup created)
58
+
@return Backup file path ([None] if no backup created)
62
59
@raises Gpx.Gpx_error on failure *)
63
-
val write_with_backup : ?validate:bool -> fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> string -> Gpx.t -> string
60
+
val write_with_backup : ?validate:bool -> 'a Eio.Path.t -> Gpx.t -> 'a Eio.Path.t option
64
61
65
62
(** {2 Stream Operations}
66
63
···
71
68
@param ?validate Optional validation flag (default: false)
72
69
@return GPX document
73
70
@raises Gpx.Gpx_error on read or parse failure *)
74
-
val from_source : ?validate:bool -> [> Eio.Flow.source_ty ] Eio.Resource.t -> Gpx.t
71
+
val from_source : ?validate:bool -> _ Eio.Flow.source -> Gpx.t
75
72
76
73
(** Write GPX to Eio sink.
77
74
@param sink Output flow
78
75
@param gpx GPX document
79
76
@param ?validate Optional validation flag (default: false)
80
77
@raises Gpx.Gpx_error on write failure *)
81
-
val to_sink : ?validate:bool -> [> Eio.Flow.sink_ty ] Eio.Resource.t -> Gpx.t -> unit
78
+
val to_sink : ?validate:bool -> _ Eio.Flow.sink -> Gpx.t -> unit
82
79
83
80
(** Print GPX statistics to sink.
84
81
@param sink Output sink
85
82
@param gpx GPX document *)
86
-
val print_stats : [> Eio.Flow.sink_ty ] Eio.Resource.t -> Gpx.t -> unit
83
+
val print_stats : _ Eio.Flow.sink -> Gpx.t -> unit
+27
-29
lib/gpx_eio/gpx_io.ml
+27
-29
lib/gpx_eio/gpx_io.ml
···
1
1
(** GPX Eio I/O operations *)
2
2
3
3
(** Read GPX from file path *)
4
-
let read_file ?(validate=false) ~fs path =
5
-
let content = Eio.Path.load Eio.Path.(fs / path) in
4
+
let read_file ?(validate=false) path =
5
+
let content = Eio.Path.load path in
6
6
match Gpx.parse_string ~validate content with
7
7
| Ok gpx -> gpx
8
8
| Error err -> raise (Gpx.Gpx_error err)
9
9
10
10
(** Write GPX to file path *)
11
-
let write_file ?(validate=false) ~fs path gpx =
11
+
let write_file ?(validate=false) path gpx =
12
12
match Gpx.write_string ~validate gpx with
13
13
| Ok xml_string ->
14
-
Eio.Path.save ~create:(`Or_truncate 0o644) Eio.Path.(fs / path) xml_string
14
+
Eio.Path.save ~create:(`Or_truncate 0o644) path xml_string
15
15
| Error err -> raise (Gpx.Gpx_error err)
16
16
17
17
(** Read GPX from Eio source *)
···
29
29
| Error err -> raise (Gpx.Gpx_error err)
30
30
31
31
(** Check if file exists *)
32
-
let file_exists ~fs path =
33
-
try
34
-
let _stat = Eio.Path.stat ~follow:true Eio.Path.(fs / path) in
35
-
true
36
-
with
37
-
| _ -> false
32
+
let file_exists = Eio.Path.is_file
38
33
39
34
(** Get file size *)
40
-
let file_size ~fs path =
35
+
let file_size path =
41
36
try
42
-
let stat = Eio.Path.stat ~follow:true Eio.Path.(fs / path) in
37
+
let stat = Eio.Path.stat ~follow:true path in
43
38
Optint.Int63.to_int stat.size
44
39
with
45
40
| exn -> raise (Gpx.Gpx_error (Gpx.Error.io_error (Printexc.to_string exn)))
46
41
47
42
(** Create backup of existing file *)
48
-
let create_backup ~fs path =
49
-
if file_exists ~fs path then
50
-
let backup_path = path ^ ".backup" in
51
-
let content = Eio.Path.load Eio.Path.(fs / path) in
52
-
Eio.Path.save ~create:(`Or_truncate 0o644) Eio.Path.(fs / backup_path) content;
53
-
backup_path
43
+
let create_backup ((fs, inner_path) as path) =
44
+
if file_exists path then
45
+
let backup_path = inner_path ^ ".backup" in
46
+
let content = Eio.Path.load path in
47
+
Eio.Path.save ~create:(`Or_truncate 0o644) (fs, backup_path) content;
48
+
Some (fs, backup_path)
54
49
else
55
-
""
50
+
None
56
51
57
52
(** Write GPX to file with automatic backup *)
58
-
let write_file_with_backup ?(validate=false) ~fs path gpx =
59
-
let backup_path = create_backup ~fs path in
53
+
let write_file_with_backup ?(validate=false) path gpx =
54
+
let backup_path = create_backup path in
60
55
try
61
-
write_file ~validate ~fs path gpx;
56
+
write_file ~validate path gpx;
62
57
backup_path
63
58
with
64
59
| Gpx.Gpx_error _ as err ->
65
60
(* Try to restore backup if write failed *)
66
-
if backup_path <> "" && file_exists ~fs backup_path then (
67
-
try
68
-
let backup_content = Eio.Path.load Eio.Path.(fs / backup_path) in
69
-
Eio.Path.save ~create:(`Or_truncate 0o644) Eio.Path.(fs / path) backup_content
70
-
with _ -> () (* Ignore restore errors *)
71
-
);
72
-
raise err
61
+
match backup_path with
62
+
| Some backup_path ->
63
+
if file_exists backup_path then (
64
+
try
65
+
let backup_content = Eio.Path.load backup_path in
66
+
Eio.Path.save ~create:(`Or_truncate 0o644) path backup_content
67
+
with _ -> () (* Ignore restore errors *)
68
+
);
69
+
raise err
70
+
| _ -> raise err
+7
-13
lib/gpx_eio/gpx_io.mli
+7
-13
lib/gpx_eio/gpx_io.mli
···
8
8
(** {1 File Operations} *)
9
9
10
10
(** Read GPX from file path.
11
-
@param fs Filesystem capability
12
11
@param path File path to read
13
12
@param ?validate Optional validation flag (default: false)
14
13
@return GPX document or error *)
15
-
val read_file : ?validate:bool -> fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> string -> Gpx.t
14
+
val read_file : ?validate:bool -> _ Eio.Path.t -> Gpx.t
16
15
17
16
(** Write GPX to file path.
18
-
@param fs Filesystem capability
19
17
@param path File path to write
20
18
@param gpx GPX document to write
21
19
@param ?validate Optional validation flag (default: false)
22
20
@raises Gpx.Gpx_error on write failure *)
23
-
val write_file : ?validate:bool -> fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> string -> Gpx.t -> unit
21
+
val write_file : ?validate:bool -> _ Eio.Path.t -> Gpx.t -> unit
24
22
25
23
(** {1 Stream Operations}
26
24
···
41
39
(** {1 Utility Functions} *)
42
40
43
41
(** Check if file exists.
44
-
@param fs Filesystem capability
45
42
@param path File path to check
46
43
@return [true] if file exists and is readable *)
47
-
val file_exists : fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> string -> bool
44
+
val file_exists : _ Eio.Path.t -> bool
48
45
49
46
(** Get file size.
50
-
@param fs Filesystem capability
51
47
@param path File path
52
48
@return File size in bytes *)
53
-
val file_size : fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> string -> int
49
+
val file_size : _ Eio.Path.t -> int
54
50
55
51
(** Create backup of existing file.
56
-
@param fs Filesystem capability
57
52
@param path Original file path
58
53
@return Backup file path *)
59
-
val create_backup : fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> string -> string
54
+
val create_backup : 'a Eio.Path.t -> 'a Eio.Path.t option
60
55
61
56
(** Write GPX to file with automatic backup.
62
57
Creates a backup of existing file before writing new content.
63
-
@param fs Filesystem capability
64
58
@param path File path to write
65
59
@param gpx GPX document to write
66
60
@param ?validate Optional validation flag (default: false)
67
-
@return Backup file path (empty string if no backup needed) *)
68
-
val write_file_with_backup : ?validate:bool -> fs:[> Eio.Fs.dir_ty ] Eio.Path.t -> string -> Gpx.t -> string
61
+
@return Backup file path ([None] if no backup needed) *)
62
+
val write_file_with_backup : ?validate:bool -> 'a Eio.Path.t -> Gpx.t -> 'a Eio.Path.t option
+7
-5
test/test_corpus_unix_eio.ml
+7
-5
test/test_corpus_unix_eio.ml
···
2
2
3
3
open Alcotest
4
4
5
+
let ( / ) = Eio.Path. ( / )
6
+
5
7
let test_data_dir = "test/data"
6
8
7
9
let test_files = [
···
44
46
let fs = Eio.Stdenv.fs env in
45
47
let path = Filename.concat test_data_dir filename in
46
48
try
47
-
let gpx = Gpx_eio.read ~fs path in
49
+
let gpx = Gpx_eio.read (fs / path) in
48
50
let validation = Gpx.validate_gpx gpx in
49
51
check bool "GPX is valid" true validation.is_valid;
50
52
check bool "Has some content" true (
···
68
70
try
69
71
Eio_main.run @@ fun env ->
70
72
let fs = Eio.Stdenv.fs env in
71
-
Ok (Gpx_eio.read ~fs path)
73
+
Ok (Gpx_eio.read (fs / path))
72
74
with
73
75
| Gpx.Gpx_error err -> Error err
74
76
in
···
120
122
let fs = Eio.Stdenv.fs env in
121
123
let path = Filename.concat test_data_dir filename in
122
124
try
123
-
let gpx_original = Gpx_eio.read ~fs path in
125
+
let gpx_original = Gpx_eio.read (fs / path) in
124
126
(* Write to temporary string via GPX core *)
125
127
match Gpx.write_string gpx_original with
126
128
| Ok xml_string ->
···
171
173
(try
172
174
Eio_main.run @@ fun env ->
173
175
let fs = Eio.Stdenv.fs env in
174
-
let _ = Gpx_eio.read ~fs path in
176
+
let _ = Gpx_eio.read (fs / path) in
175
177
failf "Eio should have failed to parse invalid.gpx"
176
178
with
177
179
| Gpx.Gpx_error _ ->
···
190
192
let start_eio = Sys.time () in
191
193
let _ = Eio_main.run @@ fun env ->
192
194
let fs = Eio.Stdenv.fs env in
193
-
try Some (Gpx_eio.read ~fs path)
195
+
try Some (Gpx_eio.read (fs / path))
194
196
with Gpx.Gpx_error _ -> None
195
197
in
196
198
let eio_time = Sys.time () -. start_eio in