}
b'^' => {
let (index, rest) = consume_int(iter.as_slice());
- if (1..=args.len()).contains(&index) && !args[index - 1].is_empty() {
- write!(f, "{}", args[index - 1][0].display(&self.table))?;
- }
iter = rest.iter();
+ let Some(arg) = args.get(index.wrapping_sub(1)) else {
+ continue;
+ };
+ if let Some(arg) = arg.get(0) {
+ write!(f, "{}", arg.display(&self.table))?;
+ }
}
b'[' => {
let (a, rest) = extract_inner_template(iter.as_slice());
let (b, rest) = extract_inner_template(rest);
let rest = rest.strip_prefix(b"]").unwrap_or(rest);
+ let (index, rest) = consume_int(rest);
+ iter = rest.iter();
+
+ let Some(mut args) = args.get(index.wrapping_sub(1)).map(|vec| vec.as_slice())
+ else {
+ continue;
+ };
+ let (mut template, mut escape) =
+ if !a.is_empty() { (a, b'%') } else { (b, b'^') };
+ while !args.is_empty() {
+ let n_consumed = self.inner_template(f, template, escape, args)?;
+ if n_consumed == 0 {
+ break;
+ }
+ args = &args[n_consumed..];
+
+ template = b;
+ escape = b'^';
+ }
+ }
+ c => write!(f, "{c}")?,
+ }
+ }
+ Ok(())
+ }
+
+ fn inner_template<'c>(
+ &self,
+ f: &mut std::fmt::Formatter<'_>,
+ template: &[u8],
+ escape: u8,
+ args: &[Value],
+ ) -> Result<usize, std::fmt::Error> {
+ let mut iter = template.iter();
+ let mut args_consumed = 0;
+ while let Some(c) = iter.next() {
+ match c {
+ b'\\' => {
+ let c = *iter.next().unwrap_or(&b'\\') as char;
+ let c = if c == 'n' { '\n' } else { c };
+ write!(f, "{c}")?;
+ }
+ c if *c == escape => {
+ let (index, rest) = consume_int(iter.as_slice());
iter = rest.iter();
+ let Some(arg) = args.get(index.wrapping_sub(1)) else {
+ continue;
+ };
+ args_consumed = args_consumed.max(index);
+ write!(f, "{}", arg.display(&self.table))?;
}
c => write!(f, "{c}")?,
}
}
- todo!()
+ Ok(args_consumed)
}
}
}
fn extract_inner_template(input: &[u8]) -> (&[u8], &[u8]) {
- todo!()
+ for (index, c) in input.iter().copied().enumerate() {
+ if c == b':' && (index == 0 || input[index-1] != b'\\') {
+ return input.split_at(index);
+ }
+ }
+ (input, &[])
}
fn interpret_show(