Compare commits

...
17 Commits
Author SHA1 Message Date
José Valim 737ac62926 Release v1.2.3 2016-02-21 22:28:30 +01:00
José Valim 9dcc0e140b Support canonical URLs
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2016-02-21 21:42:01 +01:00
José Valim e4e5481ca1 Update CHANGELOG 2016-02-21 17:57:10 +01:00
José Valim c3df6806b3 Simplify padding rules
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2016-02-21 17:56:14 +01:00
Paulo Almeida 6dc523074d Add option to omit / ignore padding
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2016-02-21 17:56:08 +01:00
Daniel Perez 5746cbf1e3 Add doc about ignore: :whitespace to Base.decode64.
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2016-02-21 17:56:05 +01:00
Artur Cygan 51966e92a7 Update base.ex
Clean up doc

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2016-02-21 17:56:01 +01:00
Daniel Perez 498057c51b Add option to ignore whitespace to base64 decoding. Close #4186.
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2016-02-21 17:55:02 +01:00
José Valim b3c26a8633 Improve helpers docs 2016-02-17 19:18:10 +01:00
José Valim 5e218e77bf Update CHANGELOG 2016-02-17 00:39:19 +01:00
José Valim 56fbf2a399 Add Mix.Project.deps_paths
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2016-02-17 00:34:59 +01:00
José Valim c3582f9617 Reject non fullfilled optional dependencies later on
Imagine this dependency tree:

    * parent
      * child
        * ecto
        * postgrex
      * ja_serializer
        * ecto

where postgrex is an optional dependency of Ecto.

