1use crate::parser::error::{WPLCodeErrorTrait, WplCodeError};
2use derive_getters::Getters;
3use smol_str::SmolStr;
4use std::collections::VecDeque;
5use std::fmt::{Display, Formatter};
6use std::io::Write;
7use wp_primitives::Parser;
8
9use crate::ast::debug::{DebugFormat, DepIndent};
10use crate::ast::{WplRule, WplRuleMeta, WplTag};
11use crate::parser::MergeTags;
12use crate::parser::wpl_pkg::wpl_package;
13
14use super::AnnFun;
15
16#[derive(Default, Clone, Getters, Debug)]
17pub struct WplPackage {
18 pub name: SmolStr,
19 pub rules: VecDeque<WplRule>,
20 pub tags: Option<AnnFun>,
21}
22
23impl WplPackage {
24 pub(crate) fn append(&mut self, p0: Vec<WplRule>) {
25 for i in p0 {
26 self.rules.push_back(i);
27 }
28 }
29}
30
31impl WplPackage {
32 pub fn export_tags(&self) -> Option<Vec<WplTag>> {
33 self.tags.as_ref().map(|x| x.export_tags())
34 }
35}
36
37#[derive(Serialize, Deserialize)]
38pub struct WplPkgMeta {
39 pub name: SmolStr,
40 pub rules: Vec<WplRuleMeta>,
41}
42
43impl From<&WplPackage> for WplPkgMeta {
44 fn from(value: &WplPackage) -> Self {
45 let mut rules = Vec::new();
46 let pkg_tags = value.export_tags();
47 for i in &value.rules {
48 let mut r_stat = WplRuleMeta::from(i);
49 if let Some(mut x) = pkg_tags.clone() {
50 r_stat.tags.append(&mut x);
51 }
52 rules.push(r_stat);
53 }
54 Self {
55 name: value.name.clone(),
56 rules,
57 }
58 }
59}
60
61impl DebugFormat for WplPackage {
62 fn write<W>(&self, w: &mut W) -> std::io::Result<()>
63 where
64 W: ?Sized + Write + DepIndent,
65 {
66 if let Some(tag) = &self.tags {
67 tag.write(w)?;
68 }
69
70 write!(w, "package {} ", self.name)?;
71 self.write_open_brace(w)?;
72 self.write_new_line(w)?;
73
74 for rule in &self.rules {
75 rule.write(w)?;
76 self.write_new_line(w)?;
77 }
78 self.write_close_brace(w)?;
79 self.write_new_line(w)?;
80
81 Ok(())
82 }
83}
84
85impl Display for WplPackage {
86 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
87 write!(f, "{}", self.fmt_string().unwrap_or_default())
88 }
89}
90
91impl MergeTags for WplPackage {
92 fn merge_tags(&mut self, _: &Option<AnnFun>) {
93 self.rules.merge_tags(&self.tags);
94 }
95}
96
97impl WplPackage {
98 pub fn new<S: Into<SmolStr>>(name: S, rules: Vec<WplRule>) -> Self {
99 let name = name.into();
100 debug_assert!(!name.is_empty());
101
102 Self {
103 name,
104 rules: VecDeque::from(rules),
105 tags: None,
106 }
107 }
108
109 pub fn parse(data: &mut &str, path: &str) -> Result<Self, WplCodeError> {
110 let package = wpl_package
111 .parse_next(data)
112 .map_err(|e| WplCodeError::from_syntax(e, data, path))?;
113 Ok(package)
114 }
115
116 pub fn is_empty(&self) -> bool {
117 self.rules.is_empty()
118 }
119}