script/xpath/
mod.rs

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
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use context::EvaluationCtx;
6use eval::Evaluatable;
7pub(crate) use eval_value::{NodesetHelpers, Value};
8use parser::OwnedParserError;
9pub(crate) use parser::{Expr, parse as parse_impl};
10
11use super::dom::node::Node;
12
13mod context;
14#[allow(dead_code)]
15mod eval;
16mod eval_function;
17#[allow(dead_code)]
18mod eval_value;
19#[allow(dead_code)]
20mod parser;
21
22/// The failure modes of executing an XPath.
23#[derive(Debug, PartialEq)]
24pub(crate) enum Error {
25    /// The XPath was syntactically invalid
26    Parsing { source: OwnedParserError },
27    /// The XPath could not be executed
28    Evaluating { source: eval::Error },
29}
30
31impl std::fmt::Display for Error {
32    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
33        match self {
34            Error::Parsing { source } => write!(f, "Unable to parse XPath: {}", source),
35            Error::Evaluating { source } => write!(f, "Unable to evaluate XPath: {}", source),
36        }
37    }
38}
39
40impl std::error::Error for Error {
41    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
42        match self {
43            Error::Parsing { source } => Some(source),
44            Error::Evaluating { source } => Some(source),
45        }
46    }
47}
48
49/// Parse an XPath expression from a string
50pub(crate) fn parse(xpath: &str) -> Result<Expr, Error> {
51    match parse_impl(xpath) {
52        Ok(expr) => {
53            debug!("Parsed XPath: {:?}", expr);
54            Ok(expr)
55        },
56        Err(e) => {
57            debug!("Unable to parse XPath: {}", e);
58            Err(Error::Parsing { source: e })
59        },
60    }
61}
62
63/// Evaluate an already-parsed XPath expression
64pub(crate) fn evaluate_parsed_xpath(expr: &Expr, context_node: &Node) -> Result<Value, Error> {
65    let context = EvaluationCtx::new(context_node);
66    match expr.evaluate(&context) {
67        Ok(v) => {
68            debug!("Evaluated XPath: {:?}", v);
69            Ok(v)
70        },
71        Err(e) => {
72            debug!("Unable to evaluate XPath: {}", e);
73            Err(Error::Evaluating { source: e })
74        },
75    }
76}