Implement prefix contains prefix test.
Also override credo's max line length because who works in 80x25 anymore?
This commit is contained in:
parent
ee7b25e79c
commit
d4ab558f30
4 changed files with 228 additions and 18 deletions
145
.credo.exs
Normal file
145
.credo.exs
Normal file
|
@ -0,0 +1,145 @@
|
|||
# This file contains the configuration for Credo and you are probably reading
|
||||
# this after creating it with `mix credo.gen.config`.
|
||||
#
|
||||
# If you find anything wrong or unclear in this file, please report an
|
||||
# issue on GitHub: https://github.com/rrrene/credo/issues
|
||||
#
|
||||
%{
|
||||
#
|
||||
# You can have as many configs as you like in the `configs:` field.
|
||||
configs: [
|
||||
%{
|
||||
#
|
||||
# Run any exec using `mix credo -C <name>`. If no exec name is given
|
||||
# "default" is used.
|
||||
#
|
||||
name: "default",
|
||||
#
|
||||
# These are the files included in the analysis:
|
||||
files: %{
|
||||
#
|
||||
# You can give explicit globs or simply directories.
|
||||
# In the latter case `**/*.{ex,exs}` will be used.
|
||||
#
|
||||
included: ["lib/", "src/", "web/", "apps/"],
|
||||
excluded: [~r"/_build/", ~r"/deps/"]
|
||||
},
|
||||
#
|
||||
# If you create your own checks, you must specify the source files for
|
||||
# them here, so they can be loaded by Credo before running the analysis.
|
||||
#
|
||||
requires: [],
|
||||
#
|
||||
# If you want to enforce a style guide and need a more traditional linting
|
||||
# experience, you can change `strict` to `true` below:
|
||||
#
|
||||
strict: false,
|
||||
#
|
||||
# If you want to use uncolored output by default, you can change `color`
|
||||
# to `false` below:
|
||||
#
|
||||
color: true,
|
||||
#
|
||||
# You can customize the parameters of any check by adding a second element
|
||||
# to the tuple.
|
||||
#
|
||||
# To disable a check put `false` as second element:
|
||||
#
|
||||
# {Credo.Check.Design.DuplicatedCode, false}
|
||||
#
|
||||
checks: [
|
||||
{Credo.Check.Consistency.ExceptionNames},
|
||||
{Credo.Check.Consistency.LineEndings},
|
||||
{Credo.Check.Consistency.ParameterPatternMatching},
|
||||
{Credo.Check.Consistency.SpaceAroundOperators},
|
||||
{Credo.Check.Consistency.SpaceInParentheses},
|
||||
{Credo.Check.Consistency.TabsOrSpaces},
|
||||
|
||||
# For some checks, like AliasUsage, you can only customize the priority
|
||||
# Priority values are: `low, normal, high, higher`
|
||||
#
|
||||
{Credo.Check.Design.AliasUsage, priority: :low},
|
||||
|
||||
# For others you can set parameters
|
||||
|
||||
# If you don't want the `setup` and `test` macro calls in ExUnit tests
|
||||
# or the `schema` macro in Ecto schemas to trigger DuplicatedCode, just
|
||||
# set the `excluded_macros` parameter to `[:schema, :setup, :test]`.
|
||||
#
|
||||
{Credo.Check.Design.DuplicatedCode, excluded_macros: []},
|
||||
|
||||
# You can also customize the exit_status of each check.
|
||||
# If you don't want TODO comments to cause `mix credo` to fail, just
|
||||
# set this value to 0 (zero).
|
||||
#
|
||||
{Credo.Check.Design.TagTODO, exit_status: 2},
|
||||
{Credo.Check.Design.TagFIXME},
|
||||
|
||||
{Credo.Check.Readability.FunctionNames},
|
||||
{Credo.Check.Readability.LargeNumbers},
|
||||
{Credo.Check.Readability.MaxLineLength, priority: :low, max_length: 120},
|
||||
{Credo.Check.Readability.ModuleAttributeNames},
|
||||
{Credo.Check.Readability.ModuleDoc},
|
||||
{Credo.Check.Readability.ModuleNames},
|
||||
{Credo.Check.Readability.ParenthesesOnZeroArityDefs},
|
||||
{Credo.Check.Readability.ParenthesesInCondition},
|
||||
{Credo.Check.Readability.PredicateFunctionNames},
|
||||
{Credo.Check.Readability.PreferImplicitTry},
|
||||
{Credo.Check.Readability.RedundantBlankLines},
|
||||
{Credo.Check.Readability.StringSigils},
|
||||
{Credo.Check.Readability.TrailingBlankLine},
|
||||
{Credo.Check.Readability.TrailingWhiteSpace},
|
||||
{Credo.Check.Readability.VariableNames},
|
||||
{Credo.Check.Readability.Semicolons},
|
||||
{Credo.Check.Readability.SpaceAfterCommas},
|
||||
|
||||
{Credo.Check.Refactor.DoubleBooleanNegation},
|
||||
{Credo.Check.Refactor.CondStatements},
|
||||
{Credo.Check.Refactor.CyclomaticComplexity},
|
||||
{Credo.Check.Refactor.FunctionArity},
|
||||
{Credo.Check.Refactor.LongQuoteBlocks},
|
||||
{Credo.Check.Refactor.MatchInCondition},
|
||||
{Credo.Check.Refactor.NegatedConditionsInUnless},
|
||||
{Credo.Check.Refactor.NegatedConditionsWithElse},
|
||||
{Credo.Check.Refactor.Nesting},
|
||||
{Credo.Check.Refactor.PipeChainStart},
|
||||
{Credo.Check.Refactor.UnlessWithElse},
|
||||
|
||||
{Credo.Check.Warning.BoolOperationOnSameValues},
|
||||
{Credo.Check.Warning.IExPry},
|
||||
{Credo.Check.Warning.IoInspect},
|
||||
{Credo.Check.Warning.LazyLogging},
|
||||
{Credo.Check.Warning.OperationOnSameValues},
|
||||
{Credo.Check.Warning.OperationWithConstantResult},
|
||||
{Credo.Check.Warning.UnusedEnumOperation},
|
||||
{Credo.Check.Warning.UnusedFileOperation},
|
||||
{Credo.Check.Warning.UnusedKeywordOperation},
|
||||
{Credo.Check.Warning.UnusedListOperation},
|
||||
{Credo.Check.Warning.UnusedPathOperation},
|
||||
{Credo.Check.Warning.UnusedRegexOperation},
|
||||
{Credo.Check.Warning.UnusedStringOperation},
|
||||
{Credo.Check.Warning.UnusedTupleOperation},
|
||||
{Credo.Check.Warning.RaiseInsideRescue},
|
||||
|
||||
# Controversial and experimental checks (opt-in, just remove `, false`)
|
||||
#
|
||||
{Credo.Check.Refactor.ABCSize, false},
|
||||
{Credo.Check.Refactor.AppendSingleItem, false},
|
||||
{Credo.Check.Refactor.VariableRebinding, false},
|
||||
{Credo.Check.Warning.MapGetUnsafePass, false},
|
||||
{Credo.Check.Consistency.MultiAliasImportRequireUse, false},
|
||||
|
||||
# Deprecated checks (these will be deleted after a grace period)
|
||||
#
|
||||
{Credo.Check.Readability.Specs, false},
|
||||
{Credo.Check.Warning.NameRedeclarationByAssignment, false},
|
||||
{Credo.Check.Warning.NameRedeclarationByCase, false},
|
||||
{Credo.Check.Warning.NameRedeclarationByDef, false},
|
||||
{Credo.Check.Warning.NameRedeclarationByFn, false},
|
||||
|
||||
# Custom checks can be created using `mix credo.gen.check`.
|
||||
#
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -35,7 +35,7 @@ defimpl Enumerable, for: IP.Prefix do
|
|||
true
|
||||
"""
|
||||
@spec member?(Prefix.t, Address.t) :: {:ok, boolean} | {:error, module}
|
||||
def member?(prefix, %Address{} = address), do: {:ok, Prefix.contains?(prefix, address)}
|
||||
def member?(prefix, %Address{} = address), do: {:ok, Prefix.contains_address?(prefix, address)}
|
||||
|
||||
@doc """
|
||||
Allows the reduction of `prefix` into a colection of addresses.
|
||||
|
|
|
@ -228,7 +228,7 @@ defmodule IP.Prefix do
|
|||
"""
|
||||
@spec first(t) :: Address.t
|
||||
def first(%Prefix{address: %Address{address: address, version: version}, mask: mask}) do
|
||||
Address.from_integer!(address &&& mask, version)
|
||||
Address.from_integer!(lowest_address(address, mask), version)
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
@ -245,12 +245,11 @@ defmodule IP.Prefix do
|
|||
#IP.Address<2001:db8::ffff:ffff:ffff:ffff DOCUMENTATION>
|
||||
"""
|
||||
def last(%Prefix{address: %Address{address: address, version: 4}, mask: mask}) do
|
||||
Address.from_integer!((address &&& mask) + (~~~mask &&& @ipv4_mask), 4)
|
||||
Address.from_integer!(highest_address(address, mask, 4), 4)
|
||||
end
|
||||
|
||||
def last(%Prefix{address: %Address{address: address, version: 6}, mask: mask}) do
|
||||
address = (address &&& mask) + (~~~mask &&& @ipv6_mask)
|
||||
Address.from_integer!(address, 6)
|
||||
Address.from_integer!(highest_address(address, mask, 6), 6)
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
@ -260,38 +259,84 @@ defmodule IP.Prefix do
|
|||
## Examples
|
||||
|
||||
iex> IP.Prefix.from_string!("192.0.2.0/24")
|
||||
...> |> IP.Prefix.contains?(IP.Address.from_string!("192.0.2.127"))
|
||||
...> |> IP.Prefix.contains_address?(IP.Address.from_string!("192.0.2.127"))
|
||||
true
|
||||
|
||||
iex> IP.Prefix.from_string!("192.0.2.0/24")
|
||||
...> |> IP.Prefix.contains?(IP.Address.from_string!("198.51.100.1"))
|
||||
...> |> IP.Prefix.contains_address?(IP.Address.from_string!("198.51.100.1"))
|
||||
false
|
||||
|
||||
iex> IP.Prefix.from_string!("2001:db8::/64")
|
||||
...> |> IP.Prefix.contains?(IP.Address.from_string!("2001:db8::1"))
|
||||
...> |> IP.Prefix.contains_address?(IP.Address.from_string!("2001:db8::1"))
|
||||
true
|
||||
|
||||
iex> IP.Prefix.from_string!("2001:db8::/64")
|
||||
...> |> IP.Prefix.contains?(IP.Address.from_string!("2001:db8:1::1"))
|
||||
...> |> IP.Prefix.contains_address?(IP.Address.from_string!("2001:db8:1::1"))
|
||||
false
|
||||
"""
|
||||
def contains?(%Prefix{address: %Address{address: addr0, version: 4}, mask: mask} = _prefix,
|
||||
def contains_address?(%Prefix{address: %Address{address: addr0, version: 4}, mask: mask} = _prefix,
|
||||
%Address{address: addr1, version: 4} = _address)
|
||||
when (addr0 &&& mask) <= addr1
|
||||
and ((addr0 &&& mask) + (~~~(mask) &&& @ipv4_mask)) >= addr1
|
||||
when lowest_address(addr0, mask) <= addr1
|
||||
and highest_address(addr0, mask, 4) >= addr1
|
||||
do
|
||||
true
|
||||
end
|
||||
|
||||
def contains?(%Prefix{address: %Address{address: addr0, version: 6}, mask: mask} = _prefix,
|
||||
def contains_address?(%Prefix{address: %Address{address: addr0, version: 6}, mask: mask} = _prefix,
|
||||
%Address{address: addr1, version: 6} = _address)
|
||||
when (addr0 &&& mask) <= addr1
|
||||
and ((addr0 &&& mask) + (~~~(mask) &&& @ipv6_mask)) >= addr1
|
||||
when lowest_address(addr0, mask) <= addr1
|
||||
and highest_address(addr0, mask, 6) >= addr1
|
||||
do
|
||||
true
|
||||
end
|
||||
|
||||
def contains?(_prefix, _address), do: false
|
||||
def contains_address?(_prefix, _address), do: false
|
||||
|
||||
@doc """
|
||||
Returns `true` or `false` depending on whether the supplied `inside` is
|
||||
completely contained by `outside`.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> outside = IP.Prefix.from_string!("192.0.2.0/24")
|
||||
...> inside = IP.Prefix.from_string!("192.0.2.128/25")
|
||||
...> IP.Prefix.contains_prefix?(outside, inside)
|
||||
true
|
||||
|
||||
iex> outside = IP.Prefix.from_string!("192.0.2.128/25")
|
||||
...> inside = IP.Prefix.from_string!("192.0.2.0/24")
|
||||
...> IP.Prefix.contains_prefix?(outside, inside)
|
||||
false
|
||||
|
||||
iex> outside = IP.Prefix.from_string!("2001:db8::/64")
|
||||
...> inside = IP.Prefix.from_string!("2001:db8::/128")
|
||||
...> IP.Prefix.contains_prefix?(outside, inside)
|
||||
true
|
||||
|
||||
iex> outside = IP.Prefix.from_string!("2001:db8::/128")
|
||||
...> inside = IP.Prefix.from_string!("2001:db8::/64")
|
||||
...> IP.Prefix.contains_prefix?(outside, inside)
|
||||
false
|
||||
|
||||
"""
|
||||
@spec contains_prefix?(t, t) :: true | false
|
||||
def contains_prefix?(%Prefix{address: %Address{address: oaddr, version: 4}, mask: omask} = _outside,
|
||||
%Prefix{address: %Address{address: iaddr, version: 4}, mask: imask} = _inside)
|
||||
when lowest_address(oaddr, omask) <= lowest_address(iaddr, imask)
|
||||
and highest_address(oaddr, omask, 4) >= highest_address(iaddr, imask, 4)
|
||||
do
|
||||
true
|
||||
end
|
||||
|
||||
def contains_prefix?(%Prefix{address: %Address{address: oaddr, version: 6}, mask: omask} = _outside,
|
||||
%Prefix{address: %Address{address: iaddr, version: 6}, mask: imask} = _inside)
|
||||
when lowest_address(oaddr, omask) <= lowest_address(iaddr, imask)
|
||||
and highest_address(oaddr, omask, 6) >= highest_address(iaddr, imask, 6)
|
||||
do
|
||||
true
|
||||
end
|
||||
|
||||
def contains_prefix?(_outside, _inside), do: false
|
||||
|
||||
@doc """
|
||||
Generate an EUI-64 host address within the specifed IPv6 `prefix`.
|
||||
|
|
|
@ -26,4 +26,24 @@ defmodule IP.Prefix.Helpers do
|
|||
acc = fun.(n, acc)
|
||||
n_times_reduce(n - 1, acc, fun)
|
||||
end
|
||||
|
||||
defmacro lowest_address(addr, mask) do
|
||||
quote do
|
||||
unquote(addr) &&& unquote(mask)
|
||||
end
|
||||
end
|
||||
|
||||
defmacro highest_address(addr, mask, 4) do
|
||||
quote do
|
||||
(unquote(addr) &&& unquote(mask)) +
|
||||
(~~~unquote(mask) &&& 0xffffffff)
|
||||
end
|
||||
end
|
||||
|
||||
defmacro highest_address(addr, mask, 6) do
|
||||
quote do
|
||||
(unquote(addr) &&& unquote(mask)) +
|
||||
(~~~unquote(mask) &&& 0xffffffffffffffffffffffffffffffff)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue