├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── fuzz ├── .gitignore ├── Cargo.toml └── fuzz_targets │ └── parse.rs ├── src ├── generated.rs ├── lexer.rs ├── lib.rs ├── main.rs ├── parser.rs ├── range.rs ├── range_set.rs ├── semver.pest └── version.rs └── tests ├── fixtures └── fuzz-0001.txt └── genpest.rs /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | *.bk 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | cache: cargo 3 | 4 | matrix: 5 | include: 6 | 7 | - rust: stable 8 | script: 9 | - cargo test 10 | - rustup component add rustfmt-preview 11 | - cargo fmt --all -- --check 12 | - rust: beta 13 | script: 14 | - cargo test 15 | - rust: nightly 16 | script: 17 | - cargo test 18 | - rust: 1.34.0 19 | script: 20 | - cargo test 21 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "semver-parser" 3 | version = "0.10.3" 4 | authors = ["Steve Klabnik "] 5 | license = "MIT/Apache-2.0" 6 | repository = "https://github.com/steveklabnik/semver-parser" 7 | homepage = "https://github.com/steveklabnik/semver-parser" 8 | documentation = "https://docs.rs/semver-parser" 9 | description = """ 10 | Parsing of the semver spec. 11 | """ 12 | edition = "2018" 13 | 14 | keywords = ["parser", "semver", "version", "semantic"] 15 | categories = ["development-tools", "parsing"] 16 | 17 | readme = "README.md" 18 | 19 | [dependencies] 20 | pest = "2.1.0" 21 | 22 | [dev-dependencies] 23 | pest_generator = "2.1" 24 | proc-macro2 = "1.0" 25 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Steve Klabnik 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `semver-parser` 2 | 3 | ~~Parsing for the semver spec.~~ 4 | 5 | ~~We'll have better docs at 1.0.~~ 6 | 7 | Originally intended to be a way to just parse the semver spec into data structures, with no logic around matching and such, this functionality now lives in the semver crate, and therefore, is no longer used. 8 | -------------------------------------------------------------------------------- /fuzz/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | corpus 3 | artifacts 4 | coverage 5 | -------------------------------------------------------------------------------- /fuzz/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "semver-parser-fuzz" 3 | version = "0.0.0" 4 | publish = false 5 | edition = "2018" 6 | 7 | [package.metadata] 8 | cargo-fuzz = true 9 | 10 | [dependencies] 11 | libfuzzer-sys = "0.4" 12 | proc-macro2 = "1.0" 13 | 14 | [dependencies.semver-parser] 15 | path = ".." 16 | 17 | [[bin]] 18 | name = "parse" 19 | path = "fuzz_targets/parse.rs" 20 | test = false 21 | doc = false 22 | bench = false 23 | -------------------------------------------------------------------------------- /fuzz/fuzz_targets/parse.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #![no_main] 16 | 17 | use libfuzzer_sys::fuzz_target; 18 | use semver_parser::{lexer::Lexer, parser::Parser, Compat}; 19 | 20 | fuzz_target!(|data: &[u8]| { 21 | if let Ok(s) = std::str::from_utf8(data) { 22 | let _ = format!("{}\n{}", "", s).parse::(); 23 | 24 | // Fuzz Lexer 25 | let mut lexer = Lexer::new(s); 26 | while let Some(token) = lexer.next() { 27 | match token { 28 | Err(_) => break, 29 | Ok(_) => {} 30 | } 31 | } 32 | 33 | // Fuzz Parser 34 | if let Ok(mut parser) = Parser::new(s) { 35 | let _ = parser.version(); 36 | } 37 | 38 | // Fuzz Compat 39 | for compat in &[Compat::Cargo, Compat::Npm] { 40 | let _ = format!("{:?}", compat); 41 | } 42 | } 43 | }); 44 | -------------------------------------------------------------------------------- /src/generated.rs: -------------------------------------------------------------------------------- 1 | //! This is @generated code, do not edit by hand. 2 | //! See `semver.pest` and `genpest.rs`. 3 | #![allow(unused_attributes)] 4 | use super::SemverParser; 5 | 6 | #[allow(non_upper_case_globals)] 7 | const _PEST_GRAMMAR_SemverParser: [&'static str; 0usize] = []; 8 | #[allow(dead_code, non_camel_case_types, clippy::upper_case_acronyms)] 9 | #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] 10 | pub enum Rule { 11 | #[doc = "End-of-input"] 12 | EOI, 13 | r#range_set, 14 | r#logical_or, 15 | r#range, 16 | r#empty, 17 | r#hyphen, 18 | r#simple, 19 | r#primitive, 20 | r#primitive_op, 21 | r#partial, 22 | r#xr, 23 | r#xr_op, 24 | r#nr, 25 | r#tilde, 26 | r#caret, 27 | r#qualifier, 28 | r#parts, 29 | r#part, 30 | r#space, 31 | } 32 | impl Rule { 33 | pub fn all_rules() -> &'static [Rule] { 34 | &[ 35 | Rule::r#range_set, 36 | Rule::r#logical_or, 37 | Rule::r#range, 38 | Rule::r#empty, 39 | Rule::r#hyphen, 40 | Rule::r#simple, 41 | Rule::r#primitive, 42 | Rule::r#primitive_op, 43 | Rule::r#partial, 44 | Rule::r#xr, 45 | Rule::r#xr_op, 46 | Rule::r#nr, 47 | Rule::r#tilde, 48 | Rule::r#caret, 49 | Rule::r#qualifier, 50 | Rule::r#parts, 51 | Rule::r#part, 52 | Rule::r#space, 53 | ] 54 | } 55 | } 56 | #[allow(clippy::all)] 57 | impl ::pest::Parser for SemverParser { 58 | fn parse<'i>( 59 | rule: Rule, 60 | input: &'i str, 61 | ) -> ::std::result::Result<::pest::iterators::Pairs<'i, Rule>, ::pest::error::Error> { 62 | mod rules { 63 | #![allow(clippy::upper_case_acronyms)] 64 | pub mod hidden { 65 | use super::super::Rule; 66 | #[inline] 67 | #[allow(dead_code, non_snake_case, unused_variables)] 68 | pub fn skip( 69 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 70 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 71 | Ok(state) 72 | } 73 | } 74 | pub mod visible { 75 | use super::super::Rule; 76 | #[inline] 77 | #[allow(non_snake_case, unused_variables)] 78 | pub fn r#range_set( 79 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 80 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 81 | state.rule(Rule::r#range_set, |state| { 82 | state.sequence(|state| { 83 | self::r#SOI(state) 84 | .and_then(|state| super::hidden::skip(state)) 85 | .and_then(|state| { 86 | state.sequence(|state| { 87 | state.optional(|state| { 88 | self::r#space(state).and_then(|state| { 89 | state.repeat(|state| { 90 | state.sequence(|state| { 91 | super::hidden::skip(state).and_then(|state| self::r#space(state)) 92 | }) 93 | }) 94 | }) 95 | }) 96 | }) 97 | }) 98 | .and_then(|state| super::hidden::skip(state)) 99 | .and_then(|state| self::r#range(state)) 100 | .and_then(|state| super::hidden::skip(state)) 101 | .and_then(|state| { 102 | state.sequence(|state| { 103 | state.optional(|state| { 104 | state 105 | .sequence(|state| { 106 | self::r#logical_or(state) 107 | .and_then(|state| super::hidden::skip(state)) 108 | .and_then(|state| self::r#range(state)) 109 | }) 110 | .and_then(|state| { 111 | state.repeat(|state| { 112 | state.sequence(|state| { 113 | super::hidden::skip(state).and_then(|state| { 114 | state.sequence(|state| { 115 | self::r#logical_or(state) 116 | .and_then(|state| super::hidden::skip(state)) 117 | .and_then(|state| self::r#range(state)) 118 | }) 119 | }) 120 | }) 121 | }) 122 | }) 123 | }) 124 | }) 125 | }) 126 | .and_then(|state| super::hidden::skip(state)) 127 | .and_then(|state| { 128 | state.sequence(|state| { 129 | state.optional(|state| { 130 | self::r#space(state).and_then(|state| { 131 | state.repeat(|state| { 132 | state.sequence(|state| { 133 | super::hidden::skip(state).and_then(|state| self::r#space(state)) 134 | }) 135 | }) 136 | }) 137 | }) 138 | }) 139 | }) 140 | .and_then(|state| super::hidden::skip(state)) 141 | .and_then(|state| self::r#EOI(state)) 142 | }) 143 | }) 144 | } 145 | #[inline] 146 | #[allow(non_snake_case, unused_variables)] 147 | pub fn r#logical_or( 148 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 149 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 150 | state.rule(Rule::r#logical_or, |state| { 151 | state.sequence(|state| { 152 | state 153 | .sequence(|state| { 154 | state.optional(|state| { 155 | self::r#space(state).and_then(|state| { 156 | state.repeat(|state| { 157 | state.sequence(|state| { 158 | super::hidden::skip(state).and_then(|state| self::r#space(state)) 159 | }) 160 | }) 161 | }) 162 | }) 163 | }) 164 | .and_then(|state| super::hidden::skip(state)) 165 | .and_then(|state| state.match_string("||")) 166 | .and_then(|state| super::hidden::skip(state)) 167 | .and_then(|state| { 168 | state.sequence(|state| { 169 | state.optional(|state| { 170 | self::r#space(state).and_then(|state| { 171 | state.repeat(|state| { 172 | state.sequence(|state| { 173 | super::hidden::skip(state).and_then(|state| self::r#space(state)) 174 | }) 175 | }) 176 | }) 177 | }) 178 | }) 179 | }) 180 | }) 181 | }) 182 | } 183 | #[inline] 184 | #[allow(non_snake_case, unused_variables)] 185 | pub fn r#range( 186 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 187 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 188 | state.rule(Rule::r#range, |state| { 189 | self::r#hyphen(state) 190 | .or_else(|state| { 191 | state.sequence(|state| { 192 | self::r#simple(state) 193 | .and_then(|state| super::hidden::skip(state)) 194 | .and_then(|state| { 195 | state.sequence(|state| { 196 | state.optional(|state| { 197 | state 198 | .sequence(|state| { 199 | state 200 | .optional(|state| state.match_string(",")) 201 | .and_then(|state| super::hidden::skip(state)) 202 | .and_then(|state| { 203 | state.sequence(|state| { 204 | self::r#space(state) 205 | .and_then(|state| super::hidden::skip(state)) 206 | .and_then(|state| { 207 | state.sequence(|state| { 208 | state.optional(|state| { 209 | self::r#space(state).and_then(|state| { 210 | state.repeat(|state| { 211 | state.sequence(|state| { 212 | super::hidden::skip(state) 213 | .and_then(|state| self::r#space(state)) 214 | }) 215 | }) 216 | }) 217 | }) 218 | }) 219 | }) 220 | }) 221 | }) 222 | .and_then(|state| super::hidden::skip(state)) 223 | .and_then(|state| self::r#simple(state)) 224 | }) 225 | .and_then(|state| { 226 | state.repeat(|state| { 227 | state.sequence(|state| { 228 | super::hidden::skip(state).and_then(|state| { 229 | state.sequence(|state| { 230 | state 231 | .optional(|state| state.match_string(",")) 232 | .and_then(|state| super::hidden::skip(state)) 233 | .and_then(|state| { 234 | state.sequence(|state| { 235 | self::r#space(state) 236 | .and_then(|state| super::hidden::skip(state)) 237 | .and_then(|state| { 238 | state.sequence(|state| { 239 | state.optional(|state| { 240 | self::r#space(state).and_then(|state| { 241 | state.repeat(|state| { 242 | state.sequence(|state| { 243 | super::hidden::skip(state) 244 | .and_then(|state| self::r#space(state)) 245 | }) 246 | }) 247 | }) 248 | }) 249 | }) 250 | }) 251 | }) 252 | }) 253 | .and_then(|state| super::hidden::skip(state)) 254 | .and_then(|state| self::r#simple(state)) 255 | }) 256 | }) 257 | }) 258 | }) 259 | }) 260 | }) 261 | }) 262 | }) 263 | }) 264 | }) 265 | .or_else(|state| self::r#empty(state)) 266 | }) 267 | } 268 | #[inline] 269 | #[allow(non_snake_case, unused_variables)] 270 | pub fn r#empty( 271 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 272 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 273 | state.rule(Rule::r#empty, |state| state.match_string("")) 274 | } 275 | #[inline] 276 | #[allow(non_snake_case, unused_variables)] 277 | pub fn r#hyphen( 278 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 279 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 280 | state.rule(Rule::r#hyphen, |state| { 281 | state.sequence(|state| { 282 | self::r#partial(state) 283 | .and_then(|state| super::hidden::skip(state)) 284 | .and_then(|state| { 285 | state.sequence(|state| { 286 | self::r#space(state) 287 | .and_then(|state| super::hidden::skip(state)) 288 | .and_then(|state| { 289 | state.sequence(|state| { 290 | state.optional(|state| { 291 | self::r#space(state).and_then(|state| { 292 | state.repeat(|state| { 293 | state.sequence(|state| { 294 | super::hidden::skip(state).and_then(|state| self::r#space(state)) 295 | }) 296 | }) 297 | }) 298 | }) 299 | }) 300 | }) 301 | }) 302 | }) 303 | .and_then(|state| super::hidden::skip(state)) 304 | .and_then(|state| state.match_string("-")) 305 | .and_then(|state| super::hidden::skip(state)) 306 | .and_then(|state| { 307 | state.sequence(|state| { 308 | self::r#space(state) 309 | .and_then(|state| super::hidden::skip(state)) 310 | .and_then(|state| { 311 | state.sequence(|state| { 312 | state.optional(|state| { 313 | self::r#space(state).and_then(|state| { 314 | state.repeat(|state| { 315 | state.sequence(|state| { 316 | super::hidden::skip(state).and_then(|state| self::r#space(state)) 317 | }) 318 | }) 319 | }) 320 | }) 321 | }) 322 | }) 323 | }) 324 | }) 325 | .and_then(|state| super::hidden::skip(state)) 326 | .and_then(|state| self::r#partial(state)) 327 | }) 328 | }) 329 | } 330 | #[inline] 331 | #[allow(non_snake_case, unused_variables)] 332 | pub fn r#simple( 333 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 334 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 335 | state.rule(Rule::r#simple, |state| { 336 | self::r#primitive(state) 337 | .or_else(|state| self::r#partial(state)) 338 | .or_else(|state| self::r#tilde(state)) 339 | .or_else(|state| self::r#caret(state)) 340 | }) 341 | } 342 | #[inline] 343 | #[allow(non_snake_case, unused_variables)] 344 | pub fn r#primitive( 345 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 346 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 347 | state.rule(Rule::r#primitive, |state| { 348 | state.sequence(|state| { 349 | self::r#primitive_op(state) 350 | .and_then(|state| super::hidden::skip(state)) 351 | .and_then(|state| { 352 | state.sequence(|state| { 353 | state.optional(|state| { 354 | self::r#space(state).and_then(|state| { 355 | state.repeat(|state| { 356 | state.sequence(|state| { 357 | super::hidden::skip(state).and_then(|state| self::r#space(state)) 358 | }) 359 | }) 360 | }) 361 | }) 362 | }) 363 | }) 364 | .and_then(|state| super::hidden::skip(state)) 365 | .and_then(|state| self::r#partial(state)) 366 | }) 367 | }) 368 | } 369 | #[inline] 370 | #[allow(non_snake_case, unused_variables)] 371 | pub fn r#primitive_op( 372 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 373 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 374 | state.rule(Rule::r#primitive_op, |state| { 375 | state 376 | .match_string("<=") 377 | .or_else(|state| state.match_string(">=")) 378 | .or_else(|state| state.match_string(">")) 379 | .or_else(|state| state.match_string("<")) 380 | .or_else(|state| state.match_string("=")) 381 | }) 382 | } 383 | #[inline] 384 | #[allow(non_snake_case, unused_variables)] 385 | pub fn r#partial( 386 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 387 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 388 | state.rule(Rule::r#partial, |state| { 389 | state.sequence(|state| { 390 | self::r#xr(state) 391 | .and_then(|state| super::hidden::skip(state)) 392 | .and_then(|state| { 393 | state.optional(|state| { 394 | state.sequence(|state| { 395 | state 396 | .match_string(".") 397 | .and_then(|state| super::hidden::skip(state)) 398 | .and_then(|state| self::r#xr(state)) 399 | .and_then(|state| super::hidden::skip(state)) 400 | .and_then(|state| { 401 | state.optional(|state| { 402 | state.sequence(|state| { 403 | state 404 | .match_string(".") 405 | .and_then(|state| super::hidden::skip(state)) 406 | .and_then(|state| self::r#xr(state)) 407 | .and_then(|state| super::hidden::skip(state)) 408 | .and_then(|state| state.optional(|state| self::r#qualifier(state))) 409 | }) 410 | }) 411 | }) 412 | }) 413 | }) 414 | }) 415 | }) 416 | }) 417 | } 418 | #[inline] 419 | #[allow(non_snake_case, unused_variables)] 420 | pub fn r#xr( 421 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 422 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 423 | state.rule(Rule::r#xr, |state| { 424 | self::r#xr_op(state).or_else(|state| self::r#nr(state)) 425 | }) 426 | } 427 | #[inline] 428 | #[allow(non_snake_case, unused_variables)] 429 | pub fn r#xr_op( 430 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 431 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 432 | state.rule(Rule::r#xr_op, |state| { 433 | state 434 | .match_string("x") 435 | .or_else(|state| state.match_string("X")) 436 | .or_else(|state| state.match_string("*")) 437 | }) 438 | } 439 | #[inline] 440 | #[allow(non_snake_case, unused_variables)] 441 | pub fn r#nr( 442 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 443 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 444 | state.rule(Rule::r#nr, |state| { 445 | state.match_string("0").or_else(|state| { 446 | state.sequence(|state| { 447 | state 448 | .match_range('1'..'9') 449 | .and_then(|state| super::hidden::skip(state)) 450 | .and_then(|state| { 451 | state.sequence(|state| { 452 | state.optional(|state| { 453 | state.match_range('0'..'9').and_then(|state| { 454 | state.repeat(|state| { 455 | state.sequence(|state| { 456 | super::hidden::skip(state) 457 | .and_then(|state| state.match_range('0'..'9')) 458 | }) 459 | }) 460 | }) 461 | }) 462 | }) 463 | }) 464 | }) 465 | }) 466 | }) 467 | } 468 | #[inline] 469 | #[allow(non_snake_case, unused_variables)] 470 | pub fn r#tilde( 471 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 472 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 473 | state.rule(Rule::r#tilde, |state| { 474 | state.sequence(|state| { 475 | state 476 | .match_string("~>") 477 | .or_else(|state| state.match_string("~")) 478 | .and_then(|state| super::hidden::skip(state)) 479 | .and_then(|state| { 480 | state.sequence(|state| { 481 | state.optional(|state| { 482 | self::r#space(state).and_then(|state| { 483 | state.repeat(|state| { 484 | state.sequence(|state| { 485 | super::hidden::skip(state).and_then(|state| self::r#space(state)) 486 | }) 487 | }) 488 | }) 489 | }) 490 | }) 491 | }) 492 | .and_then(|state| super::hidden::skip(state)) 493 | .and_then(|state| self::r#partial(state)) 494 | }) 495 | }) 496 | } 497 | #[inline] 498 | #[allow(non_snake_case, unused_variables)] 499 | pub fn r#caret( 500 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 501 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 502 | state.rule(Rule::r#caret, |state| { 503 | state.sequence(|state| { 504 | state 505 | .match_string("^") 506 | .and_then(|state| super::hidden::skip(state)) 507 | .and_then(|state| { 508 | state.sequence(|state| { 509 | state.optional(|state| { 510 | self::r#space(state).and_then(|state| { 511 | state.repeat(|state| { 512 | state.sequence(|state| { 513 | super::hidden::skip(state).and_then(|state| self::r#space(state)) 514 | }) 515 | }) 516 | }) 517 | }) 518 | }) 519 | }) 520 | .and_then(|state| super::hidden::skip(state)) 521 | .and_then(|state| self::r#partial(state)) 522 | }) 523 | }) 524 | } 525 | #[inline] 526 | #[allow(non_snake_case, unused_variables)] 527 | pub fn r#qualifier( 528 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 529 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 530 | state.rule(Rule::r#qualifier, |state| { 531 | state.sequence(|state| { 532 | state 533 | .match_string("-") 534 | .or_else(|state| state.match_string("+")) 535 | .and_then(|state| super::hidden::skip(state)) 536 | .and_then(|state| self::r#parts(state)) 537 | }) 538 | }) 539 | } 540 | #[inline] 541 | #[allow(non_snake_case, unused_variables)] 542 | pub fn r#parts( 543 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 544 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 545 | state.rule(Rule::r#parts, |state| { 546 | state.sequence(|state| { 547 | self::r#part(state) 548 | .and_then(|state| super::hidden::skip(state)) 549 | .and_then(|state| { 550 | state.sequence(|state| { 551 | state.optional(|state| { 552 | state 553 | .sequence(|state| { 554 | state 555 | .match_string(".") 556 | .and_then(|state| super::hidden::skip(state)) 557 | .and_then(|state| self::r#part(state)) 558 | }) 559 | .and_then(|state| { 560 | state.repeat(|state| { 561 | state.sequence(|state| { 562 | super::hidden::skip(state).and_then(|state| { 563 | state.sequence(|state| { 564 | state 565 | .match_string(".") 566 | .and_then(|state| super::hidden::skip(state)) 567 | .and_then(|state| self::r#part(state)) 568 | }) 569 | }) 570 | }) 571 | }) 572 | }) 573 | }) 574 | }) 575 | }) 576 | }) 577 | }) 578 | } 579 | #[inline] 580 | #[allow(non_snake_case, unused_variables)] 581 | pub fn r#part( 582 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 583 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 584 | state.rule(Rule::r#part, |state| { 585 | self::r#nr(state).or_else(|state| { 586 | state.sequence(|state| { 587 | state 588 | .match_string("-") 589 | .or_else(|state| state.match_range('0'..'9')) 590 | .or_else(|state| state.match_range('A'..'Z')) 591 | .or_else(|state| state.match_range('a'..'z')) 592 | .and_then(|state| super::hidden::skip(state)) 593 | .and_then(|state| { 594 | state.sequence(|state| { 595 | state.optional(|state| { 596 | state 597 | .match_string("-") 598 | .or_else(|state| state.match_range('0'..'9')) 599 | .or_else(|state| state.match_range('A'..'Z')) 600 | .or_else(|state| state.match_range('a'..'z')) 601 | .and_then(|state| { 602 | state.repeat(|state| { 603 | state.sequence(|state| { 604 | super::hidden::skip(state).and_then(|state| { 605 | state 606 | .match_string("-") 607 | .or_else(|state| state.match_range('0'..'9')) 608 | .or_else(|state| state.match_range('A'..'Z')) 609 | .or_else(|state| state.match_range('a'..'z')) 610 | }) 611 | }) 612 | }) 613 | }) 614 | }) 615 | }) 616 | }) 617 | }) 618 | }) 619 | }) 620 | } 621 | #[inline] 622 | #[allow(non_snake_case, unused_variables)] 623 | pub fn r#space( 624 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 625 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 626 | state 627 | .match_string(" ") 628 | .or_else(|state| state.match_string("\t")) 629 | } 630 | #[inline] 631 | #[allow(dead_code, non_snake_case, unused_variables)] 632 | pub fn EOI( 633 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 634 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 635 | state.rule(Rule::EOI, |state| state.end_of_input()) 636 | } 637 | #[inline] 638 | #[allow(dead_code, non_snake_case, unused_variables)] 639 | pub fn SOI( 640 | state: ::std::boxed::Box<::pest::ParserState<'_, Rule>>, 641 | ) -> ::pest::ParseResult<::std::boxed::Box<::pest::ParserState<'_, Rule>>> { 642 | state.start_of_input() 643 | } 644 | } 645 | pub use self::visible::*; 646 | } 647 | ::pest::state(input, |state| match rule { 648 | Rule::r#range_set => rules::r#range_set(state), 649 | Rule::r#logical_or => rules::r#logical_or(state), 650 | Rule::r#range => rules::r#range(state), 651 | Rule::r#empty => rules::r#empty(state), 652 | Rule::r#hyphen => rules::r#hyphen(state), 653 | Rule::r#simple => rules::r#simple(state), 654 | Rule::r#primitive => rules::r#primitive(state), 655 | Rule::r#primitive_op => rules::r#primitive_op(state), 656 | Rule::r#partial => rules::r#partial(state), 657 | Rule::r#xr => rules::r#xr(state), 658 | Rule::r#xr_op => rules::r#xr_op(state), 659 | Rule::r#nr => rules::r#nr(state), 660 | Rule::r#tilde => rules::r#tilde(state), 661 | Rule::r#caret => rules::r#caret(state), 662 | Rule::r#qualifier => rules::r#qualifier(state), 663 | Rule::r#parts => rules::r#parts(state), 664 | Rule::r#part => rules::r#part(state), 665 | Rule::r#space => rules::r#space(state), 666 | Rule::EOI => rules::EOI(state), 667 | }) 668 | } 669 | } 670 | -------------------------------------------------------------------------------- /src/lexer.rs: -------------------------------------------------------------------------------- 1 | //! Lexer for semver ranges. 2 | //! 3 | //! Breaks a string of input into an iterator of tokens that can be used with a parser. 4 | //! 5 | //! This should be used with the [`parser`] module. 6 | //! 7 | //! [`parser`]: ../parser/index.html 8 | //! 9 | //! # Examples 10 | //! 11 | //! Example without errors: 12 | //! 13 | //! ```rust 14 | //! use semver_parser::lexer::{Lexer, Token}; 15 | //! 16 | //! let mut l = Lexer::new("foo 123 *"); 17 | //! 18 | //! assert_eq!(Some(Ok(Token::AlphaNumeric("foo"))), l.next()); 19 | //! assert_eq!(Some(Ok(Token::Whitespace(3, 4))), l.next()); 20 | //! assert_eq!(Some(Ok(Token::Numeric(123))), l.next()); 21 | //! assert_eq!(Some(Ok(Token::Whitespace(7, 8))), l.next()); 22 | //! assert_eq!(Some(Ok(Token::Star)), l.next()); 23 | //! assert_eq!(None, l.next()); 24 | //! ``` 25 | //! 26 | //! Example with error: 27 | //! 28 | //! ```rust 29 | //! use semver_parser::lexer::{Lexer, Token, Error}; 30 | //! 31 | //! let mut l = Lexer::new("foo / *"); 32 | //! 33 | //! assert_eq!(Some(Ok(Token::AlphaNumeric("foo"))), l.next()); 34 | //! assert_eq!(Some(Ok(Token::Whitespace(3, 4))), l.next()); 35 | //! assert_eq!(Some(Err(Error::UnexpectedChar('/'))), l.next()); 36 | //! ``` 37 | 38 | use self::Error::*; 39 | use self::Token::*; 40 | use std::str; 41 | 42 | macro_rules! scan_while { 43 | ($slf:expr, $start:expr, $first:pat $(| $rest:pat)*) => {{ 44 | let mut __end = $start; 45 | 46 | loop { 47 | if let Some((idx, c)) = $slf.one() { 48 | __end = idx; 49 | 50 | match c { 51 | $first $(| $rest)* => $slf.step(), 52 | _ => break, 53 | } 54 | 55 | continue; 56 | } else { 57 | __end = $slf.input.len(); 58 | } 59 | 60 | break; 61 | } 62 | 63 | __end 64 | }} 65 | } 66 | 67 | /// Semver tokens. 68 | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] 69 | pub enum Token<'input> { 70 | /// `=` 71 | Eq, 72 | /// `>` 73 | Gt, 74 | /// `<` 75 | Lt, 76 | /// `<=` 77 | LtEq, 78 | /// `>=` 79 | GtEq, 80 | /// '^` 81 | Caret, 82 | /// '~` 83 | Tilde, 84 | /// '*` 85 | Star, 86 | /// `.` 87 | Dot, 88 | /// `,` 89 | Comma, 90 | /// `-` 91 | Hyphen, 92 | /// `+` 93 | Plus, 94 | /// '||' 95 | Or, 96 | /// any number of whitespace (`\t\r\n `) and its span. 97 | Whitespace(usize, usize), 98 | /// Numeric component, like `0` or `42`. 99 | Numeric(u64), 100 | /// Alphanumeric component, like `alpha1` or `79deadbe`. 101 | AlphaNumeric(&'input str), 102 | } 103 | 104 | impl<'input> Token<'input> { 105 | /// Check if the current token is a whitespace token. 106 | pub fn is_whitespace(&self) -> bool { 107 | match *self { 108 | Whitespace(..) => true, 109 | _ => false, 110 | } 111 | } 112 | 113 | /// Check if the current token is a wildcard token. 114 | pub fn is_wildcard(&self) -> bool { 115 | match *self { 116 | Star | AlphaNumeric("X") | AlphaNumeric("x") => true, 117 | _ => false, 118 | } 119 | } 120 | } 121 | 122 | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] 123 | pub enum Error { 124 | /// Unexpected character. 125 | UnexpectedChar(char), 126 | } 127 | 128 | /// Lexer for semver tokens belonging to a range. 129 | #[derive(Debug)] 130 | pub struct Lexer<'input> { 131 | input: &'input str, 132 | chars: str::CharIndices<'input>, 133 | // lookahead 134 | c1: Option<(usize, char)>, 135 | c2: Option<(usize, char)>, 136 | } 137 | 138 | impl<'input> Lexer<'input> { 139 | /// Construct a new lexer for the given input. 140 | pub fn new(input: &str) -> Lexer { 141 | let mut chars = input.char_indices(); 142 | let c1 = chars.next(); 143 | let c2 = chars.next(); 144 | 145 | Lexer { 146 | input, 147 | chars, 148 | c1, 149 | c2, 150 | } 151 | } 152 | 153 | /// Shift all lookahead storage by one. 154 | fn step(&mut self) { 155 | self.c1 = self.c2; 156 | self.c2 = self.chars.next(); 157 | } 158 | 159 | fn step_n(&mut self, n: usize) { 160 | for _ in 0..n { 161 | self.step(); 162 | } 163 | } 164 | 165 | /// Access the one character, or set it if it is not set. 166 | fn one(&mut self) -> Option<(usize, char)> { 167 | self.c1 168 | } 169 | 170 | /// Access two characters. 171 | fn two(&mut self) -> Option<(usize, char, char)> { 172 | self.c1 173 | .and_then(|(start, c1)| self.c2.map(|(_, c2)| (start, c1, c2))) 174 | } 175 | 176 | /// Consume a component. 177 | /// 178 | /// A component can either be an alphanumeric or numeric. 179 | /// Does not permit leading zeroes if numeric. 180 | fn component(&mut self, start: usize) -> Result, Error> { 181 | let end = scan_while!(self, start, '0'..='9' | 'A'..='Z' | 'a'..='z'); 182 | let input = &self.input[start..end]; 183 | 184 | let mut it = input.chars(); 185 | let (a, b) = (it.next(), it.next()); 186 | 187 | // exactly zero 188 | if a == Some('0') && b.is_none() { 189 | return Ok(Numeric(0)); 190 | } 191 | 192 | if a != Some('0') { 193 | if let Ok(numeric) = input.parse::() { 194 | return Ok(Numeric(numeric)); 195 | } 196 | } 197 | 198 | Ok(AlphaNumeric(input)) 199 | } 200 | 201 | /// Consume whitespace. 202 | fn whitespace(&mut self, start: usize) -> Result, Error> { 203 | let end = scan_while!(self, start, ' ' | '\t' | '\n' | '\r'); 204 | Ok(Whitespace(start, end)) 205 | } 206 | } 207 | 208 | impl<'input> Iterator for Lexer<'input> { 209 | type Item = Result, Error>; 210 | 211 | fn next(&mut self) -> Option { 212 | #[allow(clippy::never_loop)] 213 | loop { 214 | // two subsequent char tokens. 215 | if let Some((_, a, b)) = self.two() { 216 | let two = match (a, b) { 217 | ('<', '=') => Some(LtEq), 218 | ('>', '=') => Some(GtEq), 219 | ('|', '|') => Some(Or), 220 | _ => None, 221 | }; 222 | 223 | if let Some(two) = two { 224 | self.step_n(2); 225 | return Some(Ok(two)); 226 | } 227 | } 228 | 229 | // single char and start of numeric tokens. 230 | if let Some((start, c)) = self.one() { 231 | let tok = match c { 232 | ' ' | '\t' | '\n' | '\r' => { 233 | self.step(); 234 | return Some(self.whitespace(start)); 235 | } 236 | '=' => Eq, 237 | '>' => Gt, 238 | '<' => Lt, 239 | '^' => Caret, 240 | '~' => Tilde, 241 | '*' => Star, 242 | '.' => Dot, 243 | ',' => Comma, 244 | '-' => Hyphen, 245 | '+' => Plus, 246 | '0'..='9' | 'a'..='z' | 'A'..='Z' => { 247 | self.step(); 248 | return Some(self.component(start)); 249 | } 250 | c => return Some(Err(UnexpectedChar(c))), 251 | }; 252 | 253 | self.step(); 254 | return Some(Ok(tok)); 255 | }; 256 | 257 | return None; 258 | } 259 | } 260 | } 261 | 262 | #[cfg(test)] 263 | mod tests { 264 | use super::*; 265 | 266 | fn lex(input: &str) -> Vec { 267 | Lexer::new(input).map(Result::unwrap).collect::>() 268 | } 269 | 270 | #[test] 271 | pub fn simple_tokens() { 272 | assert_eq!( 273 | lex("=><<=>=^~*.,-+||"), 274 | vec![Eq, Gt, Lt, LtEq, GtEq, Caret, Tilde, Star, Dot, Comma, Hyphen, Plus, Or,] 275 | ); 276 | } 277 | 278 | #[test] 279 | pub fn whitespace() { 280 | assert_eq!( 281 | lex(" foo \t\n\rbar"), 282 | vec![ 283 | Whitespace(0, 2), 284 | AlphaNumeric("foo"), 285 | Whitespace(5, 9), 286 | AlphaNumeric("bar"), 287 | ] 288 | ); 289 | } 290 | 291 | #[test] 292 | pub fn components() { 293 | assert_eq!(lex("42"), vec![Numeric(42)]); 294 | assert_eq!(lex("0"), vec![Numeric(0)]); 295 | assert_eq!(lex("01"), vec![AlphaNumeric("01")]); 296 | assert_eq!(lex("01"), vec![AlphaNumeric("01")]); 297 | assert_eq!(lex("5885644aa"), vec![AlphaNumeric("5885644aa")]); 298 | assert_eq!(lex("beta2"), vec![AlphaNumeric("beta2")]); 299 | assert_eq!(lex("beta.2"), vec![AlphaNumeric("beta"), Dot, Numeric(2)]); 300 | } 301 | 302 | #[test] 303 | pub fn is_wildcard() { 304 | assert_eq!(Star.is_wildcard(), true); 305 | assert_eq!(AlphaNumeric("x").is_wildcard(), true); 306 | assert_eq!(AlphaNumeric("X").is_wildcard(), true); 307 | assert_eq!(AlphaNumeric("other").is_wildcard(), false); 308 | } 309 | 310 | #[test] 311 | pub fn empty() { 312 | assert_eq!(lex(""), vec![]); 313 | } 314 | 315 | #[test] 316 | pub fn numeric_all_numbers() { 317 | let expected: Vec = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 318 | .into_iter() 319 | .map(Numeric) 320 | .collect::>(); 321 | 322 | let actual: Vec<_> = lex("0 1 2 3 4 5 6 7 8 9") 323 | .into_iter() 324 | .filter(|t| !t.is_whitespace()) 325 | .collect(); 326 | 327 | assert_eq!(actual, expected); 328 | } 329 | } 330 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | struct SemverParser; 2 | #[rustfmt::skip] 3 | mod generated; 4 | use self::generated::*; 5 | 6 | mod range_set; 7 | pub use crate::range_set::Compat; 8 | pub use crate::range_set::RangeSet; 9 | 10 | mod range; 11 | pub use crate::range::Comparator; 12 | pub use crate::range::Identifier; 13 | pub use crate::range::Op; 14 | pub use crate::range::Range; 15 | 16 | // from old lib: 17 | pub mod lexer; 18 | pub mod parser; 19 | // pub mod range; 20 | pub mod version; 21 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use semver_parser::Compat; 2 | use semver_parser::RangeSet; 3 | use std::error::Error; 4 | 5 | fn main() -> Result<(), Box> { 6 | // default operation 7 | let range_set: RangeSet = "1.2.3".parse()?; 8 | println!("Found range set: {:?}", range_set); 9 | 10 | // npm compatibility 11 | let range_set = RangeSet::parse("1.2.3", Compat::Npm)?; 12 | println!("Found range set (node): {:?}", range_set); 13 | 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /src/parser.rs: -------------------------------------------------------------------------------- 1 | // this is only for parsing versions now 2 | 3 | use std::fmt; 4 | use std::mem; 5 | 6 | use self::Error::*; 7 | use crate::lexer::{self, Lexer, Token}; 8 | use crate::version::{Identifier, Version}; 9 | 10 | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] 11 | pub enum Error<'input> { 12 | /// Needed more tokens for parsing, but none are available. 13 | UnexpectedEnd, 14 | /// Unexpected token. 15 | UnexpectedToken(Token<'input>), 16 | /// An error occurred in the lexer. 17 | Lexer(lexer::Error), 18 | /// More input available. 19 | MoreInput(Vec>), 20 | /// Encountered empty predicate in a set of predicates. 21 | EmptyPredicate, 22 | /// Encountered an empty range. 23 | EmptyRange, 24 | } 25 | 26 | impl<'input> From for Error<'input> { 27 | fn from(value: lexer::Error) -> Self { 28 | Error::Lexer(value) 29 | } 30 | } 31 | 32 | impl<'input> fmt::Display for Error<'input> { 33 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 34 | use self::Error::*; 35 | 36 | match *self { 37 | UnexpectedEnd => write!(fmt, "expected more input"), 38 | UnexpectedToken(ref token) => write!(fmt, "encountered unexpected token: {:?}", token), 39 | Lexer(ref error) => write!(fmt, "lexer error: {:?}", error), 40 | MoreInput(ref tokens) => write!(fmt, "expected end of input, but got: {:?}", tokens), 41 | EmptyPredicate => write!(fmt, "encountered empty predicate"), 42 | EmptyRange => write!(fmt, "encountered empty range"), 43 | } 44 | } 45 | } 46 | 47 | /// impl for backwards compatibility. 48 | impl<'input> From> for String { 49 | fn from(value: Error<'input>) -> Self { 50 | value.to_string() 51 | } 52 | } 53 | 54 | /// A recursive-descent parser for parsing version requirements. 55 | pub struct Parser<'input> { 56 | /// Source of token. 57 | lexer: Lexer<'input>, 58 | /// Lookaehead. 59 | c1: Option>, 60 | } 61 | 62 | impl<'input> Parser<'input> { 63 | /// Construct a new parser for the given input. 64 | pub fn new(input: &'input str) -> Result, Error<'input>> { 65 | let mut lexer = Lexer::new(input); 66 | 67 | let c1 = if let Some(c1) = lexer.next() { 68 | Some(c1?) 69 | } else { 70 | None 71 | }; 72 | 73 | Ok(Parser { lexer, c1 }) 74 | } 75 | 76 | /// Pop one token. 77 | #[inline(always)] 78 | fn pop(&mut self) -> Result, Error<'input>> { 79 | let c1 = if let Some(c1) = self.lexer.next() { 80 | Some(c1?) 81 | } else { 82 | None 83 | }; 84 | 85 | mem::replace(&mut self.c1, c1).ok_or_else(|| UnexpectedEnd) 86 | } 87 | 88 | /// Peek one token. 89 | #[inline(always)] 90 | fn peek(&mut self) -> Option<&Token<'input>> { 91 | self.c1.as_ref() 92 | } 93 | 94 | /// Skip whitespace if present. 95 | fn skip_whitespace(&mut self) -> Result<(), Error<'input>> { 96 | match self.peek() { 97 | Some(&Token::Whitespace(_, _)) => self.pop().map(|_| ()), 98 | _ => Ok(()), 99 | } 100 | } 101 | 102 | /// Parse a single component. 103 | /// 104 | /// Returns `None` if the component is a wildcard. 105 | pub fn component(&mut self) -> Result, Error<'input>> { 106 | match self.pop()? { 107 | Token::Numeric(number) => Ok(Some(number)), 108 | ref t if t.is_wildcard() => Ok(None), 109 | tok => Err(UnexpectedToken(tok)), 110 | } 111 | } 112 | 113 | /// Parse a single numeric. 114 | pub fn numeric(&mut self) -> Result> { 115 | match self.pop()? { 116 | Token::Numeric(number) => Ok(number), 117 | tok => Err(UnexpectedToken(tok)), 118 | } 119 | } 120 | 121 | /// Optionally parse a dot, then a component. 122 | /// 123 | /// The second component of the tuple indicates if a wildcard has been encountered, and is 124 | /// always `false` if the first component is `Some`. 125 | /// 126 | /// If a dot is not encountered, `(None, false)` is returned. 127 | /// 128 | /// If a wildcard is encountered, `(None, true)` is returned. 129 | pub fn dot_component(&mut self) -> Result<(Option, bool), Error<'input>> { 130 | match self.peek() { 131 | Some(&Token::Dot) => {} 132 | _ => return Ok((None, false)), 133 | } 134 | 135 | // pop the peeked dot. 136 | self.pop()?; 137 | self.component().map(|n| (n, n.is_none())) 138 | } 139 | 140 | /// Parse a dot, then a numeric. 141 | pub fn dot_numeric(&mut self) -> Result> { 142 | match self.pop()? { 143 | Token::Dot => {} 144 | tok => return Err(UnexpectedToken(tok)), 145 | } 146 | 147 | self.numeric() 148 | } 149 | 150 | /// Parse an string identifier. 151 | /// 152 | /// Like, `foo`, or `bar`, or `beta-1`. 153 | pub fn identifier(&mut self) -> Result> { 154 | self.bounded_identifier(0) 155 | } 156 | 157 | fn bounded_identifier(&mut self, count: u32) -> Result> { 158 | if count > 255 { 159 | panic!("Cannot have more than 255 identifiers"); 160 | } 161 | 162 | let identifier = match self.pop()? { 163 | Token::AlphaNumeric(identifier) => { 164 | // TODO: Borrow? 165 | Identifier::AlphaNumeric(identifier.to_string()) 166 | } 167 | Token::Numeric(n) => Identifier::Numeric(n), 168 | tok => return Err(UnexpectedToken(tok)), 169 | }; 170 | 171 | if let Some(&Token::Hyphen) = self.peek() { 172 | // pop the peeked hyphen 173 | self.pop()?; 174 | // concat with any following identifiers 175 | Ok(identifier 176 | .concat("-") 177 | .concat(&self.bounded_identifier(count + 1)?.to_string())) 178 | } else { 179 | Ok(identifier) 180 | } 181 | } 182 | 183 | /// Parse all pre-release identifiers, separated by dots. 184 | /// 185 | /// Like, `abcdef.1234`. 186 | fn pre(&mut self) -> Result, Error<'input>> { 187 | match self.peek() { 188 | Some(&Token::Hyphen) => {} 189 | _ => return Ok(vec![]), 190 | } 191 | 192 | // pop the peeked hyphen. 193 | self.pop()?; 194 | self.parts() 195 | } 196 | 197 | /// Parse a dot-separated set of identifiers. 198 | fn parts(&mut self) -> Result, Error<'input>> { 199 | let mut parts = Vec::new(); 200 | 201 | parts.push(self.identifier()?); 202 | 203 | while let Some(&Token::Dot) = self.peek() { 204 | self.pop()?; 205 | 206 | parts.push(self.identifier()?); 207 | } 208 | 209 | Ok(parts) 210 | } 211 | 212 | /// Parse optional build metadata. 213 | /// 214 | /// Like, `` (empty), or `+abcdef`. 215 | fn plus_build_metadata(&mut self) -> Result, Error<'input>> { 216 | match self.peek() { 217 | Some(&Token::Plus) => {} 218 | _ => return Ok(vec![]), 219 | } 220 | 221 | // pop the plus. 222 | self.pop()?; 223 | self.parts() 224 | } 225 | 226 | /// Parse a version. 227 | /// 228 | /// Like, `1.0.0` or `3.0.0-beta.1`. 229 | pub fn version(&mut self) -> Result> { 230 | self.skip_whitespace()?; 231 | 232 | let major = self.numeric()?; 233 | let minor = self.dot_numeric()?; 234 | let patch = self.dot_numeric()?; 235 | let pre = self.pre()?; 236 | let build = self.plus_build_metadata()?; 237 | 238 | self.skip_whitespace()?; 239 | 240 | Ok(Version { 241 | major, 242 | minor, 243 | patch, 244 | pre, 245 | build, 246 | }) 247 | } 248 | 249 | /// Check if we have reached the end of input. 250 | pub fn is_eof(&mut self) -> bool { 251 | self.c1.is_none() 252 | } 253 | 254 | /// Get the rest of the tokens in the parser. 255 | /// 256 | /// Useful for debugging. 257 | pub fn tail(&mut self) -> Result>, Error<'input>> { 258 | let mut out = Vec::new(); 259 | 260 | if let Some(t) = self.c1.take() { 261 | out.push(t); 262 | } 263 | 264 | while let Some(t) = self.lexer.next() { 265 | out.push(t?); 266 | } 267 | 268 | Ok(out) 269 | } 270 | } 271 | 272 | #[cfg(test)] 273 | mod tests { 274 | use crate::version::parse; 275 | 276 | #[test] 277 | #[should_panic(expected = "Cannot have more than 255 identifiers")] 278 | fn fuzz_0001() { 279 | let version = std::fs::read_to_string("tests/fixtures/fuzz-0001.txt").expect("should be able to read version from file"); 280 | 281 | parse(&version).ok(); 282 | } 283 | 284 | } -------------------------------------------------------------------------------- /src/range.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | 3 | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] 4 | pub struct Range { 5 | pub comparator_set: Vec, 6 | pub compat: range_set::Compat, 7 | } 8 | 9 | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] 10 | pub struct Comparator { 11 | pub op: Op, 12 | pub major: u64, 13 | pub minor: u64, 14 | pub patch: u64, 15 | pub pre: Vec, 16 | } 17 | 18 | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] 19 | pub enum Op { 20 | Lt, 21 | Lte, 22 | Gt, 23 | Gte, 24 | Eq, 25 | } 26 | 27 | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] 28 | pub enum Identifier { 29 | Numeric(u64), 30 | AlphaNumeric(String), 31 | } 32 | 33 | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] 34 | pub struct Partial { 35 | major: Option, 36 | minor: Option, 37 | patch: Option, 38 | pre: Vec, 39 | kind: PartialKind, 40 | } 41 | 42 | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] 43 | pub enum PartialKind { 44 | XRangeOnly, 45 | MajorOnly, 46 | MajorMinor, 47 | MajorMinorPatch, 48 | } 49 | 50 | impl Partial { 51 | pub fn new() -> Self { 52 | Self { 53 | major: None, 54 | minor: None, 55 | patch: None, 56 | pre: Vec::new(), 57 | kind: PartialKind::XRangeOnly, 58 | } 59 | } 60 | 61 | pub fn as_comparator(&self, op: Op) -> Comparator { 62 | Comparator { 63 | op, 64 | major: self.major.unwrap_or(0), 65 | minor: self.minor.unwrap_or(0), 66 | patch: self.patch.unwrap_or(0), 67 | pre: self.pre.clone(), 68 | } 69 | } 70 | 71 | pub fn inc_major(&mut self) -> &mut Self { 72 | self.major = Some(self.major.unwrap_or(0) + 1); 73 | self 74 | } 75 | 76 | pub fn inc_minor(&mut self) -> &mut Self { 77 | self.minor = Some(self.minor.unwrap_or(0) + 1); 78 | self 79 | } 80 | 81 | pub fn inc_patch(&mut self) -> &mut Self { 82 | self.patch = Some(self.patch.unwrap_or(0) + 1); 83 | self 84 | } 85 | 86 | pub fn zero_missing(&mut self) -> &mut Self { 87 | self.major = Some(self.major.unwrap_or(0)); 88 | self.minor = Some(self.minor.unwrap_or(0)); 89 | self.patch = Some(self.patch.unwrap_or(0)); 90 | self 91 | } 92 | 93 | pub fn zero_minor(&mut self) -> &mut Self { 94 | self.minor = Some(0); 95 | self 96 | } 97 | 98 | pub fn zero_patch(&mut self) -> &mut Self { 99 | self.patch = Some(0); 100 | self 101 | } 102 | 103 | pub fn no_pre(&mut self) -> &mut Self { 104 | self.pre = Vec::new(); 105 | self 106 | } 107 | } 108 | 109 | pub fn from_pair_iterator( 110 | parsed_range: pest::iterators::Pair<'_, Rule>, 111 | compat: range_set::Compat, 112 | ) -> Result { 113 | // First of all, do we have the correct iterator? 114 | if parsed_range.as_rule() != Rule::range { 115 | return Err(String::from("Error parsing range")); 116 | } 117 | 118 | let mut comparator_set = Vec::new(); 119 | 120 | // Now we need to parse each comparator set out of the range 121 | for record in parsed_range.into_inner() { 122 | match record.as_rule() { 123 | Rule::hyphen => { 124 | let mut hyphen_set = simple::from_hyphen_range(record)?; 125 | comparator_set.append(&mut hyphen_set); 126 | } 127 | Rule::simple => { 128 | let mut comparators = simple::from_pair_iterator(record, compat)?; 129 | comparator_set.append(&mut comparators); 130 | } 131 | Rule::empty => { 132 | comparator_set.push(Partial::new().zero_missing().as_comparator(Op::Gte)); 133 | } 134 | _ => unreachable!(), 135 | } 136 | } 137 | 138 | Ok(Range { 139 | comparator_set, 140 | compat, 141 | }) 142 | } 143 | 144 | pub mod simple { 145 | use super::*; 146 | 147 | pub fn from_pair_iterator( 148 | parsed_simple: pest::iterators::Pair<'_, Rule>, 149 | compat: range_set::Compat, 150 | ) -> Result, String> { 151 | // First of all, do we have the correct iterator? 152 | if parsed_simple.as_rule() != Rule::simple { 153 | return Err(String::from("Error parsing comparator set")); 154 | } 155 | 156 | let mut comparators = Vec::new(); 157 | 158 | // Now we need to parse each comparator set out of the range 159 | for record in parsed_simple.into_inner() { 160 | match record.as_rule() { 161 | Rule::partial => { 162 | let components: Vec<_> = record.into_inner().collect(); 163 | 164 | let mut partial = parse_partial(components); 165 | 166 | match partial.kind { 167 | PartialKind::XRangeOnly => { 168 | // '*', 'x', 'X' --> ">=0.0.0" 169 | comparators.push(partial.zero_missing().as_comparator(Op::Gte)); 170 | } 171 | PartialKind::MajorOnly => { 172 | // "1", "1.*", or "1.*.*" --> ">=1.0.0 <2.0.0" 173 | // "1.*.3" == "1.*" 174 | comparators.push(partial.clone().zero_missing().as_comparator(Op::Gte)); 175 | comparators 176 | .push(partial.inc_major().zero_missing().as_comparator(Op::Lt)); 177 | } 178 | PartialKind::MajorMinor => { 179 | // "1.2" or "1.2.*" --> ">=1.2.0 <1.3.0" 180 | comparators.push(partial.clone().zero_patch().as_comparator(Op::Gte)); 181 | comparators 182 | .push(partial.inc_minor().zero_patch().as_comparator(Op::Lt)); 183 | } 184 | PartialKind::MajorMinorPatch => { 185 | match compat { 186 | range_set::Compat::Npm => { 187 | // for node, "1.2.3" is "=1.2.3" 188 | comparators.push(partial.as_comparator(Op::Eq)); 189 | } 190 | range_set::Compat::Cargo => { 191 | // for cargo, "1.2.3" is parsed as "^1.2.3" 192 | handle_caret_range(partial, &mut comparators); 193 | } 194 | } 195 | } 196 | } 197 | } 198 | Rule::primitive => { 199 | let mut components: Vec<_> = record.into_inner().collect(); 200 | let op_component = components.remove(0); 201 | 202 | let op = match op_component.as_str() { 203 | "=" => Op::Eq, 204 | "<" => Op::Lt, 205 | "<=" => Op::Lte, 206 | ">" => Op::Gt, 207 | ">=" => Op::Gte, 208 | _ => unreachable!(), 209 | }; 210 | 211 | let partial_component = components.remove(0); 212 | let components: Vec<_> = partial_component.into_inner().collect(); 213 | let mut partial = parse_partial(components); 214 | 215 | // equal is different because it can be a range with 2 comparators 216 | if op == Op::Eq { 217 | match partial.kind { 218 | PartialKind::XRangeOnly => { 219 | // '=*' --> ">=0.0.0" 220 | comparators.push(partial.zero_missing().as_comparator(Op::Gte)); 221 | } 222 | PartialKind::MajorOnly => { 223 | // "=1", "=1.*", or "=1.*.*" --> ">=1.0.0 <2.0.0" 224 | comparators 225 | .push(partial.clone().zero_missing().as_comparator(Op::Gte)); 226 | comparators 227 | .push(partial.inc_major().zero_missing().as_comparator(Op::Lt)); 228 | } 229 | PartialKind::MajorMinor => { 230 | // "=1.2" or "=1.2.*" --> ">=1.2.0 <1.3.0" 231 | comparators 232 | .push(partial.clone().zero_patch().as_comparator(Op::Gte)); 233 | comparators 234 | .push(partial.inc_minor().zero_patch().as_comparator(Op::Lt)); 235 | } 236 | PartialKind::MajorMinorPatch => { 237 | comparators.push(partial.as_comparator(Op::Eq)); 238 | } 239 | } 240 | } else { 241 | match partial.kind { 242 | PartialKind::XRangeOnly => { 243 | match op { 244 | Op::Eq => comparators 245 | .push(partial.zero_missing().as_comparator(Op::Gte)), 246 | Op::Lt => comparators 247 | .push(partial.zero_missing().as_comparator(Op::Lt)), 248 | Op::Lte => comparators 249 | .push(partial.zero_missing().as_comparator(Op::Gte)), 250 | Op::Gt => comparators 251 | .push(partial.zero_missing().as_comparator(Op::Lt)), 252 | Op::Gte => comparators 253 | .push(partial.zero_missing().as_comparator(Op::Gte)), 254 | } 255 | } 256 | PartialKind::MajorOnly => { 257 | // ">1", "=1", etc. 258 | // ">1.*.3" == ">1.*" 259 | match op { 260 | Op::Lte => comparators.push( 261 | partial 262 | .inc_major() 263 | .zero_minor() 264 | .zero_patch() 265 | .as_comparator(Op::Lt), 266 | ), 267 | _ => comparators.push(partial.zero_missing().as_comparator(op)), 268 | } 269 | } 270 | PartialKind::MajorMinor => { 271 | // ">1.2", "<1.2.*", etc. 272 | match op { 273 | Op::Lte => comparators.push( 274 | partial.inc_minor().zero_patch().as_comparator(Op::Lt), 275 | ), 276 | _ => comparators.push(partial.zero_patch().as_comparator(op)), 277 | } 278 | } 279 | PartialKind::MajorMinorPatch => { 280 | comparators.push(partial.as_comparator(op)); 281 | } 282 | } 283 | } 284 | } 285 | Rule::caret => { 286 | let mut components: Vec<_> = record.into_inner().collect(); 287 | 288 | let partial_component = components.remove(0); 289 | let components: Vec<_> = partial_component.into_inner().collect(); 290 | let partial = parse_partial(components); 291 | 292 | handle_caret_range(partial, &mut comparators); 293 | } 294 | Rule::tilde => { 295 | let mut components: Vec<_> = record.into_inner().collect(); 296 | 297 | let partial_component = components.remove(0); 298 | let components: Vec<_> = partial_component.into_inner().collect(); 299 | let mut partial = parse_partial(components); 300 | 301 | comparators.push(partial.clone().zero_missing().as_comparator(Op::Gte)); 302 | 303 | match partial.kind { 304 | PartialKind::XRangeOnly => { 305 | // "~*" --> ">=0.0.0" 306 | // which has already been added, so nothing to do here 307 | } 308 | PartialKind::MajorOnly => { 309 | // "~0" --> ">=0.0.0 <1.0.0" 310 | comparators.push( 311 | partial 312 | .inc_major() 313 | .zero_missing() 314 | .no_pre() 315 | .as_comparator(Op::Lt), 316 | ); 317 | } 318 | PartialKind::MajorMinor | PartialKind::MajorMinorPatch => { 319 | // "~1.2" --> ">=1.2.0 <1.3.0" 320 | // "~1.2.3" --> ">=1.2.3 <1.3.0" 321 | comparators.push( 322 | partial 323 | .inc_minor() 324 | .zero_patch() 325 | .no_pre() 326 | .as_comparator(Op::Lt), 327 | ); 328 | } 329 | } 330 | } 331 | _ => unreachable!(), 332 | } 333 | } 334 | 335 | Ok(comparators) 336 | } 337 | 338 | fn handle_caret_range(mut partial: Partial, comparators: &mut Vec) { 339 | // major version 0 is a special case for caret 340 | if partial.major == Some(0) { 341 | match partial.kind { 342 | PartialKind::XRangeOnly => unreachable!(), 343 | PartialKind::MajorOnly => { 344 | // "^0", "^0.*" --> ">=0.0.0 <1.0.0" 345 | comparators.push(partial.clone().zero_missing().as_comparator(Op::Gte)); 346 | comparators.push( 347 | partial 348 | .inc_major() 349 | .zero_missing() 350 | .no_pre() 351 | .as_comparator(Op::Lt), 352 | ); 353 | } 354 | PartialKind::MajorMinor => { 355 | // "^0.2", "^0.2.*" --> ">=0.2.0 <0.3.0" 356 | comparators.push(partial.clone().zero_missing().as_comparator(Op::Gte)); 357 | comparators.push( 358 | partial 359 | .inc_minor() 360 | .zero_patch() 361 | .no_pre() 362 | .as_comparator(Op::Lt), 363 | ); 364 | } 365 | PartialKind::MajorMinorPatch => { 366 | if partial.minor == Some(0) { 367 | // "^0.0.1" --> ">=0.0.1 <0.0.2" 368 | comparators.push(partial.as_comparator(Op::Gte)); 369 | comparators.push(partial.inc_patch().no_pre().as_comparator(Op::Lt)); 370 | } else { 371 | // "^0.2.3" --> ">=0.2.3 <0.3.0" 372 | comparators.push(partial.as_comparator(Op::Gte)); 373 | comparators.push( 374 | partial 375 | .inc_minor() 376 | .zero_patch() 377 | .no_pre() 378 | .as_comparator(Op::Lt), 379 | ); 380 | } 381 | } 382 | } 383 | } else { 384 | match partial.kind { 385 | PartialKind::XRangeOnly => { 386 | // "^*" --> ">=0.0.0" 387 | comparators.push(partial.zero_missing().as_comparator(Op::Gte)); 388 | } 389 | _ => { 390 | // "^1", "^1.*" --> ">=1.0.0 <2.0.0" 391 | // "^1.2", "^1.2.*" --> ">=1.2.0 <2.0.0" 392 | // "^1.2.3" --> ">=1.2.3 <2.0.0" 393 | comparators.push(partial.clone().zero_missing().as_comparator(Op::Gte)); 394 | comparators.push( 395 | partial 396 | .inc_major() 397 | .zero_minor() 398 | .zero_patch() 399 | .no_pre() 400 | .as_comparator(Op::Lt), 401 | ); 402 | } 403 | } 404 | } 405 | } 406 | 407 | pub fn from_hyphen_range( 408 | parsed_simple: pest::iterators::Pair<'_, Rule>, 409 | ) -> Result, String> { 410 | // First of all, do we have the correct iterator? 411 | if parsed_simple.as_rule() != Rule::hyphen { 412 | return Err(String::from("Error parsing comparator set")); 413 | } 414 | 415 | let mut comparators = Vec::new(); 416 | 417 | // At this point, we have 2 partial records 418 | let mut records = parsed_simple.into_inner(); 419 | 420 | let components1: Vec<_> = records.next().unwrap().into_inner().collect(); 421 | let mut partial1 = parse_partial(components1); 422 | match partial1.kind { 423 | PartialKind::XRangeOnly => { 424 | // don't need to include this - the range will be limited by the 2nd part of hyphen 425 | // range 426 | } 427 | _ => comparators.push(partial1.zero_missing().as_comparator(Op::Gte)), 428 | } 429 | 430 | let components2: Vec<_> = records.next().unwrap().into_inner().collect(); 431 | let mut partial2 = parse_partial(components2); 432 | 433 | match partial2.kind { 434 | PartialKind::XRangeOnly => { 435 | // only include this if the first part of the hyphen range was also '*' 436 | if partial1.kind == PartialKind::XRangeOnly { 437 | comparators.push(partial2.zero_missing().as_comparator(Op::Gte)); 438 | } 439 | } 440 | PartialKind::MajorOnly => { 441 | // "1.2.3 - 2" --> ">=1.2.3 <3.0.0" 442 | comparators.push( 443 | partial2 444 | .inc_major() 445 | .zero_minor() 446 | .zero_patch() 447 | .as_comparator(Op::Lt), 448 | ); 449 | } 450 | PartialKind::MajorMinor => { 451 | // "1.2.3 - 2.3.x" --> ">=1.2.3 <2.4.0" 452 | comparators.push(partial2.inc_minor().zero_patch().as_comparator(Op::Lt)); 453 | } 454 | PartialKind::MajorMinorPatch => { 455 | // "1.2.3 - 2.3.4" --> ">=1.2.3 <=2.3.4" 456 | comparators.push(partial2.as_comparator(Op::Lte)); 457 | } 458 | } 459 | 460 | Ok(comparators) 461 | } 462 | 463 | fn parse_partial(mut components: Vec>) -> Partial { 464 | let mut partial = Partial::new(); 465 | 466 | // there will be at least one component 467 | let one = components.remove(0); 468 | 469 | match one.as_rule() { 470 | Rule::xr => { 471 | let inner = one.into_inner().next().unwrap(); 472 | match inner.as_rule() { 473 | Rule::xr_op => { 474 | // for "*", ">=*", etc. 475 | partial.major = None; 476 | partial.kind = PartialKind::XRangeOnly; 477 | // end the pattern here 478 | return partial; 479 | } 480 | Rule::nr => { 481 | partial.major = Some(inner.as_str().parse::().unwrap()); 482 | } 483 | _ => unreachable!(), 484 | } 485 | } 486 | _ => unreachable!(), 487 | } 488 | 489 | if components.is_empty() { 490 | // only the major has been given 491 | partial.kind = PartialKind::MajorOnly; 492 | return partial; 493 | } else { 494 | let two = components.remove(0); 495 | 496 | match two.as_rule() { 497 | Rule::xr => { 498 | let inner = two.into_inner().next().unwrap(); 499 | match inner.as_rule() { 500 | Rule::xr_op => { 501 | partial.minor = None; 502 | // only the major has been given, minor is xrange (ignore anything after) 503 | partial.kind = PartialKind::MajorOnly; 504 | return partial; 505 | } 506 | Rule::nr => { 507 | partial.minor = Some(inner.as_str().parse::().unwrap()); 508 | } 509 | _ => unreachable!(), 510 | } 511 | } 512 | _ => unreachable!(), 513 | } 514 | } 515 | 516 | if components.is_empty() { 517 | // only major and minor have been given 518 | partial.kind = PartialKind::MajorMinor; 519 | return partial; 520 | } else { 521 | let three = components.remove(0); 522 | 523 | match three.as_rule() { 524 | Rule::xr => { 525 | let inner = three.into_inner().next().unwrap(); 526 | match inner.as_rule() { 527 | Rule::xr_op => { 528 | partial.patch = None; 529 | // only major and minor have been given, patch is xrange 530 | partial.kind = PartialKind::MajorMinor; 531 | return partial; 532 | } 533 | Rule::nr => { 534 | partial.patch = Some(inner.as_str().parse::().unwrap()); 535 | } 536 | _ => unreachable!(), 537 | } 538 | } 539 | _ => unreachable!(), 540 | } 541 | } 542 | 543 | // at this point we at least have all three fields 544 | partial.kind = PartialKind::MajorMinorPatch; 545 | 546 | if !components.is_empty() { 547 | // there's only going to be one, let's move it out 548 | let pre = components.remove(0); 549 | // now we want to look at the inner bit, so that we don't have the leading - 550 | let mut pre: Vec<_> = pre.into_inner().collect(); 551 | let pre = pre.remove(0); 552 | let pre = pre.as_str(); 553 | 554 | // now we have all of the stuff in pre, so we split by . to get each bit 555 | for bit in pre.split('.') { 556 | let identifier = match bit.parse::() { 557 | Ok(num) => Identifier::Numeric(num), 558 | Err(_) => Identifier::AlphaNumeric(bit.to_string()), 559 | }; 560 | 561 | partial.pre.push(identifier); 562 | } 563 | } 564 | 565 | partial 566 | } 567 | } 568 | 569 | #[cfg(test)] 570 | mod tests { 571 | use super::*; 572 | use pest::Parser; 573 | 574 | fn parse_range(input: &str) -> pest::iterators::Pair<'_, Rule> { 575 | match SemverParser::parse(Rule::range, input) { 576 | Ok(mut parsed) => match parsed.next() { 577 | Some(parsed) => parsed, 578 | None => panic!("Could not parse {}", input), 579 | }, 580 | Err(e) => panic!("Parse error:\n{}", e), 581 | } 582 | } 583 | 584 | // macros to handle the test boilerplate 585 | 586 | macro_rules! range_tests { 587 | ( $( $name:ident: $value:expr, )* ) => { 588 | $( 589 | #[test] 590 | fn $name() { 591 | let (input, expected_range) = $value; 592 | 593 | let parsed_range = parse_range(input); 594 | let range = from_pair_iterator(parsed_range, range_set::Compat::Cargo).expect("parsing failed"); 595 | 596 | // get the expected length from the input range 597 | let num_comparators = range.comparator_set.len(); 598 | let expected_comparators = expected_range.comparator_set.len(); 599 | assert_eq!(expected_comparators, num_comparators, "expected number of comparators: {}, got: {}", expected_comparators, num_comparators); 600 | 601 | assert_eq!(range, expected_range); 602 | } 603 | )* 604 | }; 605 | } 606 | 607 | macro_rules! range_tests_nodecompat { 608 | ( $( $name:ident: $value:expr, )* ) => { 609 | $( 610 | #[test] 611 | fn $name() { 612 | let (input, expected_range) = $value; 613 | 614 | let parsed_range = parse_range(input); 615 | let range = from_pair_iterator(parsed_range, range_set::Compat::Npm).expect("parsing failed"); 616 | 617 | // get the expected length from the input range 618 | let num_comparators = range.comparator_set.len(); 619 | let expected_comparators = expected_range.comparator_set.len(); 620 | assert_eq!(expected_comparators, num_comparators, "expected number of comparators: {}, got: {}", expected_comparators, num_comparators); 621 | 622 | assert_eq!(range, expected_range); 623 | } 624 | )* 625 | }; 626 | } 627 | 628 | macro_rules! comp_sets { 629 | ( $( [$op:expr, $major:expr, $minor:expr, $patch:expr] ),* ) => { 630 | Range { 631 | comparator_set: vec![ 632 | $( 633 | Comparator { 634 | op: $op, 635 | major: $major, 636 | minor: $minor, 637 | patch: $patch, 638 | pre: pre!(None), 639 | }, 640 | )* 641 | ], 642 | compat: range_set::Compat::Cargo 643 | } 644 | }; 645 | // if you specify pre for one item, you have to do it for all of them 646 | ( $( [$op:expr, $major:expr, $minor:expr, $patch:expr, $pre:expr] ),* ) => { 647 | Range { 648 | comparator_set: vec![ 649 | $( 650 | Comparator { 651 | op: $op, 652 | major: $major, 653 | minor: $minor, 654 | patch: $patch, 655 | pre: $pre, 656 | }, 657 | )* 658 | ], 659 | compat: range_set::Compat::Cargo 660 | } 661 | }; 662 | } 663 | 664 | // for node compatibility 665 | macro_rules! comp_sets_node { 666 | ( $( [$op:expr, $major:expr, $minor:expr, $patch:expr] ),* ) => { 667 | Range { 668 | comparator_set: vec![ 669 | $( 670 | Comparator { 671 | op: $op, 672 | major: $major, 673 | minor: $minor, 674 | patch: $patch, 675 | pre: pre!(None), 676 | }, 677 | )* 678 | ], 679 | compat: range_set::Compat::Npm 680 | } 681 | }; 682 | } 683 | 684 | macro_rules! id_num { 685 | ( $num:expr ) => { 686 | Identifier::Numeric($num) 687 | }; 688 | } 689 | 690 | macro_rules! id_alpha { 691 | ( $alpha:expr ) => { 692 | Identifier::AlphaNumeric(String::from($alpha)) 693 | }; 694 | } 695 | 696 | macro_rules! pre { 697 | ( None ) => { 698 | Vec::new() 699 | }; 700 | ( $( $e:expr ),* ) => { 701 | vec![ 702 | $( 703 | $e, 704 | )* 705 | ] 706 | }; 707 | } 708 | 709 | macro_rules! op { 710 | ( "=" ) => { 711 | Op::Eq 712 | }; 713 | ( "<" ) => { 714 | Op::Lt 715 | }; 716 | ( "<=" ) => { 717 | Op::Lte 718 | }; 719 | ( ">" ) => { 720 | Op::Gt 721 | }; 722 | ( ">=" ) => { 723 | Op::Gte 724 | }; 725 | } 726 | 727 | // tests 728 | 729 | range_tests! { 730 | major: ("1", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )), 731 | major_minor: ("1.2", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 1, 3, 0] )), 732 | major_minor_patch: ("1.2.3", comp_sets!( [op!(">="), 1, 2, 3], [op!("<"), 2, 0, 0] )), 733 | major_0_minor_patch: ("0.2.3", comp_sets!( [op!(">="), 0, 2, 3], [op!("<"), 0, 3, 0] )), 734 | major_0_minor_0_patch: ("0.0.1", comp_sets!( [op!(">="), 0, 0, 1], [op!("<"), 0, 0, 2] )), 735 | 736 | eq_major: ("=1", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )), 737 | eq_major_minor: ("=1.2", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 1, 3, 0] )), 738 | eq_major_minor_patch: ("=1.2.3", comp_sets!( [op!("="), 1, 2, 3] )), 739 | eq_all: ("=*", comp_sets!( [op!(">="), 0, 0, 0] )), 740 | eq_major_star: ("=1.*", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )), 741 | eq_major_minor_star: ("=1.2.*", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 1, 3, 0] )), 742 | 743 | lt_major: ("<1", comp_sets!( [op!("<"), 1, 0, 0] )), 744 | lt_major_minor: ("<1.2", comp_sets!( [op!("<"), 1, 2, 0] )), 745 | lt_major_minor_patch: ("<1.2.3", comp_sets!( [op!("<"), 1, 2, 3] )), 746 | lt_all: ("<*", comp_sets!( [op!("<"), 0, 0, 0] )), 747 | lt_major_star: ("<1.*", comp_sets!( [op!("<"), 1, 0, 0] )), 748 | lt_major_minor_star: ("<1.2.*", comp_sets!( [op!("<"), 1, 2, 0] )), 749 | 750 | lte_major: ("<=1", comp_sets!( [op!("<"), 2, 0, 0] )), 751 | lte_major_minor: ("<=1.2", comp_sets!( [op!("<"), 1, 3, 0] )), 752 | lte_major_minor_patch: ("<=1.2.3", comp_sets!( [op!("<="), 1, 2, 3] )), 753 | lte_all: ("<=*", comp_sets!( [op!(">="), 0, 0, 0] )), 754 | lte_major_star: ("<=1.*", comp_sets!( [op!("<"), 2, 0, 0] )), 755 | lte_major_minor_star: ("<=1.2.*", comp_sets!( [op!("<"), 1, 3, 0] )), 756 | 757 | gt_major: (">1", comp_sets!( [op!(">"), 1, 0, 0] )), 758 | gt_major_minor: (">1.2", comp_sets!( [op!(">"), 1, 2, 0] )), 759 | gt_major_minor_patch: (">1.2.3", comp_sets!( [op!(">"), 1, 2, 3] )), 760 | gt_all: (">*", comp_sets!( [op!("<"), 0, 0, 0] )), 761 | gt_major_star: (">1.*", comp_sets!( [op!(">"), 1, 0, 0] )), 762 | gt_major_minor_star: (">1.2.*", comp_sets!( [op!(">"), 1, 2, 0] )), 763 | 764 | gte_major: (">=1", comp_sets!( [op!(">="), 1, 0, 0] )), 765 | gte_major_minor: (">=1.2", comp_sets!( [op!(">="), 1, 2, 0] )), 766 | gte_major_minor_patch: (">=1.2.3", comp_sets!( [op!(">="), 1, 2, 3] )), 767 | gte_all: (">=*", comp_sets!( [op!(">="), 0, 0, 0] )), 768 | gte_major_star: (">=1.*", comp_sets!( [op!(">="), 1, 0, 0] )), 769 | gte_major_minor_star: (">=1.2.*", comp_sets!( [op!(">="), 1, 2, 0] )), 770 | 771 | tilde_major: ("~1", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )), 772 | tilde_major_0: ("~0", comp_sets!( [op!(">="), 0, 0, 0], [op!("<"), 1, 0, 0] )), 773 | tilde_major_xrange: ("~1.x", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )), 774 | tilde_major_2: ("~>1", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )), 775 | tilde_major_minor: ("~1.2", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 1, 3, 0] )), 776 | tilde_major_minor_xrange: ("~1.2.x", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 1, 3, 0] )), 777 | tilde_major_minor_2: ("~>1.2", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 1, 3, 0] )), 778 | tilde_major_minor_patch: ("~1.2.3", comp_sets!( [op!(">="), 1, 2, 3], [op!("<"), 1, 3, 0] )), 779 | tilde_major_minor_patch_pre: ("~1.2.3-beta", comp_sets!( [op!(">="), 1, 2, 3, pre!(id_alpha!("beta"))], [op!("<"), 1, 3, 0, pre!()] )), 780 | tilde_major_minor_patch_2: ("~>1.2.3", comp_sets!( [op!(">="), 1, 2, 3], [op!("<"), 1, 3, 0] )), 781 | tilde_major_0_minor_patch: ("~0.2.3", comp_sets!( [op!(">="), 0, 2, 3], [op!("<"), 0, 3, 0] )), 782 | tilde_all: ("~*", comp_sets!( [op!(">="), 0, 0, 0] )), 783 | 784 | caret_major: ("^1", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )), 785 | caret_major_xrange: ("^1.x", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )), 786 | caret_major_minor: ("^1.2", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 2, 0, 0] )), 787 | caret_major_minor_xrange: ("^1.2.x", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 2, 0, 0] )), 788 | caret_major_minor_patch: ("^1.2.3", comp_sets!( [op!(">="), 1, 2, 3], [op!("<"), 2, 0, 0] )), 789 | caret_major_minor_patch_pre: ("^1.2.3-beta.4", comp_sets!( [op!(">="), 1, 2, 3, pre!(id_alpha!("beta"), id_num!(4))], [op!("<"), 2, 0, 0, pre!()] )), 790 | 791 | caret_major_0: ("^0", comp_sets!( [op!(">="), 0, 0, 0], [op!("<"), 1, 0, 0] )), 792 | caret_major_0_xrange: ("^0.x", comp_sets!( [op!(">="), 0, 0, 0], [op!("<"), 1, 0, 0] )), 793 | caret_major_0_minor_0: ("^0.0", comp_sets!( [op!(">="), 0, 0, 0], [op!("<"), 0, 1, 0] )), 794 | caret_major_0_minor_0_xrange: ("^0.0.x", comp_sets!( [op!(">="), 0, 0, 0], [op!("<"), 0, 1, 0] )), 795 | caret_major_0_minor: ("^0.1", comp_sets!( [op!(">="), 0, 1, 0], [op!("<"), 0, 2, 0] )), 796 | caret_major_0_minor_xrange: ("^0.1.x", comp_sets!( [op!(">="), 0, 1, 0], [op!("<"), 0, 2, 0] )), 797 | caret_major_0_minor_patch: ("^0.1.2", comp_sets!( [op!(">="), 0, 1, 2], [op!("<"), 0, 2, 0] )), 798 | caret_major_0_minor_0_patch: ("^0.0.1", comp_sets!( [op!(">="), 0, 0, 1], [op!("<"), 0, 0, 2] )), 799 | caret_major_0_minor_0_pre: ("^0.0.1-beta", comp_sets!( [op!(">="), 0, 0, 1, pre!(id_alpha!("beta"))], [op!("<"), 0, 0, 2, pre!()] )), 800 | caret_all: ("^*", comp_sets!( [op!(">="), 0, 0, 0] )), 801 | 802 | two_comparators_1: (">1.2.3 <4.5.6", comp_sets!( [op!(">"), 1, 2, 3], [op!("<"), 4, 5, 6] )), 803 | two_comparators_2: ("^1.2 ^1", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 2, 0, 0], [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )), 804 | 805 | comparator_with_pre: ("=1.2.3-rc.1", comp_sets!( [op!("="), 1, 2, 3, pre!(id_alpha!("rc"), id_num!(1))] )), 806 | 807 | hyphen_major: ("1 - 4", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 5, 0, 0] )), 808 | hyphen_major_x: ("1.* - 4.*", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 5, 0, 0] )), 809 | hyphen_major_minor_x: ("1.2.x - 4.5.x", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 4, 6, 0] )), 810 | hyphen_major_minor_patch: ("1.2.3 - 4.5.6", comp_sets!( [op!(">="), 1, 2, 3], [op!("<="), 4, 5, 6] )), 811 | hyphen_with_pre: ("1.2.3-rc1 - 4.5.6", comp_sets!( [op!(">="), 1, 2, 3, pre!(id_alpha!("rc1"))], [op!("<="), 4, 5, 6, pre!()] )), 812 | hyphen_xrange_minor_only1: ("1.*.3 - 3.4.5", comp_sets!( [op!(">="), 1, 0, 0], [op!("<="), 3, 4, 5] )), 813 | hyphen_xrange_minor_only2: ("1.2.3 - 3.*.5", comp_sets!( [op!(">="), 1, 2, 3], [op!("<"), 4, 0, 0] )), 814 | 815 | hyphen_all_to_something: ("* - 3.4.5", comp_sets!( [op!("<="), 3, 4, 5] )), 816 | hyphen_to_all: ("1.2.3 - *", comp_sets!( [op!(">="), 1, 2, 3] )), 817 | hyphen_all_to_all: ("* - *", comp_sets!( [op!(">="), 0, 0, 0] )), 818 | 819 | gte_space: (">= 1.2.3", comp_sets!( [op!(">="), 1, 2, 3] )), 820 | gte_tab: (">=\t1.2.3", comp_sets!( [op!(">="), 1, 2, 3] )), 821 | gte_two_spaces: (">= 1.2.3", comp_sets!( [op!(">="), 1, 2, 3] )), 822 | gt_space: ("> 1.2.3", comp_sets!( [op!(">"), 1, 2, 3] )), 823 | gt_two_spaces: ("> 1.2.3", comp_sets!( [op!(">"), 1, 2, 3] )), 824 | lte_space: ("<= 1.2.3", comp_sets!( [op!("<="), 1, 2, 3] )), 825 | lte_two_spaces: ("<= 1.2.3", comp_sets!( [op!("<="), 1, 2, 3] )), 826 | lt_space: ("< 1.2.3", comp_sets!( [op!("<"), 1, 2, 3] )), 827 | lt_two_spaces: ("< 1.2.3", comp_sets!( [op!("<"), 1, 2, 3] )), 828 | eq_space: ("= 1.2.3", comp_sets!( [op!("="), 1, 2, 3] )), 829 | eq_two_spaces: ("= 1.2.3", comp_sets!( [op!("="), 1, 2, 3] )), 830 | caret_space: ("^ 1.2.3", comp_sets!( [op!(">="), 1, 2, 3], [op!("<"), 2, 0, 0] )), 831 | tilde_space: ("~ 1.2.3", comp_sets!( [op!(">="), 1, 2, 3], [op!("<"), 1, 3, 0] )), 832 | hyphen_spacing: ("1.2.3 - 4.5.6", comp_sets!( [op!(">="), 1, 2, 3], [op!("<="), 4, 5, 6] )), 833 | 834 | // digit options 835 | digits: ("=0.2.3", comp_sets!( [op!("="), 0, 2, 3] )), 836 | digits_2: ("=11.2.3", comp_sets!( [op!("="), 11, 2, 3] )), 837 | digits_3: ("=1.12.3", comp_sets!( [op!("="), 1, 12, 3] )), 838 | digits_4: ("=1.2.13", comp_sets!( [op!("="), 1, 2, 13] )), 839 | digits_5: ("=1.2.5678", comp_sets!( [op!("="), 1, 2, 5678] )), 840 | 841 | xrange_major_x: ("1.x", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )), 842 | xrange_major_x_x: ("1.x.x", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )), 843 | xrange_major_minor_x: ("1.2.x", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 1, 3, 0] )), 844 | xrange_major_xx: ("1.X", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )), 845 | xrange_major_xx_xx: ("1.X.X", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )), 846 | xrange_major_minor_xx: ("1.2.X", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 1, 3, 0] )), 847 | xrange_star: ("*", comp_sets!( [op!(">="), 0, 0, 0] )), 848 | xrange_x: ("x", comp_sets!( [op!(">="), 0, 0, 0] )), 849 | xrange_xx: ("X", comp_sets!( [op!(">="), 0, 0, 0] )), 850 | xrange_major_star: ("1.*", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )), 851 | xrange_major_star_star: ("1.*.*", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )), 852 | xrange_major_minor_star: ("1.2.*", comp_sets!( [op!(">="), 1, 2, 0], [op!("<"), 1, 3, 0] )), 853 | xrange_with_pre: ("1.*.*-beta", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )), 854 | // this is handled as "1.*": 855 | xrange_minor_only: ("1.*.3", comp_sets!( [op!(">="), 1, 0, 0], [op!("<"), 2, 0, 0] )), 856 | 857 | // special cases 858 | gte_star: (">=*", comp_sets!( [op!(">="), 0, 0, 0] )), 859 | empty: ("", comp_sets!( [op!(">="), 0, 0, 0] )), 860 | } 861 | 862 | range_tests_nodecompat! { 863 | node_major_minor_patch: ("1.2.3", comp_sets_node!( [op!("="), 1, 2, 3] )), 864 | } 865 | } 866 | -------------------------------------------------------------------------------- /src/range_set.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use pest::Parser; 3 | 4 | use std::str::FromStr; 5 | 6 | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] 7 | pub struct RangeSet { 8 | pub ranges: Vec, 9 | pub compat: Compat, 10 | } 11 | 12 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] 13 | pub enum Compat { 14 | Cargo, // default 15 | Npm, 16 | } 17 | 18 | impl RangeSet { 19 | fn new() -> RangeSet { 20 | RangeSet { 21 | ranges: Vec::new(), 22 | compat: Compat::Cargo, // default 23 | } 24 | } 25 | 26 | pub fn parse(input: &str, compat: Compat) -> Result { 27 | let range_set = match SemverParser::parse(Rule::range_set, input) { 28 | Ok(mut parsed) => match parsed.next() { 29 | Some(parsed) => parsed, 30 | None => return Err(String::from("Could not parse a range set")), 31 | }, 32 | Err(e) => return Err(e.to_string()), 33 | }; 34 | 35 | from_pair_iterator(range_set, compat) 36 | } 37 | } 38 | 39 | impl FromStr for RangeSet { 40 | type Err = String; 41 | 42 | fn from_str(input: &str) -> Result { 43 | // default to cargo-compatible mode 44 | RangeSet::parse(input, Compat::Cargo) 45 | } 46 | } 47 | 48 | /// Converts an iterator of Pairs into a RangeSet 49 | fn from_pair_iterator( 50 | parsed_range_set: pest::iterators::Pair<'_, Rule>, 51 | compat: Compat, 52 | ) -> Result { 53 | // First of all, do we have the correct iterator? 54 | if parsed_range_set.as_rule() != Rule::range_set { 55 | return Err(String::from("Error parsing range set")); 56 | } 57 | 58 | // Next, we make a new, empty range 59 | let mut range_set = RangeSet::new(); 60 | range_set.compat = compat; 61 | 62 | // Now we need to parse each range out of the set 63 | for record in parsed_range_set.into_inner() { 64 | match record.as_rule() { 65 | // if we have a range... 66 | Rule::range => { 67 | // ... let's parse it and push it onto our list of ranges 68 | range_set 69 | .ranges 70 | .push(range::from_pair_iterator(record, compat)?); 71 | } 72 | 73 | // we don't need to do anything with the logical ors between ranges 74 | Rule::logical_or => (), 75 | 76 | // don't need to do anything with end-of-input 77 | Rule::EOI => (), 78 | 79 | // those are the only rules we can have, according to the grammar 80 | _ => unreachable!(), 81 | } 82 | } 83 | 84 | // and that's it! 85 | Ok(range_set) 86 | } 87 | 88 | #[cfg(test)] 89 | mod tests { 90 | use super::*; 91 | 92 | macro_rules! range_set_test { 93 | ( $name:ident: $input:expr, $($x:tt)* ) => { 94 | #[test] 95 | fn $name() { 96 | let expected_sets = vec![$($x)*]; 97 | 98 | let range_set: RangeSet = $input.parse().expect("parse failed"); 99 | 100 | assert_eq!(range_set.ranges.len(), expected_sets.len()); 101 | for it in range_set.ranges.iter().zip(expected_sets.iter()) { 102 | let (ai, bi ) = it; 103 | assert_eq!(ai.comparator_set.len(), *bi); 104 | } 105 | } 106 | }; 107 | } 108 | 109 | macro_rules! range_set_nodecompat { 110 | ( $name:ident: $input:expr, $($x:tt)* ) => { 111 | #[test] 112 | fn $name() { 113 | let expected_sets = vec![$($x)*]; 114 | 115 | let range_set = RangeSet::parse($input, Compat::Npm).expect("parse failed"); 116 | 117 | assert_eq!(range_set.ranges.len(), expected_sets.len()); 118 | for it in range_set.ranges.iter().zip(expected_sets.iter()) { 119 | let (ai, bi ) = it; 120 | assert_eq!(ai.comparator_set.len(), *bi); 121 | } 122 | } 123 | }; 124 | } 125 | 126 | macro_rules! should_error { 127 | ( $( $name:ident: $value:expr, )* ) => { 128 | $( 129 | #[test] 130 | fn $name() { 131 | assert!($value.parse::().is_err()); 132 | } 133 | )* 134 | }; 135 | } 136 | 137 | range_set_test!( one_range: "=1.2.3", 1 ); 138 | range_set_test!( one_range_cargo: "1.2.3", 2 ); // this parses as "^1.2.3" 139 | range_set_test!( one_range_with_space: " =1.2.3 ", 1 ); 140 | range_set_test!( two_ranges: ">1.2.3 || =4.5.6", 1, 1 ); 141 | range_set_test!( two_ranges_with_space: " >1.2.3 || =4.5.6 ", 1, 1 ); 142 | range_set_test!( two_ranges_with_two_comparators: ">1.2.3 <2.3.4 || >4.5.6 <5.6.7", 2, 2 ); 143 | range_set_test!( caret_range: "^1.2.3", 2 ); 144 | range_set_test!( two_empty_ranges: "||", 1, 1 ); 145 | range_set_test!( two_xranges: "1.2.* || 2.*", 2, 2 ); 146 | range_set_test!( see_issue_88: "=1.2.3+meta", 1 ); 147 | 148 | range_set_nodecompat!( node_one_range: "1.2.3", 1 ); // this parses as "=1.2.3" 149 | 150 | should_error! { 151 | err_only_gt: ">", 152 | err_only_lt: "<", 153 | err_only_lte: "<=", 154 | err_only_gte: ">=", 155 | err_only_eq: "=", 156 | err_only_tilde: "~", 157 | err_only_caret: "^", 158 | err_leading_0_major: "01.2.3", 159 | err_leading_0_minor: "1.02.3", 160 | err_leading_0_patch: "1.2.03", 161 | err_hyphen_with_gt: "1.2.3 - >3.4.5", 162 | err_hyphen_no_2nd_version: "1.2.3 - ", 163 | err_no_pre_hyphen: "~1.2.3beta", 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/semver.pest: -------------------------------------------------------------------------------- 1 | range_set = { SOI ~ space* ~ range ~ (logical_or ~ range)* ~ space* ~ EOI } 2 | logical_or = { space* ~ "||" ~ space* } 3 | range = { hyphen | simple ~ ( ","? ~ space+ ~ simple )* | empty } 4 | empty = { "" } 5 | hyphen = { partial ~ space+ ~ "-" ~ space+ ~ partial } 6 | simple = { primitive | partial | tilde | caret } 7 | primitive = { primitive_op ~ space* ~ partial } 8 | primitive_op = { ("<=" | ">=" | ">" | "<" | "=") } 9 | partial = { xr ~ ("." ~ xr ~ ("." ~ xr ~ qualifier?)?)? } 10 | xr = { xr_op | nr } 11 | xr_op = { "x" | "X" | "*" } 12 | nr = { "0" | ('1' .. '9') ~ (('0' .. '9'))* } 13 | tilde = { ( "~>" | "~" ) ~ space* ~ partial } 14 | caret = { "^" ~ space* ~ partial } 15 | qualifier = { (("-" | "+") ~ parts) } 16 | parts = { part ~ ("." ~ part)* } 17 | part = { nr | ("-" | '0' .. '9' | 'A' .. 'Z' | 'a' .. 'z')+ } 18 | space = _{ " " | "\t" } 19 | -------------------------------------------------------------------------------- /src/version.rs: -------------------------------------------------------------------------------- 1 | //! Version data and functions. 2 | //! 3 | //! This module contains [`Version`] struct, [`parse`] function for building 4 | //! [`Version`] struct from string and some helper data structures and functions. 5 | //! 6 | //! # Examples 7 | //! 8 | //! Parsing `Version` from string and checking its fields: 9 | //! 10 | //! ``` 11 | //! use semver_parser::version; 12 | //! 13 | //! # fn try_main() -> Result<(), String> { 14 | //! let version = version::parse("1.2.3-alpha1")?; 15 | //! 16 | //! assert_eq!(version.major, 1); 17 | //! assert_eq!(version.minor, 2); 18 | //! assert_eq!(version.patch, 3); 19 | //! 20 | //! let expected_pre = vec![ 21 | //! version::Identifier::AlphaNumeric(String::from("alpha1")), 22 | //! ]; 23 | //! 24 | //! assert_eq!(expected_pre, version.pre); 25 | //! # Ok(()) 26 | //! # } 27 | //! # 28 | //! # try_main().unwrap(); 29 | //! ``` 30 | //! [`Version`]: ./struct.Version.html 31 | //! [`parse`]: ./fn.parse.html 32 | 33 | use crate::parser::{self, Parser}; 34 | use std::fmt; 35 | 36 | /// Structure representing version data. 37 | /// 38 | /// `Version` struct has some public fields representing version data, like major/minor version 39 | /// string, patch number and vectors of prefix and build identifiers. 40 | /// 41 | /// # Examples 42 | /// 43 | /// Parsing `Version` from string and checking its fields: 44 | /// 45 | /// ``` 46 | /// use semver_parser::version; 47 | /// 48 | /// # fn try_main() -> Result<(), String> { 49 | /// let version = version::parse("0.1.2-alpha1")?; 50 | /// assert_eq!(version.major, 0); 51 | /// assert_eq!(version.minor, 1); 52 | /// assert_eq!(version.patch, 2); 53 | /// let expected_pre = vec![version::Identifier::AlphaNumeric(String::from("alpha1"))]; 54 | /// assert_eq!(expected_pre, version.pre); 55 | /// # Ok(()) 56 | /// # } 57 | /// # 58 | /// # try_main().unwrap(); 59 | /// ``` 60 | #[derive(Clone, PartialOrd, Ord, Hash, Debug, PartialEq, Eq)] 61 | pub struct Version { 62 | /// Major version as number (`0` in `"0.1.2"`). 63 | pub major: u64, 64 | /// Minor version as number (`1` in `"0.1.2"`). 65 | pub minor: u64, 66 | /// Patch version as number (`2` in `"0.1.2"`). 67 | pub patch: u64, 68 | /// Pre-release metadata as a vector of `Identifier` (`"alpha1"` in `"0.1.2-alpha1"` 69 | /// or `7` (numeric) in `"0.1.2-7"`, `"pre"` and `0` (numeric) in `"0.1.2-pre.0"`). 70 | pub pre: Vec, 71 | /// Build metadata as a vector of `Identifier` (`"build1"` in `"0.1.2+build1"` 72 | /// or `7` (numeric) in `"0.1.2+7"`, `"build"` and `0` (numeric) in `"0.1.2+pre.0"`). 73 | pub build: Vec, 74 | } 75 | 76 | /// Helper enum for holding data of alphanumeric or numeric suffix identifiers. 77 | /// 78 | /// This enum is used to hold suffix parts of `pre` and `build` fields of 79 | /// [`Version`] struct. Theses suffixes may be either numeric or alphanumeric. 80 | /// 81 | /// # Examples 82 | /// 83 | /// Parsing [`Version`] with pre-release part composed of two `Identifier`s: 84 | /// 85 | /// ``` 86 | /// use semver_parser::version; 87 | /// 88 | /// # fn try_main() -> Result<(), String> { 89 | /// let version = version::parse("0.1.2-alpha1.0")?; 90 | /// 91 | /// let expected_pre = vec![ 92 | /// version::Identifier::AlphaNumeric(String::from("alpha1")), 93 | /// version::Identifier::Numeric(0), 94 | /// ]; 95 | /// 96 | /// assert_eq!(expected_pre, version.pre); 97 | /// # Ok(()) 98 | /// # } 99 | /// # 100 | /// # try_main().unwrap(); 101 | /// ``` 102 | /// [`Version`]: ./struct.Version.html 103 | #[derive(Clone, PartialOrd, Ord, Hash, Debug, PartialEq, Eq)] 104 | pub enum Identifier { 105 | /// An identifier that's solely numbers. 106 | Numeric(u64), 107 | /// An identifier with letters and numbers. 108 | AlphaNumeric(String), 109 | } 110 | 111 | impl Identifier { 112 | pub fn concat(self, add_str: &str) -> Identifier { 113 | match self { 114 | Identifier::Numeric(n) => Identifier::AlphaNumeric(format!("{}{}", n, add_str)), 115 | Identifier::AlphaNumeric(s) => Identifier::AlphaNumeric(format!("{}{}", s, add_str)), 116 | } 117 | } 118 | } 119 | 120 | /// Function for parsing version string to [`Version`]. 121 | /// 122 | /// Returns `Result<`[`Version`]`, String>`, where `String` represents an error while parsing. 123 | /// 124 | /// # Examples 125 | /// 126 | /// Parsing [`Version`] from string and checking its fields: 127 | /// 128 | /// ``` 129 | /// use semver_parser::version; 130 | /// 131 | /// # fn try_main() -> Result<(), String> { 132 | /// let version = version::parse("0.1.2-alpha1")?; 133 | /// assert_eq!(version.major, 0); 134 | /// assert_eq!(version.minor, 1); 135 | /// assert_eq!(version.patch, 2); 136 | /// let expected_pre = vec![version::Identifier::AlphaNumeric(String::from("alpha1"))]; 137 | /// assert_eq!(expected_pre, version.pre); 138 | /// # Ok(()) 139 | /// # } 140 | /// # 141 | /// # try_main().unwrap(); 142 | /// ``` 143 | /// [`Version`]: ./struct.Version.html 144 | pub fn parse(input: &str) -> Result { 145 | let mut parser = Parser::new(input)?; 146 | let version = parser.version()?; 147 | 148 | if !parser.is_eof() { 149 | return Err(parser::Error::MoreInput(parser.tail()?)); 150 | } 151 | 152 | Ok(version) 153 | } 154 | 155 | impl fmt::Display for Version { 156 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 157 | write!(f, "{}.{}.{}", self.major, self.minor, self.patch).expect("write failed"); 158 | if !self.pre.is_empty() { 159 | let strs: Vec<_> = self.pre.iter().map(ToString::to_string).collect(); 160 | write!(f, "-{}", strs.join(".")).expect("write failed"); 161 | } 162 | if !self.build.is_empty() { 163 | let strs: Vec<_> = self.build.iter().map(ToString::to_string).collect(); 164 | write!(f, "+{}", strs.join(".")).expect("write failed"); 165 | } 166 | Ok(()) 167 | } 168 | } 169 | 170 | impl fmt::Display for Identifier { 171 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 172 | match *self { 173 | Identifier::Numeric(ref id) => id.fmt(f), 174 | Identifier::AlphaNumeric(ref id) => id.fmt(f), 175 | } 176 | } 177 | } 178 | 179 | #[cfg(test)] 180 | mod tests { 181 | use super::*; 182 | use crate::version; 183 | 184 | #[test] 185 | fn parse_empty() { 186 | let version = ""; 187 | 188 | let parsed = version::parse(version); 189 | 190 | assert!( 191 | parsed.is_err(), 192 | "empty string incorrectly considered a valid parse" 193 | ); 194 | } 195 | 196 | #[test] 197 | fn parse_blank() { 198 | let version = " "; 199 | 200 | let parsed = version::parse(version); 201 | 202 | assert!( 203 | parsed.is_err(), 204 | "blank string incorrectly considered a valid parse" 205 | ); 206 | } 207 | 208 | #[test] 209 | fn parse_no_minor_patch() { 210 | let version = "1"; 211 | 212 | let parsed = version::parse(version); 213 | 214 | assert!( 215 | parsed.is_err(), 216 | "'{}' incorrectly considered a valid parse", version 217 | ); 218 | } 219 | 220 | #[test] 221 | fn parse_no_patch() { 222 | let version = "1.2"; 223 | 224 | let parsed = version::parse(version); 225 | 226 | assert!( 227 | parsed.is_err(), 228 | "'{}' incorrectly considered a valid parse", version 229 | ); 230 | } 231 | 232 | #[test] 233 | fn parse_empty_pre() { 234 | let version = "1.2.3-"; 235 | 236 | let parsed = version::parse(version); 237 | 238 | assert!( 239 | parsed.is_err(), 240 | "'{}' incorrectly considered a valid parse", version 241 | ); 242 | } 243 | 244 | #[test] 245 | fn parse_letters() { 246 | let version = "a.b.c"; 247 | 248 | let parsed = version::parse(version); 249 | 250 | assert!( 251 | parsed.is_err(), 252 | "'{}' incorrectly considered a valid parse", version 253 | ); 254 | } 255 | 256 | #[test] 257 | fn parse_with_letters() { 258 | let version = "1.2.3 a.b.c"; 259 | 260 | let parsed = version::parse(version); 261 | 262 | assert!( 263 | parsed.is_err(), 264 | "'{}' incorrectly considered a valid parse", version 265 | ); 266 | } 267 | 268 | #[test] 269 | fn parse_basic_version() { 270 | let version = "1.2.3"; 271 | 272 | let parsed = version::parse(version).unwrap(); 273 | 274 | assert_eq!(1, parsed.major); 275 | assert_eq!(2, parsed.minor); 276 | assert_eq!(3, parsed.patch); 277 | } 278 | 279 | #[test] 280 | fn parse_trims_input() { 281 | let version = " 1.2.3 "; 282 | 283 | let parsed = version::parse(version).unwrap(); 284 | 285 | assert_eq!(1, parsed.major); 286 | assert_eq!(2, parsed.minor); 287 | assert_eq!(3, parsed.patch); 288 | } 289 | 290 | #[test] 291 | fn parse_no_major_leading_zeroes() { 292 | let version = "01.0.0"; 293 | 294 | let parsed = version::parse(version); 295 | 296 | assert!( 297 | parsed.is_err(), 298 | "01 incorrectly considered a valid major version" 299 | ); 300 | } 301 | 302 | #[test] 303 | fn parse_no_minor_leading_zeroes() { 304 | let version = "0.01.0"; 305 | 306 | let parsed = version::parse(version); 307 | 308 | assert!( 309 | parsed.is_err(), 310 | "01 incorrectly considered a valid minor version" 311 | ); 312 | } 313 | 314 | #[test] 315 | fn parse_no_patch_leading_zeroes() { 316 | let version = "0.0.01"; 317 | 318 | let parsed = version::parse(version); 319 | 320 | assert!( 321 | parsed.is_err(), 322 | "01 incorrectly considered a valid patch version" 323 | ); 324 | } 325 | 326 | #[test] 327 | fn parse_no_major_overflow() { 328 | let version = "98765432109876543210.0.0"; 329 | 330 | let parsed = version::parse(version); 331 | 332 | assert!( 333 | parsed.is_err(), 334 | "98765432109876543210 incorrectly considered a valid major version" 335 | ); 336 | } 337 | 338 | #[test] 339 | fn parse_no_minor_overflow() { 340 | let version = "0.98765432109876543210.0"; 341 | 342 | let parsed = version::parse(version); 343 | 344 | assert!( 345 | parsed.is_err(), 346 | "98765432109876543210 incorrectly considered a valid minor version" 347 | ); 348 | } 349 | 350 | #[test] 351 | fn parse_no_patch_overflow() { 352 | let version = "0.0.98765432109876543210"; 353 | 354 | let parsed = version::parse(version); 355 | 356 | assert!( 357 | parsed.is_err(), 358 | "98765432109876543210 incorrectly considered a valid patch version" 359 | ); 360 | } 361 | 362 | #[test] 363 | fn parse_basic_prerelease() { 364 | let version = "1.2.3-pre"; 365 | 366 | let parsed = version::parse(version).unwrap(); 367 | 368 | let expected_pre = vec![Identifier::AlphaNumeric(String::from("pre"))]; 369 | assert_eq!(expected_pre, parsed.pre); 370 | } 371 | 372 | #[test] 373 | fn parse_prerelease_alphanumeric() { 374 | let version = "1.2.3-alpha1"; 375 | 376 | let parsed = version::parse(version).unwrap(); 377 | 378 | let expected_pre = vec![Identifier::AlphaNumeric(String::from("alpha1"))]; 379 | assert_eq!(expected_pre, parsed.pre); 380 | } 381 | 382 | #[test] 383 | fn parse_prerelease_zero() { 384 | let version = "1.2.3-pre.0"; 385 | 386 | let parsed = version::parse(version).unwrap(); 387 | 388 | let expected_pre = vec![ 389 | Identifier::AlphaNumeric(String::from("pre")), 390 | Identifier::Numeric(0), 391 | ]; 392 | assert_eq!(expected_pre, parsed.pre); 393 | } 394 | 395 | #[test] 396 | fn parse_basic_build() { 397 | let version = "1.2.3+build"; 398 | 399 | let parsed = version::parse(version).unwrap(); 400 | 401 | let expected_build = vec![Identifier::AlphaNumeric(String::from("build"))]; 402 | assert_eq!(expected_build, parsed.build); 403 | } 404 | 405 | #[test] 406 | fn parse_build_alphanumeric() { 407 | let version = "1.2.3+build5"; 408 | 409 | let parsed = version::parse(version).unwrap(); 410 | 411 | let expected_build = vec![Identifier::AlphaNumeric(String::from("build5"))]; 412 | assert_eq!(expected_build, parsed.build); 413 | } 414 | 415 | #[test] 416 | fn parse_pre_and_build() { 417 | let version = "1.2.3-alpha1+build5"; 418 | 419 | let parsed = version::parse(version).unwrap(); 420 | 421 | let expected_pre = vec![Identifier::AlphaNumeric(String::from("alpha1"))]; 422 | assert_eq!(expected_pre, parsed.pre); 423 | 424 | let expected_build = vec![Identifier::AlphaNumeric(String::from("build5"))]; 425 | assert_eq!(expected_build, parsed.build); 426 | } 427 | 428 | #[test] 429 | fn parse_complex_metadata_01() { 430 | let version = "1.2.3-1.alpha1.9+build5.7.3aedf "; 431 | 432 | let parsed = version::parse(version).unwrap(); 433 | 434 | let expected_pre = vec![ 435 | Identifier::Numeric(1), 436 | Identifier::AlphaNumeric(String::from("alpha1")), 437 | Identifier::Numeric(9), 438 | ]; 439 | assert_eq!(expected_pre, parsed.pre); 440 | 441 | let expected_build = vec![ 442 | Identifier::AlphaNumeric(String::from("build5")), 443 | Identifier::Numeric(7), 444 | Identifier::AlphaNumeric(String::from("3aedf")), 445 | ]; 446 | assert_eq!(expected_build, parsed.build); 447 | } 448 | 449 | #[test] 450 | fn parse_complex_metadata_02() { 451 | let version = "0.4.0-beta.1+0851523"; 452 | 453 | let parsed = version::parse(version).unwrap(); 454 | 455 | let expected_pre = vec![ 456 | Identifier::AlphaNumeric(String::from("beta")), 457 | Identifier::Numeric(1), 458 | ]; 459 | assert_eq!(expected_pre, parsed.pre); 460 | 461 | let expected_build = vec![Identifier::AlphaNumeric(String::from("0851523"))]; 462 | assert_eq!(expected_build, parsed.build); 463 | } 464 | 465 | #[test] 466 | fn parse_metadata_overflow() { 467 | let version = "0.4.0-beta.1+98765432109876543210"; 468 | 469 | let parsed = version::parse(version).unwrap(); 470 | 471 | let expected_pre = vec![ 472 | Identifier::AlphaNumeric(String::from("beta")), 473 | Identifier::Numeric(1), 474 | ]; 475 | assert_eq!(expected_pre, parsed.pre); 476 | 477 | let expected_build = vec![Identifier::AlphaNumeric(String::from( 478 | "98765432109876543210", 479 | ))]; 480 | assert_eq!(expected_build, parsed.build); 481 | } 482 | 483 | #[test] 484 | fn parse_regression_01() { 485 | let version = "0.0.0-WIP"; 486 | 487 | let parsed = version::parse(version).unwrap(); 488 | 489 | assert_eq!(0, parsed.major); 490 | assert_eq!(0, parsed.minor); 491 | assert_eq!(0, parsed.patch); 492 | 493 | let expected_pre = vec![Identifier::AlphaNumeric(String::from("WIP"))]; 494 | assert_eq!(expected_pre, parsed.pre); 495 | } 496 | 497 | #[test] 498 | fn parse_regression_02() { 499 | // this is used by really old versions of npm, and is valid according to semver.org 500 | let version = "1.2.3-beta-1"; 501 | 502 | let parsed = version::parse(version).unwrap(); 503 | 504 | assert_eq!(1, parsed.major); 505 | assert_eq!(2, parsed.minor); 506 | assert_eq!(3, parsed.patch); 507 | 508 | let expected_pre = vec![Identifier::AlphaNumeric(String::from("beta-1"))]; 509 | assert_eq!(expected_pre, parsed.pre); 510 | } 511 | } 512 | -------------------------------------------------------------------------------- /tests/fixtures/fuzz-0001.txt: -------------------------------------------------------------------------------- 1 | 28.49.49-49.49-4-0EEA02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEUEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49EEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEUEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEE0EEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-4-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49EEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEUEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEE0EEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-4-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEE0EEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-4-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-549-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEE0EEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-4-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEE0EEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-4-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-48-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEE0EEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-4-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEE0EEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-4-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-549-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEE0EEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-4-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEE0EEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-4-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-48-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEE0EEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-4-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-4HEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEE0EEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHE-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE99-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-0EEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-42-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-499-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-4EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-EEAEEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE99-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-5EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-49-65537-0EEAEEE9AEEEHEEEEI-49-02-EEAEEE9-EEEGEEEE49EEEI-49-02-49-0-0EEAEEE9-0I-49-02-69-EEAEEE-0EEAEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEAEEEGEEEEI-49-02-32719-0-0EEAEEE7AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-1EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAE,[[?[?[?[]EEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE9-EAEEE9-0EEAE~EG~EGEEEEI-49-02-49-0-0EEA02-49-0EEAEEE9-EAEEE9--1EEAE~EGEEEEI-49-02-49-0-0EEA02-49-0EEAEEE9-EAEEE9--1EEAE~EGEEEEI-49-02-49-0-0EEAEEE9E9AEEEHEEEEI-9223372036854775808-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-E‭AEEE18446744073709551616-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-6473869209105902847-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAE,[[?[?[?[]EEHEEEEI-49-02-32719-0-0EEAEEE7AEEEHEEEEI-49-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-EAEEE9-1EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-0-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAE,[[?[?[?[]EEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE9-EAEEE9-0EEAE~EG~EGEEEEI-49-02-49-0-0EEA02-49-0EEAEEE9-EAEEE9--1EEAE~EGEEEEI-49-02-49-0-0EEAEEE9E9AEEEHEEEEI-9223372036854775808-EAEEE-0EEAEEEHEEEEI-50-02-49-0EEAEEE9-E‭AEEE9-0EEAEEEGEEEEI-49-02-49-0-0EEAEEE9AEEEHEEEEI-49-02-49-0EEAEEE9-EAEEE9-0E-49-32768-0EEAEEE9AEEEHEEEEI-49-EAEEE-0EEAE,[[?[?[?[]EEHEEEEI-49-02-1308097430959475-0EEAEEE9-EAEEE9-0EEA49-0EEAEEE9-EAEEE9-0EEAE~EG~EGEEEEI-49-18446744073709551615-49-0-161554EEA02-49-0EEAEEE9-EAEEE9-0EEAE~EGEEEEI-49-02-49-0-0EEAEEE9-0I-2-?)38737119027114448033274-0EEAE/  EE170141183460469231731687303715884105727-0]]]]]]EEAE4 -------------------------------------------------------------------------------- /tests/genpest.rs: -------------------------------------------------------------------------------- 1 | //! `pest_derive` crate has large dependency tree, and, as a build dependency, 2 | //! it imposes these deps onto our consumers. 3 | //! 4 | //! To avoid that, let's just dump generated code to string into this 5 | //! repository, and add a test that checks that the code is fresh. 6 | use std::{ 7 | fs, 8 | io::Write, 9 | process::{Command, Stdio}, 10 | time::Instant, 11 | }; 12 | 13 | const PREAMBLE: &str = "\ 14 | //! This is @generated code, do not edit by hand. 15 | //! See `semver.pest` and `genpest.rs`. 16 | #![allow(unused_attributes)] 17 | use super::SemverParser; 18 | "; 19 | 20 | #[test] 21 | fn generated_code_is_fresh() { 22 | let t = Instant::now(); 23 | 24 | let token_stream = { 25 | let grammar = include_str!("../src/semver.pest"); 26 | let input = format!( 27 | r###" 28 | #[derive(Parser)] 29 | #[grammar_inline = r#"{}"#] 30 | struct SemverParser; 31 | "###, 32 | grammar 33 | ) 34 | .parse::() 35 | .unwrap(); 36 | 37 | let ts = pest_generator::derive_parser(input.into(), true); 38 | eprintln!("Generated code in {:02?}", t.elapsed()); 39 | ts 40 | }; 41 | 42 | let current = { 43 | let current = fs::read("./src/generated.rs").unwrap_or_default(); 44 | String::from_utf8(current).unwrap() 45 | }; 46 | 47 | let is_up_to_date = { 48 | let current = normalize(¤t[PREAMBLE.len()..]); 49 | let generated = normalize(&token_stream.to_string()); 50 | current == generated 51 | }; 52 | 53 | // Rustfmt takes ages on this input, so fast-path skip it for unchanged 54 | // code. 55 | if is_up_to_date { 56 | return; 57 | } 58 | 59 | let code = { 60 | eprintln!("Reformatting (this will take couple of minutes)"); 61 | let t = Instant::now(); 62 | let code = reformat(&token_stream.to_string()); 63 | let code = format!("{}\n{}", PREAMBLE, code); 64 | eprintln!("Reformatted in {:02?}", t.elapsed()); 65 | code 66 | }; 67 | 68 | fs::write("./src/generated.rs", code).unwrap(); 69 | panic!("Generated code in the repository is outdated, updating..."); 70 | } 71 | 72 | fn reformat(code: &str) -> String { 73 | let mut cmd = Command::new("rustfmt") 74 | .args(&["--config", "tab_spaces=2"]) 75 | .stdin(Stdio::piped()) 76 | .stdout(Stdio::piped()) 77 | .spawn() 78 | .unwrap(); 79 | 80 | cmd.stdin 81 | .take() 82 | .unwrap() 83 | .write_all(code.as_bytes()) 84 | .unwrap(); 85 | let output = cmd.wait_with_output().unwrap(); 86 | assert!(output.status.success()); 87 | String::from_utf8(output.stdout).unwrap() 88 | } 89 | 90 | fn normalize(code: &str) -> String { 91 | code.replace(|c: char| c.is_ascii_whitespace() || "{},".contains(c), "") 92 | } 93 | --------------------------------------------------------------------------------