structured_io v0.7.0 StructuredIO View Source

A process for performing I/O of structured data, such as markup or binary-encoded data.

Encoding

The process operates in either binary mode or Unicode mode (see StructuredIO.start/2 and StructuredIO.start_link/2). When in binary mode, the result of a read operation is a binary, regardless of whether the data read is String.valid?/1. In Unicode mode, the result of a read operation is an error/0 if the data read is not properly encoded Unicode data.

Link to this section Summary

Types

An error result

A binary value which marks the beginning of an enclosed data element

The portion of a binary value matched in a read operation

A mode of operation for the process: either binary or Unicode

A binary value which marks the end of an enclosed or terminated data element

Functions

Returns a value that can be passed to Enum.into/2 or Enum.into/3 for writing data to the specified structured_io

Returns a value that can be passed to functions such as Enum.map/2 for reading data elements from the specified structured_io, using the specified StructuredIO function, and the specified left and/or right

Invoked when the server is started. start_link/3 or start/3 will block until it returns

Gets the mode of the specified structured_io

Reads data from the specified structured_io beginning with the specified left and ending with the occurrence of the specified right that corresponds to it, inclusive

Reads data from the specified structured_io beginning with the specified left and ending with the first occurrence of the specified right, inclusive

Reads data from the specified structured_io beginning with the specified left and ending with the occurrence of the specified right that corresponds to it, exclusive

Reads data from the specified structured_io beginning with the specified left and ending with the first occurrence of the specified right, exclusive

Reads data from the specified structured_io if and until the specified right is encountered, including right

Reads data from the specified structured_io if and until the specified right is encountered, excluding right

Starts a StructuredIO process without links (outside a supervision tree) with the specified mode and options

Starts a StructuredIO process linked to the current process with the specified mode and options

Synchronously stops the specified structured_io process

Asynchronously writes the specified data as a binary to the specified structured_io

Link to this section Types

Link to this type error() View Source
error() :: {:error, atom() | binary()}

An error result.

A binary value which marks the beginning of an enclosed data element.

See StructuredIO.read_across/3 and StructuredIO.read_between/3.

Link to this type mode() View Source
mode() :: :binary | :unicode

A mode of operation for the process: either binary or Unicode.

See StructuredIO.start/2 and StructuredIO.start_link/2.

A binary value which marks the end of an enclosed or terminated data element.

See StructuredIO.read_across/3, StructuredIO.read_between/3, StructuredIO.read_through/2, and StructuredIO.read_to/2.

Link to this section Functions

Returns a value that can be passed to Enum.into/2 or Enum.into/3 for writing data to the specified structured_io.

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:unicode)
iex> StructuredIO.read_between structured_io,
...>                           "<elem>",
...>                           "</elem>"
""
iex> collector = StructuredIO.collect(structured_io)
iex> ["<elem>foo</elem>",
...>  "<elem>bar</elem>",
...>  "<elem>baz</elem>"]
iex> |> Enum.into(collector)
iex> StructuredIO.read_between structured_io,
...>                           "<elem>",
...>                           "</elem>"
"foo"
iex> StructuredIO.read_between structured_io,
...>                           "<elem>",
...>                           "</elem>"
"bar"
iex> StructuredIO.read_between structured_io,
...>                           "<elem>",
...>                           "</elem>"
"baz"
iex> StructuredIO.read_between structured_io,
...>                           "<elem>",
...>                           "</elem>"
""
Link to this function enumerate_with(structured_io, function, right) View Source
enumerate_with(GenServer.server(), :read_through | :read_to, right()) :: StructuredIO.Enumerator.t()
Link to this function enumerate_with(structured_io, function, left, right) View Source
enumerate_with(GenServer.server(), :read_across | :read_across_ignoring_overlap | :read_between | :read_between_ignoring_overlap, left(), right()) :: StructuredIO.Enumerator.t()

Returns a value that can be passed to functions such as Enum.map/2 for reading data elements from the specified structured_io, using the specified StructuredIO function, and the specified left and/or right.

Note that enumeration is not a purely functional operation; it consumes data elements from the underlying StructuredIO process.

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:unicode)
iex> StructuredIO.write structured_io,
...>                    "<elem>foo</elem>"
:ok
iex> StructuredIO.write structured_io,
...>                    "<elem>bar</elem>"
:ok
iex> StructuredIO.write structured_io,
...>                    "<elem>baz</elem>"
:ok
iex> structured_io
...> |> StructuredIO.enumerate_with(:read_between,
...>                                "<elem>",
...>                                "</elem>")
...> |> Enum.map(&String.upcase/1)
["FOO",
 "BAR",
 "BAZ"]
iex> StructuredIO.read_between structured_io,
...>                           "<elem>",
...>                           "</elem>"
""

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:unicode)
iex> StructuredIO.write structured_io,
...>                    "foo<br/>"
:ok
iex> StructuredIO.write structured_io,
...>                    "bar<br/>"
:ok
iex> StructuredIO.write structured_io,
...>                    "baz<br/>"
:ok
iex> structured_io
...> |> StructuredIO.enumerate_with(:read_through,
...>                                "<br/>")
...> |> Enum.map(&String.upcase/1)
["FOO<BR/>",
 "BAR<BR/>",
 "BAZ<BR/>"]
iex> StructuredIO.read_through structured_io,
...>                           "<br />"
""

Invoked when the server is started. start_link/3 or start/3 will block until it returns.

args is the argument term (second argument) passed to start_link/3.

Returning {:ok, state} will cause start_link/3 to return {:ok, pid} and the process to enter its loop.

Returning {:ok, state, timeout} is similar to {:ok, state} except handle_info(:timeout, state) will be called after timeout milliseconds if no messages are received within the timeout.

Returning {:ok, state, :hibernate} is similar to {:ok, state} except the process is hibernated before entering the loop. See c:handle_call/3 for more information on hibernation.

Returning :ignore will cause start_link/3 to return :ignore and the process will exit normally without entering the loop or calling c:terminate/2. If used when part of a supervision tree the parent supervisor will not fail to start nor immediately try to restart the GenServer. The remainder of the supervision tree will be (re)started and so the GenServer should not be required by other processes. It can be started later with Supervisor.restart_child/2 as the child specification is saved in the parent supervisor. The main use cases for this are:

  • The GenServer is disabled by configuration but might be enabled later.
  • An error occurred and it will be handled by a different mechanism than the Supervisor. Likely this approach involves calling Supervisor.restart_child/2 after a delay to attempt a restart.

Returning {:stop, reason} will cause start_link/3 to return {:error, reason} and the process to exit with reason reason without entering the loop or calling c:terminate/2.

Callback implementation for GenServer.init/1.

Gets the mode of the specified structured_io.

Examples

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:binary)
iex> StructuredIO.mode structured_io
:binary

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:unicode)
iex> StructuredIO.mode structured_io
:unicode
Link to this function read_across(structured_io, left, right, timeout \\ 5000) View Source
read_across(GenServer.server(), left(), right(), timeout()) ::
  match() |
  error()

Reads data from the specified structured_io beginning with the specified left and ending with the occurrence of the specified right that corresponds to it, inclusive.

When the region bounded by the first occurrences of left and right overlaps other such regions, the result is the union of them. If data does not both begin with left and contain a corresponding right, the result is an empty binary ("").

