Extend serialization API with functions for writing to streams

This commit is contained in:
Marcel Otto 2020-11-04 10:26:30 +01:00
parent 3d28ec9085
commit ff40022f6d
4 changed files with 58 additions and 0 deletions

View file

@ -21,6 +21,17 @@ defmodule RDF.Serialization.Encoder do
"""
@callback encode!(RDF.Data.t(), keyword) :: String.t()
@doc """
Serializes a RDF data structure into a stream.
It should return a stream emitting either strings or iodata of the
serialized RDF data structure. If both forms are supported the form
should be configurable via the `:mode` option.
"""
@callback stream(RDF.Data.t(), keyword) :: Enumerable.t()
@optional_callbacks stream: 2
defmacro __using__(_) do
quote bind_quoted: [], unquote: true do
@behaviour unquote(__MODULE__)
@ -36,6 +47,16 @@ defmodule RDF.Serialization.Encoder do
end
defoverridable unquote(__MODULE__)
@before_compile unquote(__MODULE__)
end
end
defmacro __before_compile__(_env) do
quote do
@stream_support __MODULE__ |> Module.definitions_in() |> Keyword.has_key?(:stream)
@doc false
def stream_support?, do: @stream_support
end
end
end

View file

@ -151,6 +151,16 @@ defmodule RDF.Serialization.Format do
@spec write_string!(RDF.Data.t(), keyword) :: String.t()
def write_string!(data, opts \\ []), do: Writer.write_string!(encoder(), data, opts)
if @encoder.stream_support?() do
@doc """
Serializes a RDF data structure to a stream.
#{@encoder_doc_ref}
"""
@spec write_stream(RDF.Data.t(), keyword) :: Enumerable.t()
def write_stream(data, opts \\ []), do: Writer.write_stream(encoder(), data, opts)
end
@doc """
Serializes a RDF data structure to a file.

View file

@ -243,6 +243,24 @@ defmodule RDF.Serialization do
end
end
@doc """
Serializes a RDF data structure to a stream.
The format must be specified with the `format` option and a format name or the
`media_type` option and the media type of the format.
Please refer to the documentation of the encoder of a RDF serialization format
for format-specific options and what the stream emits.
"""
@spec write_stream(RDF.Data.t(), keyword) :: Enumerable.t()
def write_stream(data, opts) do
with {:ok, format} <- string_format(opts) do
format.write_stream(data, opts)
else
{:error, error} -> raise error
end
end
@doc """
Serializes a RDF data structure to a file.

View file

@ -19,6 +19,15 @@ defmodule RDF.Serialization.Writer do
encoder.encode!(data, opts)
end
@spec write_stream(module, RDF.Data.t(), keyword) :: Enumerable.t()
def write_stream(encoder, data, opts \\ []) do
if encoder.stream_support?() do
encoder.stream(data, opts)
else
raise "#{inspect(encoder)} does not support streaming"
end
end
@spec write_file(module, RDF.Data.t(), Path.t(), keyword) :: :ok | {:error, any}
def write_file(encoder, data, path, opts \\ []) do
with {:ok, encoded_string} <- write_string(encoder, data, opts) do