Bounds v0.1.0 Bounds View Source
Bounds
is a formalization of the {pos, len}
tuple that is used in Erlang to slice binaries.
A Bounds value is similar to a Range
value, with a few differences:
A Bounds value can be zero-length. (A Range value must represent at least one element.)
A Bounds value is always ascending. (A Range value may be descending.)
A Bounds value always has non-negative values. (A Range value may represent negative values.)
Bounds values are normalized as an interval [lower, upper]
for convenience of calculation. All functions
in the Bounds
module expect a %Bounds{}
to have been created by a call to a constructor function (e.g.
new/2
, from_poslen/1
, from_range/1
.) If you construct a Bounds value yourself, the following guard must hold:
%Bounds{lower: lower, upper: upper} when
is_integer(lower) and is_integer(upper) and lower >= 0 and upper >= lower
Enumeration
Like Range
, Bounds
implements Enumerable
; and thus, like Range values, Bounds values can be
understood as a compact representation of an equivalent list value.
Unlike Range
, Bounds
has several decorators which implement Enumerable
differently, to
represent the different, equivalent abstractions that a Bounds value can be understood as.
A Bounds value, passed directly to Enum
functions, will enumerate as a collection of all
integer points in the closed interval [lower, upper]
. If your algorithm wants "point" Bounds
values (values where lower == upper
) to be included as values in the enumeration, then this is the
approach you want.
A common use-case is enumerating all half-closed intervals of some length n
(e.g. [lower, lower + n)
)
which are contained by a given Bounds value. For example, if the Bounds value represents the bounds of a binary,
then you might want the bounds of each byte of the binary: [0, 1)
, [1, 2)
, etc. The functions stepwise/2
,
split_stepwise/2
, and partitioned/3
will help with this.
Link to this section Summary
Functions
Splits a Bounds value into three parts, returned as a map with the following keys
Returns a Bounds.Stepwise
decorator value, which implements Enumerable
.
Link to this section Functions
at_point(point) View Source
clamp(value_bounds, clamp_bounds) View Source
concat(bounds_enum) View Source
concat(bounds_a, bounds_b) View Source
difference(bounds, sub_bounds) View Source
endpoints(bounds) View Source
from_poslen(poslen) View Source
from_range(arg) View Source
new(r) View Source
new(pos, len) View Source
partitioned(bounds, step, offset) View Source
point?(bounds) View Source
points(m) View Source
range?(bounds) View Source
ranges(m) View Source
size(bounds) View Source
slice(bounds, other) View Source
split(bounds, offset) View Source
split_stepwise(bounds, step) View Source
Splits a Bounds value into three parts, returned as a map with the following keys:
:whole
: the bounds of the contiguous set of values whose bounds are both 1. within the original bounds, and 2. divisible bystep_size
. This is equivalent to theunion/2
of thestepwise/2
enumeration of the givenbounds
at the givenstep_size
.:partial_before
: the interval extending from the beginning of the original bounds, to the beginning ofwhole
.:partial_after
: the interval extending from the end ofwhole
, to the end of the original bounds.
Any/all of the values in this map may turn out to be zero-sized "point" Bounds.
stepwise(bounds, step_size \\ 1) View Source
Returns a Bounds.Stepwise
decorator value, which implements Enumerable
.
The values enumerated from a Bounds.Stepwise
decorator are themselves Bounds values,
representing a set of contiguous intervals, each of size step_size
. The enumeration always begins
with the interval [0, step_size)
(if it exists.)
Any bounded interval smaller than step_size
is not considered a part of the enumeration.
This enumeration strategy is useful when you have a sequence of unit-sized chunks (like the bytes
in a binary), in which a representation for one element is encoded as step_size
contiguous chunks.
The enumerated values will then represent the bounds of the representations of all
potentially-valid elements.
Examples
Get the bounds of each single byte of a binary:
iex> Bounds.from_binary("foo") |> Bounds.stepwise(1) |> Enum.to_list()
[%Bounds{lower: 0, upper: 1}, %Bounds{lower: 1, upper: 2}, %Bounds{lower: 2, upper: 3}]
Get the bounds of a sequence of 32-bit values in a binary:
iex> Bounds.from_binary("abcdEFGH") |> Bounds.stepwise(4) |> Enum.to_list()
[%Bounds{lower: 0, upper: 4}, %Bounds{lower: 4, upper: 8}]