Skip to main content

wpl/ast/
code.rs

1use std::fs::File;
2use std::io::Read;
3use std::path::{Path, PathBuf};
4
5use crate::ast::WplPackage;
6
7use crate::parser::error::{WplCodeError, WplCodeReason, WplCodeResult, error_detail};
8use crate::parser::wpl_pkg::wpl_package;
9use crate::parser::wpl_rule::wpl_rule;
10use crate::winnow::Parser;
11use derive_getters::Getters;
12use orion_error::conversion::{ErrorWith, SourceErr, ToStructError};
13use wp_primitives::comment::CommentParser;
14
15#[derive(Debug, Clone, Getters)]
16pub struct WplCode {
17    path: PathBuf,
18    code: String,
19}
20
21impl TryFrom<(PathBuf, String)> for WplCode {
22    type Error = WplCodeError;
23    fn try_from(v: (PathBuf, String)) -> WplCodeResult<Self> {
24        Self::build(v.0, v.1.as_str())
25    }
26}
27
28impl TryFrom<(PathBuf, &str)> for WplCode {
29    type Error = WplCodeError;
30    fn try_from(v: (PathBuf, &str)) -> WplCodeResult<Self> {
31        Self::build(v.0, v.1)
32    }
33}
34impl TryFrom<&str> for WplCode {
35    type Error = WplCodeError;
36    fn try_from(v: &str) -> WplCodeResult<Self> {
37        Self::build(PathBuf::new(), v)
38    }
39}
40
41impl WplCode {
42    pub fn build(path: PathBuf, code: &str) -> WplCodeResult<Self> {
43        let mut in_code = code;
44        let pure_code = CommentParser::ignore_comment(&mut in_code).map_err(|e| {
45            let msg = format!("comment proc error {} ", e);
46            WplCodeError::builder(WplCodeReason::Syntax)
47                .detail(msg)
48                .finish()
49        })?;
50
51        Ok(Self {
52            path,
53            code: pure_code.to_string(),
54        })
55    }
56    pub fn get_code(&self) -> &String {
57        &self.code
58    }
59    pub fn parse_pkg(&self) -> WplCodeResult<WplPackage> {
60        let package = wpl_package.parse(self.code.as_str()).map_err(|err| {
61            let msg = error_detail(err);
62            WplCodeError::builder(WplCodeReason::Syntax)
63                .detail(msg)
64                .finish()
65        })?;
66        Ok(package)
67    }
68    pub fn parse_rule(&self) -> WplCodeResult<WplPackage> {
69        let rule = wpl_rule.parse(self.code.as_str()).map_err(|err| {
70            let msg = error_detail(err);
71            WplCodeError::builder(WplCodeReason::Syntax)
72                .detail(msg)
73                .finish()
74        })?;
75        let mut target = WplPackage::default();
76        target.rules.push_back(rule);
77        Ok(target)
78    }
79    pub fn empty_ins() -> WplCodeResult<Self> {
80        WplCode::try_from((PathBuf::new(), ""))
81    }
82    pub fn is_empty(&self) -> bool {
83        self.code.is_empty()
84    }
85    pub fn load<P: AsRef<Path> + Clone>(wpl_file: P) -> WplCodeResult<Self> {
86        let mut buffer = Vec::with_capacity(10240);
87        let mut f = File::open(wpl_file.clone())
88            //.with_context(|| format!("conf file not found: {:?}", wpl_file))
89            .source_err(WplCodeReason::core_conf(), "open wpl file")
90            .at(wpl_file.as_ref())?;
91        //.owe_conf::<WPLCodeError>()?;
92        f.read_to_end(&mut buffer).expect("read conf file error");
93        let file_data = String::from_utf8(buffer).expect("conf file is not utf8");
94        let code = WplCode::build(PathBuf::from(wpl_file.as_ref()), file_data.as_str())?;
95        Ok(code)
96    }
97
98    pub fn mix_load<P: AsRef<Path> + Clone>(
99        arg_file: Option<P>,
100        src_rule: Option<String>,
101    ) -> WplCodeResult<Self> {
102        if let Some(rule) = src_rule {
103            let code = format!("rule cli {{  {} }}", rule);
104            return WplCode::try_from((PathBuf::from("src"), code.as_str()));
105        }
106        if let Some(rule_file) = arg_file {
107            return WplCode::load(rule_file);
108        }
109        Err(WplCodeReason::not_found_error()
110            .to_err()
111            .with_detail("miss wpl file"))
112    }
113}