package core_extended

  1. Overview
  2. Docs
Extra components that are not as closely vetted or as stable as Core

Install

Dune Dependency

Authors

Maintainers

Sources

core_extended-v0.16.0.tar.gz
sha256=ccbb4e47e76edfd0b8aa5c2d3722e8813102c624851beec0cedd77ba13c4ccfb

doc/src/core_extended.delimited_kernel/read_intf.ml.html

Source file read_intf.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
open Core

(** If we can read a row correctly but the ['a t] provided can't convert it,
    your ['a On_invalid_row.t] will define what happens.

    Here, 'read a row correctly' means that it's valid CSV (subject to your
    delimiter etc) & it has the correct number of columns. If that's not the
    case the parsers will just raise. *)
module type On_invalid_row = sig
  type 'a t

  (** The default. Raise with additional context. *)
  val raise : _ t

  (** Skip the bad row *)
  val skip : _ t

  (** Do something else!

      - [`Skip]: skip the line. Same as [skip] above.
      - [`Yield]: return the given value for this row.
      - [`Raise]: raise the given exception
      - [`Fallback]: invoke the given handler instead
  *)
  val create
    :  (line_number:int (** The line number of the bad row.  *)
        -> int String.Map.t (** Map from header to position. *)
        -> string Append_only_buffer.t (** Value at each position. *)
        -> exn (** Exception raised when trying to convert this row. *)
        -> [ `Skip | `Yield of 'a | `Raise of exn | `Fallback of 'a t ])
    -> 'a t
end

module type Open_on_rhs = sig
  type 'a t

  val at_index : int -> f:(string -> 'a) -> 'a t
  val at_header : string -> f:(string -> 'a) -> 'a t
  val at_header_opt : string -> f:(string option -> 'a) -> 'a t
end

module type Root = sig
  (** Row up to the error, and the field with the error up to the point of
      failure. Same as [Expert.Parse_state.Bad_csv_formatting]. *)
  exception Bad_csv_formatting of string list * string

  (** This provides an applicative interface for constructing values from a csv file.

      An ['a t] describes how to build an OCaml model ['a] for each row.

      Simple example:
      {[
        type t =
          { foo : int
          ; bar : string
          }

        (* Describes how to generate a [t] from a row of a csv file *)
        let parse : t Delimited_kernel.Read.t =
          let open Delimited_kernel.Read.Let_syntax in
          let%map_open foo = at_header "foo" ~f:Int.of_string
          and bar = at_header "bar" ~f:String.of_string in
          { foo; bar }
        ;;

        let _ =
          Delimited_kernel.Read.list_of_string ~header:`Yes parse
            "foo,bar\n2,\"hello, world\"\n"
        ;;
      ]}
  *)
  type 'a t

  include Applicative.S with type 'a t := 'a t

  module Open_on_rhs_intf : sig
    module type S = Open_on_rhs with type 'a t := 'a t
  end

  include
    Applicative.Let_syntax
    with type 'a t := 'a t
    with module Open_on_rhs_intf := Open_on_rhs_intf

  (** Read a field at the given index. Use [f] to convert the field from string. *)
  val at_index : int -> f:(string -> 'a) -> 'a t

  (** Read a field at the given header. Use [f] to convert the field from string.

      Note that if the given header is not provided through either the file or
      the [~header] argument to the parsers, this will fail at runtime.  *)
  val at_header : string -> f:(string -> 'a) -> 'a t

  (** Read a field at the given header, if it exists. Use [f] to convert the field from
      string. *)
  val at_header_opt : string -> f:(string option -> 'a) -> 'a t

  module Record_builder : Record_builder.S with type 'a applicative = 'a t

  module Fields_O : sig
    (** The following are convenience functions that build on [Record_builder.field] to
        make it easy to define a [t Delimited.Read.t] for some record type [t].

        Example usage:

        {[
          type t =
            { foo : int
            ; bar : bool
            }
          [@@deriving fields]

          let read : t Delimited.Read.t =
            Delimited.Read.Fields_O.(
              Fields.make_creator
                ~foo:!!Int.of_string
                ~bar:!?(Option.value_map ~default:true ~f:Bool.of_string)
              |> Delimited.Read.Record_builder.build_for_record)
        ]}
    *)

    (** Reads a single column from a field of a record. *)
    val ( !! )
      :  (string -> 'a)
      -> (_, 'a) Field.t
      -> ('a, _, _, _) Record_builder.Make_creator_types.handle_one_field

    (** Reads a single column from a field of a record, if the header exists.

        [( !? )] is to [at_header_opt] as [( !! )] is to [at_header].
    *)
    val ( !? )
      :  (string option -> 'a)
      -> (_, 'a) Field.t
      -> ('a, _, _, _) Record_builder.Make_creator_types.handle_one_field
  end

  module On_invalid_row : On_invalid_row

  (** Header parsing control *)
  module Header = Header

  (** Whole-row parsing. *)
  module Row : sig
    type 'a builder_t = 'a t

    include module type of Row

    (** A builder for [Row.t]s.

        As this parses the whole row it's slower than using the builder
        interface directly, but simpler to use. *)
    val builder : t builder_t
  end


  (** Fold the CSV rows contained in the given string. *)
  val fold_string
    :  ?strip:bool
    -> ?sep:char
    -> ?quote:[ `No_quoting | `Using of char ]
    -> ?header:Header.t
    -> ?on_invalid_row:'a On_invalid_row.t
    -> 'a t
    -> init:'b
    -> f:('b -> 'a -> 'b)
    -> string
    -> 'b

  (** Load the CSV as a list *)
  val list_of_string
    :  ?strip:bool
    -> ?sep:char
    -> ?quote:[ `No_quoting | `Using of char ]
    -> ?header:Header.t
    -> ?on_invalid_row:'a On_invalid_row.t
    -> 'a t
    -> string
    -> 'a list

  (** Read CSV file. *)
  val read_lines
    :  ?strip:bool
    -> ?sep:char
    -> ?quote:[ `No_quoting | `Using of char ]
    -> ?header:Header.t
    -> ?on_invalid_row:'a On_invalid_row.t
    -> 'a t
    -> In_channel.t
    -> 'a list

  (** Read CSV file, processing line by line. *)
  val fold_lines
    :  ?buffer_size:int
    -> ?strip:bool
    -> ?sep:char
    -> ?quote:[ `No_quoting | `Using of char ]
    -> ?header:Header.t
    -> ?on_invalid_row:'a On_invalid_row.t
    -> 'a t
    -> init:'b
    -> f:('b -> 'a -> 'b)
    -> In_channel.t
    -> 'b

  module Streaming : sig
    type 'a builder_t = 'a t
    type 'a t

    val create
      :  ?strip:bool
      -> ?sep:char
      -> ?quote:[ `No_quoting | `Using of char ]
      -> ?start_line_number:int
      -> ?on_invalid_row:'a On_invalid_row.t
      -> ?header:Header.t
      -> 'a builder_t
      -> init:'b
      -> f:('b -> 'a -> 'b)
      -> 'b t

    (** Like [create], but additionally passes the line number of the current row to [f] *)
    val create_indexed
      :  ?strip:bool
      -> ?sep:char
      -> ?quote:[ `No_quoting | `Using of char ]
      -> ?start_line_number:int
      -> ?on_invalid_row:'a On_invalid_row.t
      -> ?header:Header.t
      -> 'a builder_t
      -> init:'b
      -> f:(int -> 'b -> 'a -> 'b)
      -> 'b t

    val input_string : 'a t -> ?pos:int -> ?len:int -> string -> 'a t
    val input : 'a t -> ?pos:int -> ?len:int -> bytes -> 'a t
    val finish : 'a t -> 'a t
    val acc : 'a t -> 'a
    val headers : 'a t -> String.Set.t option
    val state : 'a t -> [ `Parsing_header | `Parsing_rows ]
  end
end

module type Expert = sig
  module Append_only_buffer = Append_only_buffer
  module Parse_state = Parse_state
  module On_invalid_row : On_invalid_row

  type 'a t

  module Builder : sig
    type nonrec 'a t = 'a t

    val lambda : (int String.Map.t -> string Append_only_buffer.t -> 'a) -> 'a t
    val return : 'a -> 'a t
  end
end
OCaml

Innovation. Community. Security.