Crate sfv

source ·
Expand description

sfv crate is an implementation of Structured Field Values for HTTP as specified in RFC 8941 for parsing and serializing HTTP field values. It also exposes a set of types that might be useful for defining new structured fields.

Data Structures

There are three types of structured fields:

  • Item - can be an Integer, Decimal, String, Token, Byte Sequence, or Boolean. It can have associated Parameters.
  • List - array of zero or more members, each of which can be an Item or an InnerList, both of which can be Parameterized.
  • Dictionary - ordered map of name-value pairs, where the names are short textual strings and the values are Items or arrays of Items (represented with InnerList), both of which can be Parameterized. There can be zero or more members, and their names are unique in the scope of the Dictionary they occur within.

There’s also a few primitive types used to construct structured field values:

  • BareItem used as Item’s value or as a parameter value in Parameters.
  • Parameters are an ordered map of key-value pairs that are associated with an Item or InnerList. The keys are unique within the scope the Parameters they occur within, and the values are BareItem.
  • InnerList is an array of zero or more Items. Can have Parameters.
  • ListEntry represents either Item or InnerList as a member of List or as member-value in Dictionary.

Examples

Parsing

use sfv::Parser;

// Parsing structured field value of Item type.
let item_header_input = "12.445;foo=bar";
let item = Parser::parse_item(item_header_input.as_bytes());
assert!(item.is_ok());
println!("{:#?}", item);

// Parsing structured field value of List type.
let list_header_input = "1;a=tok, (\"foo\" \"bar\");baz, ()";
let list = Parser::parse_list(list_header_input.as_bytes());
assert!(list.is_ok());
println!("{:#?}", list);

// Parsing structured field value of Dictionary type.
let dict_header_input = "a=?0, b, c; foo=bar, rating=1.5, fruits=(apple pear)";
let dict = Parser::parse_dictionary(dict_header_input.as_bytes());
assert!(dict.is_ok());
println!("{:#?}", dict);

Getting Parsed Value Members

use sfv::*;

let dict_header = "u=2, n=(* foo 2)";
    let dict = Parser::parse_dictionary(dict_header.as_bytes()).unwrap();

    // Case 1 - handling value if it's an Item of Integer type
    let u_val = match dict.get("u") {
        Some(ListEntry::Item(item)) => item.bare_item.as_int(),
        _ => None,
    };

    if let Some(u_val) = u_val {
        println!("{}", u_val);
    }

    // Case 2 - matching on all possible types
    match dict.get("u") {
        Some(ListEntry::Item(item)) => match &item.bare_item {
            BareItem::Token(val) => {
                // do something if it's a Token
                println!("{}", val);
            }
            BareItem::Integer(val) => {
                // do something if it's an Integer
                println!("{}", val);
            }
            BareItem::Boolean(val) => {
                // do something if it's a Boolean
                println!("{}", val);
            }
            BareItem::Decimal(val) => {
                // do something if it's a Decimal
                println!("{}", val);
            }
            BareItem::String(val) => {
                // do something if it's a String
                println!("{}", val);
            }
            BareItem::ByteSeq(val) => {
                // do something if it's a ByteSeq
                println!("{:?}", val);
            }
        },
        Some(ListEntry::InnerList(inner_list)) => {
            // do something if it's an InnerList
            println!("{:?}", inner_list.items);
        }
        None => panic!("key not found"),
    }

Structured Field Value Construction and Serialization

Creates Item with empty parameters:

use sfv::{Item, BareItem, SerializeValue};

let str_item = Item::new(BareItem::String(String::from("foo")));
assert_eq!(str_item.serialize_value().unwrap(), "\"foo\"");

Creates Item field value with parameters:

use sfv::{Item, BareItem, SerializeValue, Parameters, Decimal, FromPrimitive};

let mut params = Parameters::new();
let decimal = Decimal::from_f64(13.45655).unwrap();
params.insert("key".into(), BareItem::Decimal(decimal));
let int_item = Item::with_params(BareItem::Integer(99), params);
assert_eq!(int_item.serialize_value().unwrap(), "99;key=13.457");

Creates List field value with Item and parametrized InnerList as members:

use sfv::{Item, BareItem, InnerList, List, SerializeValue, Parameters};

let tok_item = BareItem::Token("tok".into());

// Creates Item.
let str_item = Item::new(BareItem::String(String::from("foo")));

// Creates InnerList members.
let mut int_item_params = Parameters::new();
int_item_params.insert("key".into(), BareItem::Boolean(false));
let int_item = Item::with_params(BareItem::Integer(99), int_item_params);

// Creates InnerList.
let mut inner_list_params = Parameters::new();
inner_list_params.insert("bar".into(), BareItem::Boolean(true));
let inner_list = InnerList::with_params(vec![int_item, str_item], inner_list_params);


let list: List = vec![Item::new(tok_item).into(), inner_list.into()];
assert_eq!(
    list.serialize_value().unwrap(),
    "tok, (99;key=?0 \"foo\");bar"
);

Creates Dictionary field value:

use sfv::{Parser, Item, BareItem, SerializeValue, ParseValue, Dictionary};

let member_value1 = Item::new(BareItem::String(String::from("apple")));
let member_value2 = Item::new(BareItem::Boolean(true));
let member_value3 = Item::new(BareItem::Boolean(false));

let mut dict = Dictionary::new();
dict.insert("key1".into(), member_value1.into());
dict.insert("key2".into(), member_value2.into());
dict.insert("key3".into(), member_value3.into());

assert_eq!(
    dict.serialize_value().unwrap(),
    "key1=\"apple\", key2, key3=?0"
);

Structs

  • Decimal represents a 128 bit representation of a fixed-precision decimal number. The finite set of values of type Decimal are of the form m / 10e, where m is an integer such that -296 < m < 296, and e is an integer between 0 and 28 inclusive.
  • Array of Items with associated Parameters.
  • Represents Item type structured field value. Can be used as a member of List or Dictionary.
  • Exposes methods for parsing input into structured field value.
  • Serializes Dictionary field value components incrementally.
  • Serializes Item field value components incrementally.
  • Serializes List field value components incrementally.

Enums

  • BareItem type is used to construct Items or Parameters values.
  • Represents a member of List or Dictionary structured field value.
  • Similar to BareItem, but used to serialize values via RefItemSerializer, RefListSerializer, RefDictSerializer.

Traits

  • A generic trait for converting a number to a value.
  • Parse a value from a string
  • If structured field value of List or Dictionary type is split into multiple lines, allows to parse more lines and merge them into already existing structure field value.
  • Implements parsing logic for each structured field value type.
  • Serializes structured field value into String.

Type Aliases

  • Represents Dictionary type structured field value.
  • Represents List type structured field value.
  • Parameters of Item or InnerList.