Reference

std/uri/template

std/uri/src/template.trb

UriTemplate: RFC 6570, all four levels - read once, expanded into a URI reference, and matched backwards where the template allows it (docs/design/URI.md section 9a).

type TemplateValue

type TemplateValue with Show, Equals, Hash

What a variable of a template holds: RFC 6570 section 2.3's three kinds of value. A variable that is not in the map handed to UriTemplate.expanded is undefined, and so is an empty list or an empty list of pairs.

case Text

case Text(value: String)

A string: {name} with Text("Ada") is Ada.

case Items

case Items(values: List<String>)

A list: {/path*} with Items(["a", "b"]) is /a/b.

case Pairs

case Pairs(values: List<(String, String)>)

An associative array, in order: {?keys*} with Pairs([("a", "1")]) is ?a=1.

type UriTemplate

type UriTemplate<Variables> with Show, Equals, Hash, TryFrom<String, UriError>

An RFC 6570 URI template: literal text and {…} expressions, read once with UriTemplate.tryFrom and expanded with variables into a URI reference - "/orders/{id}{?fields*}" with id = 7 and fields = ["a", "b"] is /orders/7?fields=a&fields=b.

The four levels are all there: simple strings ({var}), reserved and fragment expansion ({+var}, {#var}), the label, path, parameter and query operators with several variables ({.x,y}, {/x}, {;x}, {?x,y}, {&x}), and the prefix and explode modifiers ({var:3}, {list*}).

Variables is the type whose fields the variables are (docs/design/URI.md section 9a): a string literal where a UriTemplate<Order> is expected is read by the compiler, and a variable that is not a field of Order - or a field without a default that is no variable - is an error at the literal. UriTemplate.expandedFrom and UriTemplate.decoded go through the fields; TemplateValues is the type of a template read at run time, whose variables are whatever the map holds. Inside such a literal {id} is the template's own brace and never an interpolation, so it needs no raw.

Examples

const template: UriTemplate<TemplateValues> = "/orders/{id}{?fields}"
var values: TemplateValues = [:]
values["id"] = TemplateValue.Text "7"
print template.expanded(values)

Pitfalls

  • Matching reads a template backwards only where that is unambiguous; UriTemplate.isMatchable says whether it is.
  • A typed template read at run time, UriTemplate<Order>.tryFrom(text), is checked against Order only when it is expanded or matched; a literal is checked where it is written.

Related

  • TemplateValue - what a variable holds.
  • TemplateRoutes of std/uri - templates typed against the cases of one type, which is what a router holds.

fn tryFrom

static fn tryFrom(value: String): Result<UriTemplate<Variables>, UriError>

A text read as an RFC 6570 template.

Errors

  • UriError.InvalidTemplate for an unclosed or a nested brace, an empty expression, a variable name outside varchar, a prefix outside 1 to 9999, a reserved operator (=, ,, !, @, |), and a literal character no URI may hold.

fn templateVariables

fn templateVariables(): List<TemplateVariable>

Every variable once, in the order it first appears, with what kind of value fills it: what a value of Variables is checked against.

fn expandedFrom

fn expandedFrom(values: Variables): Result<UriReference, UriError> where Variables: Encode

The template expanded with the fields of values: each field is the variable of its name, a list field an exploded one, and a field that is None an undefined variable. Fields no variable names are left out.

Errors

fn decoded

fn decoded(reference: UriReference): Variables? where Variables: Decode

The fields of reference read back into a Variables, where the reference is an expansion of this template: the text of each variable is read as whatever its field asks for, and a variable the reference leaves out is a field that is absent, so its default applies. None where UriTemplate.matched answers None or a field cannot be read.

fn variables

fn variables(): List<String>

The names of the variables, in the order they first appear.

fn level

fn level(): Int

The lowest of RFC 6570's four levels that has every expression of this template.

fn expandedText

fn expandedText(values: TemplateValues): Result<String, UriError>

The template expanded with values, as RFC 6570 section 3 writes it. A variable that is not in values is undefined and expands to nothing.

Errors

fn expanded

fn expanded(values: TemplateValues): Result<UriReference, UriError>

The template expanded with values and read as the URI reference it is.

Errors

  • UriError.InvalidTemplate as for UriTemplate.expandedText.
  • Any refusal of UriReference.tryFrom, where the literal parts of the template do not make a URI reference with the values in them ({x}:y with x = 1a). A template whose literal parts are a path never fails here.

fn isMatchable

fn isMatchable(): Bool

Whether UriTemplate.matched can read this template backwards: its expressions are simple ones ({name}, {a,b}), path segments ({/name}, {/name*} last in the path) and query parameters ({?a,b}, {&c}), no prefix is used, and no two expressions of the path stand side by side without a literal between them.

fn matched

fn matched(reference: UriReference): TemplateValues?

The values that expand this template into reference, decoded: a simple or path variable as Text, an exploded path variable as Items, a query variable as Text where the query has it. None where the reference is not an expansion of the template, and for every template that is not UriTemplate.isMatchable. Query parameters the template does not name are ignored, and a name that appears twice takes its first value.

Examples

const template: UriTemplate<TemplateValues> = "/orders/{id}{?fields}"
const reference: UriReference = "/orders/7?fields=total"
print template.matched(reference)

fn show

fn show(): String

The template as it was written.

alias TemplateValues

type TemplateValues = Map<String, TemplateValue>

The variables of a template read at run time: whatever the map holds, by name. UriTemplate<TemplateValues> is the untyped template.

extend String with From<UriTemplate<TemplateValues>>

extend String with From<UriTemplate<TemplateValues>>

The way back out of an untyped UriTemplate, and with UriTemplate.tryFrom its conversion pair. A typed one has none: an extension cannot be generic, so show() is its text.

fn from

static fn from(value: UriTemplate<TemplateValues>): String

type TemplateVariable

type TemplateVariable with Show, Equals, Hash

One variable of a template, as a value that fills it sees it (UriTemplate.templateVariables).

field name

name: String

The name, as the template writes it.

field isOptional

isOptional: Bool

Whether it stands in a query expression ({?a}, {&b}), so that a matched reference may leave it out.

field isExploded

isExploded: Bool

Whether it is exploded ({/path*}), so that its value is a list.