Skip to content

simoexpo/SafeExStruct

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SafeExStruct Build Status Coverage Status codebeat badge

What is it?

SafeExStruct is a small library that provides help to create and validate typed struct in elixir.

How does it work?

SafeExStruct uses macro to define functions to assist the creation of a struct and check its validity. It requires the user to define a map (@fields) containing the struct fields with their relative types and then adding the instruction use SafeExStruct will automatically generate the struct and all the useful functions.

Module definition:

defmodule SimpleStruct do

    @fields %{
      string: :binary,
      num: :integer
    }

    use SafeExStruct

end

Explanation:

  • @fields define the struct with a map field_name -> field_type.
  • use SafeExStruct needs to be specified after @fields definition to add the creation and validation functions to the module.

Generated functions:

  • is_valid(struct) :: boolean: returns true if the struct is valid, i.e. if its fields types are the same of the fields types defined in @fields.
  • create(map, options \\ []) :: {:ok, struct} | {:error, :invalid_args}: creates a type-safe struct given a map field_name -> value or return an error if at least one of the given value doesn't suite the field type defined in @fields.
SimpleStruct.is_valid(%SimpleStruct{string: "name", num: 1})      # -> true
SimpleStruct.is_valid(%SimpleStruct{string: "name", num: 1.0})    # -> false

SimpleStruct.create(%{string: "name", num: 1})    # -> {:ok, %SimpleStruct{string: "simple", num: 1}}
SimpleStruct.create(%{string: "name", num: 1.0})  # -> {:error, :invalid_args}

The create/2 function define two options to allow some special behaviour:

  • ignore_unknown_fields: true | false: allow to ignore the unknown fields when trying to create the struct.
  • allow_string_keys: true | false: allow to create a struct from a map with strings keys instead of atoms.

Both these options default to false.

Available types:

  • atom -> :atom
  • binary -> :binary
  • bitstring -> :bitstring
  • boolean -> :boolean
  • float -> :float
  • function -> :function
  • integer -> :integer
  • list -> :list | {:list, elem_type}
  • map -> :map
  • number -> :number
  • nil -> :nil
  • pid -> :pid
  • port -> :port
  • reference -> :reference
  • struct -> __MODULE__ of struct.
  • tuple -> :tuple | {:tuple, tuple_of_types_of_tuple_elem}

Examples

Simple struct:

defmodule SimpleStruct do

    @fields %{
      string: :binary,
      num: :integer
    }

    use SafeExStruct

end

Define a struct with two fields string and num respectively of type binary and integer.

Struct-field struct:

defmodule StructFieldStruct do

    @fields %{
      string: :binary,
      num: :integer,
      struct: SimpleStruct
    }

    use SafeExStruct

end

Define a struct with three fields string, num and struct respectively of type binary and integer and SimpleStruct.

List-field struct without list type:

defmodule SimpleListStruct do

    @fields %{
      s: :binary,
      l: :list
    }

    use SafeExStruct

end

Define a struct with two fields s and l respectively of type binary and list without specify the list elements type.

List-field struct with list type:

defmodule AdvancedListStruct do

    @fields %{
      s: :binary,
      l: {:list, :integer}
    }

    use SafeExStruct

end

Define a struct with two fields s and l respectively of type binary and list with integer elements.

Tuple-field struct without type:

defmodule SimpleTupleStruct do

    @fields %{
      s: :binary,
      t: :tuple
    }

    use SafeExStruct

end

Define a struct with two fields s and t respectively of type binary and tuple without specify the tuple elements types.

Tuple-field struct with type:

defmodule AdvancedTupleStruct do

    @fields %{
      s: :binary,
      t: {:tuple, {:binary, :integer}}
    }

    use SafeExStruct

end

Define a struct with two fields s and t respectively of type binary and tuple. The tuple should have two elements respectively of type binary and integer.

Optional-field struct

defmodule OptionalSimpleStruct do

    @fields %{
      s: :binary,
      n: {:number, :optional, 0}
    }

    use SafeExStruct

end

Define a struct with a mandatory field s of type binary and an optional field n of type number with default value 0.

Installation

def deps do
  [
    {:safeexstruct, git: "git://github.com/simoexpo/SafeExStruct.git", tag: "v0.3.0"}
  ]
end