Because optional dependencies were rejected later on,
ecto would have its postgrex dependency stripped and
later failed to top-sort. This commit changes it to
so optional dependencies are rejected only later on.

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2016-02-17 00:34:52 +01:00
José Valim bd83a45215 Fix typespecs table
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2016-02-16 19:44:05 +01:00
José Valim 52dc944cfb Do not allow negative line numbers without generated annotation 2016-02-15 11:47:46 +01:00
José Valim 3d27c749e1 Remove outdated debug_info test 2016-02-01 09:45:23 +01:00
José Valim 75d679cdc8 Merge pull request #4247 from stephenmoloney/rstrip-bug
String.replace_trailing bug fix.
2016-02-01 09:22:05 +01:00
José Valim 2c9f28ecc3 Remove debug_info from unicode 2016-02-01 09:21:38 +01:00
15 changed files with 620 additions and 163 deletions
+15 -1
View File
@@ -85,7 +85,21 @@ ask Mix to use Rebar 3 to compile it by passing the `manager: :rebar3` option.
Once configured, Mix will prompt you to install Rebar 3 if it is not yet
available.
## v1.2.2
## v1.2.3 (2016-02-21)
### 1. Enhancements
* [Base] Add `:ignore` and `:padding` option to encoding/decoding functions
* [Mix] Add `Mix.Projects.deps_paths` that returns the dependencies path as a map
### 2. Bug fixes
* [ExUnit] Do not provide negative line numbers without generated annotation (for compatibility with Erlang 19)
* [Mix] Reject non fullfilled optional dependencies later on in the convergence resolution for proper dependency sorting
* [String] Fix incomplete data trimming on both `String.replace_trailing` and `String.rstrip`
* [String] Attach debug_info back into Unicode modules for Dialyzer support
## v1.2.2 (2016-01-31)
### 1. Enhancements
+2 -1
View File
@@ -1,6 +1,7 @@
REBAR ?= "$(CURDIR)/rebar"
PREFIX ?= /usr/local
DOCS := v1.2
CANONICAL := stable
ELIXIRC := bin/elixirc --verbose --ignore-module-conflict
ERLC := erlc -I lib/elixir/include
ERL := erl -I lib/elixir/include -noshell -pa lib/elixir/ebin
@@ -128,7 +129,7 @@ clean_exbeam:
LOGO_PATH = $(shell test -f ../docs/logo.png && echo "--logo ../docs/logo.png")
SOURCE_REF = $(shell head="$$(git rev-parse HEAD)" tag="$$(git tag --points-at $$head | tail -1)" ; echo "$${tag:-$$head}\c")
COMPILE_DOCS = bin/elixir ../ex_doc/bin/ex_doc "$(1)" "$(VERSION)" "lib/$(2)/ebin" -m "$(3)" -u "https://github.com/elixir-lang/elixir" --source-ref "$(call SOURCE_REF)" $(call LOGO_PATH) -o doc/$(2) -p http://elixir-lang.org/docs.html $(4)
COMPILE_DOCS = bin/elixir ../ex_doc/bin/ex_doc "$(1)" "$(VERSION)" "lib/$(2)/ebin" -m "$(3)" -u "https://github.com/elixir-lang/elixir" --source-ref "v$(VERSION)" $(call LOGO_PATH) -o doc/$(2) -a http://elixir-lang.org/docs/$(CANONICAL)/$(2)/ -p http://elixir-lang.org/docs.html $(4)
docs: compile ../ex_doc/bin/ex_doc docs_elixir docs_eex docs_mix docs_iex docs_ex_unit docs_logger
+1 -1
View File
@@ -1 +1 @@
1.2.2
1.2.3
+244 -127
View File
@@ -138,6 +138,15 @@ defmodule Base do
defp from_mixed(char),
do: char
defp maybe_pad(subject, false, _, _),
do: subject
defp maybe_pad(subject, _, group_size, pad) do
case rem(byte_size(subject), group_size) do
0 -> subject
x -> subject <> String.duplicate(pad, group_size - x)
end
end
@doc """
Encodes a binary string into a base 16 encoded string.
@@ -225,29 +234,56 @@ defmodule Base do
@doc """
Encodes a binary string into a base 64 encoded string.
Accepts `padding: false` option which will omit padding from
the output string.
## Examples
iex> Base.encode64("foobar")
"Zm9vYmFy"
iex> Base.encode64("foob")
"Zm9vYg=="
iex> Base.encode64("foob", padding: false)
"Zm9vYg"
"""
@spec encode64(binary) :: binary
def encode64(data) when is_binary(data) do
do_encode64(data)
@spec encode64(binary, Keyword.t) :: binary
def encode64(data, opts \\ []) when is_binary(data) do
pad_flag = Keyword.get(opts, :padding, true)
do_encode64(data, pad_flag)
end
@doc """
Decodes a base 64 encoded string into a binary string.
Accepts `ignore: :whitespace` option which will ignore all the
whitespace characters in the input string.
Accepts `padding: false` option which will ignore padding from
the input string.
## Examples
iex> Base.decode64("Zm9vYmFy")
{:ok, "foobar"}
iex> Base.decode64("Zm9vYmFy\\n", ignore: :whitespace)
{:ok, "foobar"}
iex> Base.decode64("Zm9vYg==")
{:ok, "foob"}
iex> Base.decode64("Zm9vYg", padding: false)
{:ok, "foob"}
"""
@spec decode64(binary) :: {:ok, binary} | :error
def decode64(string) when is_binary(string) do
{:ok, decode64!(string)}
@spec decode64(binary, Keyword.t) :: {:ok, binary} | :error
def decode64(string, opts \\ []) when is_binary(string) do
{:ok, decode64!(string, opts)}
rescue
ArgumentError -> :error
end
@@ -255,7 +291,11 @@ defmodule Base do
@doc """
Decodes a base 64 encoded string into a binary string.
The following alphabet is used both for encoding and decoding:
Accepts `ignore: :whitespace` option which will ignore all the
whitespace characters in the input string.
Accepts `padding: false` option which will ignore padding from
the input string.
An `ArgumentError` exception is raised if the padding is incorrect or
a non-alphabet character is present in the string.
@@ -265,44 +305,72 @@ defmodule Base do
iex> Base.decode64!("Zm9vYmFy")
"foobar"
iex> Base.decode64!("Zm9vYmFy\\n", ignore: :whitespace)
"foobar"
iex> Base.decode64!("Zm9vYg==")
"foob"
iex> Base.decode64!("Zm9vYg", padding: false)
"foob"
"""
@spec decode64!(binary) :: binary
def decode64!(string) when is_binary(string) and rem(byte_size(string), 4) == 0 do
do_decode64(string)
end
def decode64!(string) when is_binary(string) do
raise ArgumentError, "incorrect padding"
@spec decode64!(binary, Keyword.t) :: binary
def decode64!(string, opts \\ []) when is_binary(string) do
pad_flag = Keyword.get(opts, :padding, true)
string |> filter_ignored(opts[:ignore]) |> do_decode64(pad_flag)
end
@doc """
Encodes a binary string into a base 64 encoded string with URL and filename
safe alphabet.
Accepts `padding: false` option which will omit padding from
the output string.
## Examples
iex> Base.url_encode64(<<255, 127, 254, 252>>)
"_3_-_A=="
iex> Base.url_encode64(<<255, 127, 254, 252>>, padding: false)
"_3_-_A"
"""
@spec url_encode64(binary) :: binary
def url_encode64(data) when is_binary(data) do
do_encode64url(data)
@spec url_encode64(binary, Keyword.t) :: binary
def url_encode64(data, opts \\ []) when is_binary(data) do
pad_flag = Keyword.get(opts, :padding, true)
do_encode64url(data, pad_flag)
end
@doc """
Decodes a base 64 encoded string with URL and filename safe alphabet
into a binary string.
Accepts `ignore: :whitespace` option which will ignore all the
whitespace characters in the input string.
Accepts `padding: false` option which will ignore padding from
the input string.
## Examples
iex> Base.url_decode64("_3_-_A==")
{:ok, <<255, 127, 254, 252>>}
iex> Base.url_decode64("_3_-_A==\\n", ignore: :whitespace)
{:ok, <<255, 127, 254, 252>>}
iex> Base.url_decode64("_3_-_A", padding: false)
{:ok, <<255, 127, 254, 252>>}
"""
@spec url_decode64(binary) :: {:ok, binary} | :error
def url_decode64(string) when is_binary(string) do
{:ok, url_decode64!(string)}
@spec url_decode64(binary, Keyword.t) :: {:ok, binary} | :error
def url_decode64(string, opts \\ []) when is_binary(string) do
{:ok, url_decode64!(string, opts)}
rescue
ArgumentError -> :error
end
@@ -311,6 +379,12 @@ defmodule Base do
Decodes a base 64 encoded string with URL and filename safe alphabet
into a binary string.
Accepts `ignore: :whitespace` option which will ignore all the
whitespace characters in the input string.
Accepts `padding: false` option which will ignore padding from
the input string.
An `ArgumentError` exception is raised if the padding is incorrect or
a non-alphabet character is present in the string.
@@ -319,14 +393,18 @@ defmodule Base do
iex> Base.url_decode64!("_3_-_A==")
<<255, 127, 254, 252>>
iex> Base.url_decode64!("_3_-_A==\\n", ignore: :whitespace)
<<255, 127, 254, 252>>
iex> Base.url_decode64!("_3_-_A", padding: false)
<<255, 127, 254, 252>>
"""
@spec url_decode64!(binary) :: binary
def url_decode64!(string) when is_binary(string) and rem(byte_size(string), 4) == 0 do
do_decode64url(string)
end
def url_decode64!(string) when is_binary(string) do
raise ArgumentError, "incorrect padding"
@spec url_decode64!(binary, Keyword.t) :: binary
def url_decode64!(string, opts \\ []) when is_binary(string) do
pad_flag = Keyword.get(opts, :padding, true)
string |> filter_ignored(opts[:ignore]) |> do_decode64url(pad_flag)
end
@doc """
@@ -335,6 +413,9 @@ defmodule Base do
Accepts an atom `:upper` (default) for encoding to upper case characters or
`:lower` for lower case characters.
Accepts `padding: false` option which will omit padding from
the output string.
## Examples
iex> Base.encode32("foobar")
@@ -343,12 +424,16 @@ defmodule Base do
iex> Base.encode32("foobar", case: :lower)
"mzxw6ytboi======"
iex> Base.encode32("foobar", padding: false)
"MZXW6YTBOI"
"""
@spec encode32(binary) :: binary
@spec encode32(binary, Keyword.t) :: binary
def encode32(data, opts \\ []) when is_binary(data) do
case = Keyword.get(opts, :case, :upper)
do_encode32(case, data)
pad_flag = Keyword.get(opts, :padding, true)
do_encode32(case, data, pad_flag)
end
@doc """
@@ -358,6 +443,9 @@ defmodule Base do
`:lower` for lower case characters. `:mixed` can be given for mixed case
characters.
Accepts `padding: false` option which will ignore padding from
the input string.
## Examples
iex> Base.decode32("MZXW6YTBOI======")
@@ -369,6 +457,9 @@ defmodule Base do
iex> Base.decode32("mzXW6ytBOi======", case: :mixed)
{:ok, "foobar"}
iex> Base.decode32("MZXW6YTBOI", padding: false)
{:ok, "foobar"}
"""
@spec decode32(binary) :: {:ok, binary} | :error
@spec decode32(binary, Keyword.t) :: {:ok, binary} | :error
@@ -385,6 +476,9 @@ defmodule Base do
`:lower` for lower case characters. `:mixed` can be given for mixed case
characters.
Accepts `padding: false` option which will ignore padding from
the input string.
An `ArgumentError` exception is raised if the padding is incorrect or
a non-alphabet character is present in the string.
@@ -399,18 +493,16 @@ defmodule Base do
iex> Base.decode32!("mzXW6ytBOi======", case: :mixed)
"foobar"
iex> Base.decode32!("MZXW6YTBOI", padding: false)
"foobar"
"""
@spec decode32!(binary) :: binary
@spec decode32!(binary, Keyword.t) :: binary
def decode32!(string, opts \\ [])
def decode32!(string, opts) when is_binary(string) and rem(byte_size(string), 8) == 0 do
def decode32!(string, opts \\ []) when is_binary(string) do
case = Keyword.get(opts, :case, :upper)
do_decode32(case, string)
end
def decode32!(string, _opts) when is_binary(string) do
raise ArgumentError, "incorrect padding"
pad_flag = Keyword.get(opts, :padding, true)
do_decode32(case, string, pad_flag)
end
@doc """
@@ -420,6 +512,9 @@ defmodule Base do
Accepts an atom `:upper` (default) for encoding to upper case characters or
`:lower` for lower case characters.
Accepts `padding: false` option which will omit padding from
the output string.
## Examples
iex> Base.hex_encode32("foobar")
@@ -428,12 +523,16 @@ defmodule Base do
iex> Base.hex_encode32("foobar", case: :lower)
"cpnmuoj1e8======"
iex> Base.hex_encode32("foobar", padding: false)
"CPNMUOJ1E8"
"""
@spec hex_encode32(binary) :: binary
@spec hex_encode32(binary, Keyword.t) :: binary
def hex_encode32(data, opts \\ []) when is_binary(data) do
case = Keyword.get(opts, :case, :upper)
do_hex_encode32(case, data)
pad_flag = Keyword.get(opts, :padding, true)
do_hex_encode32(case, data, pad_flag)
end
@doc """
@@ -444,6 +543,9 @@ defmodule Base do
`:lower` for lower case characters. `:mixed` can be given for mixed case
characters.
Accepts `padding: false` option which will ignore padding from
the input string.
## Examples
iex> Base.hex_decode32("CPNMUOJ1E8======")
@@ -455,6 +557,9 @@ defmodule Base do
iex> Base.hex_decode32("cpnMuOJ1E8======", case: :mixed)
{:ok, "foobar"}
iex> Base.hex_decode32("CPNMUOJ1E8", padding: false)
{:ok, "foobar"}
"""
@spec hex_decode32(binary) :: {:ok, binary} | :error
@spec hex_decode32(binary, Keyword.t) :: {:ok, binary} | :error
@@ -472,6 +577,9 @@ defmodule Base do
`:lower` for lower case characters. `:mixed` can be given for mixed case
characters.
Accepts `padding: false` option which will ignore padding from
the input string.
An `ArgumentError` exception is raised if the padding is incorrect or
a non-alphabet character is present in the string.
@@ -486,18 +594,21 @@ defmodule Base do
iex> Base.hex_decode32!("cpnMuOJ1E8======", case: :mixed)
"foobar"
iex> Base.hex_decode32!("CPNMUOJ1E8", padding: false)
"foobar"
"""
@spec hex_decode32!(binary) :: binary
@spec hex_decode32!(binary, Keyword.t) :: binary
def hex_decode32!(string, opts \\ [])
def hex_decode32!(string, opts) when is_binary(string) and rem(byte_size(string), 8) == 0 do
def hex_decode32!(string, opts \\ []) when is_binary(string) do
case = Keyword.get(opts, :case, :upper)
do_hex_decode32(case, string)
pad_flag = Keyword.get(opts, :padding, true)
do_hex_decode32(case, string, pad_flag)
end
def hex_decode32!(string, _opts) when is_binary(string) do
raise ArgumentError, "incorrect padding"
defp filter_ignored(string, nil), do: string
defp filter_ignored(string, :whitespace) do
for <<c::8 <- string>>, not c in '\s\t\r\n', into: <<>>, do: <<c::8>>
end
defp do_encode16(_, <<>>), do: <<>>
@@ -525,213 +636,219 @@ defmodule Base do
end
end
defp do_encode64(<<>>), do: <<>>
defp do_encode64(data) do
defp do_encode64(<<>>, _), do: <<>>
defp do_encode64(data, pad_flag) do
split = 3 * div(byte_size(data), 3)
<<main::size(split)-binary, rest::binary>> = data
main = for <<c::6 <- main>>, into: <<>>, do: <<enc64(c)::8>>
case rest do
tail = case rest do
<<c1::6, c2::6, c3::4>> ->
<<main::binary, enc64(c1)::8, enc64(c2)::8, enc64(bsl(c3, 2))::8, ?=>>
<<enc64(c1)::8, enc64(c2)::8, enc64(bsl(c3, 2))::8>>
<<c1::6, c2::2>> ->
<<main::binary, enc64(c1)::8, enc64(bsl(c2, 4))::8, ?=, ?=>>
<<enc64(c1)::8, enc64(bsl(c2, 4))::8>>
<<>> ->
main
<<>>
end
main <> maybe_pad(tail, pad_flag, 4, "=")
end
defp do_decode64(<<>>), do: <<>>
defp do_decode64(string) do
defp do_decode64(<<>>, _), do: <<>>
defp do_decode64(string, false) do
maybe_pad(string, true, 4, "=") |> do_decode64(true)
end
defp do_decode64(string, _pad_flag) when rem(byte_size(string), 4) == 0 do
split = byte_size(string) - 4
<<main::size(split)-binary, rest::binary>> = string
main = for <<c::8 <- main>>, into: <<>>, do: <<dec64(c)::6>>
case rest do
tail = case rest do
<<c1::8, c2::8, ?=, ?=>> ->
<<main::binary, dec64(c1)::6, bsr(dec64(c2), 4)::2>>
<<dec64(c1)::6, bsr(dec64(c2), 4)::2>>
<<c1::8, c2::8, c3::8, ?=>> ->
<<main::binary, dec64(c1)::6, dec64(c2)::6, bsr(dec64(c3), 2)::4>>
<<dec64(c1)::6, dec64(c2)::6, bsr(dec64(c3), 2)::4>>
<<c1::8, c2::8, c3::8, c4::8>> ->
<<main::binary, dec64(c1)::6, dec64(c2)::6, dec64(c3)::6, dec64(c4)::6>>
<<dec64(c1)::6, dec64(c2)::6, dec64(c3)::6, dec64(c4)::6>>
<<>> ->
main
<<>>
end
main <> tail
end
defp do_decode64(_, _) do
raise ArgumentError, "incorrect padding"
end
defp do_encode64url(<<>>), do: <<>>
defp do_encode64url(data) do
defp do_encode64url(<<>>, _), do: <<>>
defp do_encode64url(data, pad_flag) do
split = 3 * div(byte_size(data), 3)
<<main::size(split)-binary, rest::binary>> = data
main = for <<c::6 <- main>>, into: <<>>, do: <<enc64url(c)::8>>
case rest do
tail = case rest do
<<c1::6, c2::6, c3::4>> ->
<<main::binary, enc64url(c1)::8, enc64url(c2)::8, enc64url(bsl(c3, 2))::8, ?=>>
<<enc64url(c1)::8, enc64url(c2)::8, enc64url(bsl(c3, 2))::8>>
<<c1::6, c2::2>> ->
<<main::binary, enc64url(c1)::8, enc64url(bsl(c2, 4))::8, ?=, ?=>>
<<enc64url(c1)::8, enc64url(bsl(c2, 4))::8>>
<<>> ->
main
<<>>
end
main <> maybe_pad(tail, pad_flag, 4, "=")
end
defp do_decode64url(<<>>), do: <<>>
defp do_decode64url(string) do
defp do_decode64url(<<>>, _), do: <<>>
defp do_decode64url(string, false) do
maybe_pad(string, true, 4, "=") |> do_decode64url(true)
end
defp do_decode64url(string, _pad_flag) when rem(byte_size(string), 4) == 0 do
split = byte_size(string) - 4
<<main::size(split)-binary, rest::binary>> = string
main = for <<c::8 <- main>>, into: <<>>, do: <<dec64url(c)::6>>
case rest do
tail = case rest do
<<c1::8, c2::8, ?=, ?=>> ->
<<main::binary, dec64url(c1)::6, bsr(dec64url(c2), 4)::2>>
<<dec64url(c1)::6, bsr(dec64url(c2), 4)::2>>
<<c1::8, c2::8, c3::8, ?=>> ->
<<main::binary, dec64url(c1)::6, dec64url(c2)::6, bsr(dec64url(c3), 2)::4>>
<<dec64url(c1)::6, dec64url(c2)::6, bsr(dec64url(c3), 2)::4>>
<<c1::8, c2::8, c3::8, c4::8>> ->
<<main::binary, dec64url(c1)::6, dec64url(c2)::6, dec64url(c3)::6, dec64url(c4)::6>>
<<dec64url(c1)::6, dec64url(c2)::6, dec64url(c3)::6, dec64url(c4)::6>>
<<>> ->
main
<<>>
end
main <> tail
end
defp do_decode64url(_, _) do
raise ArgumentError, "incorrect padding"
end
defp do_encode32(_, <<>>), do: <<>>
defp do_encode32(_, <<>>, _), do: <<>>
for {case, fun} <- [upper: :to_upper, lower: :to_lower] do
defp do_encode32(unquote(case), data) do
defp do_encode32(unquote(case), data, pad_flag) do
split = 5 * div(byte_size(data), 5)
<<main::size(split)-binary, rest::binary>> = data
main = for <<c::5 <- main>>, into: <<>>, do: <<unquote(fun)(enc32(c))::8>>
case rest do
tail = case rest do
<<c1::5, c2::5, c3::5, c4::5, c5::5, c6::5, c7::2>> ->
<<main::binary,
unquote(fun)(enc32(c1))::8, unquote(fun)(enc32(c2))::8,
<<unquote(fun)(enc32(c1))::8, unquote(fun)(enc32(c2))::8,
unquote(fun)(enc32(c3))::8, unquote(fun)(enc32(c4))::8,
unquote(fun)(enc32(c5))::8, unquote(fun)(enc32(c6))::8,
unquote(fun)(enc32(bsl(c7, 3)))::8, ?=>>
unquote(fun)(enc32(bsl(c7, 3)))::8>>
<<c1::5, c2::5, c3::5, c4::5, c5::4>> ->
<<main::binary,
unquote(fun)(enc32(c1))::8, unquote(fun)(enc32(c2))::8,
<<unquote(fun)(enc32(c1))::8, unquote(fun)(enc32(c2))::8,
unquote(fun)(enc32(c3))::8, unquote(fun)(enc32(c4))::8,
unquote(fun)(enc32(bsl(c5, 1)))::8, ?=, ?=, ?=>>
unquote(fun)(enc32(bsl(c5, 1)))::8>>
<<c1::5, c2::5, c3::5, c4::1>> ->
<<main::binary,
unquote(fun)(enc32(c1))::8, unquote(fun)(enc32(c2))::8,
unquote(fun)(enc32(c3))::8, unquote(fun)(enc32(bsl(c4, 4)))::8,
?=, ?=, ?=, ?=>>
<<unquote(fun)(enc32(c1))::8, unquote(fun)(enc32(c2))::8,
unquote(fun)(enc32(c3))::8, unquote(fun)(enc32(bsl(c4, 4)))::8>>
<<c1::5, c2::3>> ->
<<main::binary,
unquote(fun)(enc32(c1))::8, unquote(fun)(enc32(bsl(c2, 2)))::8, ?=, ?=,
?=, ?=, ?=, ?=>>
<<unquote(fun)(enc32(c1))::8, unquote(fun)(enc32(bsl(c2, 2)))::8>>
<<>> ->
main
<<>>
end
main <> maybe_pad(tail, pad_flag, 8, "=")
end
end
defp do_decode32(_, <<>>), do: <<>>
defp do_decode32(_, <<>>, _), do: <<>>
defp do_decode32(case, string, false),
do: do_decode32(case, maybe_pad(string, true, 8, "="), true)
for {case, fun} <- [upper: :from_upper, lower: :from_lower, mixed: :from_mixed] do
defp do_decode32(unquote(case), string) do
defp do_decode32(unquote(case), string, _pad_flag) when rem(byte_size(string), 8) == 0 do
split = byte_size(string) - 8
<<main::size(split)-binary, rest::binary>> = string
main = for <<c::8 <- main>>, into: <<>>, do: <<dec32(unquote(fun)(c))::5>>
case rest do
tail = case rest do
<<c1::8, c2::8, ?=, ?=, ?=, ?=, ?=, ?=>> ->
<<main::binary, dec32(unquote(fun)(c1))::5,
bsr(dec32(unquote(fun)(c2)), 2)::3>>
<<dec32(unquote(fun)(c1))::5, bsr(dec32(unquote(fun)(c2)), 2)::3>>
<<c1::8, c2::8, c3::8, c4::8, ?=, ?=, ?=, ?=>> ->
<<main::binary,
dec32(unquote(fun)(c1))::5, dec32(unquote(fun)(c2))::5,
<<dec32(unquote(fun)(c1))::5, dec32(unquote(fun)(c2))::5,
dec32(unquote(fun)(c3))::5, bsr(dec32(unquote(fun)(c4)), 4)::1>>
<<c1::8, c2::8, c3::8, c4::8, c5::8, ?=, ?=, ?=>> ->
<<main::binary,
dec32(unquote(fun)(c1))::5, dec32(unquote(fun)(c2))::5,
<<dec32(unquote(fun)(c1))::5, dec32(unquote(fun)(c2))::5,
dec32(unquote(fun)(c3))::5, dec32(unquote(fun)(c4))::5,
bsr(dec32(unquote(fun)(c5)), 1)::4>>
<<c1::8, c2::8, c3::8, c4::8, c5::8, c6::8, c7::8, ?=>> ->
<<main::binary,
dec32(unquote(fun)(c1))::5, dec32(unquote(fun)(c2))::5,
<<dec32(unquote(fun)(c1))::5, dec32(unquote(fun)(c2))::5,
dec32(unquote(fun)(c3))::5, dec32(unquote(fun)(c4))::5,
dec32(unquote(fun)(c5))::5, dec32(unquote(fun)(c6))::5,
bsr(dec32(unquote(fun)(c7)), 3)::2>>
<<c1::8, c2::8, c3::8, c4::8, c5::8, c6::8, c7::8, c8::8>> ->
<<main::binary,
dec32(unquote(fun)(c1))::5, dec32(unquote(fun)(c2))::5,
<<dec32(unquote(fun)(c1))::5, dec32(unquote(fun)(c2))::5,
dec32(unquote(fun)(c3))::5, dec32(unquote(fun)(c4))::5,
dec32(unquote(fun)(c5))::5, dec32(unquote(fun)(c6))::5,
dec32(unquote(fun)(c7))::5, dec32(unquote(fun)(c8))::5>>
<<>> ->
main
<<>>
end
main <> tail
end
end
defp do_hex_encode32(_, <<>>), do: <<>>
defp do_decode32(_, _, _),
do: raise ArgumentError, "incorrect padding"
defp do_hex_encode32(_, <<>>, _), do: <<>>
for {case, fun} <- [upper: :to_upper, lower: :to_lower] do
defp do_hex_encode32(unquote(case), data) do
defp do_hex_encode32(unquote(case), data, pad_flag) do
split = 5 * div(byte_size(data), 5)
<<main::size(split)-binary, rest::binary>> = data
main = for <<c::5 <- main>>, into: <<>>, do: <<unquote(fun)(enc32hex(c))::8>>
case rest do
tail = case rest do
<<c1::5, c2::5, c3::5, c4::5, c5::5, c6::5, c7::2>> ->
<<main::binary,
unquote(fun)(enc32hex(c1))::8, unquote(fun)(enc32hex(c2))::8,
<<unquote(fun)(enc32hex(c1))::8, unquote(fun)(enc32hex(c2))::8,
unquote(fun)(enc32hex(c3))::8, unquote(fun)(enc32hex(c4))::8,
unquote(fun)(enc32hex(c5))::8, unquote(fun)(enc32hex(c6))::8,
unquote(fun)(enc32hex(bsl(c7, 3)))::8, ?=>>
unquote(fun)(enc32hex(bsl(c7, 3)))::8>>
<<c1::5, c2::5, c3::5, c4::5, c5::4>> ->
<<main::binary,
unquote(fun)(enc32hex(c1))::8, unquote(fun)(enc32hex(c2))::8,
<<unquote(fun)(enc32hex(c1))::8, unquote(fun)(enc32hex(c2))::8,
unquote(fun)(enc32hex(c3))::8, unquote(fun)(enc32hex(c4))::8,
unquote(fun)(enc32hex(bsl(c5, 1)))::8, ?=, ?=, ?=>>
unquote(fun)(enc32hex(bsl(c5, 1)))::8>>
<<c1::5, c2::5, c3::5, c4::1>> ->
<<main::binary,
unquote(fun)(enc32hex(c1))::8, unquote(fun)(enc32hex(c2))::8,
unquote(fun)(enc32hex(c3))::8, unquote(fun)(enc32hex(bsl(c4, 4)))::8,
?=, ?=, ?=, ?=>>
<<unquote(fun)(enc32hex(c1))::8, unquote(fun)(enc32hex(c2))::8,
unquote(fun)(enc32hex(c3))::8, unquote(fun)(enc32hex(bsl(c4, 4)))::8>>
<<c1::5, c2::3>> ->
<<main::binary,
unquote(fun)(enc32hex(c1))::8, unquote(fun)(enc32hex(bsl(c2, 2)))::8, ?=, ?=,
?=, ?=, ?=, ?=>>
<<unquote(fun)(enc32hex(c1))::8, unquote(fun)(enc32hex(bsl(c2, 2)))::8>>
<<>> ->
main
<<>>
end
main <> maybe_pad(tail, pad_flag, 8, "=")
end
end
defp do_hex_decode32(_, <<>>), do: <<>>
defp do_hex_decode32(_, <<>>, _), do: <<>>
defp do_hex_decode32(case, string, false),
do: do_hex_decode32(case, maybe_pad(string, true, 8, "="), true)
for {case, fun} <- [upper: :from_upper, lower: :from_lower, mixed: :from_mixed] do
defp do_hex_decode32(unquote(case), string) do
defp do_hex_decode32(unquote(case), string, _pad_flag) when rem(byte_size(string), 8) == 0 do
split = byte_size(string) - 8
<<main::size(split)-binary, rest::binary>> = string
main = for <<c::8 <- main>>, into: <<>>, do: <<dec32hex(unquote(fun)(c))::5>>
case rest do
tail = case rest do
<<c1::8, c2::8, ?=, ?=, ?=, ?=, ?=, ?=>> ->
<<main::binary, dec32hex(unquote(fun)(c1))::5,
bsr(dec32hex(unquote(fun)(c2)), 2)::3>>
<<dec32hex(unquote(fun)(c1))::5, bsr(dec32hex(unquote(fun)(c2)), 2)::3>>
<<c1::8, c2::8, c3::8, c4::8, ?=, ?=, ?=, ?=>> ->
<<main::binary,
dec32hex(unquote(fun)(c1))::5, dec32hex(unquote(fun)(c2))::5,
<<dec32hex(unquote(fun)(c1))::5, dec32hex(unquote(fun)(c2))::5,
dec32hex(unquote(fun)(c3))::5, bsr(dec32hex(unquote(fun)(c4)), 4)::1>>
<<c1::8, c2::8, c3::8, c4::8, c5::8, ?=, ?=, ?=>> ->
<<main::binary,
dec32hex(unquote(fun)(c1))::5, dec32hex(unquote(fun)(c2))::5,
<<dec32hex(unquote(fun)(c1))::5, dec32hex(unquote(fun)(c2))::5,
dec32hex(unquote(fun)(c3))::5, dec32hex(unquote(fun)(c4))::5,
bsr(dec32hex(unquote(fun)(c5)), 1)::4>>
<<c1::8, c2::8, c3::8, c4::8, c5::8, c6::8, c7::8, ?=>> ->
<<main::binary,
dec32hex(unquote(fun)(c1))::5, dec32hex(unquote(fun)(c2))::5,
<<dec32hex(unquote(fun)(c1))::5, dec32hex(unquote(fun)(c2))::5,
dec32hex(unquote(fun)(c3))::5, dec32hex(unquote(fun)(c4))::5,
dec32hex(unquote(fun)(c5))::5, dec32hex(unquote(fun)(c6))::5,
bsr(dec32hex(unquote(fun)(c7)), 3)::2>>
<<c1::8, c2::8, c3::8, c4::8, c5::8, c6::8, c7::8, c8::8>> ->
<<main::binary,
dec32hex(unquote(fun)(c1))::5, dec32hex(unquote(fun)(c2))::5,
<<dec32hex(unquote(fun)(c1))::5, dec32hex(unquote(fun)(c2))::5,
dec32hex(unquote(fun)(c3))::5, dec32hex(unquote(fun)(c4))::5,
dec32hex(unquote(fun)(c5))::5, dec32hex(unquote(fun)(c6))::5,
dec32hex(unquote(fun)(c7))::5, dec32hex(unquote(fun)(c8))::5>>
<<>> ->
main
<<>>
end
main <> tail
end
end
defp do_hex_decode32(_, _, _),
do: raise ArgumentError, "incorrect padding"
end
+1 -1
View File
@@ -661,7 +661,7 @@ defmodule String do
replace_trailing(string, match, replacement, prefix_size, suffix_size, "")
end
defp replace_trailing(string, match, replacement, prefix_size, suffix_size, acc) when prefix_size > 0 do
defp replace_trailing(string, match, replacement, prefix_size, suffix_size, acc) when prefix_size >= 0 do
case string do
<<prefix::size(prefix_size)-binary, suffix::size(suffix_size)-binary>> when suffix == match ->
replace_trailing(prefix, match, replacement, prefix_size - suffix_size, suffix_size, acc <> replacement)
+1 -1
View File
@@ -100,8 +100,8 @@ Built-in type | Defined as
`list()` | `[any()]`
`maybe_improper_list()` | `maybe_improper_list(any(), any())`
`nonempty_list()` | `nonempty_list(any())`
`iolist()` | `maybe_improper_list(byte() \| binary() \| iolist(), binary() \| [])`
`iodata()` | `iolist()` \| `binary()`
`iolist()` | `maybe_improper_list(byte()` \| `binary()` \| `iolist(), binary()` \| `[])`
`module()` | `atom()` \| `tuple()`
`arity()` | `0..255`
`mfa()` | `{atom(), atom(), arity()}`
+280
View File
@@ -93,6 +93,18 @@ defmodule BaseTest do
assert "MDEyMzQ1Njc4OSFAIzBeJiooKTs6PD4sLiBbXXt9" == encode64(<<"0123456789!@#0^&*();:<>,. []{}">>)
end
test "encode64 omit padding one pad" do
assert "SGVsbG8gV29ybGQ" == encode64("Hello World", padding: false)
end
test "encode64 omit padding two pads" do
assert "QWxhZGRpbjpvcGVuIHNlc2FtZQ" == encode64("Aladdin:open sesame", padding: false)
end
test "encode64 omit padding no pad" do
assert "QWxhZGRpbjpvcGVuIHNlc2Ft" == encode64("Aladdin:open sesam", padding: false)
end
test "decode64 empty" do
assert {:ok, ""} == decode64("")
end
@@ -135,6 +147,18 @@ defmodule BaseTest do
end
end
test "decode64 whitespace" do
assert :error == decode64("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t")
assert {:ok, "Aladdin:open sesam"} == decode64("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t", ignore: :whitespace)
end
test "decode64! whitespace" do
assert_raise ArgumentError, "non-alphabet digit found: \"\\n\" (byte 10)", fn ->
decode64!("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t")
end
assert "Aladdin:open sesam" == decode64!("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t", ignore: :whitespace)
end
test "decode64 incorrect padding" do
assert :error == decode64("SGVsbG8gV29ybGQ")
end
@@ -145,6 +169,38 @@ defmodule BaseTest do
end
end
test "decode64 ignore padding two pads" do
assert {:ok, "Aladdin:open sesame"} == decode64("QWxhZGRpbjpvcGVuIHNlc2FtZQ", padding: false)
end
test "decode64! ignore padding two pads" do
assert "Aladdin:open sesame" == decode64!("QWxhZGRpbjpvcGVuIHNlc2FtZQ", padding: false)
end
test "decode64 ignore padding one pad" do
assert {:ok, "Hello World"} == decode64("SGVsbG8gV29ybGQ", padding: false)
end
test "decode64! ignore padding one pad" do
assert "Hello World" == decode64!("SGVsbG8gV29ybGQ", padding: false)
end
test "decode64 ignore padding no pad" do
assert {:ok, "Aladdin:open sesam"} == decode64("QWxhZGRpbjpvcGVuIHNlc2Ft", padding: false)
end
test "decode64! ignore padding no pad" do
assert "Aladdin:open sesam" == decode64!("QWxhZGRpbjpvcGVuIHNlc2Ft", padding: false)
end
test "decode64 ignore padding incorrect padding" do
assert {:ok, "Hello World"} == decode64("SGVsbG8gV29ybGQ", padding: false)
end
test "decode64! ignore padding incorrect padding" do
assert "Hello World" == decode64!("SGVsbG8gV29ybGQ", padding: false)
end
test "url_encode64 empty" do
assert "" == url_encode64("")
end
@@ -162,6 +218,18 @@ defmodule BaseTest do
assert "MDEyMzQ1Njc4OSFAIzBeJiooKTs6PD4sLiBbXXt9" == url_encode64(<<"0123456789!@#0^&*();:<>,. []{}">>)
end
test "url_encode64 omit padding two pads" do
assert "QWxhZGRpbjpvcGVuIHNlc2FtZQ" == url_encode64("Aladdin:open sesame", padding: false)
end
test "url_encode64 omit padding one pad" do
assert "SGVsbG8gV29ybGQ" == url_encode64("Hello World", padding: false)
end
test "url_encode64 omit padding no pad" do
assert "QWxhZGRpbjpvcGVuIHNlc2Ft" == url_encode64("Aladdin:open sesam", padding: false)
end
test "url_encode64 no URL unsafe characters" do
refute "/3/+/A==" == url_encode64(<<255, 127, 254, 252>>)
assert "_3_-_A==" == url_encode64(<<255, 127, 254, 252>>)
@@ -199,6 +267,18 @@ defmodule BaseTest do
assert "Aladdin:open sesam" == url_decode64!("QWxhZGRpbjpvcGVuIHNlc2Ft")
end
test "url_decode64 whitespace" do
assert :error == url_decode64("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t")
assert {:ok, "Aladdin:open sesam"} == url_decode64("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t", ignore: :whitespace)
end
test "url_decode64! whitespace" do
assert_raise ArgumentError, "non-alphabet digit found: \"\\n\" (byte 10)", fn ->
url_decode64!("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t")
end
assert "Aladdin:open sesam" == url_decode64!("\nQWxhZGRp bjpvcGVu\sIHNlc2Ft\t", ignore: :whitespace)
end
test "url_decode64 non-alphabet digit" do
assert :error == url_decode64("Zm9)")
end
@@ -219,6 +299,38 @@ defmodule BaseTest do
end
end
test "url_decode64 ignore padding two pads" do
assert {:ok, "Aladdin:open sesame"} == url_decode64("QWxhZGRpbjpvcGVuIHNlc2FtZQ", padding: false)
end
test "url_decode64! ignore padding two pads" do
assert "Aladdin:open sesame" == url_decode64!("QWxhZGRpbjpvcGVuIHNlc2FtZQ", padding: false)
end
test "url_decode64 ignore padding one pad" do
assert {:ok, "Hello World"} == url_decode64("SGVsbG8gV29ybGQ", padding: false)
end
test "url_decode64! ignore padding one pad" do
assert "Hello World" == url_decode64!("SGVsbG8gV29ybGQ", padding: false)
end
test "url_decode64 ignore padding no pad" do
assert {:ok, "Aladdin:open sesam"} == url_decode64("QWxhZGRpbjpvcGVuIHNlc2Ft", padding: false)
end
test "url_decode64! ignore padding no pad" do
assert "Aladdin:open sesam" == url_decode64!("QWxhZGRpbjpvcGVuIHNlc2Ft", padding: false)
end
test "url_decode64 ignore padding incorrect padding" do
assert {:ok, "Hello World"} == url_decode64("SGVsbG8gV29ybGQ", padding: false)
end
test "url_decode64! ignore padding incorrect padding" do
assert "Hello World" == url_decode64!("SGVsbG8gV29ybGQ", padding: false)
end
test "encode32 empty" do
assert "" == encode32("")
end
@@ -244,6 +356,26 @@ defmodule BaseTest do
assert "MZXW6YTB" == encode32("fooba")
end
test "encode32 omit padding one pad" do
assert "MZXW6YQ" == encode32("foob", padding: false)
end
test "encode32 omit padding three pads" do
assert "MZXW6" == encode32("foo", padding: false)
end
test "encode32 omit padding four pads" do
assert "MZXQ" == encode32("fo", padding: false)
end
test "encode32 omit padding six pads" do
assert "MZXW6YTBOI" == encode32("foobar", padding: false)
end
test "encode32 omit padding no pads" do
assert "MZXW6YTB" == encode32("fooba", padding: false)
end
test "encode32 lowercase" do
assert "mzxw6ytb" == encode32("fooba", case: :lower)
end
@@ -342,6 +474,70 @@ defmodule BaseTest do
end
end
test "decode32 ignore padding one pad" do
assert {:ok, "foob"} == decode32("MZXW6YQ", padding: false)
end
test "decode32! ignore padding one pad" do
assert "foob" == decode32!("MZXW6YQ", padding: false)
end
test "decode32 ignore padding three pads" do
assert {:ok, "foo"} == decode32("MZXW6", padding: false)
end
test "decode32! ignore padding three pads" do
assert "foo" == decode32!("MZXW6", padding: false)
end
test "decode32 ignore padding four pads" do
assert {:ok, "fo"} == decode32("MZXQ", padding: false)
end
test "decode32! ignore padding four pads" do
assert "fo" == decode32!("MZXQ", padding: false)
end
test "decode32 ignore padding lowercase" do
assert {:ok, "fo"} == decode32("mzxq", case: :lower, padding: false)
end
test "decode32! ignore padding lowercase" do
assert "fo" == decode32!("mzxq", case: :lower, padding: false)
end
test "decode32 ignore padding mixed case" do
assert {:ok, "fo"} == decode32("mZXq", case: :mixed, padding: false)
end
test "decode32! ignore padding mixed case" do
assert "fo" == decode32!("mZXq", case: :mixed, padding: false)
end
test "decode32 ignore padding six pads" do
assert {:ok, "foobar"} == decode32("MZXW6YTBOI", padding: false)
end
test "decode32! ignore padding six pads" do
assert "foobar" == decode32!("MZXW6YTBOI", padding: false)
end
test "decode32 ignore padding no pads" do
assert {:ok, "fooba"} == decode32("MZXW6YTB", padding: false)
end
test "decode32! ignore padding no pads" do
assert "fooba" == decode32!("MZXW6YTB", padding: false)
end
test "decode32 ignore padding incorrect padding" do
assert {:ok, "foob"} == decode32("MZXW6YQ", padding: false)
end
test "decode32! ignore padding incorrect padding" do
"foob" = decode32!("MZXW6YQ", padding: false)
end
test "hex_encode32 empty" do
assert "" == hex_encode32("")
end
@@ -367,6 +563,26 @@ defmodule BaseTest do
assert "CPNMUOJ1" == hex_encode32("fooba")
end
test "hex_encode32 omit padding one pad" do
assert "CPNMUOG" == hex_encode32("foob", padding: false)
end
test "hex_encode32 omit padding three pads" do
assert "CPNMU" == hex_encode32("foo", padding: false)
end
test "hex_encode32 omit padding four pads" do
assert "CPNG" == hex_encode32("fo", padding: false)
end
test "hex_encode32 omit padding six pads" do
assert "CPNMUOJ1E8" == hex_encode32("foobar", padding: false)
end
test "hex_encode32 omit padding no pads" do
assert "CPNMUOJ1" == hex_encode32("fooba", padding: false)
end
test "hex_encode32 lowercase" do
assert "cpnmuoj1" == hex_encode32("fooba", case: :lower)
end
@@ -470,4 +686,68 @@ defmodule BaseTest do
decode16!("012" <> <<0>>)
end
end
test "hex_decode32 ignore padding one pad" do
assert {:ok, "foob"} == hex_decode32("CPNMUOG", padding: false)
end
test "hex_decode32! ignore padding one pad" do
assert "foob" == hex_decode32!("CPNMUOG", padding: false)
end
test "hex_decode32 ignore padding three pads" do
assert {:ok, "foo"} == hex_decode32("CPNMU", padding: false)
end
test "hex_decode32! ignore padding three pads" do
assert "foo" == hex_decode32!("CPNMU", padding: false)
end
test "hex_decode32 ignore padding four pads" do
assert {:ok, "fo"} == hex_decode32("CPNG", padding: false)
end
test "hex_decode32! ignore padding four pads" do
assert "fo" == hex_decode32!("CPNG", padding: false)
end
test "hex_decode32 ignore padding six pads" do
assert {:ok, "foobar"} == hex_decode32("CPNMUOJ1E8", padding: false)
end
test "hex_decode32! ignore padding six pads" do
assert "foobar" == hex_decode32!("CPNMUOJ1E8", padding: false)
end
test "hex_decode32 ignore padding no pads" do
assert {:ok, "fooba"} == hex_decode32("CPNMUOJ1", padding: false)
end
test "hex_decode32! ignore padding no pads" do
assert "fooba" == hex_decode32!("CPNMUOJ1", padding: false)
end
test "hex_decode32 ignore padding incorrect padding" do
assert {:ok, "foob"} == hex_decode32("CPNMUOG", padding: false)
end
test "hex_decode32! ignore padding incorrect padding" do
"foob" = hex_decode32!("CPNMUOG", padding: false)
end
test "hex_decode32 ignoring padding lowercase" do
assert {:ok, "fo"} == hex_decode32("cpng", case: :lower, padding: false)
end
test "hex_decode32! ignore padding lowercase" do
assert "fo" == hex_decode32!("cpng", case: :lower, padding: false)
end
test "hex_decode32 ignore padding mixed case" do
assert {:ok, "fo"} == hex_decode32("cPNg====", case: :mixed, padding: false)
end
test "hex_decode32! ignore padding mixed case" do
assert "fo" == hex_decode32!("cPNg", case: :mixed, padding: false)
end
end
+14 -6
View File
@@ -160,6 +160,17 @@ defmodule StringTest do
assert String.capitalize("fin") == "Fin"
end
test "replace_trailing" do
assert String.replace_trailing(" abc aa", "a", "") == " abc "
assert String.replace_trailing(" abc __", "_", "") == " abc "
assert String.replace_trailing(" aaaaaaaaa", "a", "") == " "
assert String.replace_trailing("aaaaaaaaaa", "a", "") == ""
assert String.replace_trailing("]]]]]]]]]]", "]", "") == ""
assert String.replace_trailing(" cat 猫猫", "猫", "") == " cat "
assert String.replace_trailing("test", "t", "") == "tes"
assert String.replace_trailing("t", "t", "") == ""
end
test "rstrip" do
assert String.rstrip("") == ""
assert String.rstrip("1\n") == "1"
@@ -172,6 +183,9 @@ defmodule StringTest do
assert String.rstrip("a abc a" <> <<194, 133>>) == "a abc a"
assert String.rstrip(" abc aa", ?a) == " abc "
assert String.rstrip(" abc __", ?_) == " abc "
assert String.rstrip(" aaaaaaaaa", ?a) == " "
assert String.rstrip("aaaaaaaaaa", ?a) == ""
assert String.rstrip("]]]]]]]]]]", ?]) == ""
assert String.rstrip(" cat 猫猫", ?猫) == " cat "
end
@@ -539,10 +553,4 @@ defmodule StringTest do
assert String.jaro_distance("jon", "john") == 0.9166666666666666
assert String.jaro_distance("jon", "jan") == 0.7777777777777777
end
test "skip debug_info in metadata modules" do
assert String.Unicode.__info__(:compile)[:options] == []
assert String.Graphemes.__info__(:compile)[:options] == []
assert String.Normalizer.__info__(:compile)[:options] == []
end
end
-3
View File
@@ -10,7 +10,6 @@ end
defmodule String.Unicode do
@moduledoc false
@compile {:debug_info, false}
def version, do: {7, 0, 0}
data_path = Path.join(__DIR__, "UnicodeData.txt")
@@ -205,7 +204,6 @@ end
defmodule String.Graphemes do
@moduledoc false
@compile {:debug_info, false}
cluster_path = Path.join(__DIR__, "GraphemeBreakProperty.txt")
regex = ~r/(?:^([0-9A-F]+)(?:\.\.([0-9A-F]+))?)\s+;\s(\w+)/m
@@ -415,7 +413,6 @@ end
defmodule String.Normalizer do
@moduledoc false
@compile {:debug_info, false}
decomposition_path = Path.join(__DIR__, "Decomposition.txt")
+12 -8
View File
@@ -103,12 +103,13 @@ defmodule ExUnit.Assertions do
# to avoid silly warnings though.
return =
no_warning(quote do
if right do
right
else
raise ExUnit.AssertionError,
expr: expr,
message: "Expected truthy, got #{inspect right}"
case right do
x when x in [nil, false] ->
raise ExUnit.AssertionError,
expr: expr,
message: "Expected truthy, got #{inspect right}"
_ ->
:ok
end
end)
@@ -416,8 +417,11 @@ defmodule ExUnit.Assertions do
|> elem(1)
end
defp no_warning({name, meta, args}) do
{name, [line: -1] ++ meta, args}
defp no_warning({name, meta, [expr, [do: clauses]]}) do
clauses = Enum.map clauses, fn {:->, meta, args} ->
{:->, [generated: true] ++ Keyword.put(meta, :line, -1), args}
end
{name, meta, [expr, [do: clauses]]}
end
@doc """
+1 -2
View File
@@ -27,9 +27,9 @@ defmodule IEx.Helpers do
* `cd/1` - changes the current directory
* `clear/0` - clears the screen
* `flush/0` - flushes all messages sent to the shell
* `i/1` - prints information about the given data type
* `h/0` - prints this help message
* `h/1` - prints help for the given module, function or macro
* `i/1` - prints information about the given data type
* `import_file/1` - evaluates the given file in the shell's context
* `l/1` - loads the given module's beam code
* `ls/0` - lists the contents of the current directory
@@ -42,7 +42,6 @@ defmodule IEx.Helpers do
* `t/1` — prints type information
* `v/0` — retrieves the last value from the history
* `v/1` — retrieves the nth value from the history
* `import_file/1` — evaluates the given file in the shell's context
Help for all of those functions can be consulted directly from
the command line using the `h` helper itself. Try:
+21 -11
View File
@@ -92,15 +92,18 @@ defmodule Mix.Dep.Converger do
# In case no lock was given, we will use the local lock
# which is potentially stale. So remote.deps/2 needs to always
# check if the data it finds in the lock is actually valid.
all(main, apps, callback, rest, lock, env, fn dep ->
if cached = deps[dep.app] do
{:loaded, cached}
else
{:unloaded, dep, remote.deps(dep, lock)}
end
end)
{deps, rest, lock} =
all(main, apps, callback, rest, lock, env, fn dep ->
if cached = deps[dep.app] do
{:loaded, cached}
else
{:unloaded, dep, remote.deps(dep, lock)}
end
end)
{reject_non_fullfilled_optional(deps), rest, lock}
else
{deps, rest, lock}
{reject_non_fullfilled_optional(deps), rest, lock}
end
end
@@ -173,12 +176,12 @@ defmodule Mix.Dep.Converger do
Mix.Dep.Loader.load(dep, children)
end
dep = %{dep | deps: reject_non_fullfilled_optional(dep.deps, current_breadths)}
{acc, rest, lock} =
all(t, [dep|acc], upper_breadths, current_breadths, callback, rest, lock, env, cache)
new_breadths = Enum.map(dep.deps, &(&1.app)) ++ current_breadths
all(dep.deps, acc, current_breadths, new_breadths, callback, rest, lock, env, cache)
deps = reject_non_fullfilled_optional(dep.deps, current_breadths)
new_breadths = Enum.map(deps, &(&1.app)) ++ current_breadths
all(deps, acc, current_breadths, new_breadths, callback, rest, lock, env, cache)
end
end
@@ -286,6 +289,13 @@ defmodule Mix.Dep.Converger do
Enum.all?(keys, &(Keyword.fetch(opts1, &1) == Keyword.fetch(opts2, &1)))
end
defp reject_non_fullfilled_optional(deps) do
apps = Enum.map(deps, & &1.app)
for dep <- deps do
update_in dep.deps, &reject_non_fullfilled_optional(&1, apps)
end
end
defp reject_non_fullfilled_optional(children, upper_breadths) do
Enum.reject children, fn %Mix.Dep{app: app, opts: opts} ->
opts[:optional] && not(app in upper_breadths)
+16
View File
@@ -236,6 +236,22 @@ defmodule Mix.Project do
Path.expand config[:deps_path]
end
@doc """
Returns the full path of all dependencies as a map.
## Examples
Mix.Project.deps_paths
#=> %{foo: "deps/foo", bar: "custom/path/dep"}
"""
@spec deps_paths() :: %{atom => Path.t}
def deps_paths do
Enum.reduce Mix.Dep.loaded(env: Mix.env), %{}, fn
%{app: app, opts: opts}, acc -> Map.put acc, app, opts[:dest]
end
end
@doc """
Returns the build path for this project.
+11
View File
@@ -53,6 +53,17 @@ defmodule Mix.DepTest do
end
end
test "extracts all dependencies paths from the given project" do
Mix.Project.push DepsApp
in_fixture "deps_status", fn ->
paths = Mix.Project.deps_paths
assert map_size(paths) == 6
assert paths[:ok] =~ "deps/ok"
assert paths[:uncloned] =~ "deps/uncloned"
end
end
test "fails on invalid dependencies" do
assert_wrong_dependency [{:ok}]
assert_wrong_dependency [{:ok, nil}]
+1 -1
View File
@@ -1,6 +1,6 @@
{application, elixir,
[{description, "elixir"},
{vsn, "1.2.2"},
{vsn, "1.2.3"},
{modules, [
elixir
]},