Examples

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:binary)
iex> StructuredIO.write structured_io,
...>                    <<0, 0, 0, 1, 2, 3, 0, 0, 0, 4, 5, 6, 255, 255, 255, 255, 255>>
:ok
iex> StructuredIO.read_across structured_io,
...>                          <<0, 0, 0>>,
...>                          <<255, 255, 255>>
""
iex> StructuredIO.write structured_io,
...>                    <<255, 0, 0, 0, 7, 8, 9, 255, 255, 255>>
:ok
iex> StructuredIO.read_across structured_io,
...>                          <<0, 0, 0>>,
...>                          <<255, 255, 255>>
<<0, 0, 0, 1, 2, 3, 0, 0, 0, 4, 5, 6, 255, 255, 255, 255, 255, 255>>
iex> StructuredIO.read_across structured_io,
...>                          <<0, 0, 0>>,
...>                          <<255, 255, 255>>
<<0, 0, 0, 7, 8, 9, 255, 255, 255>>
iex> StructuredIO.read_across structured_io,
...>                          <<0, 0, 0>>,
...>                          <<255, 255, 255>>
""

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:unicode)
iex> StructuredIO.write structured_io,
...>                    "<elem>foo<elem>bar</elem></elem"
:ok
iex> StructuredIO.read_across structured_io,
...>                          "<elem>",
...>                          "</elem>"
""
iex> StructuredIO.write structured_io,
...>                    "><elem>baz</elem>"
:ok
iex> StructuredIO.read_across structured_io,
...>                          "<elem>",
...>                          "</elem>"
"<elem>foo<elem>bar</elem></elem>"
iex> StructuredIO.read_across structured_io,
...>                          "<elem>",
...>                          "</elem>"
"<elem>baz</elem>"
iex> StructuredIO.read_across structured_io,
...>                          "<elem>",
...>                          "</elem>"
""

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:binary)
iex> StructuredIO.write structured_io,
...>                    "<elem>"
:ok
iex> <<fragment1::binary-size(3), fragment2::binary>> = "😕"
iex> StructuredIO.write structured_io,
...>                    fragment1
:ok
iex> StructuredIO.read_across structured_io,
...>                          "<elem>",
...>                          "</elem>"
""
iex> StructuredIO.write structured_io,
...>                    fragment2
:ok
iex> StructuredIO.write structured_io,
...>                    "</elem>"
:ok
iex> StructuredIO.read_across structured_io,
...>                          "<elem>",
...>                          "</elem>"
"<elem>😕</elem>"
iex> StructuredIO.read_across structured_io,
...>                          "<elem>",
...>                          "</elem>"
""

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:unicode)
iex> StructuredIO.write structured_io,
...>                    "<elem>"
:ok
iex> <<fragment1::binary-size(3), fragment2::binary>> = "😕"
iex> StructuredIO.write structured_io,
...>                    fragment1
:ok
iex> StructuredIO.read_across structured_io,
...>                          "<elem>",
...>                          "</elem>"
{:error,
 "UnicodeConversionError: incomplete encoding starting at #{inspect fragment1}"}
iex> StructuredIO.write structured_io,
...>                    fragment2
:ok
iex> StructuredIO.write structured_io,
...>                    "</elem>"
:ok
iex> StructuredIO.read_across structured_io,
...>                          "<elem>",
...>                          "</elem>"
"<elem>😕</elem>"
iex> StructuredIO.read_across structured_io,
...>                          "<elem>",
...>                          "</elem>"
""
Link to this function read_across_ignoring_overlap(structured_io, left, right, timeout \\ 5000) View Source
read_across_ignoring_overlap(GenServer.server(), left(), right(), timeout()) ::
  match() |
  error()

Reads data from the specified structured_io beginning with the specified left and ending with the first occurrence of the specified right, inclusive.

If data does not both begin with left and contain right, the result is an empty binary ("").

Examples

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:binary)
iex> StructuredIO.write structured_io,
...>                    <<0, 0, 0, 1, 2, 3, 0, 0, 0, 4, 5, 6, 255, 255>>
:ok
iex> StructuredIO.read_across_ignoring_overlap structured_io,
...>                                           <<0, 0, 0>>,
...>                                           <<255, 255, 255>>
""
iex> StructuredIO.write structured_io,
...>                    <<255>>
:ok
iex> StructuredIO.read_across_ignoring_overlap structured_io,
...>                                           <<0, 0, 0>>,
...>                                           <<255, 255, 255>>
<<0, 0, 0, 1, 2, 3, 0, 0, 0, 4, 5, 6, 255, 255, 255>>

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:unicode)
iex> StructuredIO.write structured_io,
...>                    "<elem>foo<elem>bar</elem"
:ok
iex> StructuredIO.read_across_ignoring_overlap structured_io,
...>                                           "<elem>",
...>                                           "</elem>"
""
iex> StructuredIO.write structured_io,
...>                    ">"
:ok
iex> StructuredIO.read_across_ignoring_overlap structured_io,
...>                                           "<elem>",
...>                                           "</elem>"
"<elem>foo<elem>bar</elem>"
Link to this function read_between(structured_io, left, right, timeout \\ 5000) View Source
read_between(GenServer.server(), left(), right(), timeout()) ::
  match() |
  error()

