TOML 1.1 codecs for OCaml
at main 157 lines 5.4 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 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