ankql/
conversion.rs

1use crate::ast::Predicate;
2use crate::ast::{self, Selection};
3use crate::error::ParseError;
4use crate::parser;
5use std::convert::TryFrom;
6
7impl<'a> TryFrom<&'a str> for Predicate {
8    type Error = ParseError;
9
10    fn try_from(value: &'a str) -> Result<Self, Self::Error> { Ok(parser::parse_selection(value)?.predicate) }
11}
12impl TryFrom<String> for Predicate {
13    type Error = ParseError;
14
15    fn try_from(value: String) -> Result<Self, Self::Error> { Ok(parser::parse_selection(&value)?.predicate) }
16}
17impl<'a> TryFrom<&'a str> for Selection {
18    type Error = ParseError;
19
20    fn try_from(value: &'a str) -> Result<Self, Self::Error> { parser::parse_selection(value) }
21}
22impl TryFrom<String> for Selection {
23    type Error = ParseError;
24
25    fn try_from(value: String) -> Result<Self, Self::Error> { parser::parse_selection(&value) }
26}
27
28impl TryFrom<ast::Expr> for Predicate {
29    type Error = ParseError;
30
31    fn try_from(value: ast::Expr) -> Result<Self, Self::Error> {
32        match value {
33            ast::Expr::Predicate(p) => Ok(p),
34            ast::Expr::Placeholder => Ok(Predicate::Placeholder),
35            ast::Expr::Literal(ast::Literal::Bool(true)) => Ok(Predicate::True),
36            ast::Expr::Literal(ast::Literal::Bool(false)) => Ok(Predicate::False),
37            _ => Err(ParseError::InvalidPredicate("Expression is not a predicate".into())),
38        }
39    }
40}
41
42#[cfg(feature = "wasm")]
43impl TryFrom<wasm_bindgen::JsValue> for ast::Expr {
44    type Error = ParseError;
45
46    fn try_from(value: wasm_bindgen::JsValue) -> Result<Self, Self::Error> {
47        if value.is_null() || value.is_undefined() {
48            // TASK: Add NULL literal to ankql AST https://github.com/ankurah/ankurah/issues/143
49            return Ok(ast::Expr::Literal(ast::Literal::String("NULL_IMPROBABLE_VALUE".to_string())));
50        }
51
52        // Try string first
53        if let Some(s) = value.as_string() {
54            return Ok(ast::Expr::Literal(ast::Literal::String(s)));
55        }
56
57        // Try boolean
58        if let Some(b) = value.as_bool() {
59            return Ok(ast::Expr::Literal(ast::Literal::Bool(b)));
60        }
61
62        // Try number
63        if let Some(n) = value.as_f64() {
64            // Use I64 for integers, F64 for floats
65            if n.fract() == 0.0 {
66                let n_int = n as i64;
67                return Ok(ast::Expr::Literal(ast::Literal::I64(n_int)));
68            } else {
69                return Ok(ast::Expr::Literal(ast::Literal::F64(n)));
70            }
71        }
72
73        // If nothing matches, return error
74        Err(ParseError::InvalidPredicate("Unsupported JsValue type for conversion to Expr".into()))
75    }
76}