forked from
anil.recoil.org/ocaml-tomlt
TOML 1.1 codecs for OCaml
1(*---------------------------------------------------------------------------
2 Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
3 SPDX-License-Identifier: ISC
4 ---------------------------------------------------------------------------*)
5
6(** Bytesrw integration for {{:https://toml.io/en/v1.1.0}TOML 1.1} parsing and
7 encoding.
8
9 This module provides I/O operations for TOML values and codecs using
10 {{:https://erratique.ch/software/bytesrw}Bytesrw} for efficient streaming.
11
12 {2 Quick Start}
13
14 Parse a TOML string:
15 {[
16 let config =
17 Tomlt_bytesrw.of_string
18 {|
19 [server]
20 host = "localhost"
21 port = 8080
22 |}
23 in
24 match config with
25 | Ok t ->
26 let server = Tomlt.Toml.get "server" t in
27 let host = Tomlt.Toml.to_string (Tomlt.Toml.get "host" server) in
28 let port = Tomlt.Toml.to_int (Tomlt.Toml.get "port" server) in
29 Printf.printf "Server: %s:%Ld\n" host port
30 | Error e -> prerr_endline (Tomlt.Toml.Error.to_string e)
31 ]}
32
33 Use with codecs:
34 {[
35 type config = { host : string; port : int }
36
37 let config_codec =
38 Tomlt.(
39 Table.(
40 obj (fun host port -> { host; port })
41 |> mem "host" string ~enc:(fun c -> c.host)
42 |> mem "port" int ~enc:(fun c -> c.port)
43 |> finish))
44
45 let config = Tomlt_bytesrw.decode_string config_codec toml_string
46 ]}
47
48 {2 Module Overview}
49
50 - {!section:parse} - Parsing TOML from strings and readers
51 - {!section:encode} - Encoding TOML to strings and writers
52 - {!section:codec_io} - Codec I/O operations
53 - {!section:tagged_json} - Tagged JSON for toml-test compatibility *)
54
55open Bytesrw
56
57(** {1:parse Parsing (Decoding)}
58
59 Parse TOML from various sources. *)
60
61val of_string : string -> (Tomlt.Toml.t, Tomlt.Toml.Error.t) result
62(** [of_string s] parses [s] as a TOML document. *)
63
64val of_reader :
65 ?file:string -> Bytes.Reader.t -> (Tomlt.Toml.t, Tomlt.Toml.Error.t) result
66(** [of_reader r] parses a TOML document from reader [r].
67 @param file Optional filename for error messages. *)
68
69val parse : string -> Tomlt.Toml.t
70(** [parse s] parses [s] as a TOML document.
71 @raise Tomlt.Toml.Error.Error on parse errors. *)
72
73val parse_reader : ?file:string -> Bytes.Reader.t -> Tomlt.Toml.t
74(** [parse_reader r] parses a TOML document from reader [r].
75 @param file Optional filename for error messages.
76 @raise Tomlt.Toml.Error.Error on parse errors. *)
77
78(** {1:encode Encoding}
79
80 Encode TOML values to strings and writers. *)
81
82val to_string : Tomlt.Toml.t -> string
83(** [to_string t] encodes [t] as a TOML-formatted string.
84 @raise Invalid_argument if [t] is not a [Table]. *)
85
86val to_writer : Bytes.Writer.t -> Tomlt.Toml.t -> unit
87(** [to_writer w t] writes [t] as TOML to writer [w].
88
89 Use with {!Bytesrw.Bytes.Writer} to write to various destinations:
90 {[
91 (* To buffer *)
92 let buf = Buffer.create 256 in
93 Tomlt_bytesrw.to_writer (Bytes.Writer.of_buffer buf) value;
94 Buffer.contents buf
95 (* To channel *)
96 Tomlt_bytesrw.to_writer
97 (Bytes.Writer.of_out_channel oc)
98 value
99 ]}
100
101 @raise Invalid_argument if [t] is not a [Table]. *)
102
103(** {1:codec_io Codec I/O Operations}
104
105 Convenience functions that combine parsing/encoding with codec operations.
106*)
107
108val decode_string : 'a Tomlt.t -> string -> ('a, Tomlt.Toml.Error.t) result
109(** [decode_string c s] parses TOML string [s] and decodes with codec [c]. *)
110
111val decode_string_exn : 'a Tomlt.t -> string -> 'a
112(** [decode_string_exn c s] is like [decode_string] but raises on error.
113 @raise Tomlt.Toml.Error.Error on parse or decode failure. *)
114
115val encode_string : 'a Tomlt.t -> 'a -> string
116(** [encode_string c v] encodes [v] using codec [c] to a TOML-formatted string.
117*)
118
119val decode_reader :
120 ?file:string ->
121 'a Tomlt.t ->
122 Bytes.Reader.t ->
123 ('a, Tomlt.Toml.Error.t) result
124(** [decode_reader c r] parses TOML from reader [r] and decodes with codec [c].
125 @param file Optional filename for error messages. *)
126
127val encode_writer : 'a Tomlt.t -> 'a -> Bytes.Writer.t -> unit
128(** [encode_writer c v w] encodes [v] using codec [c] and writes TOML to writer
129 [w]. *)
130
131(** {1:tagged_json Tagged JSON}
132
133 Functions for interoperating with the
134 {{:https://github.com/toml-lang/toml-test}toml-test} suite's tagged JSON
135 format. These functions are primarily for testing and validation. *)
136
137module Tagged_json : sig
138 val encode : Tomlt.Toml.t -> string
139 (** [encode t] converts TOML value [t] to tagged JSON format.
140
141 The tagged JSON format wraps each value with type information:
142 - Strings: [{"type": "string", "value": "..."}]
143 - Integers: [{"type": "integer", "value": "..."}]
144 - Floats: [{"type": "float", "value": "..."}]
145 - Booleans: [{"type": "bool", "value": "true"|"false"}]
146 - Datetimes: [{"type": "datetime", "value": "..."}]
147 - Arrays: [[...]]
148 - Tables: [{...}] *)
149
150 val decode : string -> Tomlt.Toml.t
151 (** [decode s] parses tagged JSON string [s] into a TOML value.
152 @raise Failure if the JSON is malformed or has invalid types. *)
153
154 val decode_and_encode_toml : string -> (string, string) result
155 (** [decode_and_encode_toml json] decodes tagged JSON and encodes as TOML.
156 Used by the toml-test encoder harness. *)
157end