Reads data from the specified structured_io beginning with the specified left and ending with the occurrence of the specified right that corresponds to it, exclusive.

If data does not both begin with left and contain a corresponding right, the result is an empty binary ("").

Examples

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:binary)
iex> StructuredIO.write structured_io,
...>                    <<0, 0, 0, 1, 2, 3, 0, 0, 0, 4, 5, 6, 255, 255, 255, 255, 255>>
:ok
iex> StructuredIO.read_between structured_io,
...>                           <<0, 0, 0>>,
...>                           <<255, 255, 255>>
""
iex> StructuredIO.write structured_io,
...>                    <<255>>
:ok
iex> StructuredIO.read_between structured_io,
...>                           <<0, 0, 0>>,
...>                           <<255, 255, 255>>
<<1, 2, 3, 0, 0, 0, 4, 5, 6, 255, 255, 255>>

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:unicode)
iex> StructuredIO.write structured_io,
...>                    "<elem>foo<elem>bar</elem></elem"
:ok
iex> StructuredIO.read_between structured_io,
...>                           "<elem>",
...>                           "</elem>"
""
iex> StructuredIO.write structured_io,
...>                    ">"
:ok
iex> StructuredIO.read_between structured_io,
...>                           "<elem>",
...>                           "</elem>"
"foo<elem>bar</elem>"

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:binary)
iex> StructuredIO.write structured_io,
...>                    "<elem>"
:ok
iex> <<fragment1::binary-size(3), fragment2::binary>> = "😕"
iex> StructuredIO.write structured_io,
...>                    fragment1
:ok
iex> StructuredIO.read_between structured_io,
...>                           "<elem>",
...>                           "</elem>"
""
iex> StructuredIO.write structured_io,
...>                    fragment2
:ok
iex> StructuredIO.write structured_io,
...>                    "</elem>"
:ok
iex> StructuredIO.read_between structured_io,
...>                           "<elem>",
...>                           "</elem>"
"😕"
iex> StructuredIO.read_between structured_io,
...>                           "<elem>",
...>                           "</elem>"
""

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:unicode)
iex> StructuredIO.write structured_io,
...>                    "<elem>"
:ok
iex> <<fragment1::binary-size(3), fragment2::binary>> = "😕"
iex> StructuredIO.write structured_io,
...>                    fragment1
:ok
iex> StructuredIO.read_between structured_io,
...>                           "<elem>",
...>                           "</elem>"
{:error,
 "UnicodeConversionError: incomplete encoding starting at #{inspect fragment1}"}
iex> StructuredIO.write structured_io,
...>                    fragment2
:ok
iex> StructuredIO.write structured_io,
...>                    "</elem>"
:ok
iex> StructuredIO.read_between structured_io,
...>                           "<elem>",
...>                           "</elem>"
"😕"
iex> StructuredIO.read_between structured_io,
...>                           "<elem>",
...>                           "</elem>"
""
Link to this function read_between_ignoring_overlap(structured_io, left, right, timeout \\ 5000) View Source
read_between_ignoring_overlap(GenServer.server(), left(), right(), timeout()) ::
  match() |
  error()

Reads data from the specified structured_io beginning with the specified left and ending with the first occurrence of the specified right, exclusive.

If data does not both begin with left and contain right, the result is an empty binary ("").

