Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v0.2.0 #15

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Install from [Hex.pm](https://hex.pm/packages/xdr):

```elixir
def deps do
[{:xdr, "~> 0.1.2"}]
[{:xdr, "~> 0.2.0"}]
end
```

Expand Down Expand Up @@ -56,7 +56,8 @@ XDR.Type.Optional

| Version | Change Summary |
| ------- | -------------- |
| [v0.1.2](https://hex.pm/packages/xdr/0.1.2) | [negative integers in Enums](https://github.com/sunny-g/xdr/pull/11)
| [v0.2.0](https://hex.pm/packages/xdr/0.2.0) (in-progress) | [unify `__using__` API, upgrade to Elixir 1.6](https://github.com/sunny-g/xdr/pull/14) |
| [v0.1.2](https://hex.pm/packages/xdr/0.1.2) | [negative integers in Enums](https://github.com/sunny-g/xdr/pull/11) |
| [v0.1.1](https://hex.pm/packages/xdr/0.1.1) | [minor bugfix](https://github.com/sunny-g/xdr/pull/6) |
| [v0.1.0](https://hex.pm/packages/xdr/0.1.0) | initial release |

Expand Down
4 changes: 3 additions & 1 deletion lib/xdr/type/bool.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ defmodule XDR.Type.Bool do
@type t :: boolean
@type xdr :: Enum.xdr()

use XDR.Type.Enum, false: 0, true: 1
use XDR.Type.Enum,
false: 0,
true: 1
end
5 changes: 3 additions & 2 deletions lib/xdr/type/double_float.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule XDR.Type.DoubleFloat do
"""

alias XDR.Type.Base
import XDR.Util.Macros
import XDR.Util.Guards

@behaviour XDR.Type.Base

Expand All @@ -16,7 +16,8 @@ defmodule XDR.Type.DoubleFloat do

@length 8

defguard is_xdr_double(double) when is_float(double) or is_integer(double)
defguard is_xdr_double(double)
when is_float(double) or is_integer(double)

@doc false
def length, do: @length
Expand Down
22 changes: 9 additions & 13 deletions lib/xdr/type/enum.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ defmodule XDR.Type.Enum do
@moduledoc """
RFC 4506, Section 4.3 - Enumeration
"""

require OK
import XDR.Util.Macros
import XDR.Util.Guards
alias XDR.Type.{Base, Int}

@typedoc """
Expand All @@ -16,13 +14,13 @@ defmodule XDR.Type.Enum do
@type decode_error :: {:error, :invalid_xdr | :invalid_enum}
@type encode_error :: {:error, :invalid | :invalid_name | :invalid_enum}

defmacro __using__(opts) do
defmacro __using__(spec) do
# TODO: update this to statically compile spec into pattern-matched methods
if not Keyword.keyword?(opts) do
if not Keyword.keyword?(spec) do
raise "Enum spec must be a keyword list"
end

if Enum.any?(opts, fn
if Enum.any?(spec, fn
{_, {:-, _, [v]}} -> not is_number(v)
{_, v} -> not is_number(v)
end) do
Expand All @@ -33,10 +31,10 @@ defmodule XDR.Type.Enum do
@behaviour XDR.Type.Base

defdelegate length, to: unquote(__MODULE__)
def new(name), do: unquote(__MODULE__).new(name, unquote(opts))
def valid?(name), do: unquote(__MODULE__).valid?(name, unquote(opts))
def encode(name), do: unquote(__MODULE__).encode(name, unquote(opts))
def decode(name), do: unquote(__MODULE__).decode(name, unquote(opts))
def new(name), do: unquote(__MODULE__).new(name, unquote(spec))
def valid?(name), do: unquote(__MODULE__).valid?(name, unquote(spec))
def encode(name), do: unquote(__MODULE__).encode(name, unquote(spec))
def decode(name), do: unquote(__MODULE__).decode(name, unquote(spec))
end
end

Expand Down Expand Up @@ -88,9 +86,7 @@ defmodule XDR.Type.Enum do
def decode(_, enum) when not is_list(enum), do: {:error, :invalid_enum}

def decode(xdr, enum) do
OK.with do
{val, rest} <- Int.decode(xdr)

with {:ok, {val, rest}} <- Int.decode(xdr) do
case Enum.find(enum, &Kernel.===(elem(&1, 1), val)) do
{k, _} -> {:ok, {k, rest}}
nil -> {:error, :invalid_enum}
Expand Down
7 changes: 5 additions & 2 deletions lib/xdr/type/fixed_array.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule XDR.Type.FixedArray do
"""

alias XDR.Type.Base
import XDR.Util.Macros
import XDR.Util.Guards

@typedoc """
A binary of any length
Expand All @@ -14,7 +14,10 @@ defmodule XDR.Type.FixedArray do
@type xdr :: Base.xdr()
@type decode_error :: {:error, reason :: :invalid | :xdr_too_small}

defmacro __using__(len: len, type: type) do
defmacro __using__(spec) do
len = Keyword.get(spec, :len)
type = Keyword.get(spec, :type)

if not (is_integer(len) and len >= 0) do
raise "invalid length"
end
Expand Down
2 changes: 1 addition & 1 deletion lib/xdr/type/fixed_opaque.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule XDR.Type.FixedOpaque do

alias XDR.Type.Base
alias XDR.Util
import XDR.Util.Macros
import XDR.Util.Guards

@typedoc """
A binary of any length
Expand Down
2 changes: 1 addition & 1 deletion lib/xdr/type/float.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule XDR.Type.Float do
"""

alias XDR.Type.Base
import XDR.Util.Macros
import XDR.Util.Guards

@behaviour XDR.Type.Base

Expand Down
7 changes: 3 additions & 4 deletions lib/xdr/type/hyper_int.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ defmodule XDR.Type.HyperInt do
RFC 4506, Section 4.5 - Hyper Integer
"""

require Math
alias XDR.Type.Base
import XDR.Util.Macros
import XDR.Util.Guards

@behaviour XDR.Type.Base

Expand All @@ -15,8 +14,8 @@ defmodule XDR.Type.HyperInt do
@type t :: -9_223_372_036_854_775_808..9_223_372_036_854_775_807
@type xdr :: <<_::_*64>>

@min_hyper_int -Math.pow(2, 63)
@max_hyper_int Math.pow(2, 63) - 1
@min_hyper_int -9_223_372_036_854_775_808
@max_hyper_int 9_223_372_036_854_775_807
@length 8

defguard is_hyper_int(int)
Expand Down
5 changes: 2 additions & 3 deletions lib/xdr/type/hyper_uint.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ defmodule XDR.Type.HyperUint do
RFC 4506, Section 4.5 - Unsigned Hyper Integer
"""

require Math
alias XDR.Type.Base
import XDR.Util.Macros
import XDR.Util.Guards

@behaviour XDR.Type.Base

Expand All @@ -16,7 +15,7 @@ defmodule XDR.Type.HyperUint do
@type xdr :: <<_::_*64>>

@min_hyper_uint 0
@max_hyper_uint Math.pow(2, 64) - 1
@max_hyper_uint 18_446_744_073_709_551_615
@length 8

defguard is_hyper_uint(uint)
Expand Down
7 changes: 3 additions & 4 deletions lib/xdr/type/int.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ defmodule XDR.Type.Int do
RFC 4506, Section 4.1 - Integer
"""

require Math
alias XDR.Type.Base
import XDR.Util.Macros
import XDR.Util.Guards

@behaviour XDR.Type.Base

Expand All @@ -15,8 +14,8 @@ defmodule XDR.Type.Int do
@type t :: -2_147_483_648..2_147_483_647
@type xdr :: Base.xdr()

@min_int -Math.pow(2, 31)
@max_int Math.pow(2, 31) - 1
@min_int -2_147_483_648
@max_int 2_147_483_647
@length 4

defguard is_int(int)
Expand Down
6 changes: 4 additions & 2 deletions lib/xdr/type/optional.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ defmodule XDR.Type.Optional do
}

defmacro __using__(for: optional_type) do
required = quote do: require(unquote(optional_type))

quote do
@behaviour XDR.Type.Base
unquote(required)

@type t :: nil | any
@type t :: nil | unquote(optional_type).t()
@type type :: module
@type xdr :: Base.xdr()

Expand Down
7 changes: 3 additions & 4 deletions lib/xdr/type/string.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ defmodule XDR.Type.String do
RFC 4506, Section 4.11 - String
"""

require Math
alias XDR.Type.Base
alias XDR.Type.VariableOpaque

Expand All @@ -15,14 +14,14 @@ defmodule XDR.Type.String do
@type max :: VariableOpaque.max()
@type decode_error :: VariableOpaque.decode_error()

@max_len Math.pow(2, 32) - 1
@max_len 2_147_483_647

defguard is_xdr_string(string, max_len)
when is_bitstring(string) and is_integer(max_len) and max_len <= @max_len and
byte_size(string) <= max_len

defmacro __using__(opts \\ []) do
max_len = Keyword.get(opts, :max_len, @max_len)
defmacro __using__(spec) do
max_len = Keyword.get(spec, :max_len, @max_len)

if max_len > @max_len do
raise "max length too large"
Expand Down
30 changes: 15 additions & 15 deletions lib/xdr/type/struct.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@ defmodule XDR.Type.Struct do
RFC 4506, Section 4.14 - Structure
"""

require OK
alias XDR.Type.Base

defmacro __using__(spec) do
keys = Keyword.keys(spec)
values = Keyword.values(spec)

required =
for module <- values do
quote do: require(unquote(module))
end

quote do
import XDR.Util.Macros
import XDR.Util.Guards
unquote(required)

@behaviour XDR.Type.Base

Expand Down Expand Up @@ -75,30 +81,24 @@ defmodule XDR.Type.Struct do
# HELPERS
# ---------------------------------------------------------------------------#

def valid?(struct, {key, module}),
do:
struct
|> Map.get(key)
|> module.valid?
def valid?(struct, {key, module}) do
struct
|> Map.get(key)
|> module.valid?
end

def encode(_struct, {_, _}, {:error, reason}), do: {:error, reason}

def encode(struct, {key, module}, {:ok, curr_xdr}) do
OK.with do
xdr <-
struct
|> Map.get(key)
|> module.encode

with {:ok, xdr} <- struct |> Map.get(key) |> module.encode do
{:ok, curr_xdr <> xdr}
end
end

def decode({_, _}, {:error, reason}), do: {:error, reason}

def decode({key, module}, {:ok, {struct, xdr}}) do
OK.with do
{val, rest} <- module.decode(xdr)
with {:ok, {val, rest}} <- module.decode(xdr) do
{:ok, {Map.put(struct, key, val), rest}}
end
end
Expand Down
5 changes: 2 additions & 3 deletions lib/xdr/type/uint.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ defmodule XDR.Type.Uint do

@behaviour XDR.Type.Base

require Math
alias XDR.Type.Base
import XDR.Util.Macros
import XDR.Util.Guards

@typedoc """
Integer between 0 and 2^32 - 1
Expand All @@ -16,7 +15,7 @@ defmodule XDR.Type.Uint do
@type xdr :: Base.xdr()

@min_uint 0
@max_uint Math.pow(2, 32) - 1
@max_uint 4_294_967_295
@length 4

defguard is_uint(uint)
Expand Down
29 changes: 12 additions & 17 deletions lib/xdr/type/union.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ defmodule XDR.Type.Union do
RFC 4506, Section 4.15 - Discriminated Union
"""

require OK
import OK, only: [~>>: 2]
import XDR.Util

alias XDR.Type.{
Expand All @@ -30,7 +28,12 @@ defmodule XDR.Type.Union do
@type attributes :: [{atom, switch}]

defmacro __using__(spec) do
switch_module = get_switch(spec)
required = quote do: require(unquote(switch_module))

quote do
unquote(required)

@behaviour XDR.Type.Base

def length, do: :union
Expand Down Expand Up @@ -96,10 +99,8 @@ defmodule XDR.Type.Union do
attribute_module = get_attribute(discriminant, spec)

if valid?({discriminant, val}, spec) do
OK.with do
switch <- switch_module.encode(discriminant)
arm <- attribute_module.encode(val)

with {:ok, switch} <- switch_module.encode(discriminant),
{:ok, arm} <- attribute_module.encode(val) do
{:ok, switch <> arm}
end
else
Expand All @@ -123,13 +124,9 @@ defmodule XDR.Type.Union do
end

if valid?(discriminant, spec) and not is_nil(case_module) do
OK.with do
switch <- switch_module.encode(discriminant)

arm <-
case_module.new()
~>> case_module.encode()

with {:ok, switch} <- switch_module.encode(discriminant),
{:ok, val} <- case_module.new(),
{:ok, arm} <- case_module.encode(val) do
{:ok, switch <> arm}
end
else
Expand All @@ -145,10 +142,8 @@ defmodule XDR.Type.Union do
def decode(<<discriminant_xdr::binary-size(4), arm_xdr::binary>>, spec) do
switch_module = get_switch(spec)

OK.with do
{discriminant, _} <- switch_module.decode(discriminant_xdr)
{arm, rest} <- decode_arm(discriminant, arm_xdr, spec)

with {:ok, {discriminant, _}} <- switch_module.decode(discriminant_xdr),
{:ok, {arm, rest}} <- decode_arm(discriminant, arm_xdr, spec) do
if is_nil(arm) and arm_xdr === rest do
{:ok, {discriminant, rest}}
else
Expand Down
Loading