structured_io v1.1.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
A number of bytes or graphemes in a measured data element
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
Gets the mode of the specified structured_io
Reads data from the specified structured_io
in the specified quantity. In
binary mode, count
is a number of bytes; in Unicode mode, count
is a number
of graphemes
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
Stops the specified structured_io
process
Writes the specified data
to the specified structured_io
Link to this section Types
A number of bytes or graphemes in a measured data element.
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.
Link to this section Functions
collect(GenServer.server()) :: StructuredIO.Collector.t()
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>"
""
enumerate_with(GenServer.server(), :read_through | :read_to, right()) :: StructuredIO.Enumerator.t()
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 />"
""
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
read(GenServer.server(), count(), timeout()) :: match() | error()
Reads data from the specified structured_io
in the specified quantity. In
binary mode, count
is a number of bytes; in Unicode mode, count
is a number
of graphemes.
If the data in the process does not contain at least the expected quantity of
data, the result is an empty binary (""
).
Examples
iex> {:ok,
...> structured_io} = StructuredIO.start_link(:binary)
iex> StructuredIO.write structured_io,
...> <<23, 45>>
:ok
iex> StructuredIO.read structured_io,
...> 3
""
iex> StructuredIO.write structured_io,
...> <<67>>
:ok
iex> StructuredIO.read structured_io,
...> 3
<<23, 45, 67>>
iex> StructuredIO.read structured_io,
...> 3
""
iex> {:ok,
...> structured_io} = StructuredIO.start_link(:unicode)
iex> StructuredIO.write structured_io,
...> "\r\nfo"
:ok
iex> StructuredIO.read structured_io,
...> 4
""
iex> StructuredIO.write structured_io,
...> "o"
:ok
iex> StructuredIO.read structured_io,
...> 4
"\r\nfoo"
iex> StructuredIO.read structured_io,
...> 4
""
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 structured_io,
...> 4
""
iex> StructuredIO.write structured_io,
...> fragment2
:ok
iex> StructuredIO.read structured_io,
...> 4
"😕"
iex> StructuredIO.read structured_io,
...> 4
""
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 structured_io,
...> 1
{:error,
"UnicodeConversionError: incomplete encoding starting at #{inspect fragment1}"}
iex> StructuredIO.write structured_io,
...> fragment2
:ok
iex> StructuredIO.read structured_io,
...> 1
"😕"
iex> StructuredIO.read structured_io,
...> 1
""
See StructuredIO.mode/1
.
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.
If the data in the process 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>"
""
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 the data in the process 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>"
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 the data in the process 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>"
""
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 the data in the process 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"
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/>"
""
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/>"
""
start(mode(), GenServer.options()) :: GenServer.on_start()
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"}
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.
stop(GenServer.server(), term(), timeout()) :: :ok
Stops the specified structured_io
process.
write(GenServer.server(), iodata() | IO.chardata() | String.Chars.t()) :: :ok | error()
Writes the specified data
to the specified structured_io
.
No timeout is available because the operation is performed asynchronously.
See StructuredIO.read_across/3
,
StructuredIO.read_between/3
,
StructuredIO.read_through/2
, and StructuredIO.read_to/2
for examples.