lyceris/minecraft/parse.rs
1use std::env::consts::OS;
2
3use crate::{error::Error, json::version::meta::vanilla::{Action, Name, Rule}};
4
5use super::TARGET_ARCH;
6
7/// Trait for parsing rules related to operating system and architecture.
8pub trait ParseRule {
9 /// Parses the rules and determines if the current environment is allowed.
10 ///
11 /// # Returns
12 /// A boolean indicating whether the current environment meets the rules.
13 fn parse_rule(&self) -> bool;
14}
15
16impl ParseRule for [Rule] {
17 /// Parses the rules for an array of `Rule` and determines if the current environment is allowed.
18 ///
19 /// # Returns
20 /// A boolean indicating whether the current environment meets the rules.
21 fn parse_rule(&self) -> bool {
22 let parsed_os: Name = match OS {
23 "linux" => Name::Linux,
24 "windows" => Name::Windows,
25 "macos" => Name::Osx,
26 _ => panic!("Unknown operating system!"),
27 };
28
29 if self.is_empty() {
30 true
31 } else {
32 let mut should_push = false;
33 for rule in self {
34 if rule.action == Action::Disallow {
35 if let Some(os) = &rule.os {
36 if os.name.is_some()
37 && os.name != Some(parsed_os.clone())
38 && os.arch.is_some()
39 && os.arch != Some(TARGET_ARCH.to_string())
40 {
41 continue;
42 } else {
43 break;
44 }
45 } else {
46 continue;
47 }
48 } else if rule.action == Action::Allow {
49 if let Some(os) = &rule.os {
50 if (os.name.is_some() && os.name != Some(parsed_os.clone()))
51 || (os.arch.is_some() && os.arch != Some(TARGET_ARCH.to_string()))
52 {
53 continue;
54 } else {
55 should_push = true;
56 break;
57 }
58 } else {
59 should_push = true;
60 continue;
61 }
62 }
63 }
64 should_push
65 }
66 }
67}
68
69impl ParseRule for Option<Vec<Rule>> {
70 /// Parses the rules for an optional vector of `Rule` and determines if the current environment is allowed.
71 ///
72 /// # Returns
73 /// A boolean indicating whether the current environment meets the rules.
74 fn parse_rule(&self) -> bool {
75 match self {
76 Some(rules) => {
77 let parsed_os: Name = match OS {
78 "linux" => Name::Linux,
79 "windows" => Name::Windows,
80 "macos" => Name::Osx,
81 _ => panic!("Unknown operating system!"),
82 };
83
84 if rules.is_empty() {
85 true
86 } else {
87 let mut should_push = false;
88 for rule in rules {
89 if rule.action == Action::Disallow {
90 if let Some(os) = &rule.os {
91 if os.name.is_some()
92 && os.name != Some(parsed_os.clone())
93 && os.arch.is_some()
94 && os.arch != Some(TARGET_ARCH.to_string())
95 {
96 continue;
97 } else {
98 break;
99 }
100 } else {
101 continue;
102 }
103 } else if rule.action == Action::Allow {
104 if let Some(os) = &rule.os {
105 if (os.name.is_some() && os.name != Some(parsed_os.clone()))
106 || (os.arch.is_some()
107 && os.arch != Some(TARGET_ARCH.to_string()))
108 {
109 continue;
110 } else {
111 should_push = true;
112 break;
113 }
114 } else {
115 should_push = true;
116 continue;
117 }
118 }
119 }
120 should_push
121 }
122 }
123 None => true,
124 }
125 }
126}
127
128/// Parses the library path from the given artifact string.
129///
130/// # Parameters
131/// - `artifact`: The artifact string in the format "group:name:version[@classifier]".
132///
133/// # Returns
134/// A `Result` containing the parsed library path as a string or an error if the format is invalid.
135pub fn parse_lib_path(artifact: &str) -> crate::Result<String> {
136 let name_items: Vec<&str> = artifact.split(':').collect();
137 if name_items.len() < 3 {
138 return Err(Error::Parse(format!("Invalid artifact format: {}", artifact)));
139 }
140
141 let package = name_items[0];
142 let name = name_items[1];
143 let version_ext: Vec<&str> = name_items[2].split('@').collect();
144 let version = version_ext[0];
145 let ext = version_ext.get(1).unwrap_or(&"jar");
146
147 if name_items.len() == 3 {
148 Ok(format!(
149 "{}/{}/{}/{}-{}.{}",
150 package.replace('.', "/"),
151 name,
152 version,
153 name,
154 version,
155 ext
156 ))
157 } else {
158 let data_ext: Vec<&str> = name_items[3].split('@').collect();
159 let data = data_ext[0];
160 let data_ext = data_ext.get(1).unwrap_or(&"jar");
161
162 Ok(format!(
163 "{}/{}/{}/{}-{}-{}.{}",
164 package.replace('.', "/"),
165 name,
166 version,
167 name,
168 version,
169 data,
170 data_ext
171 ))
172 }
173}