1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
mod component;
use std::fmt::{
self,
Formatter,
};
use crate::{
model::{
template::component::Component,
value::Values,
},
process::{
expand::{
Expand,
Expansion,
},
parse::{
ParseError,
// ParseRef,
TryParse,
},
},
};
// =============================================================================
// Template
// =============================================================================
// Types
/// The `Template` type is the basis for most simple tasks. Parsing and
/// expansion are both template functions.
#[derive(Debug, Eq, PartialEq)]
pub struct Template<'t> {
components: Vec<Component<'t>>,
}
impl<'t> Template<'t> {
/// Creates a new `Expansion` using the given `Values`, which may then be
/// rendered using the `to_string` function provided by the `Display` trait.
///
/// ```
/// # use uri_template_system_core::{ Template, Values, Value };
/// #
/// let template = Template::parse("hello/{name}!").unwrap();
/// let values = Values::default().add("name", Value::item("world"));
///
/// assert_eq!("hello/world!", template.expand(&values).to_string());
#[must_use]
pub const fn expand<'e>(&'e self, values: &'e Values) -> Expansion<'e, 't> {
Expansion::new(self, values)
}
/// Parses a string representing a potential template, and returns a new
/// template instance if valid. See <https://datatracker.ietf.org/doc/html/rfc6570>
/// for the grammar of a valid URI Template. `uri-template-system` supports
/// all operators and modifiers up-to and including Level 4.
///
/// ```
/// # use uri_template_system_core::Template;
/// #
/// let template = Template::parse("my/valid/{template}");
///
/// assert!(template.is_ok());
/// ```
pub fn parse(raw: &'t str) -> Result<Self, ParseError> {
Self::try_parse(raw, 0).map(|(_, template)| template)
}
const fn new(components: Vec<Component<'t>>) -> Self {
Self { components }
}
}
// -----------------------------------------------------------------------------
// Parse
impl<'t> TryParse<'t> for Template<'t> {
fn try_parse(raw: &'t str, global: usize) -> Result<(usize, Self), ParseError> {
Vec::<Component<'t>>::try_parse(raw, global)
.map(|(position, components)| (position, Self::new(components)))
}
}
// -----------------------------------------------------------------------------
// Expand
impl<'t> Expand for Template<'t> {
fn expand(&self, values: &Values, f: &mut Formatter<'_>) -> fmt::Result {
self.components
.iter()
.try_for_each(|component| component.expand(values, f))
}
}