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::{ErrorOwe, ErrorWith, ToStructError, UvsFrom};
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            WplCodeError::from(WplCodeReason::Syntax(format!("comment proc error {} ", e)))
46        })?;
47
48        Ok(Self {
49            path,
50            code: pure_code.to_string(),
51        })
52    }
53    pub fn get_code(&self) -> &String {
54        &self.code
55    }
56    pub fn parse_pkg(&self) -> WplCodeResult<WplPackage> {
57        let package = wpl_package
58            .parse(self.code.as_str())
59            .map_err(|err| WplCodeError::from(WplCodeReason::Syntax(error_detail(err))))?;
60        Ok(package)
61    }
62    pub fn parse_rule(&self) -> WplCodeResult<WplPackage> {
63        let rule = wpl_rule
64            .parse(self.code.as_str())
65            .map_err(|err| WplCodeError::from(WplCodeReason::Syntax(error_detail(err))))?;
66        let mut target = WplPackage::default();
67        target.rules.push_back(rule);
68        Ok(target)
69    }
70    pub fn empty_ins() -> WplCodeResult<Self> {
71        WplCode::try_from((PathBuf::new(), ""))
72    }
73    pub fn is_empty(&self) -> bool {
74        self.code.is_empty()
75    }
76    pub fn load<P: AsRef<Path> + Clone>(wpl_file: P) -> WplCodeResult<Self> {
77        let mut buffer = Vec::with_capacity(10240);
78        let mut f = File::open(wpl_file.clone())
79            //.with_context(|| format!("conf file not found: {:?}", wpl_file))
80            .owe_conf()
81            .with(wpl_file.as_ref())?;
82        //.owe_conf::<WPLCodeError>()?;
83        f.read_to_end(&mut buffer).expect("read conf file error");
84        let file_data = String::from_utf8(buffer).expect("conf file is not utf8");
85        let code = WplCode::build(PathBuf::from(wpl_file.as_ref()), file_data.as_str())?;
86        Ok(code)
87    }
88
89    pub fn mix_load<P: AsRef<Path> + Clone>(
90        arg_file: Option<P>,
91        src_rule: Option<String>,
92    ) -> WplCodeResult<Self> {
93        if let Some(rule) = src_rule {
94            let code = format!("rule cli {{  {} }}", rule);
95            return WplCode::try_from((PathBuf::from("src"), code.as_str()));
96        }
97        if let Some(rule_file) = arg_file {
98            return WplCode::load(rule_file);
99        }
100        Err(WplCodeReason::from_not_found()
101            .to_err()
102            .with_detail("miss wpl file"))
103    }
104}