Saucexages v0.2.0 Saucexages.IO.SauceBinary View Source
Functions for working with SAUCE containing and related binaries.
Provides basic building blocks for reading, writing, fixing, and analyzing binaries that may or may not contain SAUCE blocks.
Notes
Because of the way SAUCE works with regard to EOF position + bugs in practice with EOF characters, it may be highly inefficient to use some of these functions with large binaries. As such, several versions of similar functions (ex: split_all vs. split_sauce) exist to allow you to work only with the parts of a binary you need. If you still have issues with large files, prefer to work with the SauceFile
and FileReader
modules instead.
Link to this section Summary
Functions
Returns the contents before any SAUCE and other EOF data
Returns a list of comment block line undecoded comment line binaries, if any
Returns the number of comment lines stored in the SAUCE record as {:ok, line_count}
Extracts the SAUCE comment block from a binary and returns the comment block binary with the comment line count as {:ok, {comments_bin, line_count}}
Checks if a binary has a SAUCE comment block
Extracts the SAUCE comment block from a binary or returns a comment fragment if the binary is a comment fragment
Checks if a binary has a SAUCE comments fragment
Returns the contents before any SAUCE block
Returns the byte size of the contents in the binary, before any potential SAUCE block
Dynamically counts the number of comment lines in a SAUCE binary and return it as {:ok, line_count}
Scans a binary for a comment block and returns it if found
Terminates a binary with an EOF character
Determines if a binary is terminated by an EOF character
Searches for the first occurrence of a SAUCE comment block in a binary and returns the {position, length}
corresponding to the SAUCE comment block
Searches for the first occurrence of a SAUCE comment block fragment in a binary and returns the {position, length}
corresponding to the SAUCE comment block
Searches for the first occurrence of a SAUCE record in a binary and returns the {pos, length}
corresponding to the start of the SAUCE block
Checks if a binary is a SAUCE comment block
Checks if a binary is a SAUCE record
Returns SAUCE comment block if the provided binary is a SAUCE comment block, otherwise an empty binary
Returns SAUCE record binary if the provided binary is a SAUCE record, otherwise an empty binary
Reads a given field_id
from a binary SAUCE record and returns the undecoded result as binary
Reads a given field_id
from a binary SAUCE record or binary containing a SAUCE, and returns the undecoded result as binary
Extracts the SAUCE record and comment block from a binary, and returns {:ok, {sauce_bin, comments_bin}
Checks if a binary has a SAUCE record
Extracts the SAUCE block as a single binary as it appears within a SAUCE binary - a comments block (if any) followed by a SAUCE record
Extracts the SAUCE record from a binary and the number of comment lines present
Extracts the SAUCE record from a binary
Extracts the SAUCE record from a binary and returns {:ok, sauce_bin}
Splits a binary into its component parts with respect to SAUCE
Splits a binary into its components by SAUCE record
Splits a binary, trimming the file contents and returning the SAUCE and SAUCE comment block if each exists as a 2-tuple in the form of {sauce_record, comment_block}
Splits a binary according to a specified number of comment_lines
and returns a 3-tuple, where the first element is the file binary, if any, the second element is the SAUCE binary, if any, and the third element is the comments binary, if any
Checks if a binary most likely has a valid SAUCE using a relaxed set of constraints that avoid a full decode
Checks to see if a binary is a SAUCE comment block
Checks if a binary is a SAUCE record, returning :ok
if true, and {:error, :no_sauce}
if false
Writes a given field_id
and a given encoded binary value
to a binary that already contains a SAUCE record
Link to this section Types
Link to this section Functions
Returns the contents before any SAUCE and other EOF data.
May truncate any other data that might co-exist with a SAUCE block.
Returns a list of comment block line undecoded comment line binaries, if any.
comment_lines(binary()) :: {:ok, non_neg_integer()} | {:error, :no_sauce} | {:error, term()}
Returns the number of comment lines stored in the SAUCE record as {:ok, line_count}
.
This value can serve as a pointer for helping you locate a SAUCE comment block in a binary and can be used for reading the comments a variety of ways, such as via split_with/1
.
Note: This value may or may not match the number of lines stored in the comment block. As such, you should exhibit caution when relying on either. See the reasons for this in count_comment_lines/1
.
comments(binary()) :: {:ok, {comments_binary(), non_neg_integer()}} | {:error, :no_sauce} | {:error, :no_comments} | {:error, term()}
Extracts the SAUCE comment block from a binary and returns the comment block binary with the comment line count as {:ok, {comments_bin, line_count}}
.
The line count corresponds to the number of comment lines that have been read based on the comment_lines
field in the SAUCE record, and may be used for decoding purposes.
If the SAUCE comment block cannot be found, {:error, :no_comments
} is returned.
Checks if a binary has a SAUCE comment block.
comments_fragment(binary()) :: {:ok, comments_binary()}
Extracts the SAUCE comment block from a binary or returns a comment fragment if the binary is a comment fragment.
If a SAUCE record exists after the comment block, it will be trimmed. Because there is no other terminator for a comments fragment other than a SAUCE record, it is possible that additional data may be returned that is not part of comments. You should therefore manually parse the data to see if it is actually comment data or otherwise relevant.
If you want to be sure you have a valid comment block, you should instead use comments/1
which will check for the presence of a SAUCE record as a terminator. Alternatively, you can safely use this function if you have previously split a binary and know that the SAUCE terminator existed previously, for example after calling split_sauce/1
.
Useful for casual introspection of SAUCE files and diagnosing damaged files.
Checks if a binary has a SAUCE comments fragment.
contents(binary(), boolean()) :: {:ok, contents_binary()} | {:error, term()}
Returns the contents before any SAUCE block.
An optional terminate?
flag may be passed which will append an EOF character to the end of the contents if one does not already exist. This is useful in cases such as writing a new SAUCE record where you want to avoid appending extra EOF characters or ensure one is present to ensure SAUCE can be read properly after write. By default, contents is returned as is, and therefore you must opt-in to termination.
Returns the byte size of the contents in the binary, before any potential SAUCE block.
count_comment_lines(binary()) :: {:ok, non_neg_integer()} | {:error, :no_sauce} | {:error, :no_comments} | {:error, term()}
Dynamically counts the number of comment lines in a SAUCE binary and return it as {:ok, line_count}
.
Note that this number may not match the comment_line
field found in a SAUCE record. Major reasons for this include:
- The SAUCE block itself is corrupted.
- The SAUCE record
comment_lines
field was not updated properly by a SAUCE writer. - The SAUCE comment block was not updated properly by a SAUCE writer.
Useful for finding and fixing damaged SAUCE files.
Use comment_lines/1
if you want to read the comment lines stored in the SAUCE record directly.
discover_comments(binary()) :: comments_binary()
Scans a binary for a comment block and returns it if found.
Terminates a binary with an EOF character.
Determines if a binary is terminated by an EOF character.
match_comment_block(binary(), Enum.t()) :: {non_neg_integer(), pos_integer()} | :nomatch
Searches for the first occurrence of a SAUCE comment block in a binary and returns the {position, length}
corresponding to the SAUCE comment block.
If no comment block is found, :nomatch is returned.
Options may be provided according to :binary.match
.
Additionally, the :eof?
boolean option may be specified to search for a match against the end-of-file character (EOF) that is required in a SAUCE file. When searching sub-binaries or damaged files, you may wish to avoid this requirement by specifying [eof?: false]
as an option, while conversely you may wish to set it true to explicitly check for a correct comment block.
The returned {position, length}
will always match that of the comment block itself and does not include the EOF character as part of the position or length.
Note: A comment block cannot exist by definition if no SAUCE record exists. If the binary has no SAUCE, the comments data will be ignored as it is invalid and not guaranteed to be part of a SAUCE comment block. If you wish to manage the presence of an erroneous comment block for fixing a SAUCE, cleaning a file, or other purposes, use match_comments_fragment
which removes this requirement.
match_comments_fragment(binary(), Enum.t()) :: {non_neg_integer(), pos_integer()} | :nomatch
Searches for the first occurrence of a SAUCE comment block fragment in a binary and returns the {position, length}
corresponding to the SAUCE comment block.
If no comment block is found, :nomatch is returned.
Options may be provided according to :binary.match
.
Additionally, the :eof?
boolean option may be specified to search for a match against the end-of-file character (EOF) that is required in a SAUCE file. When searching sub-binaries or damaged files, you may wish to avoid this requirement by specifying [eof?: false]
as an option, while conversely you may wish to set it true to explicitly check for a correct comment block.
The returned {position, length}
will always match that of the comment block itself and does not include the EOF character as part of the position or length.
Note: A comment block cannot exist by definition if no SAUCE record exists. If the binary has no SAUCE, the comments data will still be returned. If you wish to manage the presence of an erroneous comment block for fixing a SAUCE, cleaning a file, or other purposes, use match_comment_block
which adds this requirement.
match_sauce_record(binary(), Enum.t()) :: {non_neg_integer(), pos_integer()} | :nomatch
Searches for the first occurrence of a SAUCE record in a binary and returns the {pos, length}
corresponding to the start of the SAUCE block.
If no comment block is found, :nomatch is returned.
Options may be provided according to :binary.match
.
Additionally, the :eof?
boolean option may be specified to search for a match against the end-of-file character (EOF) that is required in a SAUCE file. This can be used to search for a SAUCE record without comments, a sub-binary, or damaged files. Note that when comments are present, specifying [eof?: true]
will result in never matching a SAUCE record.
If you need to verify that the EOF character is present before SAUCE data, it is suggested that you first call match_comment_block(bin, [eof?: true])
or read the SAUCE comment lines field to get the length and position of the comment block, and check the result to verify the EOF character’s correct position with respect to the SAUCE data.
The returned {position, length}
will always match that of the comment block itself and does not include the EOF character as part of the position or length.
matches_comment_block?(comments_binary()) :: boolean()
Checks if a binary is a SAUCE comment block.
Note: This does not validate a comment block, nor does it scan an entire binary for the presence of a comment block. Instead, it merely matches if the entire binary is a comment block, rather than has a comment block.
If you wish to check if a binary has a comment block, instead use comments?/1
matches_sauce?(sauce_binary()) :: boolean()
Checks if a binary is a SAUCE record.
Note: This does not validate a SAUCE record, nor does it scan an entire binary for the presence of a SAUCE record. Instead, it merely matches if the entire binary is a SAUCE record, rather than has a SAUCE record.
If you wish to check if a binary has a SAUCE record, instead use sauce?/1
maybe_comments(comments_binary()) :: comments_binary() | <<_::0>>
Returns SAUCE comment block if the provided binary is a SAUCE comment block, otherwise an empty binary.
maybe_sauce_record(sauce_binary()) :: sauce_binary() | <<_::0>>
Returns SAUCE record binary if the provided binary is a SAUCE record, otherwise an empty binary.
read_field!(sauce_binary(), Saucexages.Sauce.field_id()) :: binary() | :no_sauce
Reads a given field_id
from a binary SAUCE record and returns the undecoded result as binary.
Throws if the given binary is not or does not contain a SAUCE record.
read_field(sauce_binary(), Saucexages.Sauce.field_id()) :: {:ok, binary()} | {:error, :no_sauce} | {:error, term()}
Reads a given field_id
from a binary SAUCE record or binary containing a SAUCE, and returns the undecoded result as binary.
If the binary does not have a SAUCE record, :no_sauce
is returned.
Returns {:ok, value}
if the value exists where the value will be raw binary. Returns {:error, reason}
if there is a problem reading the field. If the binary has no SAUCE record to read, {:error, :no_sauce}
is returned.
sauce(binary()) :: {:ok, {sauce_binary(), comments_binary()}} | {:error, :no_sauce} | {:error, term()}
Extracts the SAUCE record and comment block from a binary, and returns {:ok, {sauce_bin, comments_bin}
.
If no SAUCE is found, {:error, :no_sauce}
will be returned.
Checks if a binary has a SAUCE record.
sauce_block(binary()) :: {:ok, sauce_block_binary()} | {:error, :no_sauce} | {:error, term()}
Extracts the SAUCE block as a single binary as it appears within a SAUCE binary - a comments block (if any) followed by a SAUCE record.
If no SAUCE is found, {:error, :no_sauce}
will be returned.
sauce_handle(binary()) :: {:ok, {sauce_binary(), non_neg_integer()}} | {:error, :no_sauce} | {:error, term()}
Extracts the SAUCE record from a binary and the number of comment lines present.
The returned comment lines can be used to properly fetch the comments block later from the same binary such as via split_with/1
.
Extracts the SAUCE record from a binary.
If the SAUCE record cannot be found, an empty binary is returned.
sauce_record(binary()) :: {:ok, sauce_binary()} | {:error, :no_sauce} | {:error, term()}
Extracts the SAUCE record from a binary and returns {:ok, sauce_bin}
.
If the SAUCE record cannot be found, {:error, :no_sauce
} is returned.
split_all(binary()) :: {contents_binary(), sauce_binary(), comments_binary()}
Splits a binary into its component parts with respect to SAUCE.
A 3-tuple is returned in the form {contents_bin, sauce_bin, comments_bin}
that consists of the file contents, SAUCE record, if any, and comments, if any.
split_record(binary()) :: {contents_binary(), sauce_binary()}
Splits a binary into its components by SAUCE record.
Returns a 2-tuple where the first element is the remaining file binary, if any, and the second element is the SAUCE record binary, if any.
Note: The first element may or may not contain SAUCE comments. If you wish to extract all possible components of a file that may have a SAUCE, use split_all/1
instead. If you wish to obtain the file contents only use contents/1
instead.
split_sauce(binary()) :: {sauce_binary(), comments_binary()}
Splits a binary, trimming the file contents and returning the SAUCE and SAUCE comment block if each exists as a 2-tuple in the form of {sauce_record, comment_block}
.
Any element of the tuple that does not exist will be returned as an empty binary.
split_with(binary(), non_neg_integer()) :: {contents_binary(), sauce_binary(), comments_binary()}
Splits a binary according to a specified number of comment_lines
and returns a 3-tuple, where the first element is the file binary, if any, the second element is the SAUCE binary, if any, and the third element is the comments binary, if any.
If the comment_lines
do not match a valid comment block, no comments will be returned.
Checks if a binary most likely has a valid SAUCE using a relaxed set of constraints that avoid a full decode.
Useful for deciding whether or not a SAUCE is damaged or worth further actions.
verify_comment_block(comments_binary()) :: :ok | {:error, :no_sauce}
Checks to see if a binary is a SAUCE comment block.
verify_sauce_record(sauce_binary()) :: :ok | {:error, :no_sauce}
Checks if a binary is a SAUCE record, returning :ok
if true, and {:error, :no_sauce}
if false.
write_field(binary(), Saucexages.Sauce.field_id(), binary()) :: {:ok, sauce_binary()} | {:error, :no_sauce} | {:error, term()}
Writes a given field_id
and a given encoded binary value
to a binary that already contains a SAUCE record.
Writing using this method should be considered “unsafe” unless the values are validated and encoded in advance.
The field_id
must be a valid SAUCE field and the value must be binary of the valid corresponding size according to the SAUCE spec.
Can be used for building in-place updates of a SAUCE along with a proper field encoder.