Paths and steps¶
Two ways address a node. A Step is the real one; a dotted path is sugar over
it, smaller than it looks, and knowing exactly how small saves an afternoon.
Steps¶
root.Get(yamldoc.StringStep("server"), yamldoc.StringStep("port"))
servers.Get(yamldoc.IndexStep(0), yamldoc.StringStep("name"))
ports.Get(yamldoc.KeyStep(yamldoc.IntKey(8080)))
| Step | Matches |
|---|---|
StringStep(s) |
A mapping entry whose key is the string s, spelt exactly so; StringStep("a.b") is the key a.b |
IndexStep(i) |
The ith item of a sequence, zero-based; past the end is ErrNotFound |
KeyStep(k) |
A mapping entry whose key is semantically equal to the typed Key: IntKey(8) matches 8, 0o10 and 0x8; BoolKey(true) matches true; a NullKey matches ~; BigIntKey, FloatKey, TimeKey and BinaryKey reach keys no other library can address at all |
A StringStep matches string keys only. A key that resolves to an integer
under the document's schema is reached with KeyStep(IntKey(n)), not with
StringStep("n"). Where two entries have equal keys the lookup is
ErrAmbiguous rather than a guess.
Steps go through anchors and stop at aliases: an anchored mapping is walked
into with its anchor intact, and an alias is a reference, reached by
AliasTarget rather than walked through by accident.
Dotted paths¶
path = segment ( "." segment )*
segment = key index* | index+ (a bare index only as the first segment)
index = "[" digits "]"
A path is a dotted list of string mapping keys, each optionally followed by
bracketed integers, walked from the document root. A bracket means what
the container it lands on can take: on a sequence, [n] is the nth
item; on a mapping, it is the entry whose key is the integer n, matched
by value, so ports[8080] finds 8080: and 0x1F90: alike. There is no
wildcard, no filter, no negative index, no escape character and no quoting;
PathSteps splits on every dot, reads each [n] as an IndexStep, and
refuses an empty segment, a malformed bracket, a signed or zero-padded
index, or ] inside a key with ErrPath. The bracket rule is applied by
the Document helpers as they walk; a Step handed to Node.Get keeps
its own meaning, so IndexStep on a mapping is still ErrKind there.
doc.Get("server.tls.cert") // root → "server" → "tls" → "cert"
doc.Get("servers[0].port") // root → "servers" → item 0 → "port"
doc.Get("matrix[1][0]") // root → "matrix" → item 1 → item 0
doc.Get("ports[8080]") // root → "ports" → the entry keyed 8080
doc.Get("[0].name") // a root sequence: item 0 → "name"
doc.Get("") // the root
doc.Set("", value) // ErrPath: Set and Remove need a step
Sequence elements¶
doc.Get("servers") // the whole sequence
doc.Get("servers[1].name") // "beta"
doc.Get("servers[2]") // ErrNotFound: past the end
doc.Get("servers.name") // ErrKind: a sequence has no keys
doc.Get("servers[0][0]") // ErrNotFound: the first item has no key 0
Writing through an index follows the shape of the sequence rather than inventing one:
doc.Set(path, v) |
Effect |
|---|---|
servers[0].port |
replaces port in the first item, comments intact |
servers[1] |
replaces the second item whole |
servers[2] |
appends, because 2 is the sequence's length |
servers[5] |
ErrNotFound: a gap cannot be filled in |
ports[9090] when ports is a mapping |
writes the entry keyed by the integer 9090, creating it if absent |
groups[0].name when groups is absent |
creates groups as a one-item sequence holding {name: v}: a bracket never creates a mapping |
groups[1].name when groups is absent |
ErrNotFound: only [0] can start a new sequence |
doc.Remove("servers[0]") removes the item, and the items that survive keep
their comments. Inside Edit, the same reach is IndexStep, with
tx.Insert(servers, IndexStep(i), v) to add before i and tx.Replace to
change an item in place.
Keys containing a dot¶
A path cannot reach a.b: because it reads as two segments, and it cannot
reach a key containing [ or ] either, because those read as an index.
Such a key is listed by Entries like any other, and StringStep reaches
it; see
Edit a value for writing one.
Non-string keys¶
doc.Get("ports.8080") compares the string 8080 to keys and finds nothing
under a schema where 8080 is an integer; doc.Get("ports[8080]") finds
it, because a bracket on a mapping is an integer key. Any other key type,
a boolean, a float, a timestamp, needs KeyStep, or Lookup(key) from
Node.Mapping().