BACnet.Internal (bacstack v0.0.1)

View Source

Internal module for working with various things.

Summary

Guards

Checks whether the given argument is Process.dest().

Checks whether the given argument is GenServer.server(), it also includes the {:via, mod, term} format, as GenServer.call/3 uses GenServer.whereis/1 to resolve the server argument.

Types

Valid type checker types. This is mostly used for BACnet object properties.

Functions

Checks the type of value and verifies more complex type it is of the same type as the given type.

Generates valid?/1 clause body based on the given module's :t typespec, it must reference a struct.

Resolves a type (struct) to a map of fields to typespecs (resolve_type/2-like).

Resolves an AST type to something check_type/2 works with.

Calculates the integer bitmask of a tuple of booleans.

Guards

is_dest(dest)

(macro)
@spec is_dest(term()) :: Macro.t()

Checks whether the given argument is Process.dest().

is_server(server)

(macro)
@spec is_server(term()) :: Macro.t()

Checks whether the given argument is GenServer.server(), it also includes the {:via, mod, term} format, as GenServer.call/3 uses GenServer.whereis/1 to resolve the server argument.

Types

typechecker_types()

@type typechecker_types() ::
  nil
  | :any
  | :boolean
  | :string
  | :octet_string
  | :signed_integer
  | :unsigned_integer
  | :real
  | :double
  | :bitstring
  | {:array, typechecker_types()}
  | {:array, typechecker_types(), pos_integer()}
  | {:constant, atom()}
  | {:in_list, term()}
  | {:in_range, integer(), integer()}
  | {:list, typechecker_types()}
  | {:literal, term()}
  | {:struct, module()}
  | {:tuple, [typechecker_types()]}
  | {:type_list, [typechecker_types()]}
  | {:with_validator, typechecker_types(), Macro.t()}

Valid type checker types. This is mostly used for BACnet object properties.

Following types are supported:

  • nil - nil
  • :any - any()/term()
  • :boolean - boolean()
  • :string - String.t()
  • :octet_string - binary()
  • :signed_integer - integer()
  • :unsigned_integer - non_neg_integer()
  • :real - float(), also allowing :NaN, :inf, :infn
  • :double - value check same as :real (for bac_object/2, this type must be explicitely specified)
  • :bitstring - tuple of booleans
  • {:array, subtype} (validates a BACnetArray and every value of it being of subtype)
  • {:array, subtype, fixed_size} (validates a BACnetArray with fixed size of fixed_size and every value of it being of subtype)
  • {:constant, type} - Constants.type()
  • {:in_list, values}
  • {:in_range, low, high} - x..y
  • {:list, type} - [type()]
  • {:literal, value_check} (checks if value equals to value_check using the match ===/2 operator)
  • {:struct, module} (calls the module's valid?/1 function, if exported)
  • {:tuple, [type]} (checks in sequence if the tuple element matches to the type in the same index)
  • {:type_list, [type]} - type_a()|type_b() (checks if the value passes one of the type checks in types list)
  • {:with_validator, type, validator_function_ast} - First checks the type and then calls the validator function, which is AST that gets first evaluated and then called with the value. The AST must evaluate to a single arity function.

Functions

check_type(type, value)

@spec check_type(typechecker_types(), term()) :: boolean()

Checks the type of value and verifies more complex type it is of the same type as the given type.

generate_valid_clause(module, env)

@spec generate_valid_clause(module(), Macro.Env.t()) :: Macro.t()

Generates valid?/1 clause body based on the given module's :t typespec, it must reference a struct.

resolve_struct_type(module, type, env, opts \\ [])

@spec resolve_struct_type(module(), atom(), Macro.Env.t(), Keyword.t()) :: map()

Resolves a type (struct) to a map of fields to typespecs (resolve_type/2-like).

This function only works with BACnet data structures and not with types, such as exposed by the module ApplicationTags. Since tuples are used in that module to structure data together, tuples are used in BACnet data structures as bitstrings (as seen in ApplicationTags bitstrings). As such wrong typespecs will be generated and cannot be used for validation.

For structs that do not define any fields, an empty map will be returned.

Tuple types such as {binary(), integer()} will be resolved to {:tuple, [:octet_string, :integer]}.

iex(1)> resolve_struct_type(BACnet.Protocol.EventParameters.ChangeOfBitstring, :t, __ENV__)
%{
  alarm_values: {:list, :bitstring},
  bitmask: :bitstring,
  time_delay: :unsigned_integer,
  time_delay_normal: {:type_list, [:unsigned_integer, {:literal, nil}]}
}

Available options:

  • ignore_underlined_keys: boolean() - Ignores/skips keys starting with _, as such the resolved types will exclude types for underline-prefixed keys.

resolve_type(type, env)

@spec resolve_type(Macro.t(), Macro.Env.t()) :: term()

Resolves an AST type to something check_type/2 works with.

tuple_to_int(tuple)

@spec tuple_to_int(tuple()) :: non_neg_integer()

Calculates the integer bitmask of a tuple of booleans.