runtime_format/
compiled.rs1use core::fmt;
2
3use crate::{parse::ParseSegment, FormatArgs, FormatError, FormatKey, ToFormatParser};
4
5pub struct ParsedFmt<'a> {
39 segments: tinyvec::TinyVec<[ParseSegment<'a>; 8]>,
40}
41
42impl<'a> ToFormatParser<'a> for ParsedFmt<'a> {
43 type Parser = std::iter::Copied<std::slice::Iter<'a, ParseSegment<'a>>>;
44
45 fn to_parser(&'a self) -> Self::Parser {
46 self.segments.iter().copied()
47 }
48
49 fn unparsed(_: Self::Parser) -> &'a str {
50 ""
51 }
52}
53
54impl fmt::Debug for ParsedFmt<'_> {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 f.debug_struct("CompiledFormatter")
57 .field("segments", &self.segments)
58 .finish()
59 }
60}
61
62impl<'a> ParsedFmt<'a> {
63 pub fn new(s: &'a str) -> Result<Self, FormatError<'a>> {
68 let mut segments = s.to_parser();
69 let this = Self {
70 segments: segments.by_ref().collect(),
71 };
72
73 if !segments.s.is_empty() {
74 Err(FormatError::Parse(segments.s))
75 } else {
76 Ok(this)
77 }
78 }
79
80 pub fn keys(&self) -> impl Iterator<Item = &'_ str> {
90 self.segments.iter().filter_map(|segment| match segment {
91 ParseSegment::Literal(_) => None,
92 ParseSegment::Key(key) => Some(*key),
93 })
94 }
95
96 pub fn with_args<'fs, 'fk, F: FormatKey>(
98 &'fs self,
99 fmt: &'fk F,
100 ) -> FormatArgs<'fs, 'fk, Self, F> {
101 FormatArgs::new(self, fmt)
102 }
103}
104
105impl<'a> TryFrom<&'a str> for ParsedFmt<'a> {
106 type Error = FormatError<'a>;
107
108 fn try_from(value: &'a str) -> Result<Self, Self::Error> {
109 Self::new(value)
110 }
111}
112
113impl<'a> FromIterator<ParseSegment<'a>> for ParsedFmt<'a> {
114 fn from_iter<T: IntoIterator<Item = ParseSegment<'a>>>(iter: T) -> Self {
115 Self {
116 segments: FromIterator::from_iter(iter),
117 }
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use core::fmt;
124
125 use crate::{FormatError, FormatKey, FormatKeyError};
126
127 use super::ParsedFmt;
128
129 struct Message;
130 impl FormatKey for Message {
131 fn fmt(&self, key: &str, f: &mut fmt::Formatter<'_>) -> Result<(), FormatKeyError> {
132 match key {
133 "recipient" => f.write_str("World").map_err(FormatKeyError::Fmt),
134 "time_descriptor" => f.write_str("morning").map_err(FormatKeyError::Fmt),
135 _ => Err(FormatKeyError::UnknownKey),
136 }
137 }
138 }
139
140 #[test]
141 fn compiled_happy_path() {
142 let formatter =
143 ParsedFmt::new("Hello, {recipient}. Hope you are having a nice {time_descriptor}.")
144 .unwrap();
145 let expected = "Hello, World. Hope you are having a nice morning.";
146 assert_eq!(formatter.with_args(&Message).to_string(), expected);
147 }
148
149 #[test]
150 fn compiled_failed_parsing() {
151 let err =
152 ParsedFmt::new("Hello, {recipient}. Hope you are having a nice {time_descriptor.")
153 .unwrap_err();
154 assert_eq!(err, FormatError::Parse("time_descriptor."));
155 }
156
157 #[test]
158 fn compiled_keys() {
159 let parsed =
160 ParsedFmt::new("Hello, {recipient}. Hope you are having a nice {time_descriptr}.")
161 .unwrap();
162 let keys: Vec<_> = parsed.keys().collect();
163 assert_eq!(keys, ["recipient", "time_descriptr"]);
164 }
165}