Skip to main content

icu_pattern/
lib.rs

1// This file is part of ICU4X. For terms of use, please see the file
2// called LICENSE at the top level of the ICU4X source tree
3// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4
5// https://github.com/unicode-org/icu4x/blob/main/documents/process/boilerplate.md#library-annotations
6#![cfg_attr(not(any(test, doc)), no_std)]
7#![cfg_attr(
8    not(test),
9    deny(
10        clippy::indexing_slicing,
11        clippy::unwrap_used,
12        clippy::expect_used,
13        clippy::panic,
14    )
15)]
16// #![warn(missing_docs)]
17
18//! `icu_pattern` is a utility crate of the [`ICU4X`] project.
19//!
20//! It includes a [`Pattern`] type which supports patterns with various storage backends.
21//!
22//! The types are tightly coupled with the [`writeable`] crate.
23//!
24//! # Examples
25//!
26//! Parsing and interpolating with a single-placeholder pattern:
27//!
28//! ```
29//! use icu_pattern::SinglePlaceholderPattern;
30//! use writeable::assert_writeable_eq;
31//!
32//! // Parse a pattern string:
33//! let pattern = SinglePlaceholderPattern::try_from_str(
34//!     "Hello, {0}!",
35//!     Default::default(),
36//! )
37//! .unwrap();
38//!
39//! // Interpolate into the pattern string:
40//! assert_writeable_eq!(pattern.interpolate(["World"]), "Hello, World!");
41//! ```
42//!
43//! [`ICU4X`]: ../icu/index.html
44//! [`FromStr`]: core::str::FromStr
45
46#[cfg(feature = "alloc")]
47extern crate alloc;
48
49#[cfg(feature = "alloc")]
50mod builder;
51mod common;
52mod double;
53mod error;
54mod frontend;
55mod multi_named;
56#[cfg(feature = "alloc")]
57mod parser;
58mod single;
59
60#[doc(no_inline)]
61pub use PatternError as Error;
62#[cfg(feature = "unstable")]
63pub use common::ExtractionBackend;
64pub use common::PatternBackend;
65pub use common::PatternItem;
66#[cfg(feature = "alloc")]
67pub use common::PatternItemCow;
68pub use common::PlaceholderValueProvider;
69pub use common::TryWrap;
70pub use double::DoublePlaceholder;
71pub use double::DoublePlaceholderKey;
72pub use error::PatternError;
73pub use frontend::Pattern;
74#[cfg(feature = "unstable")]
75pub use frontend::PlaceholderMatches;
76#[cfg(feature = "serde")]
77pub use frontend::serde::*;
78pub use multi_named::MissingNamedPlaceholderError;
79pub use multi_named::MultiNamedPlaceholder;
80pub use multi_named::MultiNamedPlaceholderKey;
81#[cfg(feature = "alloc")]
82pub use parser::ParsedPatternItem;
83#[cfg(feature = "alloc")]
84pub use parser::Parser;
85#[cfg(feature = "alloc")]
86pub use parser::ParserError;
87#[cfg(feature = "alloc")]
88pub use parser::ParserOptions;
89#[cfg(feature = "alloc")]
90pub use parser::QuoteMode;
91pub use single::SinglePlaceholder;
92pub use single::SinglePlaceholderKey;
93
94mod private {
95    pub trait Sealed {}
96}
97
98/// # Examples
99///
100/// ```
101/// use core::str::FromStr;
102/// use icu_pattern::SinglePlaceholderPattern;
103/// use writeable::assert_writeable_eq;
104///
105/// // Create a pattern from the string syntax:
106/// let pattern = SinglePlaceholderPattern::try_from_str(
107///     "Hello, {0}!",
108///     Default::default(),
109/// )
110/// .unwrap();
111///
112/// // Interpolate some values into the pattern:
113/// assert_writeable_eq!(pattern.interpolate(["Alice"]), "Hello, Alice!");
114/// ```
115pub type SinglePlaceholderPattern = Pattern<SinglePlaceholder>;
116
117impl SinglePlaceholderPattern {
118    /// An instance of [`SinglePlaceholderPattern`] that has a single placeholder and adds no
119    /// prefix or suffix.
120    ///
121    /// # Examples
122    ///
123    /// ```
124    /// use icu_pattern::SinglePlaceholderPattern;
125    /// use writeable::assert_writeable_eq;
126    ///
127    /// assert_eq!(
128    ///     SinglePlaceholderPattern::PASS_THROUGH,
129    ///     &*SinglePlaceholderPattern::try_from_str("{0}", Default::default())
130    ///         .unwrap()
131    /// );
132    ///
133    /// assert_writeable_eq!(
134    ///     SinglePlaceholderPattern::PASS_THROUGH.interpolate(["hello, world!"]),
135    ///     "hello, world!"
136    /// );
137    /// ```
138    pub const PASS_THROUGH: &'static SinglePlaceholderPattern =
139        SinglePlaceholderPattern::from_ref_store_unchecked("\x01");
140}
141
142/// # Examples
143///
144/// ```
145/// use core::str::FromStr;
146/// use icu_pattern::DoublePlaceholderPattern;
147/// use writeable::assert_writeable_eq;
148///
149/// // Create a pattern from the string syntax:
150/// let pattern = DoublePlaceholderPattern::try_from_str(
151///     "Hello, {0} and {1}!",
152///     Default::default(),
153/// )
154/// .unwrap();
155///
156/// // Interpolate some values into the pattern:
157/// assert_writeable_eq!(
158///     pattern.interpolate(["Alice", "Bob"]),
159///     "Hello, Alice and Bob!"
160/// );
161/// ```
162pub type DoublePlaceholderPattern = Pattern<DoublePlaceholder>;
163
164/// # Examples
165///
166/// ```
167/// use core::str::FromStr;
168/// use icu_pattern::MultiNamedPlaceholderPattern;
169/// use std::collections::BTreeMap;
170/// use writeable::assert_try_writeable_eq;
171///
172/// // Create a pattern from the string syntax:
173/// let pattern = MultiNamedPlaceholderPattern::try_from_str(
174///     "Hello, {person0} and {person1}!",
175///     Default::default(),
176/// )
177/// .unwrap();
178///
179/// // Interpolate some values into the pattern:
180/// assert_try_writeable_eq!(
181///     pattern.try_interpolate(
182///         [("person0", "Alice"), ("person1", "Bob")]
183///             .into_iter()
184///             .collect::<BTreeMap<&str, &str>>()
185///     ),
186///     "Hello, Alice and Bob!"
187/// );
188/// ```
189pub type MultiNamedPlaceholderPattern = Pattern<MultiNamedPlaceholder>;
190
191#[test]
192#[cfg(feature = "alloc")]
193fn test_single_placeholder_pattern_impls() {
194    let a = SinglePlaceholderPattern::try_from_str("{0}", Default::default()).unwrap();
195    let b = SinglePlaceholderPattern::try_from_str("{0}", Default::default()).unwrap();
196    assert_eq!(a, b);
197    let c = b.clone();
198    assert_eq!(a, c);
199}