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 type comments_binary() View Source
comments_binary() :: binary()
Link to this type contents_binary() View Source
contents_binary() :: binary()
Link to this type sauce_binary() View Source
sauce_binary() :: binary()
Link to this type sauce_block_binary() View Source
sauce_block_binary() :: binary()

Link to this section Functions

Link to this function clean_contents(bin) View Source
clean_contents(binary()) :: binary()

Returns the contents before any SAUCE and other EOF data.

May truncate any other data that might co-exist with a SAUCE block.

Link to this function comment_block_lines(bin) View Source
comment_block_lines(binary()) ::
  {:ok, [binary()]}
  | {:error, :no_sauce}
  | {:error, :no_comments}
  | {:error, term()}

Returns a list of comment block line undecoded comment line binaries, if any.

Link to this function comment_lines(bin) View Source
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.

Link to this function comments(bin) View Source
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.

Link to this function comments?(bin) View Source
comments?(binary()) :: boolean()

Checks if a binary has a SAUCE comment block.

Link to this function comments_fragment(bin) View Source
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.

Link to this function comments_fragment?(bin) View Source
comments_fragment?(binary()) :: boolean()

Checks if a binary has a SAUCE comments fragment.

Link to this function contents(bin, terminate? \\ false) View Source
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.

Link to this function contents_size(bin) View Source
contents_size(binary()) :: non_neg_integer()

Returns the byte size of the contents in the binary, before any potential SAUCE block.

Link to this function count_comment_lines(bin) View Source
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.

Link to this function discover_comments(bin) View Source
discover_comments(binary()) :: comments_binary()

Scans a binary for a comment block and returns it if found.

Link to this function eof_terminate(bin) View Source
eof_terminate(binary()) :: binary()

Terminates a binary with an EOF character.

Link to this function eof_terminated?(bin) View Source
eof_terminated?(binary()) :: boolean()

Determines if a binary is terminated by an EOF character.

Link to this macro is_comment_lines(bin) View Source (macro)
Link to this function match_comment_block(bin, opts \\ [eof?: false]) View Source
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.

Link to this function match_comments_fragment(bin, opts \\ [eof?: false]) View Source
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.

Link to this function match_sauce_record(bin, opts \\ [eof?: false]) View Source
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.

Link to this function matches_comment_block?(arg1) View Source
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

Link to this function matches_sauce?(sauce_bin) View Source
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

Link to this function maybe_comments(comments_bin) View Source
maybe_comments(comments_binary()) :: comments_binary() | <<_::0>>

Returns SAUCE comment block if the provided binary is a SAUCE comment block, otherwise an empty binary.

Link to this function maybe_sauce_record(sauce_bin) View Source
maybe_sauce_record(sauce_binary()) :: sauce_binary() | <<_::0>>

Returns SAUCE record binary if the provided binary is a SAUCE record, otherwise an empty binary.

Link to this function read_field!(bin, field_id) View Source
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.

Link to this function read_field(bin, field_id) View Source
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.

Link to this function sauce(bin) View Source
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.

Link to this function sauce_block(bin) View Source
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.

Link to this function sauce_handle(bin) View Source
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.

Link to this function sauce_record!(bin) View Source
sauce_record!(binary()) :: sauce_binary()

Extracts the SAUCE record from a binary.

If the SAUCE record cannot be found, an empty binary is returned.

Link to this function sauce_record(bin) View Source
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.

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.

Link to this function split_record(bin) View Source
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.

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.

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.

Link to this function valid_sauce?(bin) View Source
valid_sauce?(binary()) :: boolean()

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.

Link to this function verify_comment_block(arg1) View Source
verify_comment_block(comments_binary()) :: :ok | {:error, :no_sauce}

Checks to see if a binary is a SAUCE comment block.

Link to this function verify_sauce_record(arg1) View Source
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.

Link to this function write_field(bin, field_id, value) View Source
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.