tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

text_elements.rs (5059B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 use fluent::FluentResource;
      6 use fluent_syntax::ast;
      7 use nsstring::nsCString;
      8 use thin_vec::ThinVec;
      9 
     10 #[repr(C)]
     11 pub struct TextElementInfo {
     12    id: nsCString,
     13    attr: nsCString,
     14    text: nsCString,
     15 }
     16 
     17 struct TextElementsCollector<'a> {
     18    current_id: Option<String>,
     19    current_attr: Option<String>,
     20    elements: &'a mut ThinVec<TextElementInfo>,
     21 }
     22 
     23 impl<'a> TextElementsCollector<'a> {
     24    pub fn new(elements: &'a mut ThinVec<TextElementInfo>) -> Self {
     25        Self {
     26            current_id: None,
     27            current_attr: None,
     28            elements,
     29        }
     30    }
     31 
     32    fn collect_inline_expression(&mut self, x: &ast::InlineExpression<&str>) {
     33        match x {
     34            ast::InlineExpression::StringLiteral { .. } => {}
     35            ast::InlineExpression::NumberLiteral { .. } => {}
     36            ast::InlineExpression::FunctionReference { arguments, .. } => {
     37                self.collect_call_arguments(arguments);
     38            }
     39            ast::InlineExpression::MessageReference { .. } => {}
     40            ast::InlineExpression::TermReference { arguments, .. } => {
     41                if let Some(y) = arguments {
     42                    self.collect_call_arguments(y);
     43                }
     44            }
     45            ast::InlineExpression::VariableReference { .. } => {}
     46            ast::InlineExpression::Placeable { expression } => {
     47                self.collect_expression(expression.as_ref());
     48            }
     49        }
     50    }
     51 
     52    fn collect_named_argument(&mut self, x: &ast::NamedArgument<&str>) {
     53        self.collect_inline_expression(&x.value);
     54    }
     55 
     56    fn collect_call_arguments(&mut self, x: &ast::CallArguments<&str>) {
     57        for y in x.positional.iter() {
     58            self.collect_inline_expression(y);
     59        }
     60        for y in x.named.iter() {
     61            self.collect_named_argument(y);
     62        }
     63    }
     64 
     65    fn collect_variant(&mut self, x: &ast::Variant<&str>) {
     66        self.collect_pattern(&x.value);
     67    }
     68 
     69    fn collect_expression(&mut self, x: &ast::Expression<&str>) {
     70        match x {
     71            ast::Expression::Select { selector, variants } => {
     72                self.collect_inline_expression(selector);
     73                for y in variants.iter() {
     74                    self.collect_variant(y);
     75                }
     76            }
     77            ast::Expression::Inline(i) => {
     78                self.collect_inline_expression(i);
     79            }
     80        }
     81    }
     82 
     83    fn collect_pattern_element(&mut self, x: &ast::PatternElement<&str>) {
     84        match x {
     85            ast::PatternElement::TextElement { value } => {
     86                self.elements.push(TextElementInfo {
     87                    id: self
     88                        .current_id
     89                        .as_ref()
     90                        .map_or_else(nsCString::new, nsCString::from),
     91                    attr: self
     92                        .current_attr
     93                        .as_ref()
     94                        .map_or_else(nsCString::new, nsCString::from),
     95                    text: nsCString::from(*value),
     96                });
     97            }
     98            ast::PatternElement::Placeable { expression } => {
     99                self.collect_expression(expression);
    100            }
    101        }
    102    }
    103 
    104    fn collect_pattern(&mut self, x: &ast::Pattern<&str>) {
    105        for y in x.elements.iter() {
    106            self.collect_pattern_element(y);
    107        }
    108    }
    109 
    110    fn collect_attribute(&mut self, x: &ast::Attribute<&str>) {
    111        self.current_attr = Some(x.id.name.to_string());
    112 
    113        self.collect_pattern(&x.value);
    114    }
    115 
    116    fn collect_message(&mut self, x: &ast::Message<&str>) {
    117        self.current_id = Some(x.id.name.to_string());
    118        self.current_attr = None;
    119 
    120        if let Some(ref y) = x.value {
    121            self.collect_pattern(y);
    122        }
    123        for y in x.attributes.iter() {
    124            self.collect_attribute(y);
    125        }
    126    }
    127 
    128    fn collect_term(&mut self, x: &ast::Term<&str>) {
    129        self.current_id = Some(x.id.name.to_string());
    130        self.current_attr = None;
    131 
    132        self.collect_pattern(&x.value);
    133        for y in x.attributes.iter() {
    134            self.collect_attribute(y);
    135        }
    136    }
    137 
    138    pub fn collect_entry(&mut self, x: &ast::Entry<&str>) {
    139        match x {
    140            ast::Entry::Message(m) => {
    141                self.collect_message(m);
    142            }
    143            ast::Entry::Term(t) => {
    144                self.collect_term(t);
    145            }
    146            ast::Entry::Comment(_) => {}
    147            ast::Entry::GroupComment(_) => {}
    148            ast::Entry::ResourceComment(_) => {}
    149            ast::Entry::Junk { .. } => {}
    150        }
    151    }
    152 }
    153 
    154 #[no_mangle]
    155 pub extern "C" fn fluent_resource_get_text_elements(
    156    res: &FluentResource,
    157    elements: &mut ThinVec<TextElementInfo>,
    158 ) {
    159    let mut collector = TextElementsCollector::new(elements);
    160 
    161    for entry in res.entries() {
    162        collector.collect_entry(entry);
    163    }
    164 }