mabel_eno/queries/
embed_query.rs

1use std::str::FromStr;
2
3use crate::elements::{Document, Element, Embed, EmbedImpl, Section};
4use crate::queries::{SectionQuery, SectionQueryImpl};
5use crate::{Error, Printer};
6
7pub struct EmbedQuery<'a> {
8    element_option: Option<&'a Embed>,
9    key: Option<String>,
10    parent: EmbedQueryParent<'a>,
11}
12
13pub trait EmbedQueryImpl<'a> {
14    #[allow(clippy::new_ret_no_self)]
15    fn new(
16        element_option: Option<&'a Embed>,
17        key: Option<String>,
18        parent: EmbedQueryParent<'a>,
19    ) -> EmbedQuery<'a>;
20}
21
22pub enum EmbedQueryParent<'a> {
23    Document(&'a Document),
24    Section(&'a Section),
25    SectionQuery(&'a SectionQuery<'a>),
26}
27
28impl<'a> EmbedQuery<'a> {
29    pub fn missing_error(&self) -> Error {
30        match self.parent {
31            EmbedQueryParent::Document(_) => Error::new(
32                format!(
33                    "Embed {} not found",
34                    self.key.as_deref().unwrap_or("(can have any key)")
35                ),
36                Document::LINE_NUMBER,
37            ),
38            EmbedQueryParent::Section(section) => Error::new(
39                format!(
40                    "Embed {} not found",
41                    self.key.as_deref().unwrap_or("(can have any key)")
42                ),
43                section.line_number,
44            ),
45            EmbedQueryParent::SectionQuery(section_query) => match section_query.element() {
46                Some(section) => Error::new(
47                    format!(
48                        "Embed {} not found",
49                        self.key.as_deref().unwrap_or("(can have any key)")
50                    ),
51                    section.line_number,
52                ),
53                None => section_query.missing_error(),
54            },
55        }
56    }
57
58    pub fn optional_value(&self) -> Result<Option<String>, Error> {
59        match &self.element_option {
60            Some(embed) => match &embed.get_value() {
61                Some(value) => Ok(Some(value.to_string())),
62                None => Ok(None),
63            },
64            None => Err(self.missing_error()),
65        }
66    }
67
68    pub fn required_value<T: FromStr>(&self) -> Result<T, Error>
69    where
70        <T as FromStr>::Err: std::fmt::Display,
71    {
72        match &self.element_option {
73            Some(embed) => match &embed.get_value() {
74                Some(value) => match value.parse::<T>() {
75                    Ok(converted) => Ok(converted),
76                    Err(err) => Err(Error::new(format!("{}", err), embed.line_number)),
77                },
78                None => Err(Error::new("Missing value".to_string(), embed.line_number)),
79            },
80            None => Err(self.missing_error()),
81        }
82    }
83
84    pub fn snippet(&self) -> Result<String, Error> {
85        match self.element_option {
86            Some(embed) => Ok(embed.snippet()),
87            None => Err(self.missing_error()),
88        }
89    }
90
91    pub fn snippet_with_options(
92        &self,
93        printer: &dyn Printer,
94        gutter: bool,
95    ) -> Result<String, Error> {
96        match self.element_option {
97            Some(embed) => Ok(embed.snippet_with_options(printer, gutter)),
98            None => Err(self.missing_error()),
99        }
100    }
101}
102
103impl<'a> EmbedQueryImpl<'a> for EmbedQuery<'a> {
104    fn new(
105        element_option: Option<&'a Embed>,
106        key: Option<String>,
107        parent: EmbedQueryParent<'a>,
108    ) -> EmbedQuery<'a> {
109        EmbedQuery {
110            element_option,
111            key,
112            parent,
113        }
114    }
115}