1static H_CODES: &[&str] = &[
7 "H200", "H201", "H202", "H203", "H204", "H205", "H206", "H207", "H208",
8 "H220", "H221", "H222", "H223", "H224", "H225", "H226", "H227", "H228",
9 "H229", "H230", "H231", "H232",
10 "H240", "H241", "H242",
11 "H250", "H251", "H252",
12 "H260", "H261",
13 "H270", "H271", "H272",
14 "H280", "H281", "H282", "H283", "H284",
15 "H290",
16 "H300", "H301", "H302", "H303", "H304", "H305",
17 "H310", "H311", "H312", "H313",
18 "H314", "H315", "H316", "H317", "H318", "H319", "H320",
19 "H330", "H331", "H332", "H333", "H334", "H335", "H336",
20 "H340", "H341",
21 "H350", "H351",
22 "H360", "H361", "H362",
23 "H370", "H371", "H372", "H373",
24 "H400", "H401", "H402",
25 "H410", "H411", "H412", "H413",
26 "H420",
27];
28
29static P_CODES: &[&str] = &[
30 "P101", "P102", "P103",
31 "P201", "P202",
32 "P210", "P211", "P212",
33 "P220", "P221", "P222", "P223",
34 "P230", "P231", "P232", "P233", "P234", "P235",
35 "P240", "P241", "P242", "P243", "P244",
36 "P250", "P251",
37 "P260", "P261", "P262", "P263", "P264",
38 "P270", "P271", "P272", "P273",
39 "P280", "P281", "P282", "P283", "P284", "P285",
40 "P301", "P302", "P303", "P304", "P305", "P306", "P307", "P308",
41 "P309",
45 "P310", "P311", "P312", "P313", "P314", "P315",
46 "P316", "P317", "P318",
48 "P320", "P321", "P322",
49 "P330", "P331", "P332", "P333", "P334", "P335", "P336", "P337", "P338",
50 "P340", "P341", "P342",
51 "P350", "P351", "P352", "P353",
52 "P360", "P361", "P362", "P363", "P364",
53 "P370", "P371", "P372", "P373", "P374", "P375", "P376", "P377", "P378",
54 "P380", "P381",
55 "P390", "P391",
56 "P401", "P402", "P403", "P404", "P405", "P406", "P407",
57 "P410", "P411", "P412", "P413",
58 "P420", "P422",
59 "P501", "P502", "P503",
60];
61
62pub fn is_valid_h_code(code: &str) -> bool {
63 H_CODES.binary_search(&code).is_ok()
64}
65
66pub fn is_valid_p_code(code: &str) -> bool {
68 code.split('+').all(|part| P_CODES.binary_search(&part.trim()).is_ok())
69}
70
71pub fn h_code_description(code: &str) -> Option<&'static str> {
72 match code {
73 "H200" => Some("Unstable explosive"),
74 "H201" => Some("Explosive; mass explosion hazard"),
75 "H202" => Some("Explosive; severe projection hazard"),
76 "H203" => Some("Explosive; fire, blast or projection hazard"),
77 "H204" => Some("Fire or projection hazard"),
78 "H205" => Some("May mass explode in fire"),
79 "H206" => Some("Fire, blast or projection hazard; increased risk of explosion if desensitizing agent is reduced"),
80 "H207" => Some("Fire or projection hazard; increased risk of explosion if desensitizing agent is reduced"),
81 "H208" => Some("Fire hazard; increased risk of explosion if desensitizing agent is reduced"),
82 "H220" => Some("Extremely flammable gas"),
83 "H221" => Some("Flammable gas"),
84 "H222" => Some("Extremely flammable aerosol"),
85 "H223" => Some("Flammable aerosol"),
86 "H224" => Some("Extremely flammable liquid and vapour"),
87 "H225" => Some("Highly flammable liquid and vapour"),
88 "H226" => Some("Flammable liquid and vapour"),
89 "H227" => Some("Combustible liquid"),
90 "H228" => Some("Flammable solid"),
91 "H229" => Some("Pressurized container: may burst if heated"),
92 "H230" => Some("May react explosively even in the absence of air"),
93 "H231" => Some("May react explosively even in the absence of air at elevated pressure and/or temperature"),
94 "H232" => Some("May ignite spontaneously if exposed to air"),
95 "H240" => Some("Heating may cause an explosion"),
96 "H241" => Some("Heating may cause a fire or explosion"),
97 "H242" => Some("Heating may cause a fire"),
98 "H250" => Some("Catches fire spontaneously if exposed to air"),
99 "H251" => Some("Self-heating; may catch fire"),
100 "H252" => Some("Self-heating in large quantities; may catch fire"),
101 "H260" => Some("In contact with water releases flammable gases which may ignite spontaneously"),
102 "H261" => Some("In contact with water releases flammable gas"),
103 "H270" => Some("May cause or intensify fire; oxidizer"),
104 "H271" => Some("May cause fire or explosion; strong oxidizer"),
105 "H272" => Some("May intensify fire; oxidizer"),
106 "H280" => Some("Contains gas under pressure; may explode if heated"),
107 "H281" => Some("Contains refrigerated gas; may cause cryogenic burns or injury"),
108 "H282" => Some("Extremely flammable chemical under pressure: may explode if heated"),
109 "H283" => Some("Flammable chemical under pressure: may explode if heated"),
110 "H284" => Some("Chemical under pressure: may explode if heated"),
111 "H290" => Some("May be corrosive to metals"),
112 "H300" => Some("Fatal if swallowed"),
113 "H301" => Some("Toxic if swallowed"),
114 "H302" => Some("Harmful if swallowed"),
115 "H303" => Some("May be harmful if swallowed"),
116 "H304" => Some("May be fatal if swallowed and enters airways"),
117 "H305" => Some("May be harmful if swallowed and enters airways"),
118 "H310" => Some("Fatal in contact with skin"),
119 "H311" => Some("Toxic in contact with skin"),
120 "H312" => Some("Harmful in contact with skin"),
121 "H313" => Some("May be harmful in contact with skin"),
122 "H314" => Some("Causes severe skin burns and eye damage"),
123 "H315" => Some("Causes skin irritation"),
124 "H316" => Some("Causes mild skin irritation"),
125 "H317" => Some("May cause an allergic skin reaction"),
126 "H318" => Some("Causes serious eye damage"),
127 "H319" => Some("Causes serious eye irritation"),
128 "H320" => Some("Causes eye irritation"),
129 "H330" => Some("Fatal if inhaled"),
130 "H331" => Some("Toxic if inhaled"),
131 "H332" => Some("Harmful if inhaled"),
132 "H333" => Some("May be harmful if inhaled"),
133 "H334" => Some("May cause allergy or asthma symptoms or breathing difficulties if inhaled"),
134 "H335" => Some("May cause respiratory irritation"),
135 "H336" => Some("May cause drowsiness or dizziness"),
136 "H340" => Some("May cause genetic defects"),
137 "H341" => Some("Suspected of causing genetic defects"),
138 "H350" => Some("May cause cancer"),
139 "H351" => Some("Suspected of causing cancer"),
140 "H360" => Some("May damage fertility or the unborn child"),
141 "H361" => Some("Suspected of damaging fertility or the unborn child"),
142 "H362" => Some("May cause harm to breast-fed children"),
143 "H370" => Some("Causes damage to organs"),
144 "H371" => Some("May cause damage to organs"),
145 "H372" => Some("Causes damage to organs through prolonged or repeated exposure"),
146 "H373" => Some("May cause damage to organs through prolonged or repeated exposure"),
147 "H400" => Some("Very toxic to aquatic life"),
148 "H401" => Some("Toxic to aquatic life"),
149 "H402" => Some("Harmful to aquatic life"),
150 "H410" => Some("Very toxic to aquatic life with long lasting effects"),
151 "H411" => Some("Toxic to aquatic life with long lasting effects"),
152 "H412" => Some("Harmful to aquatic life with long lasting effects"),
153 "H413" => Some("May cause long lasting harmful effects to aquatic life"),
154 "H420" => Some("Harms public health and the environment by destroying ozone in the upper atmosphere"),
155 _ => None,
156 }
157}
158
159pub fn p_code_description(code: &str) -> Option<&'static str> {
160 match code {
161 "P101" => Some("If medical advice is needed, have product container or label at hand"),
162 "P102" => Some("Keep out of reach of children"),
163 "P103" => Some("Read carefully and follow all instructions"),
164 "P201" => Some("Obtain special instructions before use"),
165 "P202" => Some("Do not handle until all safety precautions have been read and understood"),
166 "P210" => Some("Keep away from heat, hot surfaces, sparks, open flames and other ignition sources. No smoking"),
167 "P211" => Some("Do not spray on an open flame or other ignition source"),
168 "P212" => Some("Avoid heating under confinement or reduction of desensitized agent"),
169 "P220" => Some("Keep away from clothing and other combustible materials"),
170 "P221" => Some("Take precautionary measures against mixing with combustibles"),
171 "P222" => Some("Do not allow contact with air"),
172 "P223" => Some("Keep away from any possible contact with water"),
173 "P230" => Some("Keep wetted with specified agent"),
174 "P231" => Some("Handle under inert gas"),
175 "P232" => Some("Protect from moisture"),
176 "P233" => Some("Keep container tightly closed"),
177 "P234" => Some("Keep only in original packaging"),
178 "P235" => Some("Keep cool"),
179 "P240" => Some("Ground and bond container and receiving equipment"),
180 "P241" => Some("Use explosion-proof equipment"),
181 "P242" => Some("Use non-sparking tools"),
182 "P243" => Some("Take precautionary measures against static discharge"),
183 "P244" => Some("Keep valves and fittings free from oil and grease"),
184 "P250" => Some("Do not subject to grinding/shock/friction"),
185 "P251" => Some("Do not pierce or burn, even after use"),
186 "P260" => Some("Do not breathe dust/fume/gas/mist/vapours/spray"),
187 "P261" => Some("Avoid breathing dust/fume/gas/mist/vapours/spray"),
188 "P262" => Some("Do not get in eyes, on skin, or on clothing"),
189 "P263" => Some("Avoid contact during pregnancy and while nursing"),
190 "P264" => Some("Wash thoroughly after handling"),
191 "P270" => Some("Do not eat, drink or smoke when using this product"),
192 "P271" => Some("Use only outdoors or in a well-ventilated area"),
193 "P272" => Some("Contaminated work clothing should not be allowed out of the workplace"),
194 "P273" => Some("Avoid release to the environment"),
195 "P280" => Some("Wear protective gloves/protective clothing/eye protection/face protection"),
196 "P281" => Some("Use personal protective equipment as required"),
197 "P282" => Some("Wear cold insulating gloves and either face shield or eye protection"),
198 "P283" => Some("Wear fire-resistant/flame-retardant clothing"),
199 "P284" => Some("In case of inadequate ventilation wear respiratory protection"),
200 "P285" => Some("In case of inadequate ventilation use respiratory protection"),
201 "P301" => Some("IF SWALLOWED"),
202 "P302" => Some("IF ON SKIN"),
203 "P303" => Some("IF ON SKIN (or hair)"),
204 "P304" => Some("IF INHALED"),
205 "P305" => Some("IF IN EYES"),
206 "P306" => Some("IF ON CLOTHING"),
207 "P307" => Some("IF exposed"),
208 "P308" => Some("IF exposed or concerned"),
209 "P309" => Some("IF exposed or if you feel unwell"),
210 "P310" => Some("Immediately call a POISON CENTER or doctor/physician"),
211 "P311" => Some("Call a POISON CENTER or doctor/physician"),
212 "P312" => Some("Call a POISON CENTER or doctor/physician if you feel unwell"),
213 "P313" => Some("Get medical advice/attention"),
214 "P314" => Some("Get medical advice/attention if you feel unwell"),
215 "P315" => Some("Get immediate medical advice/attention"),
216 "P320" => Some("Specific treatment is urgent"),
217 "P321" => Some("Specific treatment (see supplemental first aid instructions)"),
218 "P322" => Some("Specific measures (see supplemental instructions)"),
219 "P330" => Some("Rinse mouth"),
220 "P331" => Some("Do NOT induce vomiting"),
221 "P332" => Some("If skin irritation occurs: Get medical advice/attention"),
222 "P333" => Some("If skin irritation or rash occurs: Get medical advice/attention"),
223 "P334" => Some("Immerse in cool water or wrap in wet bandages"),
224 "P335" => Some("Brush off loose particles from skin"),
225 "P336" => Some("Thaw frosted parts with lukewarm water"),
226 "P337" => Some("If eye irritation persists: Get medical advice/attention"),
227 "P338" => Some("Remove contact lenses, if present and easy to do. Continue rinsing"),
228 "P340" => Some("Remove victim to fresh air and keep at rest in a position comfortable for breathing"),
229 "P341" => Some("If breathing is difficult, remove victim to fresh air and keep at rest"),
230 "P342" => Some("If experiencing respiratory symptoms: Call a POISON CENTER or doctor/physician"),
231 "P350" => Some("Gently wash with plenty of soap and water"),
232 "P351" => Some("Rinse cautiously with water for several minutes"),
233 "P352" => Some("Wash with plenty of water"),
234 "P353" => Some("Rinse skin with water or shower"),
235 "P360" => Some("Rinse immediately contaminated clothing and skin with plenty of water before removing clothes"),
236 "P361" => Some("Take off immediately all contaminated clothing"),
237 "P362" => Some("Take off contaminated clothing and wash before reuse"),
238 "P363" => Some("Wash contaminated clothing before reuse"),
239 "P364" => Some("And wash it before reuse"),
240 "P370" => Some("In case of fire"),
241 "P371" => Some("In case of major fire and large quantities"),
242 "P372" => Some("Explosion risk"),
243 "P373" => Some("DO NOT fight fire when fire reaches explosives"),
244 "P374" => Some("Fight fire with normal precautions from a reasonable distance"),
245 "P375" => Some("Fight fire remotely due to the risk of explosion"),
246 "P376" => Some("Stop leak if safe to do so"),
247 "P377" => Some("Leaking gas fire: Do not extinguish, unless leak can be stopped safely"),
248 "P378" => Some("Use appropriate fire-fighting media"),
249 "P380" => Some("Evacuate area"),
250 "P381" => Some("In case of leakage, eliminate all ignition sources"),
251 "P390" => Some("Absorb spillage to prevent material damage"),
252 "P391" => Some("Collect spillage"),
253 "P401" => Some("Store in accordance with applicable regulations"),
254 "P402" => Some("Store in a dry place"),
255 "P403" => Some("Store in a well-ventilated place"),
256 "P404" => Some("Store in a closed container"),
257 "P405" => Some("Store locked up"),
258 "P406" => Some("Store in corrosive-resistant container with a resistant inner liner"),
259 "P407" => Some("Maintain air gap between stacks or pallets"),
260 "P410" => Some("Protect from sunlight"),
261 "P411" => Some("Store at temperatures not exceeding specified temperature"),
262 "P412" => Some("Do not expose to temperatures exceeding 50°C/122°F"),
263 "P413" => Some("Store bulk masses greater than specified mass at temperatures not exceeding specified temperature"),
264 "P420" => Some("Store separately"),
265 "P422" => Some("Store contents under specified conditions"),
266 "P501" => Some("Dispose of contents/container in accordance with local regulations"),
267 "P502" => Some("Refer to manufacturer or supplier for information on recovery or recycling"),
268 "P503" => Some("Refer to manufacturer/supplier/competent authority for information on recovery or recycling"),
269 _ => None,
270 }
271}
272
273#[cfg(test)]
274mod tests {
275 use super::*;
276
277 #[test]
278 fn valid_h_codes() {
279 assert!(is_valid_h_code("H200"));
280 assert!(is_valid_h_code("H315"));
281 assert!(is_valid_h_code("H420"));
282 assert!(!is_valid_h_code("H999"));
283 assert!(!is_valid_h_code("H"));
284 assert!(!is_valid_h_code(""));
285 }
286
287 #[test]
288 fn valid_p_codes() {
289 assert!(is_valid_p_code("P101"));
290 assert!(is_valid_p_code("P501"));
291 assert!(!is_valid_p_code("P999"));
292 }
293
294 #[test]
295 fn compound_p_codes() {
296 assert!(is_valid_p_code("P301+P330+P331"));
297 assert!(is_valid_p_code("P305+P351+P338"));
298 assert!(!is_valid_p_code("P301+P999"));
299 }
300
301 #[test]
302 fn h_code_descriptions() {
303 assert_eq!(h_code_description("H315"), Some("Causes skin irritation"));
304 assert_eq!(h_code_description("H400"), Some("Very toxic to aquatic life"));
305 assert!(h_code_description("H999").is_none());
306 }
307
308 #[test]
309 fn p_code_descriptions() {
310 assert!(p_code_description("P101").is_some());
311 assert!(p_code_description("P501").is_some());
312 assert!(p_code_description("P999").is_none());
313 }
314
315 #[test]
316 fn h_codes_sorted() {
317 let mut sorted = H_CODES.to_vec();
319 sorted.sort_unstable();
320 assert_eq!(H_CODES, sorted.as_slice());
321 }
322
323 #[test]
324 fn p_codes_sorted() {
325 let mut sorted = P_CODES.to_vec();
326 sorted.sort_unstable();
327 assert_eq!(P_CODES, sorted.as_slice());
328 }
329}