pub struct Interpolator<'i, 'p, R, E>where
    R: ReplacementProvider<'i, E>,{ /* private fields */ }
Expand description

Placeholder pattern interpolator.

The interpolator takes a pattern parser iterator and a replacement provider and generates a new iterator over elements.

The replacement may be any type, and the only bind is on the ReplacementProvider to be able to return an iterator over elements to be interplotted into the pattern in place of the placeholders based on the placeholder keys.

Examples

use icu_pattern::{
    InterpolatedKind, Interpolator, Parser, ParserOptions, Pattern,
};
use std::convert::TryInto;

#[derive(Debug, PartialEq)]
enum Element {
    Value(usize),
}

let pattern: Pattern<_> = Parser::new(
    "{0} days ago",
    ParserOptions {
        allow_raw_letters: true,
    },
)
.try_into()
.unwrap();

let replacements = vec![Element::Value(5)];

let mut interpolator = Interpolator::new(&pattern, &replacements);

let mut result = vec![];

while let Some(element) =
    interpolator.try_next().expect("Failed to advance iterator")
{
    result.push(element);
}

assert_eq!(
    result,
    &[
        InterpolatedKind::Element(&Element::Value(5)),
        InterpolatedKind::Literal(&" days ago".into()),
    ]
);

Type parameters

Lifetimes

  • i: The life time of an input pattern slice.
  • p: The life time of an input PatternToken, which is the life time of the string slice.

Element & Replacement Provider

In order to allow for wide range of inputs to be interpolated using the placeholder pattern, the Element and ReplacementProvider types are generic. This allows the consumer of the API to decide what elements the pattern should return and how will they be identified based on any type of key that can be parsed out of a string slice.

This design allows for the interpolator to remain agnostic and flexible and handles wide range of ownership and life time models.

To simplify the common use cases, the ReplacementProvider comes with implementations for Vec (where the placehoder key is usize) and HashMap (where the placeholder key is String) but the consumer is free to implement their own providers for any type they wish.

Design Decisions

The interpolator is written in an intentionally generic way to enable use against wide range of potential placeholder pattern models and use cases.

Fallible Iterator

Rust providers a strong support for iterators and iterator combinators, which fits very well into the design of this parser/interpolator model.

Unfortunately, Rust iterators at the moment are infallible, while parsers are inhereantely fallible. As such, the decision has been made to design the API in line with what we hope will become a trait signature of a fallible iterator in the future, rather than implementing a reversed infallible iterator (where the Item would be Option<Result<Item>>).

Since the interpolator chains on top of the Parser it inherits the same fallible iterator API and behavior.

Implementations§

source§

impl<'i, 'p, R, E> Interpolator<'i, 'p, R, E>where R: ReplacementProvider<'i, E>,

source

pub fn new(tokens: &'i [PatternToken<'p, R::Key>], replacements: &'i R) -> Self

Creates a new Interpolator.

Examples
use icu_pattern::{Interpolator, Parser, ParserOptions, Pattern};
use std::convert::TryInto;

enum Element {
    Literal(String),
    Token,
}

let pattern: Pattern<usize> = Parser::new(
    "{0}, {1}",
    ParserOptions {
        allow_raw_letters: false,
    },
)
.try_into()
.unwrap();
let replacements = vec![vec![Element::Token]];
let mut interpolator =
    Interpolator::<Vec<Vec<_>>, Element>::new(&pattern, &replacements);
source

pub fn try_next( &mut self ) -> Result<Option<InterpolatedKind<'i, 'p, E>>, InterpolatorError<R::Key>>where R::Key: Debug + FromStr + PartialEq + Clone, <R::Key as FromStr>::Err: Debug + PartialEq,

An iterator method that advances the iterator and returns the result of an attempt to interpolate parser and replacement provider tokens.

Examples
use icu_pattern::{
    InterpolatedKind, Interpolator, Parser, ParserOptions, Pattern,
};
use std::convert::TryInto;

#[derive(Debug, PartialEq)]
enum Element {
    TokenOne,
    TokenTwo,
}

let mut pattern: Pattern<_> = Parser::new(
    "{0}, {1}",
    ParserOptions {
        allow_raw_letters: false,
    },
)
.try_into()
.unwrap();

let replacements = vec![vec![Element::TokenOne], vec![Element::TokenTwo]];
let mut interpolator = Interpolator::new(&pattern, &replacements);

// A call to try_next() returns the next value…
assert_eq!(
    Ok(Some(InterpolatedKind::Element(&Element::TokenOne))),
    interpolator.try_next()
);
assert_eq!(
    Ok(Some(InterpolatedKind::Literal(&", ".into()))),
    interpolator.try_next()
);
assert_eq!(
    Ok(Some(InterpolatedKind::Element(&Element::TokenTwo))),
    interpolator.try_next()
);

// … and then `None` once it's over.
assert_eq!(Ok(None), interpolator.try_next());

Trait Implementations§

source§

impl<'i, 'p, R, E: Debug> Debug for Interpolator<'i, 'p, R, E>where R: ReplacementProvider<'i, E> + Debug, R::Key: Debug, R::Iter: Debug,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'i, 'p, R, E> RefUnwindSafe for Interpolator<'i, 'p, R, E>where R: RefUnwindSafe, <R as ReplacementProvider<'i, E>>::Iter: RefUnwindSafe, <R as ReplacementProvider<'i, E>>::Key: RefUnwindSafe,

§

impl<'i, 'p, R, E> Send for Interpolator<'i, 'p, R, E>where R: Sync, <R as ReplacementProvider<'i, E>>::Iter: Send, <R as ReplacementProvider<'i, E>>::Key: Sync,

§

impl<'i, 'p, R, E> Sync for Interpolator<'i, 'p, R, E>where R: Sync, <R as ReplacementProvider<'i, E>>::Iter: Sync, <R as ReplacementProvider<'i, E>>::Key: Sync,

§

impl<'i, 'p, R, E> Unpin for Interpolator<'i, 'p, R, E>where <R as ReplacementProvider<'i, E>>::Iter: Unpin,

§

impl<'i, 'p, R, E> UnwindSafe for Interpolator<'i, 'p, R, E>where R: RefUnwindSafe, <R as ReplacementProvider<'i, E>>::Iter: UnwindSafe, <R as ReplacementProvider<'i, E>>::Key: RefUnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.