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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
use super::scope::Scope; use super::{ResolverError, WriteValue}; use std::borrow::Borrow; use std::fmt; use fluent_syntax::ast; use crate::memoizer::MemoizerKind; use crate::resolver::ResolveValue; use crate::resource::FluentResource; use crate::types::FluentValue; const MAX_PLACEABLES: u8 = 100; impl<'p> WriteValue for ast::Pattern<&'p str> { fn write<'scope, 'errors, W, R, M: MemoizerKind>( &'scope self, w: &mut W, scope: &mut Scope<'scope, 'errors, R, M>, ) -> fmt::Result where W: fmt::Write, R: Borrow<FluentResource>, { let len = self.elements.len(); for elem in &self.elements { if scope.dirty { return Ok(()); } match elem { ast::PatternElement::TextElement { value } => { if let Some(ref transform) = scope.bundle.transform { w.write_str(&transform(value))?; } else { w.write_str(value)?; } } ast::PatternElement::Placeable { ref expression } => { scope.placeables += 1; if scope.placeables > MAX_PLACEABLES { scope.dirty = true; scope.add_error(ResolverError::TooManyPlaceables); return Ok(()); } let needs_isolation = scope.bundle.use_isolating && len > 1 && match expression { ast::Expression::InlineExpression( ast::InlineExpression::MessageReference { .. }, ) | ast::Expression::InlineExpression( ast::InlineExpression::TermReference { .. }, ) | ast::Expression::InlineExpression( ast::InlineExpression::StringLiteral { .. }, ) => false, _ => true, }; if needs_isolation { w.write_char('\u{2068}')?; } scope.maybe_track(w, self, expression)?; if needs_isolation { w.write_char('\u{2069}')?; } } } } Ok(()) } fn write_error<W>(&self, _w: &mut W) -> fmt::Result where W: fmt::Write, { unreachable!() } } impl<'p> ResolveValue for ast::Pattern<&'p str> { fn resolve<'source, 'errors, R, M: MemoizerKind>( &'source self, scope: &mut Scope<'source, 'errors, R, M>, ) -> FluentValue<'source> where R: Borrow<FluentResource>, { let len = self.elements.len(); if len == 1 { if let ast::PatternElement::TextElement { value } = self.elements[0] { return scope .bundle .transform .map_or_else(|| value.into(), |transform| transform(value).into()); } } let mut result = String::new(); self.write(&mut result, scope) .expect("Failed to write to a string."); result.into() } fn resolve_error(&self) -> String { unreachable!() } }