khepri_path (khepri v0.6.0)

Khepri path API.

A path is the type used by Khepri to reference nodes in the tree structure. A path describes how to reach a node from the root node.

A path, or native path, is a list of components. Components can be Erlang atoms and binaries. Example:

  %% Native path.
  Path = [stock, wood, <<"oak">>].

A path may contain conditions to tune how a node is matched or to match multiple nodes at once. This is called a path pattern. A path pattern may contain conditions in addition to regular components (Erlang atoms and binaries). See khepri_condition to learn more about conditions. Example:

  %% Path pattern with a condition on `wood'.
  PathPattern = [stock,
                 #if_all{conditions = [wood,
                                       #if_node_exists{exists = true}]},
                 oak].

To be user-friendly, string-based and binary-based Unix-like paths are accepted by most functions. The syntax of these Unix paths is described in the unix_path() type documentation. Example:

  %% Unix path, equivalent of the first native path example.
  UnixPath = "/:stock/:wood/oak".

Link to this section Summary

Types

Component name in a path to a node.

Native path to a node.

Path pattern which may match zero, one or more nodes.

A node name.
Path to a node.
Path pattern which may match zero, one or more nodes.
Path pattern component which may match zero, one or more nodes.

Unix-like path to a node.

Unix-like path pattern to a node.

Link to this section Types

-type component() :: node_id() | $/ | $. | $^.
Component name in a path to a node.
Link to this type

native_path/0

-type native_path() :: [component()].

Native path to a node.

A native path is a list of atoms, binaries and special components.

It is called native because it requires no further processing (unlike unix_path()) and is the format used internally by the state machine.

Special components are:
  1. ?KHEPRI_ROOT_NODE to explicitly mark the root node. A path is absolute by default. Using ?KHEPRI_ROOT_NODE is only useful when manipulating the root node itself (querying it or storing something in the root node).
  2. ?THIS_KHEPRI_NODE to make a relative path (the default being an absolute path). This is mostly useful for khepri_condition:keep_while() to make it easy to put a condition on the node itself.
  3. ?PARENT_KHEPRI_NODE to target the parent of a node, with the same benefits and use cases as ?THIS_KHEPRI_NODE.

Example:

  %% Native path.
  Path = [stock, wood, <<"oak">>].
Link to this type

native_pattern/0

-type native_pattern() :: [pattern_component()].

Path pattern which may match zero, one or more nodes.

A native pattern is a list of atoms, binaries, special components and conditions.

It is called native because it requires no further processing (unlike unix_pattern()) and is the format used internally by the state machine.

See native_path() for a description of special components.

Conditions are any condition defined by khepri_condition:condition().

Example:

  %% Path pattern with a condition on `wood'.
  PathPattern = [stock,
                 #if_all{conditions = [wood,
                                       #if_node_exists{exists = true}]},
                 oak].
-type node_id() :: atom() | binary().
A node name.
-type path() :: native_path() | unix_path().
Path to a node.
-type pattern() :: native_pattern() | unix_pattern().
Path pattern which may match zero, one or more nodes.
Link to this type

pattern_component/0

-type pattern_component() :: component() | khepri_condition:condition().
Path pattern component which may match zero, one or more nodes.
-type unix_path() :: string() | binary().

Unix-like path to a node.

These Unix paths have the following syntax:

  • Path components are separated by a forward slash, /.
  • Atom-based node IDs are prefixed with a : character: :wood.
  • Binary-based node IDs are written as-is: oak.
  • Atom and binaries can be percent-encoded.
  • An absolute path must start with /, otherwise it is considered a relative path
  • . and .. represent ?THIS_KHEPRI_NODE and ?PARENT_KHEPRI_NODE respectively
  • Simple glob patterns are accepted:
    • abc*def is the same as #if_name_matches{regex = "^abc.*def$"}
    • * is the same as ?KHEPRI_WILDCARD_STAR or #if_name_matches{regex = any}
    • ** is the same as ?KHEPRI_WILDCARD_STAR_STAR or if_path_matches{regex = any}

Warning: There is no special handling of Unicode in tree node names. To use Unicode, it is recommended to either use a native path or a binary-based Unix-like path. If using a string-based Unix-like path, the behavior is undefined and the call may crash. Matching against node names is also undefined behavior and may crash, regardless of the type of path being used. It will be improved in the future.

Example:
  %% Unix path, equivalent of the first native path example.
  UnixPath = "/:stock/:wood/oak".
Link to this type

unix_pattern/0

-type unix_pattern() :: string() | binary().

Unix-like path pattern to a node.

It accepts the following special characters:
  1. * anywhere in a path component behaves like a khepri_condition:if_name_matches().
  2. ** as a path component behaves like a khepri_condition:if_path_matches().

A Unix-like path pattern can't express all the conditions of a native path pattern currently.

Otherwise it works as a unix_path() and has the same syntax and limitations.

Example:
  %% Unix path pattern, matching multiple types of oak.
  UnixPathPattern = "/:stock/:wood/*oak".

Link to this section Functions

Link to this function

abspath(Path, BasePath)

-spec abspath(Path, BasePath) -> Path when Path :: native_pattern(), BasePath :: native_pattern().
Link to this function

combine_with_conditions(PathPattern, Conditions)

-spec combine_with_conditions(PathPattern, Conditions) -> PathPattern
                           when
                               PathPattern :: native_pattern(),
                               Conditions :: [khepri_condition:condition()].
Link to this function

ensure_is_valid(PathPattern)

-spec ensure_is_valid(PathPattern) -> ok | no_return() when PathPattern :: native_pattern().
Link to this function

from_binary(String)

-spec from_binary(String) -> PathPattern when String :: pattern(), PathPattern :: native_pattern().

Converts a Unix-like path to a native path.

This is the same as calling from_string(String). Therefore, it accepts Erlang strings or binaries and native paths.

See also: from_string/1.

Link to this function

from_string(String)

-spec from_string(String) -> PathPattern when String :: pattern(), PathPattern :: native_pattern().

Converts a Unix-like path to a native path.

The Unix-like string can be either an Erlang string or an Erlang binary.

For convenience, a native path is also accepted and returned as-is.
Link to this function

is_valid(PathPattern)

-spec is_valid(PathPattern) -> IsValid
            when
                PathPattern :: native_pattern(),
                IsValid :: true | {false, ComponentPattern},
                ComponentPattern :: pattern_component().
Link to this function

pattern_includes_root_node(Path)

-spec realpath(Path) -> Path when Path :: native_pattern().
Link to this function

targets_specific_node(PathPattern)

-spec targets_specific_node(PathPattern) -> Ret
                         when
                             PathPattern :: native_pattern(),
                             Ret :: {true, Path} | false,
                             Path :: native_path().
Link to this function

to_binary(NativePath)

-spec to_binary(NativePath) -> UnixPath when NativePath :: native_path(), UnixPath :: binary().
Converts a native path to a binary.
Link to this function

to_string(NativePath)

-spec to_string(NativePath) -> UnixPath when NativePath :: native_path(), UnixPath :: string().
Converts a native path to a string.