resx v0.1.0 Resx.Resource
The resource representation.
Link to this section Summary
Functions
Check if two resources or resource references point to the same resource
Retrieve the attribute for a resource or resource reference
Retrieve the attribute keys for a resource or resource reference
Retrieve the attributes for a resource or resource reference
Compare two resources
Discard the resource
Check whether a resource or resource reference exists
Finalise all pending operations on the resource
Finalise all pending operations on the resource
Compute a hash of the resource content using the default hashing function
Compute a hash of the resource content
Check what kind of reference this resource or resource reference is
Retrieve the newest of the two alike resources
Retrieve the oldest of the two alike resources
Open a resource from a pre-existing resource or a resource reference
Open a resource from a pre-existing resource or a resource reference
Get the source of the current resource or resource reference
Store the resource
Store the resource
Stream a resource from a pre-existing resource or a resource reference
Stream a resource from a pre-existing resource or a resource reference
Transform the resource
Transform the resource
Retrieve the URI for a resource or resource reference
Link to this section Types
compare_options() :: [ order: compare_order(), unsure: compare_result(), content: boolean() ]
content() :: Resx.Resource.Content.t() | Resx.Resource.Content.Stream.t()
hasher() :: {Resx.Resource.Reference.Integrity.algo(), Callback.callback(binary(), any())}
streamable_hasher() :: {Resx.Resource.Reference.Integrity.algo(), initializer :: Callback.callback(Resx.Resource.Reference.Integrity.algo(), hash_state()), updater :: Callback.callback(hash_state(), binary(), hash_state()), finaliser :: Callback.callback(hash_state(), any())}
t(content) :: %Resx.Resource{ content: content, meta: keyword(), reference: Resx.Resource.Reference.t() }
Link to this section Functions
Check if two resources or resource references point to the same resource.
attribute(t() | Resx.ref(), attribute_key()) :: {:ok, any()} | Resx.error(Resx.resource_error() | Resx.reference_error() | :unknown_key)
Retrieve the attribute for a resource or resource reference.
attribute_keys(t() | Resx.ref()) :: {:ok, [attribute_key()]} | Resx.error(Resx.resource_error() | Resx.reference_error())
Retrieve the attribute keys for a resource or resource reference.
attributes(t() | Resx.ref()) :: {:ok, %{optional(attribute_key()) => any()}} | Resx.error(Resx.resource_error() | Resx.reference_error())
Retrieve the attributes for a resource or resource reference.
compare(t(), t(), compare_options()) :: compare_result()
Compare two resources.
The result of the comparison will be one of the following:
nil
- The two resources are not alike. And therefore not equal.:eq
- The two resources are equal. This will either be integrity equality or if the:content
option is set totrue
then the content's must also be equal.:lt
or:gt
- The first resource is older or newer than the second. This is based on the integrity timestamps in the order specified in the:order
option. A:first
order will iterate through the sources from the original to the current, while:last
order will iterate from current to original. The first one with a differing timestamp will be used. Note that this does not tell you the equality of the two resources (to do that checkResx.Resource.Reference.Integrity.compare/2
or manually compare).:ne
- The two resources are not equal. They have equal timestamps for all sources, but one of the sources does not have an equal checksum or if the:content
option was set totrue
, then also if the content's are not equal.:na
- The two resources cannot be determined. The timestamps are all equal for all sources, but there were no checksums to compare against for the final iteration (see:order
). If the:content
option is set to true, then the final result will be determined by the content comparison, because of this:na
will no longer be a possible result (it will instead be either:eq
or:ne
). The:unsure
option can be to change the result term, e.g. if uncertain comparisons should just be considered not equal, then[unsure: :ne]
could be passed as an option.
The following options may be passed to this function:
:order
- The source order in which the comparisons should occur. An order of:first
will iterate from the original source to the current, while:last
will iterate from the current source to the original. By default this is:first
.:unsure
- Override the result returned when the comparison result is ambiguous. By default this is set to:na
.:content
- Expects a boolean indicating whether the content data should be compared as well or not. By default this is set tofalse
.
discard(t() | Resx.ref(), keyword()) :: :ok | Resx.error(Resx.resource_error() | Resx.reference_error())
Discard the resource.
Only resources or resource references that implement the Resx.Storer
behaviour should be passed to this.
exists?(t() | Resx.ref()) :: {:ok, boolean()} | Resx.error(Resx.reference_error())
Check whether a resource or resource reference exists.
finalise!(t() | Resx.ref(), content: boolean(), hash: boolean() | Resx.Resource.Reference.Integrity.algo() | hasher() | streamable_hasher() ) :: t() | no_return()
Finalise all pending operations on the resource.
For more details see Resx.Resource.finalise/2
.
Raises any error exceptions.
finalise(t() | Resx.ref(), content: boolean(), hash: boolean() | Resx.Resource.Reference.Integrity.algo() | hasher() | streamable_hasher() ) :: {:ok, t()} | Resx.error(Resx.resource_error() | Resx.reference_error())
Finalise all pending operations on the resource.
The result is a resource with the requested operations applied to it.
Set the :content
option to indicate whether content should be included in the final resource (e.g. if it is a stream, its result should be stored instead). By default it is.
Set the :hash
option to indicate whether the content hash should be included in the final resource, and which hashing algorithm should be used. By default it is included and is the same as calling Resx.Resource.hash/1
.
hash(t() | content()) :: Resx.Resource.Reference.Integrity.checksum()
Compute a hash of the resource content using the default hashing function.
The default hashing function can be configured by giving a :hash
option in your config.
config :resx,
hash: { :crc32, { :erlang, :crc32, 1 } }
See hash/2
for more information.
hash( t() | content(), Resx.Resource.Reference.Integrity.algo() | hasher() | streamable_hasher() ) :: Resx.Resource.Reference.Integrity.checksum()
Compute a hash of the resource content.
Meta information and resource references are not included in the hash.
Hashing algorithms can take the form of either an atom that is a valid option to :crypto.hash/2
, or a tuple of type hasher
or streamable_hasher
to provide a custom hashing function. Valid function formats are any callback variant, see Callback
for more information.
Note: If the resource content is streamable and a hasher
is provided for the algo, then the entire content will be decomposed first. If the algo is a streamable_hasher
then no decomposition will take place.
The inputs to the initialiser function of a streamable_hasher
are optional. The rest are all required.
If the requested hash is the same as the checksum found in the resource, then that checksum will be returned without rehashing the resource content.
iex> Resx.Resource.hash(%Resx.Resource.Content{ type: ["text/plain"], data: "Hello" }, { :crc32, { :erlang, :crc32, 1 } })
{ :crc32, 4157704578 }
iex> Resx.Resource.hash(%Resx.Resource.Content{ type: ["text/plain"], data: "Hello" }, { :crc32, { :erlang, :crc32, [] } })
{ :crc32, 4157704578 }
iex> Resx.Resource.hash(%Resx.Resource.Content{ type: ["text/plain"], data: "Hello" }, { :md5, { :crypto, :hash, [:md5] } })
{ :md5, <<139, 26, 153, 83, 196, 97, 18, 150, 168, 39, 171, 248, 196, 120, 4, 215>> }
iex> Resx.Resource.hash(%Resx.Resource.Content.Stream{ type: ["text/plain"], data: ["He", "l", "lo"] }, { :md5, { :crypto, :hash, [:md5] } })
{ :md5, <<139, 26, 153, 83, 196, 97, 18, 150, 168, 39, 171, 248, 196, 120, 4, 215>> }
iex> Resx.Resource.hash(%Resx.Resource.Content{ type: ["text/plain"], data: "Hello" }, { :md5, { :crypto, :hash_init, 1 }, { :crypto, :hash_update, 2 }, { :crypto, :hash_final, 1 } })
{ :md5, <<139, 26, 153, 83, 196, 97, 18, 150, 168, 39, 171, 248, 196, 120, 4, 215>> }
iex> Resx.Resource.hash(%Resx.Resource.Content.Stream{ type: ["text/plain"], data: ["He", "l", "lo"] }, { :md5, { :crypto, :hash_init, 1 }, { :crypto, :hash_update, 2 }, { :crypto, :hash_final, 1 } })
{ :md5, <<139, 26, 153, 83, 196, 97, 18, 150, 168, 39, 171, 248, 196, 120, 4, 215>> }
iex> Resx.Resource.hash(%Resx.Resource.Content{ type: ["text/plain"], data: "Hello" }, :md5)
{ :md5, <<139, 26, 153, 83, 196, 97, 18, 150, 168, 39, 171, 248, 196, 120, 4, 215>> }
iex> Resx.Resource.hash(%Resx.Resource.Content.Stream{ type: ["text/plain"], data: ["He", "l", "lo"] }, :md5)
{ :md5, <<139, 26, 153, 83, 196, 97, 18, 150, 168, 39, 171, 248, 196, 120, 4, 215>> }
iex> Resx.Resource.hash(%Resx.Resource.Content{ type: ["text/plain"], data: "Hello" }, { :hmac_md5_5, { :crypto, :hmac, [:md5, "secret", 5], 2 } })
{ :hmac_md5_5, <<243, 134, 128, 59, 99>> }
iex> Resx.Resource.hash(%Resx.Resource.Content.Stream{ type: ["text/plain"], data: ["He", "l", "lo"] }, { :hmac_md5_5, { :crypto, :hmac, [:md5, "secret", 5], 2 } })
{ :hmac_md5_5, <<243, 134, 128, 59, 99>> }
iex> Resx.Resource.hash(%Resx.Resource.Content{ type: ["text/plain"], data: "Hello" }, { :hmac_md5_5, { :crypto, :hmac_init, [:md5, "secret"], nil }, { :crypto, :hmac_update, 2 }, { :crypto, :hmac_final_n, [5], 0 } })
{ :hmac_md5_5, <<243, 134, 128, 59, 99>> }
iex> Resx.Resource.hash(%Resx.Resource.Content.Stream{ type: ["text/plain"], data: ["He", "l", "lo"] }, { :hmac_md5_5, { :crypto, :hmac_init, [:md5, "secret"], nil }, { :crypto, :hmac_update, 2 }, { :crypto, :hmac_final_n, [5], 0 } })
{ :hmac_md5_5, <<243, 134, 128, 59, 99>> }
iex> Resx.Resource.hash(%Resx.Resource.Content{ type: ["text/plain"], data: "Hello" }, { :base64, &Base.encode64/1 })
{ :base64, "SGVsbG8=" }
iex> Resx.Resource.hash(%Resx.Resource{ reference: %Resx.Resource.Reference{ integrity: %Resx.Resource.Reference.Integrity{ timestamp: DateTime.utc_now }, adapter: nil, repository: nil }, content: %Resx.Resource.Content{ type: ["text/plain"], data: "Hello" } }, :md5)
{ :md5, <<139, 26, 153, 83, 196, 97, 18, 150, 168, 39, 171, 248, 196, 120, 4, 215>> }
iex> Resx.Resource.hash(%Resx.Resource{ reference: %Resx.Resource.Reference{ integrity: %Resx.Resource.Reference.Integrity{ checksum: { :foo, 1 }, timestamp: DateTime.utc_now }, adapter: nil, repository: nil }, content: %Resx.Resource.Content{ type: ["text/plain"], data: "Hello" } }, :foo)
{ :foo, 1 }
iex> Resx.Resource.hash(%Resx.Resource{ reference: %Resx.Resource.Reference{ integrity: %Resx.Resource.Reference.Integrity{ checksum: { :foo, 1 }, timestamp: DateTime.utc_now }, adapter: nil, repository: nil }, content: %Resx.Resource.Content{ type: ["text/plain"], data: "Hello" } }, :md5)
{ :md5, <<139, 26, 153, 83, 196, 97, 18, 150, 168, 39, 171, 248, 196, 120, 4, 215>> }
Check what kind of reference this resource or resource reference is.
iex> Resx.Resource.open!("data:,foo") |> Resx.Resource.kind?(Resx.Producer)
true
iex> Resx.Resource.kind?("data:,foo", Resx.Producer)
true
iex> Resx.Resource.kind?("data:,foo", Resx.Producers.Data)
true
iex> Resx.Resource.kind?("data:,foo", Resx.Storer)
false
iex> Resx.Resource.kind?("data:,foo", Resx.Transformer)
false
Retrieve the newest of the two alike resources.
If this cannot be determined, it will return the value in the :default
option.
Comparison options can be passed to control how the two resources are compared with each other. For more details on this behaviour see Resx.Resource.compare/3
.
iex> old = Resx.Resource.open!("data:,hello")
...> new = Resx.Resource.open!(old)
...> new == Resx.Resource.newest(old, new)
true
iex> old = Resx.Resource.open!("data:,hello")
...> new = Resx.Resource.open!(old)
...> new == Resx.Resource.newest(new, old)
true
iex> old = Resx.Resource.open!("data:,foo")
...> new = Resx.Resource.open!("data:,bar")
...> Resx.Resource.newest(new, old)
nil
Retrieve the oldest of the two alike resources.
If this cannot be determined, it will return the value in the :default
option.
Comparison options can be passed to control how the two resources are compared with each other. For more details on this behaviour see Resx.Resource.compare/3
.
iex> old = Resx.Resource.open!("data:,hello")
...> new = Resx.Resource.open!(old)
...> old == Resx.Resource.oldest(old, new)
true
iex> old = Resx.Resource.open!("data:,hello")
...> new = Resx.Resource.open!(old)
...> old == Resx.Resource.oldest(new, old)
true
iex> old = Resx.Resource.open!("data:,foo")
...> new = Resx.Resource.open!("data:,bar")
...> Resx.Resource.oldest(new, old)
nil
open!(t() | Resx.ref(), keyword()) :: Resx.Resource.t(Resx.Resource.Content.t()) | no_return()
Open a resource from a pre-existing resource or a resource reference.
Raises a Resx.Resource.OpenError
if the resource could not be opened.
For more details see Resx.Resource.open/2
.
open(t() | Resx.ref(), keyword()) :: {:ok, Resx.Resource.t(Resx.Resource.Content.t())} | Resx.error(Resx.resource_error() | Resx.reference_error())
Open a resource from a pre-existing resource or a resource reference.
source(t() | Resx.ref()) :: {:ok, Resx.ref() | nil} | Resx.error(Resx.reference_error())
Get the source of the current resource or resource reference.
It will return { :ok, nil }
if there is no source.
Store the resource.
If a resource reference is given, a stream will be opened to that resource.
Raises a Resx.Storer.StoreError
if the resource cannot be saved, or a Resx.Resource.OpenError
if the resource could not be opened.
For more details see Resx.Storer.save!/2
.
store(t() | Resx.ref(), module(), keyword()) :: {:ok, t()} | Resx.error(Resx.resource_error() | Resx.reference_error())
Store the resource.
If a resource reference is given, a stream will be opened to that resource.
For more details see Resx.Storer.save/2
.
stream!(t() | Resx.ref(), keyword()) :: Resx.Resource.t(Resx.Resource.Content.Stream.t()) | no_return()
Stream a resource from a pre-existing resource or a resource reference.
Raises a Resx.Resource.OpenError
if the resource could not be streamed.
For more details see Resx.Resource.stream/2
.
stream(t() | Resx.ref(), keyword()) :: {:ok, Resx.Resource.t(Resx.Resource.Content.Stream.t())} | Resx.error(Resx.resource_error() | Resx.reference_error())
Stream a resource from a pre-existing resource or a resource reference.
Transform the resource.
If a resource reference is given, a stream will be opened to that resource.
Raises a Resx.Transformer.TransformError
if the transformation cannot be applied, or a Resx.Resource.OpenError
if the resource could not be opened.
For more details see Resx.Transformer.apply!/2
.
transform(t() | Resx.ref(), module(), keyword()) :: {:ok, t()} | Resx.error(Resx.resource_error() | Resx.reference_error())
Transform the resource.
If a resource reference is given, a stream will be opened to that resource.
For more details see Resx.Transformer.apply/2
.
uri(t() | Resx.Resource.Reference.t()) :: {:ok, Resx.uri()} | Resx.error(Resx.resource_error() | Resx.reference_error())
Retrieve the URI for a resource or resource reference.