Module hb_singleton.erl¶
A parser that translates AO-Core HTTP API requests in TABM format into an ordered list of messages to evaluate.
Description¶
The details of this format
are described in docs/ao-core-http-api.md
.
Syntax overview:
Singleton: Message containing keys and a <code>path</code> field,
which may also contain a query string of key-value pairs.
Path:
- /Part1/Part2/.../PartN/ => [Part1, Part2, ..., PartN]
- /ID/Part2/.../PartN => [ID, Part2, ..., PartN]
Part: (Key + Resolution), Device?, #{ K => V}?
- Part => #{ path => Part }
- <code>Part&Key=Value => #{ path => Part, Key => Value }</code>
- <code>Part&Key => #{ path => Part, Key => true }</code>
- <code>Part&k1=v1&k2=v2 => #{ path => Part, k1 => `<<"v1">></code>, k2 => <code><<"v2">></code> }'
- <code>Part~Device => {as, Device, #{ path => Part }}</code>
- <code>Part~D&K1=V1 => {as, D, #{ path => Part, K1 => `<<"v1">></code> }}'
- <code>pt&k1+int=1 => #{ path => pt, k1 => 1 }</code>
- <code>pt~d&k1+int=1 => {as, d, #{ path => pt, k1 => 1 }}</code>
- <code>(/nested/path) => Resolution of the path /nested/path</code>
- <code>(/nested/path&k1=v1) => (resolve /nested/path)#{k1 => v1}</code>
- <code>(/nested/path~D&K1=V1) => (resolve /nested/path)#{K1 => V1}</code>
- <code>pt&k1+res=(/a/b/c) => #{ path => pt, k1 => (resolve /a/b/c) }</code>
Key:
- key: <code><<"value">></code> => #{ key => <code><<"value">></code>, ... } for all messages
- n.key: <code><<"value">></code> => #{ key => <code><<"value">></code>, ... } for Nth message
- key+int: 1 => #{ key => 1, ... }
- key+res: /nested/path => #{ key => (resolve /nested/path), ... }
- N.Key+res=(/a/b/c) => #{ Key => (resolve /a/b/c), ... }
Data Types¶
ao_message()¶
ao_message() = map() | binary()
tabm_message()¶
tabm_message() = map()
Function Index¶
all_path_parts/2* | Extract all of the parts from the binary, given (a list of) separators. |
append_path/2* | |
apply_types/2* | Step 3: Apply types to values and remove specifiers. |
basic_hashpath_test/0* | |
basic_hashpath_to_test/0* | |
build_messages/3* | Step 5: Merge the base message with the scoped messages. |
decode_string/1* | Attempt Cowboy URL decode, then sanitize the result. |
do_build/4* | |
from/2 | Normalize a singleton TABM message into a list of executable AO-Core messages. |
group_scoped/2* | Step 4: Group headers/query by N-scope. |
inlined_keys_test/0* | |
inlined_keys_to_test/0* | |
maybe_join/2* | Join a list of items with a separator, or return the first item if there is only one item. |
maybe_subpath/2* | Check if the string is a subpath, returning it in parsed form, or the original string with a specifier. |
maybe_typed/3* | Parse a key's type (applying it to the value) and device name if present. |
multiple_inlined_keys_test/0* | |
multiple_inlined_keys_to_test/0* | |
multiple_messages_test/0* | |
multiple_messages_to_test/0* | |
normalize_base/1* | Normalize the base path. |
parse_explicit_message_test/0* | |
parse_full_path/1* | Parse the relative reference into path, query, and fragment. |
parse_inlined_key_val/2* | Extrapolate the inlined key-value pair from a path segment. |
parse_part/2* | Parse a path part into a message or an ID. |
parse_part_mods/3* | Parse part modifiers: 1. |
parse_scope/1* | Get the scope of a key. |
part/2* | Extract the characters from the binary until a separator is found. |
part/4* | |
path_messages/2* | Step 2: Decode, split and sanitize the path. |
path_parts/2* | Split the path into segments, filtering out empty segments and segments that are too long. |
path_parts_test/0* | |
scoped_key_test/0* | |
scoped_key_to_test/0* | |
simple_to_test/0* | |
single_message_test/0* | |
subpath_in_inlined_test/0* | |
subpath_in_inlined_to_test/0* | |
subpath_in_key_test/0* | |
subpath_in_key_to_test/0* | |
subpath_in_path_test/0* | |
subpath_in_path_to_test/0* | |
to/1 | Convert a list of AO-Core message into TABM message. |
to_suite_test_/0* | |
type/1* | |
typed_key_test/0* | |
typed_key_to_test/0* |
Function Details¶
all_path_parts/2 *¶
all_path_parts(Sep, Bin) -> any()
Extract all of the parts from the binary, given (a list of) separators.
append_path/2 *¶
append_path(PathPart, Message) -> any()
apply_types/2 *¶
apply_types(Msg, Opts) -> any()
Step 3: Apply types to values and remove specifiers.
basic_hashpath_test/0 *¶
basic_hashpath_test() -> any()
basic_hashpath_to_test/0 *¶
basic_hashpath_to_test() -> any()
build_messages/3 *¶
build_messages(Msgs, ScopedModifications, Opts) -> any()
Step 5: Merge the base message with the scoped messages.
decode_string/1 *¶
decode_string(B) -> any()
Attempt Cowboy URL decode, then sanitize the result.
do_build/4 *¶
do_build(I, Rest, ScopedKeys, Opts) -> any()
from/2¶
from(RawMsg, Opts) -> any()
Normalize a singleton TABM message into a list of executable AO-Core messages.
group_scoped/2 *¶
group_scoped(Map, Msgs) -> any()
Step 4: Group headers/query by N-scope.
N.Key
=> applies to Nth step. Otherwise => global
inlined_keys_test/0 *¶
inlined_keys_test() -> any()
inlined_keys_to_test/0 *¶
inlined_keys_to_test() -> any()
maybe_join/2 *¶
maybe_join(Items, Sep) -> any()
Join a list of items with a separator, or return the first item if there is only one item. If there are no items, return an empty binary.
maybe_subpath/2 *¶
maybe_subpath(Str, Opts) -> any()
Check if the string is a subpath, returning it in parsed form, or the original string with a specifier.
maybe_typed/3 *¶
maybe_typed(Key, Value, Opts) -> any()
Parse a key's type (applying it to the value) and device name if present.
We allow characters as type indicators because some URL-string encoders
(e.g. Chrome) will encode `+` characters in a form that query-string parsers
interpret as
characters.
multiple_inlined_keys_test/0 *¶
multiple_inlined_keys_test() -> any()
multiple_inlined_keys_to_test/0 *¶
multiple_inlined_keys_to_test() -> any()
multiple_messages_test/0 *¶
multiple_messages_test() -> any()
multiple_messages_to_test/0 *¶
multiple_messages_to_test() -> any()
normalize_base/1 *¶
normalize_base(Rest) -> any()
Normalize the base path.
parse_explicit_message_test/0 *¶
parse_explicit_message_test() -> any()
parse_full_path/1 *¶
parse_full_path(RelativeRef) -> any()
Parse the relative reference into path, query, and fragment.
parse_inlined_key_val/2 *¶
parse_inlined_key_val(Bin, Opts) -> any()
Extrapolate the inlined key-value pair from a path segment. If the
key has a value, it may provide a type (as with typical keys), but if a
value is not provided, it is assumed to be a boolean true
.
parse_part/2 *¶
parse_part(ID, Opts) -> any()
Parse a path part into a message or an ID. Applies the syntax rules outlined in the module doc, in the following order: 1. ID 2. Part subpath resolutions 3. Inlined key-value pairs 4. Device specifier
parse_part_mods/3 *¶
parse_part_mods(X1, Msg, Opts) -> any()
Parse part modifiers:
1. ~Device
=> {as, Device, Msg}
2. &K=V
=> Msg#{ K => V }
parse_scope/1 *¶
parse_scope(KeyBin) -> any()
Get the scope of a key. Adds 1 to account for the base message.
part/2 *¶
part(Sep, Bin) -> any()
Extract the characters from the binary until a separator is found. The first argument of the function is an explicit separator character, or a list of separator characters. Returns a tuple with the separator, the accumulated characters, and the rest of the binary.
part/4 *¶
part(Seps, X2, Depth, CurrAcc) -> any()
path_messages/2 *¶
path_messages(RawBin, Opts) -> any()
Step 2: Decode, split and sanitize the path. Split by /
but avoid
subpath components, such that their own path parts are not dissociated from
their parent path.
path_parts/2 *¶
path_parts(Sep, PathBin) -> any()
Split the path into segments, filtering out empty segments and segments that are too long.
path_parts_test/0 *¶
path_parts_test() -> any()
scoped_key_test/0 *¶
scoped_key_test() -> any()
scoped_key_to_test/0 *¶
scoped_key_to_test() -> any()
simple_to_test/0 *¶
simple_to_test() -> any()
single_message_test/0 *¶
single_message_test() -> any()
subpath_in_inlined_test/0 *¶
subpath_in_inlined_test() -> any()
subpath_in_inlined_to_test/0 *¶
subpath_in_inlined_to_test() -> any()
subpath_in_key_test/0 *¶
subpath_in_key_test() -> any()
subpath_in_key_to_test/0 *¶
subpath_in_key_to_test() -> any()
subpath_in_path_test/0 *¶
subpath_in_path_test() -> any()
subpath_in_path_to_test/0 *¶
subpath_in_path_to_test() -> any()
to/1¶
to(Messages::[ao_message()]) -> tabm_message()
Convert a list of AO-Core message into TABM message.
to_suite_test_/0 *¶
to_suite_test_() -> any()
type/1 *¶
type(Value) -> any()
typed_key_test/0 *¶
typed_key_test() -> any()
typed_key_to_test/0 *¶
typed_key_to_test() -> any()