Search results

There are no results.

std.uri.Values

type pub inline Values

A mapping of URI/percent-encoded key-value pairs.

RFC 3986 doesn't specify how exactly a URI encoded/query string should be interpreted. This type separates pairs using a & and separates the key and value using a =. The characters &, =, ? and # (along with multi-byte characters) are percent-encoded when found in a key or value.

Duplicate pairs are allowed, meaning the query string ?key=10&key=20 results in a mapping containing two values for key.

While the keys of each pair are a String and thus must be valid UTF-8, the values are ByteArray values, allowing for arbitrary bytes (after percent decoding) as the values.

The order of key-value pairs is the same as the order in which they are inserted, similar to std.map.Map.

Examples

import std.uri (Values)

let map = Values.new

map.add('name', 'Alice')
map.add('age', '42')
map.add('name', 'Bob')
map.add('age', '50')

map.to_string # => 'name=Alice&age=42&name=Bob&age=50'

Static methods

new

Show source code
Hide source code
fn pub static new -> Values {
  Values(Map.new)
}
fn pub static new -> Values

Returns an empty Values.

Examples

import std.uri (Values)

Values.new.size # => 0

parse

Show source code
Hide source code
fn pub static parse[B: Bytes](input: ref B) -> Option[Values] {
  let map = Values.new

  for chunk in Slice.new(input, 0, input.size).split('&') {
    if chunk.empty? { next }

    match chunk.split_once('=') {
      case Some((lhs, rhs)) -> {
        let key = try parse_query(lhs)
        let val = try parse_query(rhs)

        map.add(key.into_string, val)
      }
      case _ -> {
        let key = try parse_query(chunk)

        map.add(key.into_string, ByteArray.new)
      }
    }
  }

  Option.Some(map)
}
fn pub static parse[B: Bytes](input: ref B) -> Option[Values]

Parses and decodes a URI encoded set of key-value pairs.

If the input is invalid (e.g. it contains invalid percent-encoded sequences), an Option.None is returned.

RFC 3986 doesn't specify how exactly a query string should be interpreted. This method follows the widely adopted approach of splitting pairs on a & and splitting keys and values on the first =.

Duplicate pairs are allowed, meaning ?key=10&key=20 yields the pairs ('key', 10) and ('key', 20).

Examples

import std.uri (Values)

let map = Values.parse('name=Alice&age=42').get

map.string('name') # => Result.Ok('Alice')
map.string('age') # => Result.Ok('42')

Instance methods

!=

Show source code
Hide source code
fn pub !=(other: ref Self) -> Bool {
  !(self == other)
}
fn pub !=(other: ref Self) -> Bool

Returns true if self and the given object are not equal to each other.

==

Show source code
Hide source code
fn pub ==(other: ref Values) -> Bool {
  @map == other.map
}
fn pub ==(other: ref Values) -> Bool

Returns true if self and the given object are equal to each other.

This operator is used to perform structural equality. This means two objects residing in different memory locations may be considered equal, provided their structure is equal. For example, two different arrays may be considered to have structural equality if they contain the exact same values.

add

Show source code
Hide source code
fn pub mut add[B: Bytes](name: String, value: ref B) {
  let value = value.to_byte_array

  match @map.try_set(name, QueryValue.Single(value)) {
    case Error((name, Single(_), Single(new))) -> {
      let ex = match @map.remove(name) {
        case Ok(Single(v)) -> v
        case _ -> panic('unreachable')
      }

      @map.set(name, QueryValue.Multiple([ex, new]))
    }
    case Error((_, Multiple(ex), Single(new))) -> ex.push(new)
    case _ -> {}
  }
}
fn pub mut add[B: Bytes](name: String, value: ref B)

Adds a key-value pair to self.

If the key is already present, the value is added to the list instead of overwriting the previous value.

Examples

import std.uri (Values)

let map = Values.new

map.add('name', 'Alice')
map.add('name', 'Bob')

clear

Show source code
Hide source code
fn pub mut clear {
  @map.clear
}
fn pub mut clear

Removes all key-value pairs in self.

Examples

import std.uri (Values)

let map = Values.new

map.add('name', 'Alice')
map.add('name', 'Bob')
map.clear

map.size # => 0

clone

Show source code
Hide source code
fn pub clone -> Self {
  Self(@map.clone)
}
fn pub clone -> Values

Creates a clone of self.

The returned value is an owned value that is the same type as the receiver of this method. For example, cloning a ref Array[Int] results in a Array[Int], not another ref Array[Int].

encode

Show source code
Hide source code
fn pub encode(into: mut ByteArray) {
  let mut pairs = 0

  for (key, val) in @map.iter {
    match val {
      case Single(v) -> {
        if pairs > 0 { into.push(AMP) }

        encode_query_pair_into(key, v, into)
        pairs += 1
      }
      case Multiple(vals) -> {
        for val in vals.iter {
          if pairs > 0 { into.push(AMP) }

          encode_query_pair_into(key, val, into)
          pairs += 1
        }
      }
    }
  }
}
fn pub encode(into: mut ByteArray)

Encodes self as a sequence of bytes into the given ByteArray.

After encoding the data it can be safely used in a query string component or as the body for an application/x-www-form-urlencoded encoded form.

If you just want a String instead of writing the data to an existing ByteArray, use Values.to_string instead.

Examples

import std.uri (Values)

let buf = ByteArray.new
let map = Values.new

map.add('foo bar', 'value')
map.add('key#?&=', 'value#?&=')
map.encode(buf)

buf.to_string # => 'foo%20bar=value&key%23?%26%3D=value%23?%26%3D'

fmt

Show source code
Hide source code
fn pub fmt(formatter: mut Formatter) {
  formatter.object('Values').field('map', @map).finish
}
fn pub fmt(formatter: mut Formatter)