Examples

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:binary)
iex> StructuredIO.write structured_io,
...>                    <<0, 0, 0, 1, 2, 3, 0, 0, 0, 4, 5, 6, 255, 255>>
:ok
iex> StructuredIO.read_between_ignoring_overlap structured_io,
...>                                            <<0, 0, 0>>,
...>                                            <<255, 255, 255>>
""
iex> StructuredIO.write structured_io,
...>                    <<255>>
:ok
iex> StructuredIO.read_between_ignoring_overlap structured_io,
...>                                            <<0, 0, 0>>,
...>                                            <<255, 255, 255>>
<<1, 2, 3, 0, 0, 0, 4, 5, 6>>

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:unicode)
iex> StructuredIO.write structured_io,
...>                    "<elem>foo<elem>bar</elem"
:ok
iex> StructuredIO.read_between_ignoring_overlap structured_io,
...>                                            "<elem>",
...>                                            "</elem>"
""
iex> StructuredIO.write structured_io,
...>                    ">"
:ok
iex> StructuredIO.read_between_ignoring_overlap structured_io,
...>                                            "<elem>",
...>                                            "</elem>"
"foo<elem>bar"
Link to this function read_through(structured_io, right, timeout \\ 5000) View Source
read_through(GenServer.server(), right(), timeout()) ::
  match() |
  error()

Reads data from the specified structured_io if and until the specified right is encountered, including right.

If right is not encountered, the result is an empty binary ("").

Examples

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:binary)
iex> StructuredIO.write structured_io,
...>                    <<1, 2, 3, 255, 255>>
:ok
iex> StructuredIO.read_through structured_io,
...>                           <<255, 255, 255>>
""
iex> StructuredIO.write structured_io,
...>                    <<255, 4, 5, 6, 255, 255, 255>>
:ok
iex> StructuredIO.read_through structured_io,
...>                           <<255, 255, 255>>
<<1, 2, 3, 255, 255, 255>>
iex> StructuredIO.read_through structured_io,
...>                           <<255, 255, 255>>
<<4, 5, 6, 255, 255, 255>>
iex> StructuredIO.read_through structured_io,
...>                           <<255, 255, 255>>
""

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:unicode)
iex> StructuredIO.write structured_io,
...>                    "foo<br/"
:ok
iex> StructuredIO.read_through structured_io,
...>                           "<br/>"
""
iex> StructuredIO.write structured_io,
...>                    ">bar<br/>"
:ok
iex> StructuredIO.read_through structured_io,
...>                           "<br/>"
"foo<br/>"
iex> StructuredIO.read_through structured_io,
...>                           "<br/>"
"bar<br/>"
iex> StructuredIO.read_through structured_io,
...>                           "<br/>"
""

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:binary)
iex> <<fragment1::binary-size(3), fragment2::binary>> = "😕"
iex> StructuredIO.write structured_io,
...>                    fragment1
:ok
iex> StructuredIO.read_through structured_io,
...>                           "<br/>"
""
iex> StructuredIO.write structured_io,
...>                    fragment2
:ok
iex> StructuredIO.write structured_io,
...>                    "<br/>"
:ok
iex> StructuredIO.read_through structured_io,
...>                           "<br/>"
"😕<br/>"
iex> StructuredIO.read_through structured_io,
...>                           "<br/>"
""

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:unicode)
iex> <<fragment1::binary-size(3), fragment2::binary>> = "😕"
iex> StructuredIO.write structured_io,
...>                    fragment1
:ok
iex> StructuredIO.read_through structured_io,
...>                           "<br/>"
{:error,
 "UnicodeConversionError: incomplete encoding starting at #{inspect fragment1}"}
iex> StructuredIO.write structured_io,
...>                    fragment2
:ok
iex> StructuredIO.write structured_io,
...>                    "<br/>"
:ok
iex> StructuredIO.read_through structured_io,
...>                           "<br/>"
"😕<br/>"
iex> StructuredIO.read_through structured_io,
...>                           "<br/>"
""
Link to this function read_to(structured_io, right, timeout \\ 5000) View Source
read_to(GenServer.server(), right(), timeout()) :: match() | error()

Reads data from the specified structured_io if and until the specified right is encountered, excluding right.

If right is not encountered, the result is an empty binary ("").

