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