Formats self in a human-readable format for debugging purposes.

get

Show source code
Hide source code
fn pub get(name: String) -> Result[ref ByteArray, MissingKey[String]] {
  match value(name) {
    case Ok(Single(v)) -> Result.Ok(v)
    case Ok(Multiple(v)) -> Result.Ok(v.get(0).or_panic)
    case _ -> Result.Error(MissingKey.new(name))
  }
}
fn pub get(name: String) -> Result[ref ByteArray, MissingKey[String]]

Returns the first value of the given key.

If the key is missing, a MissingKey error is returned.

Examples

import std.uri (Values)

let map = Values.new

map.add('name', 'Alice')

map.get('name').map(fn (v) { v.to_string }) # => Result.Ok('Alice')
map.get('age') # => Result.Error(MissingKey(...))

get_all

Show source code
Hide source code
fn pub get_all(name: String) -> Stream[ref ByteArray] {
  match @map.get(name) {
    case Ok(Single(v)) -> {
      let mut done = false

      Stream.new(fn move {
        if done := true { Option.None } else { Option.Some(v) }
      })
    }
    case Ok(Multiple(v)) -> v.iter
    case _ -> Stream.new(fn move { Option.None })
  }
}
fn pub get_all(name: String) -> Stream[ref ByteArray]

Returns an iterator over all the values of the given key.

If the key isn't assigned any values, the returned iterator yields no values.

Examples

import std.uri (Values)

let map = Values.new

map.add('name', 'Alice')
map.add('name', 'Bob')

let iter = map.get_all('name')

iter.next.map(fn (v) { v.to_string }) # => Option.Some('Alice')
iter.next.map(fn (v) { v.to_string }) # => Option.Some('Bob')

keys

Show source code
Hide source code
fn pub keys -> Stream[String] {
  @map.keys
}
fn pub keys -> Stream[String]

Returns an iterator over the parameter names.

Examples

import std.uri (Values)

let map = Values.new

map.add('name', 'Alice')
map.add('name', 'Bob')

let iter = map.keys

iter.next # => Option.Some(('name'))
iter.next # => Option.None

remove

Show source code
Hide source code
fn pub mut remove[B: Bytes](name: String, value: ref B) {
  let rm = match @map.get_mut(name) {
    case Ok(Single(v)) -> v.equals?(value)
    case Ok(Multiple(v)) -> {
      v.remove_if(fn (v) { v.equals?(value) })
      v.empty?
    }
    case _ -> false
  }

  if rm { @map.remove(name) }
}
fn pub mut remove[B: Bytes](name: String, value: ref B)

Removes all key-value pairs that match the given key and value.

Examples

import std.uri (Values)

let map = Values.new

map.add('name', 'Alice')
map.add('name', 'Bob')
map.remove('name', 'Alice')

map.get('name').map(fn (v) { v.to_string }) # => Result.Ok('Bob')

remove_all

Show source code
Hide source code
fn pub mut remove_all(name: String) {
  @map.remove(name)
}
fn pub mut remove_all(name: String)

Removes all values of the key name.

Examples

import std.uri (Values)

let map = Values.new

map.add('name', 'Alice')
map.add('name', 'Bob')
map.remove_all('name')

map.get('name') # => Result.Error(MissingKey(...))
map.size # => 0

size

Show source code
Hide source code
fn pub inline size -> Int {
  @map.size
}
fn pub inline size -> Int

Returns the number of key-value pairs in self.

Examples

import std.uri (Values)

let map = Values.new

map.size # => 0

map.add('name', 'Alice')
map.size # => 1

string

Show source code
Hide source code
fn pub string(name: String) -> Result[String, MissingKey[String]] {
  match get(name) {
    case Ok(v) -> Result.Ok(v.to_string)
    case Error(e) -> Result.Error(e)
  }
}
fn pub string(name: String) -> Result[String, MissingKey[String]]

Returns the first value of the given key, returning it as a String.

By far the most common case when working with URI encoded key-value pairs is to retrieve a single value as a String. Using this method you don't need to manually map the Result[ref ByteArray, ...] from Values.get to a Result[String, ...].

Refer to the documentation of Values.get for more details.

Examples

import std.uri (Values)

let map = Values.new

map.add('name', 'Alice')

map.string('name') # => Result.Ok('Alice')
map.string('age') # => Result.Error(MissingKey(...))

to_query

Show source code
Hide source code
fn pub to_query -> Query {
  Query(to_string)
}
fn pub to_query -> Query

Returns a Query containing the percent-encoded key-value pairs.

Examples

import std.uri (Uri, Values)

let uri = Uri.new
let map = Values.new

map.add('name', 'Alice')
uri.query = map.to_query
uri.to_string # => '?name=Alice'

to_string

Show source code
Hide source code
fn pub to_string -> String {
  let buf = ByteArray.new

  encode(buf)
  buf.into_string
}
fn pub to_string -> String

Returns a String containing the (optionally percent-encoded) key-value pairs as a URI compatible String.

value

Show source code
Hide source code
fn pub value(name: String) -> Result[ref QueryValue, MissingKey[String]] {
  @map.get(name)
}
fn pub value(name: String) -> Result[ref QueryValue, MissingKey[String]]

Returns the raw value of the given key.

If the key is missing, a MissingKey error is returned.

Examples

import std.uri (Values)

let map = Values.new

map.add('name', 'Alice')
map.value('name') # => Result.Ok(QueryValue.Single(...))

Implemented traits

std.clone.

Clone

impl Clone for Values
std.cmp.

Equal

impl Equal for Values
std.fmt.

Format

impl Format for Values
std.string.

ToString

impl ToString for Values