Examples

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:binary)
iex> StructuredIO.write structured_io,
...>                    <<1, 2, 3, 255, 255>>
:ok
iex> StructuredIO.read_to structured_io,
...>                      <<255, 255, 255>>
""
iex> StructuredIO.write structured_io,
...>                    <<255, 4, 5, 6, 255, 255, 255>>
:ok
iex> StructuredIO.read_to structured_io,
...>                      <<255, 255, 255>>
<<1, 2, 3>>
iex> StructuredIO.read_through structured_io,
...>                           <<255, 255, 255>>
<<255, 255, 255>>
iex> StructuredIO.read_to structured_io,
...>                      <<255, 255, 255>>
<<4, 5, 6>>
iex> StructuredIO.read_to structured_io,
...>                      <<255, 255, 255>>
""

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:unicode)
iex> StructuredIO.write structured_io,
...>                    "foo<br/"
:ok
iex> StructuredIO.read_to structured_io,
...>                      "<br/>"
""
iex> StructuredIO.write structured_io,
...>                    ">bar<br/>"
:ok
iex> StructuredIO.read_to structured_io,
...>                      "<br/>"
"foo"
iex> StructuredIO.read_through structured_io,
...>                           "<br/>"
"<br/>"
iex> StructuredIO.read_to structured_io,
...>                      "<br/>"
"bar"
iex> StructuredIO.read_to structured_io,
...>                      "<br/>"
""

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:binary)
iex> <<fragment1::binary-size(3), fragment2::binary>> = "😕"
iex> StructuredIO.write structured_io,
...>                    fragment1
:ok
iex> StructuredIO.read_to structured_io,
...>                      "<br/>"
""
iex> StructuredIO.write structured_io,
...>                    fragment2
:ok
iex> StructuredIO.write structured_io,
...>                    "<br/>"
:ok
iex> StructuredIO.read_to structured_io,
...>                      "<br/>"
"😕"
iex> StructuredIO.read_to structured_io,
...>                      "<br/>"
""

iex> {:ok,
...>  structured_io} = StructuredIO.start_link(:unicode)
iex> <<fragment1::binary-size(3), fragment2::binary>> = "😕"
iex> StructuredIO.write structured_io,
...>                    fragment1
:ok
iex> StructuredIO.read_to structured_io,
...>                      "<br/>"
{:error,
 "UnicodeConversionError: incomplete encoding starting at #{inspect fragment1}"}
iex> StructuredIO.write structured_io,
...>                    fragment2
:ok
iex> StructuredIO.write structured_io,
...>                    "<br/>"
:ok
iex> StructuredIO.read_to structured_io,
...>                      "<br/>"
"😕"
iex> StructuredIO.read_to structured_io,
...>                      "<br/>"
""

Starts a StructuredIO process without links (outside a supervision tree) with the specified mode and options.

Examples

iex> StructuredIO.start :super_pursuit_mode
{:error,
 "invalid mode :super_pursuit_mode"}

See StructuredIO.start_link/2.

Link to this function start_link(mode, options \\ []) View Source
start_link(mode(), GenServer.options()) :: GenServer.on_start()

Starts a StructuredIO process linked to the current process with the specified mode and options.

Examples

iex> StructuredIO.start_link :super_pursuit_mode
{:error,
 "invalid mode :super_pursuit_mode"}

See StructuredIO.mode/1, StructuredIO.read_across/3, StructuredIO.read_between/3, StructuredIO.read_through/2, and StructuredIO.read_to/2 for more examples.

Link to this function stop(structured_io, reason \\ :normal, timeout \\ :infinity) View Source
stop(GenServer.server(), term(), timeout()) :: :ok

Synchronously stops the specified structured_io process.

Link to this function write(structured_io, data) View Source
write(GenServer.server(), iodata() | IO.chardata() | String.Chars.t()) ::
  :ok |
  error()

Asynchronously writes the specified data as a binary to the specified structured_io.

See StructuredIO.read_across/3, StructuredIO.read_between/3, StructuredIO.read_through/2, and StructuredIO.read_to/2 for examples.