Skip to content

zotonic/dispatch_compiler

Repository files navigation

Test License

dispatch_compiler

Compiles dispatch rules to an Erlang module for quick matching.

The dispatch compiler takes a list of dispatch rules and creates an Erlang module that matches those rules.

The compiled Erlang module exports a single function: match/2.

Dispatch rules

Dispatch rules are lists of tokens with some extra information:

{name, ["foo", "bar", id], controller_name, [controller,options]}

The path parts can be one of the following:

  • a string "foo". This is translated to a binary and must match literally
  • an atom id this binds the variable to the token and is returned
  • the atom '*', this binds to any left tokens, which could be an empty list
  • regular expressions {id, "^[0-9]+$"}
  • regular expressions with re compile options {id, "^[a-z]+$", [caseless]}

It is also possible to define functions to perform runtime checks on the tokens.

Functions can be defined as:

  • A module, function pair: {var, {foo, bar}}, this will call foo:bar(Token, Context)
  • A module, function, args triple: {var, {foo, bar, [some, args]}}, this will call foo:bar(Token, Context, some, args)
  • A function with a single arg: {var, fun(<<C,Rest/binary>>) -> C < $z end}
  • A function with a two arguments: {var, fun(<<C,Rest/binary>>, Context) -> C < $z end}

Functions must return one of the following

  • true on a match
  • false if not matched
  • {ok, Term} to bind the variable to the return Term

Usage

First compile the dispatch rules to an Erlang module:

Rules = [
    {test, ["a", v], foo, []},
    {wildcard, ["w", '*'], foo, []}
],
ok = dispatch_compiler:compile_load('mydispatch', Rules).

Now the compiled module can be used to match (the undefined will be passed as Context to any functions in the dispatch rules):

1> mydispatch:match([<<"a">>, <<"b">>], undefined).
{ok, { {test, ["a", v], foo, []}, [{v,<<"b">>}]}}

The return value contains the matched dispatch rule and any bound variables. The first matching rule is returned.

Another example showing a matching wildcard:

2> mydispatch:match([<<"w">>, <<"b">>, <<"c">>], undefined).
{ok, { {wildcard, ["w", '*'], foo, []}, [{'*',[<<"b">>, <<"c">>]}]}}

If no dispatch rule could be matched, then fail is returned:

3> mydispatch:match([<<"a">>, <<"b">>, <<"c">>], undefined).
fail

Tests

Run make test to run the tests.

Documentation generation

Edoc

Generate public API

rebar3 edoc

Generate private API

rebar3 as edoc_private edoc

ExDoc

rebar3 ex_doc --logo doc/img/logo.png --output edoc

About

Compiles dispatch rules to an Erlang module for quick dispatch matching.

Resources

License

Stars

Watchers

Forks

Packages

No packages published