yaml-rust-0.4.3/.gitignore010064400007670000024000000000551304033245100136570ustar0000000000000000target Cargo.lock *.swp /perf.* /coverage.sh yaml-rust-0.4.3/.travis.yml010064400007670000024000000005441344013434500140110ustar0000000000000000language: rust matrix: include: - rust: stable - rust: beta - rust: nightly - rust: 1.17.0 script: cargo build - rust: 1.24.1 - rust: nightly env: CLIPPY script: | if rustup component add clippy-preview; then cargo clippy -- -Dclippy fi script: - cargo build - cargo test yaml-rust-0.4.3/appveyor.yml010064400007670000024000000006361344013434500142720ustar0000000000000000install: - ps: Start-FileDownload 'https://static.rust-lang.org/dist/rust-1.24.1-i686-pc-windows-gnu.exe' - rust-1.24.1-i686-pc-windows-gnu.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin - SET PATH=%PATH%;C:\MinGW\bin - rustc -V - cargo -V - git submodule update --init --recursive build: false test_script: - cargo test --verbose yaml-rust-0.4.3/Cargo.toml.orig010064400007670000024000000007301344013445500145660ustar0000000000000000[package] name = "yaml-rust" version = "0.4.3" # remember to update html_root_url authors = ["Yuheng Chen "] homepage = "http://chyh1990.github.io/yaml-rust/" documentation = "https://docs.rs/yaml-rust" license = "MIT/Apache-2.0" description = "The missing YAML 1.2 parser for rust" repository = "https://github.com/chyh1990/yaml-rust" readme = "README.md" [dependencies] linked-hash-map = ">=0.0.9, <0.6" [dev-dependencies] quickcheck = "0.7" yaml-rust-0.4.3/Cargo.toml0000644000000017170000000000000110400ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g. crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "yaml-rust" version = "0.4.3" authors = ["Yuheng Chen "] description = "The missing YAML 1.2 parser for rust" homepage = "http://chyh1990.github.io/yaml-rust/" documentation = "https://docs.rs/yaml-rust" readme = "README.md" license = "MIT/Apache-2.0" repository = "https://github.com/chyh1990/yaml-rust" [dependencies.linked-hash-map] version = ">=0.0.9, <0.6" [dev-dependencies.quickcheck] version = "0.7" yaml-rust-0.4.3/examples/dump_yaml.rs010064400007670000024000000017761344013434500160630ustar0000000000000000extern crate yaml_rust; use std::env; use std::fs::File; use std::io::prelude::*; use yaml_rust::yaml; fn print_indent(indent: usize) { for _ in 0..indent { print!(" "); } } fn dump_node(doc: &yaml::Yaml, indent: usize) { match *doc { yaml::Yaml::Array(ref v) => { for x in v { dump_node(x, indent + 1); } } yaml::Yaml::Hash(ref h) => { for (k, v) in h { print_indent(indent); println!("{:?}:", k); dump_node(v, indent + 1); } } _ => { print_indent(indent); println!("{:?}", doc); } } } fn main() { let args: Vec<_> = env::args().collect(); let mut f = File::open(&args[1]).unwrap(); let mut s = String::new(); f.read_to_string(&mut s).unwrap(); let docs = yaml::YamlLoader::load_from_str(&s).unwrap(); for doc in &docs { println!("---"); dump_node(doc, 0); } } yaml-rust-0.4.3/LICENSE-APACHE010064400007670000024000000251371304033245100136230ustar0000000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. yaml-rust-0.4.3/LICENSE-MIT010064400007670000024000000020661304033245100133270ustar0000000000000000The MIT License (MIT) Copyright (c) 2015 Chen Yuheng Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. yaml-rust-0.4.3/README.md010064400007670000024000000063561344013434500131660ustar0000000000000000# yaml-rust The missing YAML 1.2 implementation for Rust. [![Travis](https://travis-ci.org/chyh1990/yaml-rust.svg?branch=master)](https://travis-ci.org/chyh1990/yaml-rust) [![AppVeyor](https://ci.appveyor.com/api/projects/status/scf47535ckp4ylg4?svg=true)](https://ci.appveyor.com/project/chyh1990/yaml-rust) [![crates.io](https://img.shields.io/crates/v/yaml-rust.svg)](https://crates.io/crates/yaml-rust) [![docs.rs](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/yaml-rust) `yaml-rust` is a pure Rust YAML 1.2 implementation, which enjoys the memory safety property and other benefits from the Rust language. The parser is heavily influenced by `libyaml` and `yaml-cpp`. ## Quick Start Add the following to the Cargo.toml of your project: ```toml [dependencies] yaml-rust = "0.4" ``` and import: ```rust extern crate yaml_rust; ``` Use `yaml::YamlLoader` to load the YAML documents and access it as Vec/HashMap: ```rust extern crate yaml_rust; use yaml_rust::{YamlLoader, YamlEmitter}; fn main() { let s = " foo: - list1 - list2 bar: - 1 - 2.0 "; let docs = YamlLoader::load_from_str(s).unwrap(); // Multi document support, doc is a yaml::Yaml let doc = &docs[0]; // Debug support println!("{:?}", doc); // Index access for map & array assert_eq!(doc["foo"][0].as_str().unwrap(), "list1"); assert_eq!(doc["bar"][1].as_f64().unwrap(), 2.0); // Chained key/array access is checked and won't panic, // return BadValue if they are not exist. assert!(doc["INVALID_KEY"][100].is_badvalue()); // Dump the YAML object let mut out_str = String::new(); { let mut emitter = YamlEmitter::new(&mut out_str); emitter.dump(doc).unwrap(); // dump the YAML object to a String } println!("{}", out_str); } ``` Note that `yaml_rust::Yaml` implements `Index<&'a str>` & `Index`: * `Index` assumes the container is an Array * `Index<&'a str>` assumes the container is a string to value Map * otherwise, `Yaml::BadValue` is returned If your document does not conform to this convention (e.g. map with complex type key), you can use the `Yaml::as_XXX` family API to access your documents. ## Features * Pure Rust * Ruby-like Array/Hash access API * Low-level YAML events emission ## Specification Compliance This implementation aims to provide YAML parser fully compatible with the YAML 1.2 specification. The parser can correctly parse almost all examples in the specification, except for the following known bugs: * Empty plain scalar in certain contexts However, the widely used library `libyaml` also fails to parse these examples, so it may not be a huge problem for most users. ## Goals * Encoder * Tag directive * Alias while desearilization ## License Licensed under either of * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ## Contribution Fork & PR on Github. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. yaml-rust-0.4.3/src/emitter.rs010064400007670000024000000404041344013434500145050ustar0000000000000000use std::convert::From; use std::error::Error; use std::fmt::{self, Display}; use yaml::{Hash, Yaml}; #[derive(Copy, Clone, Debug)] pub enum EmitError { FmtError(fmt::Error), BadHashmapKey, } impl Error for EmitError { fn description(&self) -> &str { match *self { EmitError::FmtError(ref err) => err.description(), EmitError::BadHashmapKey => "bad hashmap key", } } fn cause(&self) -> Option<&Error> { None } } impl Display for EmitError { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match *self { EmitError::FmtError(ref err) => Display::fmt(err, formatter), EmitError::BadHashmapKey => formatter.write_str("bad hashmap key"), } } } impl From for EmitError { fn from(f: fmt::Error) -> Self { EmitError::FmtError(f) } } pub struct YamlEmitter<'a> { writer: &'a mut fmt::Write, best_indent: usize, compact: bool, level: isize, } pub type EmitResult = Result<(), EmitError>; // from serialize::json fn escape_str(wr: &mut fmt::Write, v: &str) -> Result<(), fmt::Error> { wr.write_str("\"")?; let mut start = 0; for (i, byte) in v.bytes().enumerate() { let escaped = match byte { b'"' => "\\\"", b'\\' => "\\\\", b'\x00' => "\\u0000", b'\x01' => "\\u0001", b'\x02' => "\\u0002", b'\x03' => "\\u0003", b'\x04' => "\\u0004", b'\x05' => "\\u0005", b'\x06' => "\\u0006", b'\x07' => "\\u0007", b'\x08' => "\\b", b'\t' => "\\t", b'\n' => "\\n", b'\x0b' => "\\u000b", b'\x0c' => "\\f", b'\r' => "\\r", b'\x0e' => "\\u000e", b'\x0f' => "\\u000f", b'\x10' => "\\u0010", b'\x11' => "\\u0011", b'\x12' => "\\u0012", b'\x13' => "\\u0013", b'\x14' => "\\u0014", b'\x15' => "\\u0015", b'\x16' => "\\u0016", b'\x17' => "\\u0017", b'\x18' => "\\u0018", b'\x19' => "\\u0019", b'\x1a' => "\\u001a", b'\x1b' => "\\u001b", b'\x1c' => "\\u001c", b'\x1d' => "\\u001d", b'\x1e' => "\\u001e", b'\x1f' => "\\u001f", b'\x7f' => "\\u007f", _ => continue, }; if start < i { wr.write_str(&v[start..i])?; } wr.write_str(escaped)?; start = i + 1; } if start != v.len() { wr.write_str(&v[start..])?; } wr.write_str("\"")?; Ok(()) } impl<'a> YamlEmitter<'a> { pub fn new(writer: &'a mut fmt::Write) -> YamlEmitter { YamlEmitter { writer, best_indent: 2, compact: true, level: -1, } } /// Set 'compact inline notation' on or off, as described for block /// [sequences](http://www.yaml.org/spec/1.2/spec.html#id2797382) /// and /// [mappings](http://www.yaml.org/spec/1.2/spec.html#id2798057). /// /// In this form, blocks cannot have any properties (such as anchors /// or tags), which should be OK, because this emitter doesn't /// (currently) emit those anyways. pub fn compact(&mut self, compact: bool) { self.compact = compact; } /// Determine if this emitter is using 'compact inline notation'. pub fn is_compact(&self) -> bool { self.compact } pub fn dump(&mut self, doc: &Yaml) -> EmitResult { // write DocumentStart writeln!(self.writer, "---")?; self.level = -1; self.emit_node(doc) } fn write_indent(&mut self) -> EmitResult { if self.level <= 0 { return Ok(()); } for _ in 0..self.level { for _ in 0..self.best_indent { write!(self.writer, " ")?; } } Ok(()) } fn emit_node(&mut self, node: &Yaml) -> EmitResult { match *node { Yaml::Array(ref v) => self.emit_array(v), Yaml::Hash(ref h) => self.emit_hash(h), Yaml::String(ref v) => { if need_quotes(v) { escape_str(self.writer, v)?; } else { write!(self.writer, "{}", v)?; } Ok(()) } Yaml::Boolean(v) => { if v { self.writer.write_str("true")?; } else { self.writer.write_str("false")?; } Ok(()) } Yaml::Integer(v) => { write!(self.writer, "{}", v)?; Ok(()) } Yaml::Real(ref v) => { write!(self.writer, "{}", v)?; Ok(()) } Yaml::Null | Yaml::BadValue => { write!(self.writer, "~")?; Ok(()) } // XXX(chenyh) Alias _ => Ok(()), } } fn emit_array(&mut self, v: &[Yaml]) -> EmitResult { if v.is_empty() { write!(self.writer, "[]")?; } else { self.level += 1; for (cnt, x) in v.iter().enumerate() { if cnt > 0 { writeln!(self.writer)?; self.write_indent()?; } write!(self.writer, "-")?; self.emit_val(true, x)?; } self.level -= 1; } Ok(()) } fn emit_hash(&mut self, h: &Hash) -> EmitResult { if h.is_empty() { self.writer.write_str("{}")?; } else { self.level += 1; for (cnt, (k, v)) in h.iter().enumerate() { let complex_key = match *k { Yaml::Hash(_) | Yaml::Array(_) => true, _ => false, }; if cnt > 0 { writeln!(self.writer)?; self.write_indent()?; } if complex_key { write!(self.writer, "?")?; self.emit_val(true, k)?; writeln!(self.writer)?; self.write_indent()?; write!(self.writer, ":")?; self.emit_val(true, v)?; } else { self.emit_node(k)?; write!(self.writer, ":")?; self.emit_val(false, v)?; } } self.level -= 1; } Ok(()) } /// Emit a yaml as a hash or array value: i.e., which should appear /// following a ":" or "-", either after a space, or on a new line. /// If `inline` is true, then the preceeding characters are distinct /// and short enough to respect the compact flag. fn emit_val(&mut self, inline: bool, val: &Yaml) -> EmitResult { match *val { Yaml::Array(ref v) => { if (inline && self.compact) || v.is_empty() { write!(self.writer, " ")?; } else { writeln!(self.writer)?; self.level += 1; self.write_indent()?; self.level -= 1; } self.emit_array(v) } Yaml::Hash(ref h) => { if (inline && self.compact) || h.is_empty() { write!(self.writer, " ")?; } else { writeln!(self.writer)?; self.level += 1; self.write_indent()?; self.level -= 1; } self.emit_hash(h) } _ => { write!(self.writer, " ")?; self.emit_node(val) } } } } /// Check if the string requires quoting. /// Strings starting with any of the following characters must be quoted. /// :, &, *, ?, |, -, <, >, =, !, %, @ /// Strings containing any of the following characters must be quoted. /// {, }, [, ], ,, #, ` /// /// If the string contains any of the following control characters, it must be escaped with double quotes: /// \0, \x01, \x02, \x03, \x04, \x05, \x06, \a, \b, \t, \n, \v, \f, \r, \x0e, \x0f, \x10, \x11, \x12, \x13, \x14, \x15, \x16, \x17, \x18, \x19, \x1a, \e, \x1c, \x1d, \x1e, \x1f, \N, \_, \L, \P /// /// Finally, there are other cases when the strings must be quoted, no matter if you're using single or double quotes: /// * When the string is true or false (otherwise, it would be treated as a boolean value); /// * When the string is null or ~ (otherwise, it would be considered as a null value); /// * When the string looks like a number, such as integers (e.g. 2, 14, etc.), floats (e.g. 2.6, 14.9) and exponential numbers (e.g. 12e7, etc.) (otherwise, it would be treated as a numeric value); /// * When the string looks like a date (e.g. 2014-12-31) (otherwise it would be automatically converted into a Unix timestamp). fn need_quotes(string: &str) -> bool { fn need_quotes_spaces(string: &str) -> bool { string.starts_with(' ') || string.ends_with(' ') } string == "" || need_quotes_spaces(string) || string.starts_with(|character: char| match character { '&' | '*' | '?' | '|' | '-' | '<' | '>' | '=' | '!' | '%' | '@' => true, _ => false, }) || string.contains(|character: char| match character { ':' | '{' | '}' | '[' | ']' | ',' | '#' | '`' | '\"' | '\'' | '\\' | '\0'...'\x06' | '\t' | '\n' | '\r' | '\x0e'...'\x1a' | '\x1c'...'\x1f' => true, _ => false, }) || [ // http://yaml.org/type/bool.html // Note: 'y', 'Y', 'n', 'N', is not quoted deliberately, as in libyaml. PyYAML also parse // them as string, not booleans, although it is volating the YAML 1.1 specification. // See https://github.com/dtolnay/serde-yaml/pull/83#discussion_r152628088. "yes", "Yes", "YES", "no", "No", "NO", "True", "TRUE", "true", "False", "FALSE", "false", "on", "On", "ON", "off", "Off", "OFF", // http://yaml.org/type/null.html "null", "Null", "NULL", "~", ] .contains(&string) || string.starts_with('.') || string.parse::().is_ok() || string.parse::().is_ok() } #[cfg(test)] mod test { use super::*; use YamlLoader; #[test] fn test_emit_simple() { let s = " # comment a0 bb: val a1: b1: 4 b2: d a2: 4 # i'm comment a3: [1, 2, 3] a4: - [a1, a2] - 2 "; let docs = YamlLoader::load_from_str(&s).unwrap(); let doc = &docs[0]; let mut writer = String::new(); { let mut emitter = YamlEmitter::new(&mut writer); emitter.dump(doc).unwrap(); } println!("original:\n{}", s); println!("emitted:\n{}", writer); let docs_new = match YamlLoader::load_from_str(&writer) { Ok(y) => y, Err(e) => panic!(format!("{}", e)), }; let doc_new = &docs_new[0]; assert_eq!(doc, doc_new); } #[test] fn test_emit_complex() { let s = r#" cataloge: product: &coffee { name: Coffee, price: 2.5 , unit: 1l } product: &cookies { name: Cookies!, price: 3.40 , unit: 400g} products: *coffee: amount: 4 *cookies: amount: 4 [1,2,3,4]: array key 2.4: real key true: bool key {}: empty hash key "#; let docs = YamlLoader::load_from_str(&s).unwrap(); let doc = &docs[0]; let mut writer = String::new(); { let mut emitter = YamlEmitter::new(&mut writer); emitter.dump(doc).unwrap(); } let docs_new = match YamlLoader::load_from_str(&writer) { Ok(y) => y, Err(e) => panic!(format!("{}", e)), }; let doc_new = &docs_new[0]; assert_eq!(doc, doc_new); } #[test] fn test_emit_avoid_quotes() { let s = r#"--- a7: 你好 boolean: "true" boolean2: "false" date: 2014-12-31 empty_string: "" empty_string1: " " empty_string2: " a" empty_string3: " a " exp: "12e7" field: ":" field2: "{" field3: "\\" field4: "\n" field5: "can't avoid quote" float: "2.6" int: "4" nullable: "null" nullable2: "~" products: "*coffee": amount: 4 "*cookies": amount: 4 ".milk": amount: 1 "2.4": real key "[1,2,3,4]": array key "true": bool key "{}": empty hash key x: test y: avoid quoting here z: string with spaces"#; let docs = YamlLoader::load_from_str(&s).unwrap(); let doc = &docs[0]; let mut writer = String::new(); { let mut emitter = YamlEmitter::new(&mut writer); emitter.dump(doc).unwrap(); } assert_eq!(s, writer, "actual:\n\n{}\n", writer); } #[test] fn emit_quoted_bools() { let input = r#"--- string0: yes string1: no string2: "true" string3: "false" string4: "~" null0: ~ [true, false]: real_bools [True, TRUE, False, FALSE, y,Y,yes,Yes,YES,n,N,no,No,NO,on,On,ON,off,Off,OFF]: false_bools bool0: true bool1: false"#; let expected = r#"--- string0: "yes" string1: "no" string2: "true" string3: "false" string4: "~" null0: ~ ? - true - false : real_bools ? - "True" - "TRUE" - "False" - "FALSE" - y - Y - "yes" - "Yes" - "YES" - n - N - "no" - "No" - "NO" - "on" - "On" - "ON" - "off" - "Off" - "OFF" : false_bools bool0: true bool1: false"#; let docs = YamlLoader::load_from_str(&input).unwrap(); let doc = &docs[0]; let mut writer = String::new(); { let mut emitter = YamlEmitter::new(&mut writer); emitter.dump(doc).unwrap(); } assert_eq!( expected, writer, "expected:\n{}\nactual:\n{}\n", expected, writer ); } #[test] fn test_empty_and_nested() { test_empty_and_nested_flag(false) } #[test] fn test_empty_and_nested_compact() { test_empty_and_nested_flag(true) } fn test_empty_and_nested_flag(compact: bool) { let s = if compact { r#"--- a: b: c: hello d: {} e: - f - g - h: []"# } else { r#"--- a: b: c: hello d: {} e: - f - g - h: []"# }; let docs = YamlLoader::load_from_str(&s).unwrap(); let doc = &docs[0]; let mut writer = String::new(); { let mut emitter = YamlEmitter::new(&mut writer); emitter.compact(compact); emitter.dump(doc).unwrap(); } assert_eq!(s, writer); } #[test] fn test_nested_arrays() { let s = r#"--- a: - b - - c - d - - e - f"#; let docs = YamlLoader::load_from_str(&s).unwrap(); let doc = &docs[0]; let mut writer = String::new(); { let mut emitter = YamlEmitter::new(&mut writer); emitter.dump(doc).unwrap(); } println!("original:\n{}", s); println!("emitted:\n{}", writer); assert_eq!(s, writer); } #[test] fn test_deeply_nested_arrays() { let s = r#"--- a: - b - - c - d - - e - - f - - e"#; let docs = YamlLoader::load_from_str(&s).unwrap(); let doc = &docs[0]; let mut writer = String::new(); { let mut emitter = YamlEmitter::new(&mut writer); emitter.dump(doc).unwrap(); } println!("original:\n{}", s); println!("emitted:\n{}", writer); assert_eq!(s, writer); } #[test] fn test_nested_hashes() { let s = r#"--- a: b: c: d: e: f"#; let docs = YamlLoader::load_from_str(&s).unwrap(); let doc = &docs[0]; let mut writer = String::new(); { let mut emitter = YamlEmitter::new(&mut writer); emitter.dump(doc).unwrap(); } println!("original:\n{}", s); println!("emitted:\n{}", writer); assert_eq!(s, writer); } } yaml-rust-0.4.3/src/lib.rs010064400007670000024000000053101344013450300135730ustar0000000000000000// Copyright 2015, Yuheng Chen. See the LICENSE file at the top-level // directory of this distribution. //! YAML 1.2 implementation in pure Rust. //! //! # Usage //! //! This crate is [on github](https://github.com/chyh1990/yaml-rust) and can be //! used by adding `yaml-rust` to the dependencies in your project's `Cargo.toml`. //! //! ```toml //! [dependencies.yaml-rust] //! git = "https://github.com/chyh1990/yaml-rust.git" //! ``` //! //! And this in your crate root: //! //! ```rust //! extern crate yaml_rust; //! ``` //! //! Parse a string into `Vec` and then serialize it as a YAML string. //! //! # Examples //! //! ``` //! use yaml_rust::{YamlLoader, YamlEmitter}; //! //! let docs = YamlLoader::load_from_str("[1, 2, 3]").unwrap(); //! let doc = &docs[0]; // select the first document //! assert_eq!(doc[0].as_i64().unwrap(), 1); // access elements by index //! //! let mut out_str = String::new(); //! let mut emitter = YamlEmitter::new(&mut out_str); //! emitter.dump(doc).unwrap(); // dump the YAML object to a String //! //! ``` #![doc(html_root_url = "https://docs.rs/yaml-rust/0.4.3")] #![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] #![cfg_attr(feature = "cargo-clippy", warn(cyclomatic_complexity))] #![cfg_attr( feature = "cargo-clippy", allow(match_same_arms, should_implement_trait) )] extern crate linked_hash_map; pub mod emitter; pub mod parser; pub mod scanner; pub mod yaml; // reexport key APIs pub use emitter::{EmitError, YamlEmitter}; pub use parser::Event; pub use scanner::ScanError; pub use yaml::{Yaml, YamlLoader}; #[cfg(test)] mod tests { use super::*; #[test] fn test_api() { let s = " # from yaml-cpp example - name: Ogre position: [0, 5, 0] powers: - name: Club damage: 10 - name: Fist damage: 8 - name: Dragon position: [1, 0, 10] powers: - name: Fire Breath damage: 25 - name: Claws damage: 15 - name: Wizard position: [5, -3, 0] powers: - name: Acid Rain damage: 50 - name: Staff damage: 3 "; let docs = YamlLoader::load_from_str(s).unwrap(); let doc = &docs[0]; assert_eq!(doc[0]["name"].as_str().unwrap(), "Ogre"); let mut writer = String::new(); { let mut emitter = YamlEmitter::new(&mut writer); emitter.dump(doc).unwrap(); } assert!(!writer.is_empty()); } fn try_fail(s: &str) -> Result, ScanError> { let t = YamlLoader::load_from_str(s)?; Ok(t) } #[test] fn test_fail() { let s = " # syntax error scalar key: [1, 2]] key1:a2 "; assert!(YamlLoader::load_from_str(s).is_err()); assert!(try_fail(s).is_err()); } } yaml-rust-0.4.3/src/parser.rs010064400007670000024000000706441344013434500143410ustar0000000000000000use scanner::*; use std::collections::HashMap; #[derive(Clone, Copy, PartialEq, Debug, Eq)] enum State { StreamStart, ImplicitDocumentStart, DocumentStart, DocumentContent, DocumentEnd, BlockNode, // BlockNodeOrIndentlessSequence, // FlowNode, BlockSequenceFirstEntry, BlockSequenceEntry, IndentlessSequenceEntry, BlockMappingFirstKey, BlockMappingKey, BlockMappingValue, FlowSequenceFirstEntry, FlowSequenceEntry, FlowSequenceEntryMappingKey, FlowSequenceEntryMappingValue, FlowSequenceEntryMappingEnd, FlowMappingFirstKey, FlowMappingKey, FlowMappingValue, FlowMappingEmptyValue, End, } /// `Event` is used with the low-level event base parsing API, /// see `EventReceiver` trait. #[derive(Clone, PartialEq, Debug, Eq)] pub enum Event { /// Reserved for internal use Nothing, StreamStart, StreamEnd, DocumentStart, DocumentEnd, /// Refer to an anchor ID Alias(usize), /// Value, style, anchor_id, tag Scalar(String, TScalarStyle, usize, Option), /// Anchor ID SequenceStart(usize), SequenceEnd, /// Anchor ID MappingStart(usize), MappingEnd, } impl Event { fn empty_scalar() -> Event { // a null scalar Event::Scalar("~".to_owned(), TScalarStyle::Plain, 0, None) } fn empty_scalar_with_anchor(anchor: usize, tag: Option) -> Event { Event::Scalar("".to_owned(), TScalarStyle::Plain, anchor, tag) } } #[derive(Debug)] pub struct Parser { scanner: Scanner, states: Vec, state: State, marks: Vec, token: Option, current: Option<(Event, Marker)>, anchors: HashMap, anchor_id: usize, } pub trait EventReceiver { fn on_event(&mut self, ev: Event); } pub trait MarkedEventReceiver { fn on_event(&mut self, ev: Event, _mark: Marker); } impl MarkedEventReceiver for R { fn on_event(&mut self, ev: Event, _mark: Marker) { self.on_event(ev) } } pub type ParseResult = Result<(Event, Marker), ScanError>; impl> Parser { pub fn new(src: T) -> Parser { Parser { scanner: Scanner::new(src), states: Vec::new(), state: State::StreamStart, marks: Vec::new(), token: None, current: None, anchors: HashMap::new(), // valid anchor_id starts from 1 anchor_id: 1, } } pub fn peek(&mut self) -> Result<&(Event, Marker), ScanError> { match self.current { Some(ref x) => Ok(x), None => { self.current = Some(self.next()?); self.peek() } } } pub fn next(&mut self) -> ParseResult { match self.current { None => self.parse(), Some(_) => Ok(self.current.take().unwrap()), } } fn peek_token(&mut self) -> Result<&Token, ScanError> { match self.token { None => { self.token = Some(self.scan_next_token()?); Ok(self.token.as_ref().unwrap()) } Some(ref tok) => Ok(tok), } } fn scan_next_token(&mut self) -> Result { let token = self.scanner.next(); match token { None => match self.scanner.get_error() { None => Err(ScanError::new(self.scanner.mark(), "unexpected eof")), Some(e) => Err(e), }, Some(tok) => Ok(tok), } } fn fetch_token(&mut self) -> Token { self.token .take() .expect("fetch_token needs to be preceded by peek_token") } fn skip(&mut self) { self.token = None; //self.peek_token(); } fn pop_state(&mut self) { self.state = self.states.pop().unwrap() } fn push_state(&mut self, state: State) { self.states.push(state); } fn parse(&mut self) -> ParseResult { if self.state == State::End { return Ok((Event::StreamEnd, self.scanner.mark())); } let (ev, mark) = self.state_machine()?; // println!("EV {:?}", ev); Ok((ev, mark)) } pub fn load( &mut self, recv: &mut R, multi: bool, ) -> Result<(), ScanError> { if !self.scanner.stream_started() { let (ev, mark) = self.next()?; assert_eq!(ev, Event::StreamStart); recv.on_event(ev, mark); } if self.scanner.stream_ended() { // XXX has parsed? recv.on_event(Event::StreamEnd, self.scanner.mark()); return Ok(()); } loop { let (ev, mark) = self.next()?; if ev == Event::StreamEnd { recv.on_event(ev, mark); return Ok(()); } // clear anchors before a new document self.anchors.clear(); self.load_document(ev, mark, recv)?; if !multi { break; } } Ok(()) } fn load_document( &mut self, first_ev: Event, mark: Marker, recv: &mut R, ) -> Result<(), ScanError> { assert_eq!(first_ev, Event::DocumentStart); recv.on_event(first_ev, mark); let (ev, mark) = self.next()?; self.load_node(ev, mark, recv)?; // DOCUMENT-END is expected. let (ev, mark) = self.next()?; assert_eq!(ev, Event::DocumentEnd); recv.on_event(ev, mark); Ok(()) } fn load_node( &mut self, first_ev: Event, mark: Marker, recv: &mut R, ) -> Result<(), ScanError> { match first_ev { Event::Alias(..) | Event::Scalar(..) => { recv.on_event(first_ev, mark); Ok(()) } Event::SequenceStart(_) => { recv.on_event(first_ev, mark); self.load_sequence(recv) } Event::MappingStart(_) => { recv.on_event(first_ev, mark); self.load_mapping(recv) } _ => { println!("UNREACHABLE EVENT: {:?}", first_ev); unreachable!(); } } } fn load_mapping(&mut self, recv: &mut R) -> Result<(), ScanError> { let (mut key_ev, mut key_mark) = self.next()?; while key_ev != Event::MappingEnd { // key self.load_node(key_ev, key_mark, recv)?; // value let (ev, mark) = self.next()?; self.load_node(ev, mark, recv)?; // next event let (ev, mark) = self.next()?; key_ev = ev; key_mark = mark; } recv.on_event(key_ev, key_mark); Ok(()) } fn load_sequence(&mut self, recv: &mut R) -> Result<(), ScanError> { let (mut ev, mut mark) = self.next()?; while ev != Event::SequenceEnd { self.load_node(ev, mark, recv)?; // next event let (next_ev, next_mark) = self.next()?; ev = next_ev; mark = next_mark; } recv.on_event(ev, mark); Ok(()) } fn state_machine(&mut self) -> ParseResult { // let next_tok = self.peek_token()?; // println!("cur_state {:?}, next tok: {:?}", self.state, next_tok); match self.state { State::StreamStart => self.stream_start(), State::ImplicitDocumentStart => self.document_start(true), State::DocumentStart => self.document_start(false), State::DocumentContent => self.document_content(), State::DocumentEnd => self.document_end(), State::BlockNode => self.parse_node(true, false), // State::BlockNodeOrIndentlessSequence => self.parse_node(true, true), // State::FlowNode => self.parse_node(false, false), State::BlockMappingFirstKey => self.block_mapping_key(true), State::BlockMappingKey => self.block_mapping_key(false), State::BlockMappingValue => self.block_mapping_value(), State::BlockSequenceFirstEntry => self.block_sequence_entry(true), State::BlockSequenceEntry => self.block_sequence_entry(false), State::FlowSequenceFirstEntry => self.flow_sequence_entry(true), State::FlowSequenceEntry => self.flow_sequence_entry(false), State::FlowMappingFirstKey => self.flow_mapping_key(true), State::FlowMappingKey => self.flow_mapping_key(false), State::FlowMappingValue => self.flow_mapping_value(false), State::IndentlessSequenceEntry => self.indentless_sequence_entry(), State::FlowSequenceEntryMappingKey => self.flow_sequence_entry_mapping_key(), State::FlowSequenceEntryMappingValue => self.flow_sequence_entry_mapping_value(), State::FlowSequenceEntryMappingEnd => self.flow_sequence_entry_mapping_end(), State::FlowMappingEmptyValue => self.flow_mapping_value(true), /* impossible */ State::End => unreachable!(), } } fn stream_start(&mut self) -> ParseResult { match *self.peek_token()? { Token(mark, TokenType::StreamStart(_)) => { self.state = State::ImplicitDocumentStart; self.skip(); Ok((Event::StreamStart, mark)) } Token(mark, _) => Err(ScanError::new(mark, "did not find expected ")), } } fn document_start(&mut self, implicit: bool) -> ParseResult { if !implicit { while let TokenType::DocumentEnd = self.peek_token()?.1 { self.skip(); } } match *self.peek_token()? { Token(mark, TokenType::StreamEnd) => { self.state = State::End; self.skip(); Ok((Event::StreamEnd, mark)) } Token(_, TokenType::VersionDirective(..)) | Token(_, TokenType::TagDirective(..)) | Token(_, TokenType::DocumentStart) => { // explicit document self._explict_document_start() } Token(mark, _) if implicit => { self.parser_process_directives()?; self.push_state(State::DocumentEnd); self.state = State::BlockNode; Ok((Event::DocumentStart, mark)) } _ => { // explicit document self._explict_document_start() } } } fn parser_process_directives(&mut self) -> Result<(), ScanError> { loop { match self.peek_token()?.1 { TokenType::VersionDirective(_, _) => { // XXX parsing with warning according to spec //if major != 1 || minor > 2 { // return Err(ScanError::new(tok.0, // "found incompatible YAML document")); //} } TokenType::TagDirective(..) => { // TODO add tag directive } _ => break, } self.skip(); } // TODO tag directive Ok(()) } fn _explict_document_start(&mut self) -> ParseResult { self.parser_process_directives()?; match *self.peek_token()? { Token(mark, TokenType::DocumentStart) => { self.push_state(State::DocumentEnd); self.state = State::DocumentContent; self.skip(); Ok((Event::DocumentStart, mark)) } Token(mark, _) => Err(ScanError::new( mark, "did not find expected ", )), } } fn document_content(&mut self) -> ParseResult { match *self.peek_token()? { Token(mark, TokenType::VersionDirective(..)) | Token(mark, TokenType::TagDirective(..)) | Token(mark, TokenType::DocumentStart) | Token(mark, TokenType::DocumentEnd) | Token(mark, TokenType::StreamEnd) => { self.pop_state(); // empty scalar Ok((Event::empty_scalar(), mark)) } _ => self.parse_node(true, false), } } fn document_end(&mut self) -> ParseResult { let mut _implicit = true; let marker: Marker = match *self.peek_token()? { Token(mark, TokenType::DocumentEnd) => { self.skip(); _implicit = false; mark } Token(mark, _) => mark, }; // TODO tag handling self.state = State::DocumentStart; Ok((Event::DocumentEnd, marker)) } fn register_anchor(&mut self, name: String, _: &Marker) -> Result { // anchors can be overrided/reused // if self.anchors.contains_key(name) { // return Err(ScanError::new(*mark, // "while parsing anchor, found duplicated anchor")); // } let new_id = self.anchor_id; self.anchor_id += 1; self.anchors.insert(name, new_id); Ok(new_id) } fn parse_node(&mut self, block: bool, indentless_sequence: bool) -> ParseResult { let mut anchor_id = 0; let mut tag = None; match *self.peek_token()? { Token(_, TokenType::Alias(_)) => { self.pop_state(); if let Token(mark, TokenType::Alias(name)) = self.fetch_token() { match self.anchors.get(&name) { None => { return Err(ScanError::new( mark, "while parsing node, found unknown anchor", )) } Some(id) => return Ok((Event::Alias(*id), mark)), } } else { unreachable!() } } Token(_, TokenType::Anchor(_)) => { if let Token(mark, TokenType::Anchor(name)) = self.fetch_token() { anchor_id = self.register_anchor(name, &mark)?; if let TokenType::Tag(..) = self.peek_token()?.1 { if let tg @ TokenType::Tag(..) = self.fetch_token().1 { tag = Some(tg); } else { unreachable!() } } } else { unreachable!() } } Token(_, TokenType::Tag(..)) => { if let tg @ TokenType::Tag(..) = self.fetch_token().1 { tag = Some(tg); if let TokenType::Anchor(_) = self.peek_token()?.1 { if let Token(mark, TokenType::Anchor(name)) = self.fetch_token() { anchor_id = self.register_anchor(name, &mark)?; } else { unreachable!() } } } else { unreachable!() } } _ => {} } match *self.peek_token()? { Token(mark, TokenType::BlockEntry) if indentless_sequence => { self.state = State::IndentlessSequenceEntry; Ok((Event::SequenceStart(anchor_id), mark)) } Token(_, TokenType::Scalar(..)) => { self.pop_state(); if let Token(mark, TokenType::Scalar(style, v)) = self.fetch_token() { Ok((Event::Scalar(v, style, anchor_id, tag), mark)) } else { unreachable!() } } Token(mark, TokenType::FlowSequenceStart) => { self.state = State::FlowSequenceFirstEntry; Ok((Event::SequenceStart(anchor_id), mark)) } Token(mark, TokenType::FlowMappingStart) => { self.state = State::FlowMappingFirstKey; Ok((Event::MappingStart(anchor_id), mark)) } Token(mark, TokenType::BlockSequenceStart) if block => { self.state = State::BlockSequenceFirstEntry; Ok((Event::SequenceStart(anchor_id), mark)) } Token(mark, TokenType::BlockMappingStart) if block => { self.state = State::BlockMappingFirstKey; Ok((Event::MappingStart(anchor_id), mark)) } // ex 7.2, an empty scalar can follow a secondary tag Token(mark, _) if tag.is_some() || anchor_id > 0 => { self.pop_state(); Ok((Event::empty_scalar_with_anchor(anchor_id, tag), mark)) } Token(mark, _) => Err(ScanError::new( mark, "while parsing a node, did not find expected node content", )), } } fn block_mapping_key(&mut self, first: bool) -> ParseResult { // skip BlockMappingStart if first { let _ = self.peek_token()?; //self.marks.push(tok.0); self.skip(); } match *self.peek_token()? { Token(_, TokenType::Key) => { self.skip(); match *self.peek_token()? { Token(mark, TokenType::Key) | Token(mark, TokenType::Value) | Token(mark, TokenType::BlockEnd) => { self.state = State::BlockMappingValue; // empty scalar Ok((Event::empty_scalar(), mark)) } _ => { self.push_state(State::BlockMappingValue); self.parse_node(true, true) } } } // XXX(chenyh): libyaml failed to parse spec 1.2, ex8.18 Token(mark, TokenType::Value) => { self.state = State::BlockMappingValue; Ok((Event::empty_scalar(), mark)) } Token(mark, TokenType::BlockEnd) => { self.pop_state(); self.skip(); Ok((Event::MappingEnd, mark)) } Token(mark, _) => Err(ScanError::new( mark, "while parsing a block mapping, did not find expected key", )), } } fn block_mapping_value(&mut self) -> ParseResult { match *self.peek_token()? { Token(_, TokenType::Value) => { self.skip(); match *self.peek_token()? { Token(mark, TokenType::Key) | Token(mark, TokenType::Value) | Token(mark, TokenType::BlockEnd) => { self.state = State::BlockMappingKey; // empty scalar Ok((Event::empty_scalar(), mark)) } _ => { self.push_state(State::BlockMappingKey); self.parse_node(true, true) } } } Token(mark, _) => { self.state = State::BlockMappingKey; // empty scalar Ok((Event::empty_scalar(), mark)) } } } fn flow_mapping_key(&mut self, first: bool) -> ParseResult { if first { let _ = self.peek_token()?; self.skip(); } let marker: Marker = { match *self.peek_token()? { Token(mark, TokenType::FlowMappingEnd) => mark, Token(mark, _) => { if !first { match *self.peek_token()? { Token(_, TokenType::FlowEntry) => self.skip(), Token(mark, _) => return Err(ScanError::new(mark, "while parsing a flow mapping, did not find expected ',' or '}'")) } } match *self.peek_token()? { Token(_, TokenType::Key) => { self.skip(); match *self.peek_token()? { Token(mark, TokenType::Value) | Token(mark, TokenType::FlowEntry) | Token(mark, TokenType::FlowMappingEnd) => { self.state = State::FlowMappingValue; return Ok((Event::empty_scalar(), mark)); } _ => { self.push_state(State::FlowMappingValue); return self.parse_node(false, false); } } } Token(marker, TokenType::Value) => { self.state = State::FlowMappingValue; return Ok((Event::empty_scalar(), marker)); } Token(_, TokenType::FlowMappingEnd) => (), _ => { self.push_state(State::FlowMappingEmptyValue); return self.parse_node(false, false); } } mark } } }; self.pop_state(); self.skip(); Ok((Event::MappingEnd, marker)) } fn flow_mapping_value(&mut self, empty: bool) -> ParseResult { let mark: Marker = { if empty { let Token(mark, _) = *self.peek_token()?; self.state = State::FlowMappingKey; return Ok((Event::empty_scalar(), mark)); } else { match *self.peek_token()? { Token(marker, TokenType::Value) => { self.skip(); match self.peek_token()?.1 { TokenType::FlowEntry | TokenType::FlowMappingEnd => {} _ => { self.push_state(State::FlowMappingKey); return self.parse_node(false, false); } } marker } Token(marker, _) => marker, } } }; self.state = State::FlowMappingKey; Ok((Event::empty_scalar(), mark)) } fn flow_sequence_entry(&mut self, first: bool) -> ParseResult { // skip FlowMappingStart if first { let _ = self.peek_token()?; //self.marks.push(tok.0); self.skip(); } match *self.peek_token()? { Token(mark, TokenType::FlowSequenceEnd) => { self.pop_state(); self.skip(); return Ok((Event::SequenceEnd, mark)); } Token(_, TokenType::FlowEntry) if !first => { self.skip(); } Token(mark, _) if !first => { return Err(ScanError::new( mark, "while parsing a flow sequence, expectd ',' or ']'", )); } _ => { /* next */ } } match *self.peek_token()? { Token(mark, TokenType::FlowSequenceEnd) => { self.pop_state(); self.skip(); Ok((Event::SequenceEnd, mark)) } Token(mark, TokenType::Key) => { self.state = State::FlowSequenceEntryMappingKey; self.skip(); Ok((Event::MappingStart(0), mark)) } _ => { self.push_state(State::FlowSequenceEntry); self.parse_node(false, false) } } } fn indentless_sequence_entry(&mut self) -> ParseResult { match *self.peek_token()? { Token(_, TokenType::BlockEntry) => (), Token(mark, _) => { self.pop_state(); return Ok((Event::SequenceEnd, mark)); } } self.skip(); match *self.peek_token()? { Token(mark, TokenType::BlockEntry) | Token(mark, TokenType::Key) | Token(mark, TokenType::Value) | Token(mark, TokenType::BlockEnd) => { self.state = State::IndentlessSequenceEntry; Ok((Event::empty_scalar(), mark)) } _ => { self.push_state(State::IndentlessSequenceEntry); self.parse_node(true, false) } } } fn block_sequence_entry(&mut self, first: bool) -> ParseResult { // BLOCK-SEQUENCE-START if first { let _ = self.peek_token()?; //self.marks.push(tok.0); self.skip(); } match *self.peek_token()? { Token(mark, TokenType::BlockEnd) => { self.pop_state(); self.skip(); Ok((Event::SequenceEnd, mark)) } Token(_, TokenType::BlockEntry) => { self.skip(); match *self.peek_token()? { Token(mark, TokenType::BlockEntry) | Token(mark, TokenType::BlockEnd) => { self.state = State::BlockSequenceEntry; Ok((Event::empty_scalar(), mark)) } _ => { self.push_state(State::BlockSequenceEntry); self.parse_node(true, false) } } } Token(mark, _) => Err(ScanError::new( mark, "while parsing a block collection, did not find expected '-' indicator", )), } } fn flow_sequence_entry_mapping_key(&mut self) -> ParseResult { match *self.peek_token()? { Token(mark, TokenType::Value) | Token(mark, TokenType::FlowEntry) | Token(mark, TokenType::FlowSequenceEnd) => { self.skip(); self.state = State::FlowSequenceEntryMappingValue; Ok((Event::empty_scalar(), mark)) } _ => { self.push_state(State::FlowSequenceEntryMappingValue); self.parse_node(false, false) } } } fn flow_sequence_entry_mapping_value(&mut self) -> ParseResult { match *self.peek_token()? { Token(_, TokenType::Value) => { self.skip(); self.state = State::FlowSequenceEntryMappingValue; match *self.peek_token()? { Token(mark, TokenType::FlowEntry) | Token(mark, TokenType::FlowSequenceEnd) => { self.state = State::FlowSequenceEntryMappingEnd; Ok((Event::empty_scalar(), mark)) } _ => { self.push_state(State::FlowSequenceEntryMappingEnd); self.parse_node(false, false) } } } Token(mark, _) => { self.state = State::FlowSequenceEntryMappingEnd; Ok((Event::empty_scalar(), mark)) } } } fn flow_sequence_entry_mapping_end(&mut self) -> ParseResult { self.state = State::FlowSequenceEntry; Ok((Event::MappingEnd, self.scanner.mark())) } } #[cfg(test)] mod test { use super::{Event, Parser}; #[test] fn test_peek_eq_parse() { let s = " a0 bb: val a1: &x b1: 4 b2: d a2: 4 a3: [1, 2, 3] a4: - [a1, a2] - 2 a5: *x "; let mut p = Parser::new(s.chars()); while { let event_peek = p.peek().unwrap().clone(); let event = p.next().unwrap(); assert_eq!(event, event_peek); event.0 != Event::StreamEnd } {} } } yaml-rust-0.4.3/src/scanner.rs010064400007670000024000001762651344013434500145040ustar0000000000000000use std::collections::VecDeque; use std::error::Error; use std::{char, fmt}; #[derive(Clone, Copy, PartialEq, Debug, Eq)] pub enum TEncoding { Utf8, } #[derive(Clone, Copy, PartialEq, Debug, Eq)] pub enum TScalarStyle { Any, Plain, SingleQuoted, DoubleQuoted, Literal, Foled, } #[derive(Clone, Copy, PartialEq, Debug, Eq)] pub struct Marker { index: usize, line: usize, col: usize, } impl Marker { fn new(index: usize, line: usize, col: usize) -> Marker { Marker { index, line, col } } pub fn index(&self) -> usize { self.index } pub fn line(&self) -> usize { self.line } pub fn col(&self) -> usize { self.col } } #[derive(Clone, PartialEq, Debug, Eq)] pub struct ScanError { mark: Marker, info: String, } impl ScanError { pub fn new(loc: Marker, info: &str) -> ScanError { ScanError { mark: loc, info: info.to_owned(), } } pub fn marker(&self) -> &Marker { &self.mark } } impl Error for ScanError { fn description(&self) -> &str { self.info.as_ref() } fn cause(&self) -> Option<&Error> { None } } impl fmt::Display for ScanError { // col starts from 0 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!( formatter, "{} at line {} column {}", self.info, self.mark.line, self.mark.col + 1 ) } } #[derive(Clone, PartialEq, Debug, Eq)] pub enum TokenType { NoToken, StreamStart(TEncoding), StreamEnd, /// major, minor VersionDirective(u32, u32), /// handle, prefix TagDirective(String, String), DocumentStart, DocumentEnd, BlockSequenceStart, BlockMappingStart, BlockEnd, FlowSequenceStart, FlowSequenceEnd, FlowMappingStart, FlowMappingEnd, BlockEntry, FlowEntry, Key, Value, Alias(String), Anchor(String), /// handle, suffix Tag(String, String), Scalar(TScalarStyle, String), } #[derive(Clone, PartialEq, Debug, Eq)] pub struct Token(pub Marker, pub TokenType); #[derive(Clone, PartialEq, Debug, Eq)] struct SimpleKey { possible: bool, required: bool, token_number: usize, mark: Marker, } impl SimpleKey { fn new(mark: Marker) -> SimpleKey { SimpleKey { possible: false, required: false, token_number: 0, mark, } } } #[derive(Debug)] pub struct Scanner { rdr: T, mark: Marker, tokens: VecDeque, buffer: VecDeque, error: Option, stream_start_produced: bool, stream_end_produced: bool, adjacent_value_allowed_at: usize, simple_key_allowed: bool, simple_keys: Vec, indent: isize, indents: Vec, flow_level: u8, tokens_parsed: usize, token_available: bool, } impl> Iterator for Scanner { type Item = Token; fn next(&mut self) -> Option { if self.error.is_some() { return None; } match self.next_token() { Ok(tok) => tok, Err(e) => { self.error = Some(e); None } } } } #[inline] fn is_z(c: char) -> bool { c == '\0' } #[inline] fn is_break(c: char) -> bool { c == '\n' || c == '\r' } #[inline] fn is_breakz(c: char) -> bool { is_break(c) || is_z(c) } #[inline] fn is_blank(c: char) -> bool { c == ' ' || c == '\t' } #[inline] fn is_blankz(c: char) -> bool { is_blank(c) || is_breakz(c) } #[inline] fn is_digit(c: char) -> bool { c >= '0' && c <= '9' } #[inline] fn is_alpha(c: char) -> bool { match c { '0'...'9' | 'a'...'z' | 'A'...'Z' => true, '_' | '-' => true, _ => false, } } #[inline] fn is_hex(c: char) -> bool { (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') } #[inline] fn as_hex(c: char) -> u32 { match c { '0'...'9' => (c as u32) - ('0' as u32), 'a'...'f' => (c as u32) - ('a' as u32) + 10, 'A'...'F' => (c as u32) - ('A' as u32) + 10, _ => unreachable!(), } } #[inline] fn is_flow(c: char) -> bool { match c { ',' | '[' | ']' | '{' | '}' => true, _ => false, } } pub type ScanResult = Result<(), ScanError>; impl> Scanner { /// Creates the YAML tokenizer. pub fn new(rdr: T) -> Scanner { Scanner { rdr, buffer: VecDeque::new(), mark: Marker::new(0, 1, 0), tokens: VecDeque::new(), error: None, stream_start_produced: false, stream_end_produced: false, adjacent_value_allowed_at: 0, simple_key_allowed: true, simple_keys: Vec::new(), indent: -1, indents: Vec::new(), flow_level: 0, tokens_parsed: 0, token_available: false, } } #[inline] pub fn get_error(&self) -> Option { match self.error { None => None, Some(ref e) => Some(e.clone()), } } #[inline] fn lookahead(&mut self, count: usize) { if self.buffer.len() >= count { return; } for _ in 0..(count - self.buffer.len()) { self.buffer.push_back(self.rdr.next().unwrap_or('\0')); } } #[inline] fn skip(&mut self) { let c = self.buffer.pop_front().unwrap(); self.mark.index += 1; if c == '\n' { self.mark.line += 1; self.mark.col = 0; } else { self.mark.col += 1; } } #[inline] fn skip_line(&mut self) { if self.buffer[0] == '\r' && self.buffer[1] == '\n' { self.skip(); self.skip(); } else if is_break(self.buffer[0]) { self.skip(); } } #[inline] fn ch(&self) -> char { self.buffer[0] } #[inline] fn ch_is(&self, c: char) -> bool { self.buffer[0] == c } #[allow(dead_code)] #[inline] fn eof(&self) -> bool { self.ch_is('\0') } #[inline] pub fn stream_started(&self) -> bool { self.stream_start_produced } #[inline] pub fn stream_ended(&self) -> bool { self.stream_end_produced } #[inline] pub fn mark(&self) -> Marker { self.mark } #[inline] fn read_break(&mut self, s: &mut String) { if self.buffer[0] == '\r' && self.buffer[1] == '\n' { s.push('\n'); self.skip(); self.skip(); } else if self.buffer[0] == '\r' || self.buffer[0] == '\n' { s.push('\n'); self.skip(); } else { unreachable!(); } } fn insert_token(&mut self, pos: usize, tok: Token) { let old_len = self.tokens.len(); assert!(pos <= old_len); self.tokens.push_back(tok); for i in 0..old_len - pos { self.tokens.swap(old_len - i, old_len - i - 1); } } fn allow_simple_key(&mut self) { self.simple_key_allowed = true; } fn disallow_simple_key(&mut self) { self.simple_key_allowed = false; } pub fn fetch_next_token(&mut self) -> ScanResult { self.lookahead(1); // println!("--> fetch_next_token Cur {:?} {:?}", self.mark, self.ch()); if !self.stream_start_produced { self.fetch_stream_start(); return Ok(()); } self.skip_to_next_token(); self.stale_simple_keys()?; let mark = self.mark; self.unroll_indent(mark.col as isize); self.lookahead(4); if is_z(self.ch()) { self.fetch_stream_end()?; return Ok(()); } // Is it a directive? if self.mark.col == 0 && self.ch_is('%') { return self.fetch_directive(); } if self.mark.col == 0 && self.buffer[0] == '-' && self.buffer[1] == '-' && self.buffer[2] == '-' && is_blankz(self.buffer[3]) { self.fetch_document_indicator(TokenType::DocumentStart)?; return Ok(()); } if self.mark.col == 0 && self.buffer[0] == '.' && self.buffer[1] == '.' && self.buffer[2] == '.' && is_blankz(self.buffer[3]) { self.fetch_document_indicator(TokenType::DocumentEnd)?; return Ok(()); } let c = self.buffer[0]; let nc = self.buffer[1]; match c { '[' => self.fetch_flow_collection_start(TokenType::FlowSequenceStart), '{' => self.fetch_flow_collection_start(TokenType::FlowMappingStart), ']' => self.fetch_flow_collection_end(TokenType::FlowSequenceEnd), '}' => self.fetch_flow_collection_end(TokenType::FlowMappingEnd), ',' => self.fetch_flow_entry(), '-' if is_blankz(nc) => self.fetch_block_entry(), '?' if is_blankz(nc) => self.fetch_key(), ':' if is_blankz(nc) || (self.flow_level > 0 && (is_flow(nc) || self.mark.index == self.adjacent_value_allowed_at)) => { self.fetch_value() } // Is it an alias? '*' => self.fetch_anchor(true), // Is it an anchor? '&' => self.fetch_anchor(false), '!' => self.fetch_tag(), // Is it a literal scalar? '|' if self.flow_level == 0 => self.fetch_block_scalar(true), // Is it a folded scalar? '>' if self.flow_level == 0 => self.fetch_block_scalar(false), '\'' => self.fetch_flow_scalar(true), '"' => self.fetch_flow_scalar(false), // plain scalar '-' if !is_blankz(nc) => self.fetch_plain_scalar(), ':' | '?' if !is_blankz(nc) && self.flow_level == 0 => self.fetch_plain_scalar(), '%' | '@' | '`' => Err(ScanError::new( self.mark, &format!("unexpected character: `{}'", c), )), _ => self.fetch_plain_scalar(), } } pub fn next_token(&mut self) -> Result, ScanError> { if self.stream_end_produced { return Ok(None); } if !self.token_available { self.fetch_more_tokens()?; } let t = self.tokens.pop_front().unwrap(); self.token_available = false; self.tokens_parsed += 1; if let TokenType::StreamEnd = t.1 { self.stream_end_produced = true; } Ok(Some(t)) } pub fn fetch_more_tokens(&mut self) -> ScanResult { let mut need_more; loop { need_more = false; if self.tokens.is_empty() { need_more = true; } else { self.stale_simple_keys()?; for sk in &self.simple_keys { if sk.possible && sk.token_number == self.tokens_parsed { need_more = true; break; } } } if !need_more { break; } self.fetch_next_token()?; } self.token_available = true; Ok(()) } fn stale_simple_keys(&mut self) -> ScanResult { for sk in &mut self.simple_keys { if sk.possible && (sk.mark.line < self.mark.line || sk.mark.index + 1024 < self.mark.index) { if sk.required { return Err(ScanError::new(self.mark, "simple key expect ':'")); } sk.possible = false; } } Ok(()) } fn skip_to_next_token(&mut self) { loop { self.lookahead(1); // TODO(chenyh) BOM match self.ch() { ' ' => self.skip(), '\t' if self.flow_level > 0 || !self.simple_key_allowed => self.skip(), '\n' | '\r' => { self.lookahead(2); self.skip_line(); if self.flow_level == 0 { self.allow_simple_key(); } } '#' => { while !is_breakz(self.ch()) { self.skip(); self.lookahead(1); } } _ => break, } } } fn fetch_stream_start(&mut self) { let mark = self.mark; self.indent = -1; self.stream_start_produced = true; self.allow_simple_key(); self.tokens .push_back(Token(mark, TokenType::StreamStart(TEncoding::Utf8))); self.simple_keys.push(SimpleKey::new(Marker::new(0, 0, 0))); } fn fetch_stream_end(&mut self) -> ScanResult { // force new line if self.mark.col != 0 { self.mark.col = 0; self.mark.line += 1; } self.unroll_indent(-1); self.remove_simple_key()?; self.disallow_simple_key(); self.tokens .push_back(Token(self.mark, TokenType::StreamEnd)); Ok(()) } fn fetch_directive(&mut self) -> ScanResult { self.unroll_indent(-1); self.remove_simple_key()?; self.disallow_simple_key(); let tok = self.scan_directive()?; self.tokens.push_back(tok); Ok(()) } fn scan_directive(&mut self) -> Result { let start_mark = self.mark; self.skip(); let name = self.scan_directive_name()?; let tok = match name.as_ref() { "YAML" => self.scan_version_directive_value(&start_mark)?, "TAG" => self.scan_tag_directive_value(&start_mark)?, // XXX This should be a warning instead of an error _ => { // skip current line self.lookahead(1); while !is_breakz(self.ch()) { self.skip(); self.lookahead(1); } // XXX return an empty TagDirective token Token( start_mark, TokenType::TagDirective(String::new(), String::new()), ) // return Err(ScanError::new(start_mark, // "while scanning a directive, found unknown directive name")) } }; self.lookahead(1); while is_blank(self.ch()) { self.skip(); self.lookahead(1); } if self.ch() == '#' { while !is_breakz(self.ch()) { self.skip(); self.lookahead(1); } } if !is_breakz(self.ch()) { return Err(ScanError::new( start_mark, "while scanning a directive, did not find expected comment or line break", )); } // Eat a line break if is_break(self.ch()) { self.lookahead(2); self.skip_line(); } Ok(tok) } fn scan_version_directive_value(&mut self, mark: &Marker) -> Result { self.lookahead(1); while is_blank(self.ch()) { self.skip(); self.lookahead(1); } let major = self.scan_version_directive_number(mark)?; if self.ch() != '.' { return Err(ScanError::new( *mark, "while scanning a YAML directive, did not find expected digit or '.' character", )); } self.skip(); let minor = self.scan_version_directive_number(mark)?; Ok(Token(*mark, TokenType::VersionDirective(major, minor))) } fn scan_directive_name(&mut self) -> Result { let start_mark = self.mark; let mut string = String::new(); self.lookahead(1); while is_alpha(self.ch()) { string.push(self.ch()); self.skip(); self.lookahead(1); } if string.is_empty() { return Err(ScanError::new( start_mark, "while scanning a directive, could not find expected directive name", )); } if !is_blankz(self.ch()) { return Err(ScanError::new( start_mark, "while scanning a directive, found unexpected non-alphabetical character", )); } Ok(string) } fn scan_version_directive_number(&mut self, mark: &Marker) -> Result { let mut val = 0u32; let mut length = 0usize; self.lookahead(1); while is_digit(self.ch()) { if length + 1 > 9 { return Err(ScanError::new( *mark, "while scanning a YAML directive, found extremely long version number", )); } length += 1; val = val * 10 + ((self.ch() as u32) - ('0' as u32)); self.skip(); self.lookahead(1); } if length == 0 { return Err(ScanError::new( *mark, "while scanning a YAML directive, did not find expected version number", )); } Ok(val) } fn scan_tag_directive_value(&mut self, mark: &Marker) -> Result { self.lookahead(1); /* Eat whitespaces. */ while is_blank(self.ch()) { self.skip(); self.lookahead(1); } let handle = self.scan_tag_handle(true, mark)?; self.lookahead(1); /* Eat whitespaces. */ while is_blank(self.ch()) { self.skip(); self.lookahead(1); } let is_secondary = handle == "!!"; let prefix = self.scan_tag_uri(true, is_secondary, &String::new(), mark)?; self.lookahead(1); if is_blankz(self.ch()) { Ok(Token(*mark, TokenType::TagDirective(handle, prefix))) } else { Err(ScanError::new( *mark, "while scanning TAG, did not find expected whitespace or line break", )) } } fn fetch_tag(&mut self) -> ScanResult { self.save_simple_key()?; self.disallow_simple_key(); let tok = self.scan_tag()?; self.tokens.push_back(tok); Ok(()) } fn scan_tag(&mut self) -> Result { let start_mark = self.mark; let mut handle = String::new(); let mut suffix; let mut secondary = false; // Check if the tag is in the canonical form (verbatim). self.lookahead(2); if self.buffer[1] == '<' { // Eat '!<' self.skip(); self.skip(); suffix = self.scan_tag_uri(false, false, &String::new(), &start_mark)?; if self.ch() != '>' { return Err(ScanError::new( start_mark, "while scanning a tag, did not find the expected '>'", )); } self.skip(); } else { // The tag has either the '!suffix' or the '!handle!suffix' handle = self.scan_tag_handle(false, &start_mark)?; // Check if it is, indeed, handle. if handle.len() >= 2 && handle.starts_with('!') && handle.ends_with('!') { if handle == "!!" { secondary = true; } suffix = self.scan_tag_uri(false, secondary, &String::new(), &start_mark)?; } else { suffix = self.scan_tag_uri(false, false, &handle, &start_mark)?; handle = "!".to_owned(); // A special case: the '!' tag. Set the handle to '' and the // suffix to '!'. if suffix.is_empty() { handle.clear(); suffix = "!".to_owned(); } } } self.lookahead(1); if is_blankz(self.ch()) { // XXX: ex 7.2, an empty scalar can follow a secondary tag Ok(Token(start_mark, TokenType::Tag(handle, suffix))) } else { Err(ScanError::new( start_mark, "while scanning a tag, did not find expected whitespace or line break", )) } } fn scan_tag_handle(&mut self, directive: bool, mark: &Marker) -> Result { let mut string = String::new(); self.lookahead(1); if self.ch() != '!' { return Err(ScanError::new( *mark, "while scanning a tag, did not find expected '!'", )); } string.push(self.ch()); self.skip(); self.lookahead(1); while is_alpha(self.ch()) { string.push(self.ch()); self.skip(); self.lookahead(1); } // Check if the trailing character is '!' and copy it. if self.ch() == '!' { string.push(self.ch()); self.skip(); } else if directive && string != "!" { // It's either the '!' tag or not really a tag handle. If it's a %TAG // directive, it's an error. If it's a tag token, it must be a part of // URI. return Err(ScanError::new( *mark, "while parsing a tag directive, did not find expected '!'", )); } Ok(string) } fn scan_tag_uri( &mut self, directive: bool, _is_secondary: bool, head: &str, mark: &Marker, ) -> Result { let mut length = head.len(); let mut string = String::new(); // Copy the head if needed. // Note that we don't copy the leading '!' character. if length > 1 { string.extend(head.chars().skip(1)); } self.lookahead(1); /* * The set of characters that may appear in URI is as follows: * * '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&', * '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']', * '%'. */ while match self.ch() { ';' | '/' | '?' | ':' | '@' | '&' => true, '=' | '+' | '$' | ',' | '.' | '!' | '~' | '*' | '\'' | '(' | ')' | '[' | ']' => true, '%' => true, c if is_alpha(c) => true, _ => false, } { // Check if it is a URI-escape sequence. if self.ch() == '%' { string.push(self.scan_uri_escapes(directive, mark)?); } else { string.push(self.ch()); self.skip(); } length += 1; self.lookahead(1); } if length == 0 { return Err(ScanError::new( *mark, "while parsing a tag, did not find expected tag URI", )); } Ok(string) } fn scan_uri_escapes(&mut self, _directive: bool, mark: &Marker) -> Result { let mut width = 0usize; let mut code = 0u32; loop { self.lookahead(3); if !(self.ch() == '%' && is_hex(self.buffer[1]) && is_hex(self.buffer[2])) { return Err(ScanError::new( *mark, "while parsing a tag, did not find URI escaped octet", )); } let octet = (as_hex(self.buffer[1]) << 4) + as_hex(self.buffer[2]); if width == 0 { width = match octet { _ if octet & 0x80 == 0x00 => 1, _ if octet & 0xE0 == 0xC0 => 2, _ if octet & 0xF0 == 0xE0 => 3, _ if octet & 0xF8 == 0xF0 => 4, _ => { return Err(ScanError::new( *mark, "while parsing a tag, found an incorrect leading UTF-8 octet", )); } }; code = octet; } else { if octet & 0xc0 != 0x80 { return Err(ScanError::new( *mark, "while parsing a tag, found an incorrect trailing UTF-8 octet", )); } code = (code << 8) + octet; } self.skip(); self.skip(); self.skip(); width -= 1; if width == 0 { break; } } match char::from_u32(code) { Some(ch) => Ok(ch), None => Err(ScanError::new( *mark, "while parsing a tag, found an invalid UTF-8 codepoint", )), } } fn fetch_anchor(&mut self, alias: bool) -> ScanResult { self.save_simple_key()?; self.disallow_simple_key(); let tok = self.scan_anchor(alias)?; self.tokens.push_back(tok); Ok(()) } fn scan_anchor(&mut self, alias: bool) -> Result { let mut string = String::new(); let start_mark = self.mark; self.skip(); self.lookahead(1); while is_alpha(self.ch()) { string.push(self.ch()); self.skip(); self.lookahead(1); } if string.is_empty() || match self.ch() { c if is_blankz(c) => false, '?' | ':' | ',' | ']' | '}' | '%' | '@' | '`' => false, _ => true, } { return Err(ScanError::new(start_mark, "while scanning an anchor or alias, did not find expected alphabetic or numeric character")); } if alias { Ok(Token(start_mark, TokenType::Alias(string))) } else { Ok(Token(start_mark, TokenType::Anchor(string))) } } fn fetch_flow_collection_start(&mut self, tok: TokenType) -> ScanResult { // The indicators '[' and '{' may start a simple key. self.save_simple_key()?; self.increase_flow_level()?; self.allow_simple_key(); let start_mark = self.mark; self.skip(); self.tokens.push_back(Token(start_mark, tok)); Ok(()) } fn fetch_flow_collection_end(&mut self, tok: TokenType) -> ScanResult { self.remove_simple_key()?; self.decrease_flow_level(); self.disallow_simple_key(); let start_mark = self.mark; self.skip(); self.tokens.push_back(Token(start_mark, tok)); Ok(()) } fn fetch_flow_entry(&mut self) -> ScanResult { self.remove_simple_key()?; self.allow_simple_key(); let start_mark = self.mark; self.skip(); self.tokens .push_back(Token(start_mark, TokenType::FlowEntry)); Ok(()) } fn increase_flow_level(&mut self) -> ScanResult { self.simple_keys.push(SimpleKey::new(Marker::new(0, 0, 0))); self.flow_level = self .flow_level .checked_add(1) .ok_or_else(|| ScanError::new(self.mark, "recursion limit exceeded"))?; Ok(()) } fn decrease_flow_level(&mut self) { if self.flow_level > 0 { self.flow_level -= 1; self.simple_keys.pop().unwrap(); } } fn fetch_block_entry(&mut self) -> ScanResult { if self.flow_level == 0 { // Check if we are allowed to start a new entry. if !self.simple_key_allowed { return Err(ScanError::new( self.mark, "block sequence entries are not allowed in this context", )); } let mark = self.mark; // generate BLOCK-SEQUENCE-START if indented self.roll_indent(mark.col, None, TokenType::BlockSequenceStart, mark); } else { // - * only allowed in block return Err(ScanError::new( self.mark, r#""-" is only valid inside a block"#, )); } self.remove_simple_key()?; self.allow_simple_key(); let start_mark = self.mark; self.skip(); self.tokens .push_back(Token(start_mark, TokenType::BlockEntry)); Ok(()) } fn fetch_document_indicator(&mut self, t: TokenType) -> ScanResult { self.unroll_indent(-1); self.remove_simple_key()?; self.disallow_simple_key(); let mark = self.mark; self.skip(); self.skip(); self.skip(); self.tokens.push_back(Token(mark, t)); Ok(()) } fn fetch_block_scalar(&mut self, literal: bool) -> ScanResult { self.save_simple_key()?; self.allow_simple_key(); let tok = self.scan_block_scalar(literal)?; self.tokens.push_back(tok); Ok(()) } fn scan_block_scalar(&mut self, literal: bool) -> Result { let start_mark = self.mark; let mut chomping: i32 = 0; let mut increment: usize = 0; let mut indent: usize = 0; let mut trailing_blank: bool; let mut leading_blank: bool = false; let mut string = String::new(); let mut leading_break = String::new(); let mut trailing_breaks = String::new(); // skip '|' or '>' self.skip(); self.lookahead(1); if self.ch() == '+' || self.ch() == '-' { if self.ch() == '+' { chomping = 1; } else { chomping = -1; } self.skip(); self.lookahead(1); if is_digit(self.ch()) { if self.ch() == '0' { return Err(ScanError::new( start_mark, "while scanning a block scalar, found an intendation indicator equal to 0", )); } increment = (self.ch() as usize) - ('0' as usize); self.skip(); } } else if is_digit(self.ch()) { if self.ch() == '0' { return Err(ScanError::new( start_mark, "while scanning a block scalar, found an intendation indicator equal to 0", )); } increment = (self.ch() as usize) - ('0' as usize); self.skip(); self.lookahead(1); if self.ch() == '+' || self.ch() == '-' { if self.ch() == '+' { chomping = 1; } else { chomping = -1; } self.skip(); } } // Eat whitespaces and comments to the end of the line. self.lookahead(1); while is_blank(self.ch()) { self.skip(); self.lookahead(1); } if self.ch() == '#' { while !is_breakz(self.ch()) { self.skip(); self.lookahead(1); } } // Check if we are at the end of the line. if !is_breakz(self.ch()) { return Err(ScanError::new( start_mark, "while scanning a block scalar, did not find expected comment or line break", )); } if is_break(self.ch()) { self.lookahead(2); self.skip_line(); } if increment > 0 { indent = if self.indent >= 0 { (self.indent + increment as isize) as usize } else { increment } } // Scan the leading line breaks and determine the indentation level if needed. self.block_scalar_breaks(&mut indent, &mut trailing_breaks)?; self.lookahead(1); let start_mark = self.mark; while self.mark.col == indent && !is_z(self.ch()) { // We are at the beginning of a non-empty line. trailing_blank = is_blank(self.ch()); if !literal && !leading_break.is_empty() && !leading_blank && !trailing_blank { if trailing_breaks.is_empty() { string.push(' '); } leading_break.clear(); } else { string.push_str(&leading_break); leading_break.clear(); } string.push_str(&trailing_breaks); trailing_breaks.clear(); leading_blank = is_blank(self.ch()); while !is_breakz(self.ch()) { string.push(self.ch()); self.skip(); self.lookahead(1); } // break on EOF if is_z(self.ch()) { break; } self.lookahead(2); self.read_break(&mut leading_break); // Eat the following intendation spaces and line breaks. self.block_scalar_breaks(&mut indent, &mut trailing_breaks)?; } // Chomp the tail. if chomping != -1 { string.push_str(&leading_break); } if chomping == 1 { string.push_str(&trailing_breaks); } if literal { Ok(Token( start_mark, TokenType::Scalar(TScalarStyle::Literal, string), )) } else { Ok(Token( start_mark, TokenType::Scalar(TScalarStyle::Foled, string), )) } } fn block_scalar_breaks(&mut self, indent: &mut usize, breaks: &mut String) -> ScanResult { let mut max_indent = 0; loop { self.lookahead(1); while (*indent == 0 || self.mark.col < *indent) && self.buffer[0] == ' ' { self.skip(); self.lookahead(1); } if self.mark.col > max_indent { max_indent = self.mark.col; } // Check for a tab character messing the intendation. if (*indent == 0 || self.mark.col < *indent) && self.buffer[0] == '\t' { return Err(ScanError::new(self.mark, "while scanning a block scalar, found a tab character where an intendation space is expected")); } if !is_break(self.ch()) { break; } self.lookahead(2); // Consume the line break. self.read_break(breaks); } if *indent == 0 { *indent = max_indent; if *indent < (self.indent + 1) as usize { *indent = (self.indent + 1) as usize; } if *indent < 1 { *indent = 1; } } Ok(()) } fn fetch_flow_scalar(&mut self, single: bool) -> ScanResult { self.save_simple_key()?; self.disallow_simple_key(); let tok = self.scan_flow_scalar(single)?; // From spec: To ensure JSON compatibility, if a key inside a flow mapping is JSON-like, // YAML allows the following value to be specified adjacent to the “:”. self.adjacent_value_allowed_at = self.mark.index; self.tokens.push_back(tok); Ok(()) } fn scan_flow_scalar(&mut self, single: bool) -> Result { let start_mark = self.mark; let mut string = String::new(); let mut leading_break = String::new(); let mut trailing_breaks = String::new(); let mut whitespaces = String::new(); let mut leading_blanks; /* Eat the left quote. */ self.skip(); loop { /* Check for a document indicator. */ self.lookahead(4); if self.mark.col == 0 && (((self.buffer[0] == '-') && (self.buffer[1] == '-') && (self.buffer[2] == '-')) || ((self.buffer[0] == '.') && (self.buffer[1] == '.') && (self.buffer[2] == '.'))) && is_blankz(self.buffer[3]) { return Err(ScanError::new( start_mark, "while scanning a quoted scalar, found unexpected document indicator", )); } if is_z(self.ch()) { return Err(ScanError::new( start_mark, "while scanning a quoted scalar, found unexpected end of stream", )); } self.lookahead(2); leading_blanks = false; // Consume non-blank characters. while !is_blankz(self.ch()) { match self.ch() { // Check for an escaped single quote. '\'' if self.buffer[1] == '\'' && single => { string.push('\''); self.skip(); self.skip(); } // Check for the right quote. '\'' if single => break, '"' if !single => break, // Check for an escaped line break. '\\' if !single && is_break(self.buffer[1]) => { self.lookahead(3); self.skip(); self.skip_line(); leading_blanks = true; break; } // Check for an escape sequence. '\\' if !single => { let mut code_length = 0usize; match self.buffer[1] { '0' => string.push('\0'), 'a' => string.push('\x07'), 'b' => string.push('\x08'), 't' | '\t' => string.push('\t'), 'n' => string.push('\n'), 'v' => string.push('\x0b'), 'f' => string.push('\x0c'), 'r' => string.push('\x0d'), 'e' => string.push('\x1b'), ' ' => string.push('\x20'), '"' => string.push('"'), '\'' => string.push('\''), '\\' => string.push('\\'), // NEL (#x85) 'N' => string.push(char::from_u32(0x85).unwrap()), // #xA0 '_' => string.push(char::from_u32(0xA0).unwrap()), // LS (#x2028) 'L' => string.push(char::from_u32(0x2028).unwrap()), // PS (#x2029) 'P' => string.push(char::from_u32(0x2029).unwrap()), 'x' => code_length = 2, 'u' => code_length = 4, 'U' => code_length = 8, _ => { return Err(ScanError::new( start_mark, "while parsing a quoted scalar, found unknown escape character", )) } } self.skip(); self.skip(); // Consume an arbitrary escape code. if code_length > 0 { self.lookahead(code_length); let mut value = 0u32; for i in 0..code_length { if !is_hex(self.buffer[i]) { return Err(ScanError::new(start_mark, "while parsing a quoted scalar, did not find expected hexdecimal number")); } value = (value << 4) + as_hex(self.buffer[i]); } let ch = match char::from_u32(value) { Some(v) => v, None => { return Err(ScanError::new(start_mark, "while parsing a quoted scalar, found invalid Unicode character escape code")); } }; string.push(ch); for _ in 0..code_length { self.skip(); } } } c => { string.push(c); self.skip(); } } self.lookahead(2); } self.lookahead(1); match self.ch() { '\'' if single => break, '"' if !single => break, _ => {} } // Consume blank characters. while is_blank(self.ch()) || is_break(self.ch()) { if is_blank(self.ch()) { // Consume a space or a tab character. if leading_blanks { self.skip(); } else { whitespaces.push(self.ch()); self.skip(); } } else { self.lookahead(2); // Check if it is a first line break. if leading_blanks { self.read_break(&mut trailing_breaks); } else { whitespaces.clear(); self.read_break(&mut leading_break); leading_blanks = true; } } self.lookahead(1); } // Join the whitespaces or fold line breaks. if leading_blanks { if leading_break.is_empty() { string.push_str(&leading_break); string.push_str(&trailing_breaks); trailing_breaks.clear(); leading_break.clear(); } else { if trailing_breaks.is_empty() { string.push(' '); } else { string.push_str(&trailing_breaks); trailing_breaks.clear(); } leading_break.clear(); } } else { string.push_str(&whitespaces); whitespaces.clear(); } } // loop // Eat the right quote. self.skip(); if single { Ok(Token( start_mark, TokenType::Scalar(TScalarStyle::SingleQuoted, string), )) } else { Ok(Token( start_mark, TokenType::Scalar(TScalarStyle::DoubleQuoted, string), )) } } fn fetch_plain_scalar(&mut self) -> ScanResult { self.save_simple_key()?; self.disallow_simple_key(); let tok = self.scan_plain_scalar()?; self.tokens.push_back(tok); Ok(()) } fn scan_plain_scalar(&mut self) -> Result { let indent = self.indent + 1; let start_mark = self.mark; let mut string = String::new(); let mut leading_break = String::new(); let mut trailing_breaks = String::new(); let mut whitespaces = String::new(); let mut leading_blanks = false; loop { /* Check for a document indicator. */ self.lookahead(4); if self.mark.col == 0 && (((self.buffer[0] == '-') && (self.buffer[1] == '-') && (self.buffer[2] == '-')) || ((self.buffer[0] == '.') && (self.buffer[1] == '.') && (self.buffer[2] == '.'))) && is_blankz(self.buffer[3]) { break; } if self.ch() == '#' { break; } while !is_blankz(self.ch()) { // indicators can end a plain scalar, see 7.3.3. Plain Style match self.ch() { ':' if is_blankz(self.buffer[1]) || (self.flow_level > 0 && is_flow(self.buffer[1])) => { break; } ',' | '[' | ']' | '{' | '}' if self.flow_level > 0 => break, _ => {} } if leading_blanks || !whitespaces.is_empty() { if leading_blanks { if leading_break.is_empty() { string.push_str(&leading_break); string.push_str(&trailing_breaks); trailing_breaks.clear(); leading_break.clear(); } else { if trailing_breaks.is_empty() { string.push(' '); } else { string.push_str(&trailing_breaks); trailing_breaks.clear(); } leading_break.clear(); } leading_blanks = false; } else { string.push_str(&whitespaces); whitespaces.clear(); } } string.push(self.ch()); self.skip(); self.lookahead(2); } // is the end? if !(is_blank(self.ch()) || is_break(self.ch())) { break; } self.lookahead(1); while is_blank(self.ch()) || is_break(self.ch()) { if is_blank(self.ch()) { if leading_blanks && (self.mark.col as isize) < indent && self.ch() == '\t' { return Err(ScanError::new( start_mark, "while scanning a plain scalar, found a tab", )); } if leading_blanks { self.skip(); } else { whitespaces.push(self.ch()); self.skip(); } } else { self.lookahead(2); // Check if it is a first line break if leading_blanks { self.read_break(&mut trailing_breaks); } else { whitespaces.clear(); self.read_break(&mut leading_break); leading_blanks = true; } } self.lookahead(1); } // check intendation level if self.flow_level == 0 && (self.mark.col as isize) < indent { break; } } if leading_blanks { self.allow_simple_key(); } Ok(Token( start_mark, TokenType::Scalar(TScalarStyle::Plain, string), )) } fn fetch_key(&mut self) -> ScanResult { let start_mark = self.mark; if self.flow_level == 0 { // Check if we are allowed to start a new key (not nessesary simple). if !self.simple_key_allowed { return Err(ScanError::new( self.mark, "mapping keys are not allowed in this context", )); } self.roll_indent( start_mark.col, None, TokenType::BlockMappingStart, start_mark, ); } self.remove_simple_key()?; if self.flow_level == 0 { self.allow_simple_key(); } else { self.disallow_simple_key(); } self.skip(); self.tokens.push_back(Token(start_mark, TokenType::Key)); Ok(()) } fn fetch_value(&mut self) -> ScanResult { let sk = self.simple_keys.last().unwrap().clone(); let start_mark = self.mark; if sk.possible { // insert simple key let tok = Token(sk.mark, TokenType::Key); let tokens_parsed = self.tokens_parsed; self.insert_token(sk.token_number - tokens_parsed, tok); // Add the BLOCK-MAPPING-START token if needed. self.roll_indent( sk.mark.col, Some(sk.token_number), TokenType::BlockMappingStart, start_mark, ); self.simple_keys.last_mut().unwrap().possible = false; self.disallow_simple_key(); } else { // The ':' indicator follows a complex key. if self.flow_level == 0 { if !self.simple_key_allowed { return Err(ScanError::new( start_mark, "mapping values are not allowed in this context", )); } self.roll_indent( start_mark.col, None, TokenType::BlockMappingStart, start_mark, ); } if self.flow_level == 0 { self.allow_simple_key(); } else { self.disallow_simple_key(); } } self.skip(); self.tokens.push_back(Token(start_mark, TokenType::Value)); Ok(()) } fn roll_indent(&mut self, col: usize, number: Option, tok: TokenType, mark: Marker) { if self.flow_level > 0 { return; } if self.indent < col as isize { self.indents.push(self.indent); self.indent = col as isize; let tokens_parsed = self.tokens_parsed; match number { Some(n) => self.insert_token(n - tokens_parsed, Token(mark, tok)), None => self.tokens.push_back(Token(mark, tok)), } } } fn unroll_indent(&mut self, col: isize) { if self.flow_level > 0 { return; } while self.indent > col { self.tokens.push_back(Token(self.mark, TokenType::BlockEnd)); self.indent = self.indents.pop().unwrap(); } } fn save_simple_key(&mut self) -> Result<(), ScanError> { let required = self.flow_level > 0 && self.indent == (self.mark.col as isize); if self.simple_key_allowed { let mut sk = SimpleKey::new(self.mark); sk.possible = true; sk.required = required; sk.token_number = self.tokens_parsed + self.tokens.len(); self.remove_simple_key()?; self.simple_keys.pop(); self.simple_keys.push(sk); } Ok(()) } fn remove_simple_key(&mut self) -> ScanResult { let last = self.simple_keys.last_mut().unwrap(); if last.possible && last.required { return Err(ScanError::new(self.mark, "simple key expected")); } last.possible = false; Ok(()) } } #[cfg(test)] mod test { use super::TokenType::*; use super::*; macro_rules! next { ($p:ident, $tk:pat) => {{ let tok = $p.next().unwrap(); match tok.1 { $tk => {} _ => panic!("unexpected token: {:?}", tok), } }}; } macro_rules! next_scalar { ($p:ident, $tk:expr, $v:expr) => {{ let tok = $p.next().unwrap(); match tok.1 { Scalar(style, ref v) => { assert_eq!(style, $tk); assert_eq!(v, $v); } _ => panic!("unexpected token: {:?}", tok), } }}; } macro_rules! end { ($p:ident) => {{ assert_eq!($p.next(), None); }}; } /// test cases in libyaml scanner.c #[test] fn test_empty() { let s = ""; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next!(p, StreamEnd); end!(p); } #[test] fn test_scalar() { let s = "a scalar"; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next!(p, Scalar(TScalarStyle::Plain, _)); next!(p, StreamEnd); end!(p); } #[test] fn test_explicit_scalar() { let s = "--- 'a scalar' ... "; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next!(p, DocumentStart); next!(p, Scalar(TScalarStyle::SingleQuoted, _)); next!(p, DocumentEnd); next!(p, StreamEnd); end!(p); } #[test] fn test_multiple_documents() { let s = " 'a scalar' --- 'a scalar' --- 'a scalar' "; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next!(p, Scalar(TScalarStyle::SingleQuoted, _)); next!(p, DocumentStart); next!(p, Scalar(TScalarStyle::SingleQuoted, _)); next!(p, DocumentStart); next!(p, Scalar(TScalarStyle::SingleQuoted, _)); next!(p, StreamEnd); end!(p); } #[test] fn test_a_flow_sequence() { let s = "[item 1, item 2, item 3]"; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next!(p, FlowSequenceStart); next_scalar!(p, TScalarStyle::Plain, "item 1"); next!(p, FlowEntry); next!(p, Scalar(TScalarStyle::Plain, _)); next!(p, FlowEntry); next!(p, Scalar(TScalarStyle::Plain, _)); next!(p, FlowSequenceEnd); next!(p, StreamEnd); end!(p); } #[test] fn test_a_flow_mapping() { let s = " { a simple key: a value, # Note that the KEY token is produced. ? a complex key: another value, } "; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next!(p, FlowMappingStart); next!(p, Key); next!(p, Scalar(TScalarStyle::Plain, _)); next!(p, Value); next!(p, Scalar(TScalarStyle::Plain, _)); next!(p, FlowEntry); next!(p, Key); next_scalar!(p, TScalarStyle::Plain, "a complex key"); next!(p, Value); next!(p, Scalar(TScalarStyle::Plain, _)); next!(p, FlowEntry); next!(p, FlowMappingEnd); next!(p, StreamEnd); end!(p); } #[test] fn test_block_sequences() { let s = " - item 1 - item 2 - - item 3.1 - item 3.2 - key 1: value 1 key 2: value 2 "; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next!(p, BlockSequenceStart); next!(p, BlockEntry); next_scalar!(p, TScalarStyle::Plain, "item 1"); next!(p, BlockEntry); next_scalar!(p, TScalarStyle::Plain, "item 2"); next!(p, BlockEntry); next!(p, BlockSequenceStart); next!(p, BlockEntry); next_scalar!(p, TScalarStyle::Plain, "item 3.1"); next!(p, BlockEntry); next_scalar!(p, TScalarStyle::Plain, "item 3.2"); next!(p, BlockEnd); next!(p, BlockEntry); next!(p, BlockMappingStart); next!(p, Key); next_scalar!(p, TScalarStyle::Plain, "key 1"); next!(p, Value); next_scalar!(p, TScalarStyle::Plain, "value 1"); next!(p, Key); next_scalar!(p, TScalarStyle::Plain, "key 2"); next!(p, Value); next_scalar!(p, TScalarStyle::Plain, "value 2"); next!(p, BlockEnd); next!(p, BlockEnd); next!(p, StreamEnd); end!(p); } #[test] fn test_block_mappings() { let s = " a simple key: a value # The KEY token is produced here. ? a complex key : another value a mapping: key 1: value 1 key 2: value 2 a sequence: - item 1 - item 2 "; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next!(p, BlockMappingStart); next!(p, Key); next!(p, Scalar(_, _)); next!(p, Value); next!(p, Scalar(_, _)); next!(p, Key); next!(p, Scalar(_, _)); next!(p, Value); next!(p, Scalar(_, _)); next!(p, Key); next!(p, Scalar(_, _)); next!(p, Value); // libyaml comment seems to be wrong next!(p, BlockMappingStart); next!(p, Key); next!(p, Scalar(_, _)); next!(p, Value); next!(p, Scalar(_, _)); next!(p, Key); next!(p, Scalar(_, _)); next!(p, Value); next!(p, Scalar(_, _)); next!(p, BlockEnd); next!(p, Key); next!(p, Scalar(_, _)); next!(p, Value); next!(p, BlockSequenceStart); next!(p, BlockEntry); next!(p, Scalar(_, _)); next!(p, BlockEntry); next!(p, Scalar(_, _)); next!(p, BlockEnd); next!(p, BlockEnd); next!(p, StreamEnd); end!(p); } #[test] fn test_no_block_sequence_start() { let s = " key: - item 1 - item 2 "; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next!(p, BlockMappingStart); next!(p, Key); next_scalar!(p, TScalarStyle::Plain, "key"); next!(p, Value); next!(p, BlockEntry); next_scalar!(p, TScalarStyle::Plain, "item 1"); next!(p, BlockEntry); next_scalar!(p, TScalarStyle::Plain, "item 2"); next!(p, BlockEnd); next!(p, StreamEnd); end!(p); } #[test] fn test_collections_in_sequence() { let s = " - - item 1 - item 2 - key 1: value 1 key 2: value 2 - ? complex key : complex value "; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next!(p, BlockSequenceStart); next!(p, BlockEntry); next!(p, BlockSequenceStart); next!(p, BlockEntry); next_scalar!(p, TScalarStyle::Plain, "item 1"); next!(p, BlockEntry); next_scalar!(p, TScalarStyle::Plain, "item 2"); next!(p, BlockEnd); next!(p, BlockEntry); next!(p, BlockMappingStart); next!(p, Key); next_scalar!(p, TScalarStyle::Plain, "key 1"); next!(p, Value); next_scalar!(p, TScalarStyle::Plain, "value 1"); next!(p, Key); next_scalar!(p, TScalarStyle::Plain, "key 2"); next!(p, Value); next_scalar!(p, TScalarStyle::Plain, "value 2"); next!(p, BlockEnd); next!(p, BlockEntry); next!(p, BlockMappingStart); next!(p, Key); next_scalar!(p, TScalarStyle::Plain, "complex key"); next!(p, Value); next_scalar!(p, TScalarStyle::Plain, "complex value"); next!(p, BlockEnd); next!(p, BlockEnd); next!(p, StreamEnd); end!(p); } #[test] fn test_collections_in_mapping() { let s = " ? a sequence : - item 1 - item 2 ? a mapping : key 1: value 1 key 2: value 2 "; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next!(p, BlockMappingStart); next!(p, Key); next_scalar!(p, TScalarStyle::Plain, "a sequence"); next!(p, Value); next!(p, BlockSequenceStart); next!(p, BlockEntry); next_scalar!(p, TScalarStyle::Plain, "item 1"); next!(p, BlockEntry); next_scalar!(p, TScalarStyle::Plain, "item 2"); next!(p, BlockEnd); next!(p, Key); next_scalar!(p, TScalarStyle::Plain, "a mapping"); next!(p, Value); next!(p, BlockMappingStart); next!(p, Key); next_scalar!(p, TScalarStyle::Plain, "key 1"); next!(p, Value); next_scalar!(p, TScalarStyle::Plain, "value 1"); next!(p, Key); next_scalar!(p, TScalarStyle::Plain, "key 2"); next!(p, Value); next_scalar!(p, TScalarStyle::Plain, "value 2"); next!(p, BlockEnd); next!(p, BlockEnd); next!(p, StreamEnd); end!(p); } #[test] fn test_spec_ex7_3() { let s = " { ? foo :, : bar, } "; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next!(p, FlowMappingStart); next!(p, Key); next_scalar!(p, TScalarStyle::Plain, "foo"); next!(p, Value); next!(p, FlowEntry); next!(p, Value); next_scalar!(p, TScalarStyle::Plain, "bar"); next!(p, FlowEntry); next!(p, FlowMappingEnd); next!(p, StreamEnd); end!(p); } #[test] fn test_plain_scalar_starting_with_indicators_in_flow() { // "Plain scalars must not begin with most indicators, as this would cause ambiguity with // other YAML constructs. However, the “:”, “?” and “-” indicators may be used as the first // character if followed by a non-space “safe” character, as this causes no ambiguity." let s = "{a: :b}"; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next!(p, FlowMappingStart); next!(p, Key); next_scalar!(p, TScalarStyle::Plain, "a"); next!(p, Value); next_scalar!(p, TScalarStyle::Plain, ":b"); next!(p, FlowMappingEnd); next!(p, StreamEnd); end!(p); let s = "{a: ?b}"; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next!(p, FlowMappingStart); next!(p, Key); next_scalar!(p, TScalarStyle::Plain, "a"); next!(p, Value); next_scalar!(p, TScalarStyle::Plain, "?b"); next!(p, FlowMappingEnd); next!(p, StreamEnd); end!(p); } #[test] fn test_plain_scalar_starting_with_indicators_in_block() { let s = ":a"; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next_scalar!(p, TScalarStyle::Plain, ":a"); next!(p, StreamEnd); end!(p); let s = "?a"; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next_scalar!(p, TScalarStyle::Plain, "?a"); next!(p, StreamEnd); end!(p); } #[test] fn test_plain_scalar_containing_indicators_in_block() { let s = "a:,b"; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next_scalar!(p, TScalarStyle::Plain, "a:,b"); next!(p, StreamEnd); end!(p); let s = ":,b"; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next_scalar!(p, TScalarStyle::Plain, ":,b"); next!(p, StreamEnd); end!(p); } #[test] fn test_scanner_cr() { let s = "---\r\n- tok1\r\n- tok2"; let mut p = Scanner::new(s.chars()); next!(p, StreamStart(..)); next!(p, DocumentStart); next!(p, BlockSequenceStart); next!(p, BlockEntry); next_scalar!(p, TScalarStyle::Plain, "tok1"); next!(p, BlockEntry); next_scalar!(p, TScalarStyle::Plain, "tok2"); next!(p, BlockEnd); next!(p, StreamEnd); end!(p); } #[test] fn test_uri() { // TODO } #[test] fn test_uri_escapes() { // TODO } } yaml-rust-0.4.3/src/yaml.rs010064400007670000024000000503521344013434500140010ustar0000000000000000use linked_hash_map::LinkedHashMap; use parser::*; use scanner::{Marker, ScanError, TScalarStyle, TokenType}; use std::collections::BTreeMap; use std::f64; use std::i64; use std::mem; use std::ops::Index; use std::string; use std::vec; /// A YAML node is stored as this `Yaml` enumeration, which provides an easy way to /// access your YAML document. /// /// # Examples /// /// ``` /// use yaml_rust::Yaml; /// let foo = Yaml::from_str("-123"); // convert the string to the appropriate YAML type /// assert_eq!(foo.as_i64().unwrap(), -123); /// /// // iterate over an Array /// let vec = Yaml::Array(vec![Yaml::Integer(1), Yaml::Integer(2)]); /// for v in vec.as_vec().unwrap() { /// assert!(v.as_i64().is_some()); /// } /// ``` #[derive(Clone, PartialEq, PartialOrd, Debug, Eq, Ord, Hash)] pub enum Yaml { /// Float types are stored as String and parsed on demand. /// Note that f64 does NOT implement Eq trait and can NOT be stored in BTreeMap. Real(string::String), /// YAML int is stored as i64. Integer(i64), /// YAML scalar. String(string::String), /// YAML bool, e.g. `true` or `false`. Boolean(bool), /// YAML array, can be accessed as a `Vec`. Array(self::Array), /// YAML hash, can be accessed as a `LinkedHashMap`. /// /// Insertion order will match the order of insertion into the map. Hash(self::Hash), /// Alias, not fully supported yet. Alias(usize), /// YAML null, e.g. `null` or `~`. Null, /// Accessing a nonexistent node via the Index trait returns `BadValue`. This /// simplifies error handling in the calling code. Invalid type conversion also /// returns `BadValue`. BadValue, } pub type Array = Vec; pub type Hash = LinkedHashMap; // parse f64 as Core schema // See: https://github.com/chyh1990/yaml-rust/issues/51 fn parse_f64(v: &str) -> Option { match v { ".inf" | ".Inf" | ".INF" | "+.inf" | "+.Inf" | "+.INF" => Some(f64::INFINITY), "-.inf" | "-.Inf" | "-.INF" => Some(f64::NEG_INFINITY), ".nan" | "NaN" | ".NAN" => Some(f64::NAN), _ => v.parse::().ok(), } } pub struct YamlLoader { docs: Vec, // states // (current node, anchor_id) tuple doc_stack: Vec<(Yaml, usize)>, key_stack: Vec, anchor_map: BTreeMap, } impl MarkedEventReceiver for YamlLoader { fn on_event(&mut self, ev: Event, _: Marker) { // println!("EV {:?}", ev); match ev { Event::DocumentStart => { // do nothing } Event::DocumentEnd => { match self.doc_stack.len() { // empty document 0 => self.docs.push(Yaml::BadValue), 1 => self.docs.push(self.doc_stack.pop().unwrap().0), _ => unreachable!(), } } Event::SequenceStart(aid) => { self.doc_stack.push((Yaml::Array(Vec::new()), aid)); } Event::SequenceEnd => { let node = self.doc_stack.pop().unwrap(); self.insert_new_node(node); } Event::MappingStart(aid) => { self.doc_stack.push((Yaml::Hash(Hash::new()), aid)); self.key_stack.push(Yaml::BadValue); } Event::MappingEnd => { self.key_stack.pop().unwrap(); let node = self.doc_stack.pop().unwrap(); self.insert_new_node(node); } Event::Scalar(v, style, aid, tag) => { let node = if style != TScalarStyle::Plain { Yaml::String(v) } else if let Some(TokenType::Tag(ref handle, ref suffix)) = tag { // XXX tag:yaml.org,2002: if handle == "!!" { match suffix.as_ref() { "bool" => { // "true" or "false" match v.parse::() { Err(_) => Yaml::BadValue, Ok(v) => Yaml::Boolean(v), } } "int" => match v.parse::() { Err(_) => Yaml::BadValue, Ok(v) => Yaml::Integer(v), }, "float" => match parse_f64(&v) { Some(_) => Yaml::Real(v), None => Yaml::BadValue, }, "null" => match v.as_ref() { "~" | "null" => Yaml::Null, _ => Yaml::BadValue, }, _ => Yaml::String(v), } } else { Yaml::String(v) } } else { // Datatype is not specified, or unrecognized Yaml::from_str(&v) }; self.insert_new_node((node, aid)); } Event::Alias(id) => { let n = match self.anchor_map.get(&id) { Some(v) => v.clone(), None => Yaml::BadValue, }; self.insert_new_node((n, 0)); } _ => { /* ignore */ } } // println!("DOC {:?}", self.doc_stack); } } impl YamlLoader { fn insert_new_node(&mut self, node: (Yaml, usize)) { // valid anchor id starts from 1 if node.1 > 0 { self.anchor_map.insert(node.1, node.0.clone()); } if self.doc_stack.is_empty() { self.doc_stack.push(node); } else { let parent = self.doc_stack.last_mut().unwrap(); match *parent { (Yaml::Array(ref mut v), _) => v.push(node.0), (Yaml::Hash(ref mut h), _) => { let cur_key = self.key_stack.last_mut().unwrap(); // current node is a key if cur_key.is_badvalue() { *cur_key = node.0; // current node is a value } else { let mut newkey = Yaml::BadValue; mem::swap(&mut newkey, cur_key); h.insert(newkey, node.0); } } _ => unreachable!(), } } } pub fn load_from_str(source: &str) -> Result, ScanError> { let mut loader = YamlLoader { docs: Vec::new(), doc_stack: Vec::new(), key_stack: Vec::new(), anchor_map: BTreeMap::new(), }; let mut parser = Parser::new(source.chars()); parser.load(&mut loader, true)?; Ok(loader.docs) } } macro_rules! define_as ( ($name:ident, $t:ident, $yt:ident) => ( pub fn $name(&self) -> Option<$t> { match *self { Yaml::$yt(v) => Some(v), _ => None } } ); ); macro_rules! define_as_ref ( ($name:ident, $t:ty, $yt:ident) => ( pub fn $name(&self) -> Option<$t> { match *self { Yaml::$yt(ref v) => Some(v), _ => None } } ); ); macro_rules! define_into ( ($name:ident, $t:ty, $yt:ident) => ( pub fn $name(self) -> Option<$t> { match self { Yaml::$yt(v) => Some(v), _ => None } } ); ); impl Yaml { define_as!(as_bool, bool, Boolean); define_as!(as_i64, i64, Integer); define_as_ref!(as_str, &str, String); define_as_ref!(as_hash, &Hash, Hash); define_as_ref!(as_vec, &Array, Array); define_into!(into_bool, bool, Boolean); define_into!(into_i64, i64, Integer); define_into!(into_string, String, String); define_into!(into_hash, Hash, Hash); define_into!(into_vec, Array, Array); pub fn is_null(&self) -> bool { match *self { Yaml::Null => true, _ => false, } } pub fn is_badvalue(&self) -> bool { match *self { Yaml::BadValue => true, _ => false, } } pub fn is_array(&self) -> bool { match *self { Yaml::Array(_) => true, _ => false, } } pub fn as_f64(&self) -> Option { match *self { Yaml::Real(ref v) => parse_f64(v), _ => None, } } pub fn into_f64(self) -> Option { match self { Yaml::Real(ref v) => parse_f64(v), _ => None, } } } #[cfg_attr(feature = "cargo-clippy", allow(should_implement_trait))] impl Yaml { // Not implementing FromStr because there is no possibility of Error. // This function falls back to Yaml::String if nothing else matches. pub fn from_str(v: &str) -> Yaml { if v.starts_with("0x") { let n = i64::from_str_radix(&v[2..], 16); if n.is_ok() { return Yaml::Integer(n.unwrap()); } } if v.starts_with("0o") { let n = i64::from_str_radix(&v[2..], 8); if n.is_ok() { return Yaml::Integer(n.unwrap()); } } if v.starts_with('+') && v[1..].parse::().is_ok() { return Yaml::Integer(v[1..].parse::().unwrap()); } match v { "~" | "null" => Yaml::Null, "true" => Yaml::Boolean(true), "false" => Yaml::Boolean(false), _ if v.parse::().is_ok() => Yaml::Integer(v.parse::().unwrap()), // try parsing as f64 _ if parse_f64(v).is_some() => Yaml::Real(v.to_owned()), _ => Yaml::String(v.to_owned()), } } } static BAD_VALUE: Yaml = Yaml::BadValue; impl<'a> Index<&'a str> for Yaml { type Output = Yaml; fn index(&self, idx: &'a str) -> &Yaml { let key = Yaml::String(idx.to_owned()); match self.as_hash() { Some(h) => h.get(&key).unwrap_or(&BAD_VALUE), None => &BAD_VALUE, } } } impl Index for Yaml { type Output = Yaml; fn index(&self, idx: usize) -> &Yaml { if let Some(v) = self.as_vec() { v.get(idx).unwrap_or(&BAD_VALUE) } else if let Some(v) = self.as_hash() { let key = Yaml::Integer(idx as i64); v.get(&key).unwrap_or(&BAD_VALUE) } else { &BAD_VALUE } } } impl IntoIterator for Yaml { type Item = Yaml; type IntoIter = YamlIter; fn into_iter(self) -> Self::IntoIter { YamlIter { yaml: self.into_vec().unwrap_or_else(Vec::new).into_iter(), } } } pub struct YamlIter { yaml: vec::IntoIter, } impl Iterator for YamlIter { type Item = Yaml; fn next(&mut self) -> Option { self.yaml.next() } } #[cfg(test)] mod test { use std::f64; use yaml::*; #[test] fn test_coerce() { let s = "--- a: 1 b: 2.2 c: [1, 2] "; let out = YamlLoader::load_from_str(&s).unwrap(); let doc = &out[0]; assert_eq!(doc["a"].as_i64().unwrap(), 1i64); assert_eq!(doc["b"].as_f64().unwrap(), 2.2f64); assert_eq!(doc["c"][1].as_i64().unwrap(), 2i64); assert!(doc["d"][0].is_badvalue()); } #[test] fn test_empty_doc() { let s: String = "".to_owned(); YamlLoader::load_from_str(&s).unwrap(); let s: String = "---".to_owned(); assert_eq!(YamlLoader::load_from_str(&s).unwrap()[0], Yaml::Null); } #[test] fn test_parser() { let s: String = " # comment a0 bb: val a1: b1: 4 b2: d a2: 4 # i'm comment a3: [1, 2, 3] a4: - - a1 - a2 - 2 a5: 'single_quoted' a6: \"double_quoted\" a7: 你好 " .to_owned(); let out = YamlLoader::load_from_str(&s).unwrap(); let doc = &out[0]; assert_eq!(doc["a7"].as_str().unwrap(), "你好"); } #[test] fn test_multi_doc() { let s = " 'a scalar' --- 'a scalar' --- 'a scalar' "; let out = YamlLoader::load_from_str(&s).unwrap(); assert_eq!(out.len(), 3); } #[test] fn test_anchor() { let s = " a1: &DEFAULT b1: 4 b2: d a2: *DEFAULT "; let out = YamlLoader::load_from_str(&s).unwrap(); let doc = &out[0]; assert_eq!(doc["a2"]["b1"].as_i64().unwrap(), 4); } #[test] fn test_bad_anchor() { let s = " a1: &DEFAULT b1: 4 b2: *DEFAULT "; let out = YamlLoader::load_from_str(&s).unwrap(); let doc = &out[0]; assert_eq!(doc["a1"]["b2"], Yaml::BadValue); } #[test] fn test_github_27() { // https://github.com/chyh1990/yaml-rust/issues/27 let s = "&a"; let out = YamlLoader::load_from_str(&s).unwrap(); let doc = &out[0]; assert_eq!(doc.as_str().unwrap(), ""); } #[test] fn test_plain_datatype() { let s = " - 'string' - \"string\" - string - 123 - -321 - 1.23 - -1e4 - ~ - null - true - false - !!str 0 - !!int 100 - !!float 2 - !!null ~ - !!bool true - !!bool false - 0xFF # bad values - !!int string - !!float string - !!bool null - !!null val - 0o77 - [ 0xF, 0xF ] - +12345 - [ true, false ] "; let out = YamlLoader::load_from_str(&s).unwrap(); let doc = &out[0]; assert_eq!(doc[0].as_str().unwrap(), "string"); assert_eq!(doc[1].as_str().unwrap(), "string"); assert_eq!(doc[2].as_str().unwrap(), "string"); assert_eq!(doc[3].as_i64().unwrap(), 123); assert_eq!(doc[4].as_i64().unwrap(), -321); assert_eq!(doc[5].as_f64().unwrap(), 1.23); assert_eq!(doc[6].as_f64().unwrap(), -1e4); assert!(doc[7].is_null()); assert!(doc[8].is_null()); assert_eq!(doc[9].as_bool().unwrap(), true); assert_eq!(doc[10].as_bool().unwrap(), false); assert_eq!(doc[11].as_str().unwrap(), "0"); assert_eq!(doc[12].as_i64().unwrap(), 100); assert_eq!(doc[13].as_f64().unwrap(), 2.0); assert!(doc[14].is_null()); assert_eq!(doc[15].as_bool().unwrap(), true); assert_eq!(doc[16].as_bool().unwrap(), false); assert_eq!(doc[17].as_i64().unwrap(), 255); assert!(doc[18].is_badvalue()); assert!(doc[19].is_badvalue()); assert!(doc[20].is_badvalue()); assert!(doc[21].is_badvalue()); assert_eq!(doc[22].as_i64().unwrap(), 63); assert_eq!(doc[23][0].as_i64().unwrap(), 15); assert_eq!(doc[23][1].as_i64().unwrap(), 15); assert_eq!(doc[24].as_i64().unwrap(), 12345); assert!(doc[25][0].as_bool().unwrap()); assert!(!doc[25][1].as_bool().unwrap()); } #[test] fn test_bad_hypen() { // See: https://github.com/chyh1990/yaml-rust/issues/23 let s = "{-"; assert!(YamlLoader::load_from_str(&s).is_err()); } #[test] fn test_issue_65() { // See: https://github.com/chyh1990/yaml-rust/issues/65 let b = "\n\"ll\\\"ll\\\r\n\"ll\\\"ll\\\r\r\r\rU\r\r\rU"; assert!(YamlLoader::load_from_str(&b).is_err()); } #[test] fn test_bad_docstart() { assert!(YamlLoader::load_from_str("---This used to cause an infinite loop").is_ok()); assert_eq!( YamlLoader::load_from_str("----"), Ok(vec![Yaml::String(String::from("----"))]) ); assert_eq!( YamlLoader::load_from_str("--- #here goes a comment"), Ok(vec![Yaml::Null]) ); assert_eq!( YamlLoader::load_from_str("---- #here goes a comment"), Ok(vec![Yaml::String(String::from("----"))]) ); } #[test] fn test_plain_datatype_with_into_methods() { let s = " - 'string' - \"string\" - string - 123 - -321 - 1.23 - -1e4 - true - false - !!str 0 - !!int 100 - !!float 2 - !!bool true - !!bool false - 0xFF - 0o77 - +12345 - -.INF - .NAN - !!float .INF "; let mut out = YamlLoader::load_from_str(&s).unwrap().into_iter(); let mut doc = out.next().unwrap().into_iter(); assert_eq!(doc.next().unwrap().into_string().unwrap(), "string"); assert_eq!(doc.next().unwrap().into_string().unwrap(), "string"); assert_eq!(doc.next().unwrap().into_string().unwrap(), "string"); assert_eq!(doc.next().unwrap().into_i64().unwrap(), 123); assert_eq!(doc.next().unwrap().into_i64().unwrap(), -321); assert_eq!(doc.next().unwrap().into_f64().unwrap(), 1.23); assert_eq!(doc.next().unwrap().into_f64().unwrap(), -1e4); assert_eq!(doc.next().unwrap().into_bool().unwrap(), true); assert_eq!(doc.next().unwrap().into_bool().unwrap(), false); assert_eq!(doc.next().unwrap().into_string().unwrap(), "0"); assert_eq!(doc.next().unwrap().into_i64().unwrap(), 100); assert_eq!(doc.next().unwrap().into_f64().unwrap(), 2.0); assert_eq!(doc.next().unwrap().into_bool().unwrap(), true); assert_eq!(doc.next().unwrap().into_bool().unwrap(), false); assert_eq!(doc.next().unwrap().into_i64().unwrap(), 255); assert_eq!(doc.next().unwrap().into_i64().unwrap(), 63); assert_eq!(doc.next().unwrap().into_i64().unwrap(), 12345); assert_eq!(doc.next().unwrap().into_f64().unwrap(), f64::NEG_INFINITY); assert!(doc.next().unwrap().into_f64().is_some()); assert_eq!(doc.next().unwrap().into_f64().unwrap(), f64::INFINITY); } #[test] fn test_hash_order() { let s = "--- b: ~ a: ~ c: ~ "; let out = YamlLoader::load_from_str(&s).unwrap(); let first = out.into_iter().next().unwrap(); let mut iter = first.into_hash().unwrap().into_iter(); assert_eq!( Some((Yaml::String("b".to_owned()), Yaml::Null)), iter.next() ); assert_eq!( Some((Yaml::String("a".to_owned()), Yaml::Null)), iter.next() ); assert_eq!( Some((Yaml::String("c".to_owned()), Yaml::Null)), iter.next() ); assert_eq!(None, iter.next()); } #[test] fn test_integer_key() { let s = " 0: important: true 1: important: false "; let out = YamlLoader::load_from_str(&s).unwrap(); let first = out.into_iter().next().unwrap(); assert_eq!(first[0]["important"].as_bool().unwrap(), true); } #[test] fn test_indentation_equality() { let four_spaces = YamlLoader::load_from_str( r#" hash: with: indentations "#, ) .unwrap() .into_iter() .next() .unwrap(); let two_spaces = YamlLoader::load_from_str( r#" hash: with: indentations "#, ) .unwrap() .into_iter() .next() .unwrap(); let one_space = YamlLoader::load_from_str( r#" hash: with: indentations "#, ) .unwrap() .into_iter() .next() .unwrap(); let mixed_spaces = YamlLoader::load_from_str( r#" hash: with: indentations "#, ) .unwrap() .into_iter() .next() .unwrap(); assert_eq!(four_spaces, two_spaces); assert_eq!(two_spaces, one_space); assert_eq!(four_spaces, mixed_spaces); } #[test] fn test_two_space_indentations() { // https://github.com/kbknapp/clap-rs/issues/965 let s = r#" subcommands: - server: about: server related commands subcommands2: - server: about: server related commands subcommands3: - server: about: server related commands "#; let out = YamlLoader::load_from_str(&s).unwrap(); let doc = &out.into_iter().next().unwrap(); println!("{:#?}", doc); assert_eq!(doc["subcommands"][0]["server"], Yaml::Null); assert!(doc["subcommands2"][0]["server"].as_hash().is_some()); assert!(doc["subcommands3"][0]["server"].as_hash().is_some()); } #[test] fn test_recursion_depth_check_objects() { let s = "{a:".repeat(10_000) + &"}".repeat(10_000); assert!(YamlLoader::load_from_str(&s).is_err()); } #[test] fn test_recursion_depth_check_arrays() { let s = "[".repeat(10_000) + &"]".repeat(10_000); assert!(YamlLoader::load_from_str(&s).is_err()); } } yaml-rust-0.4.3/tests/quickcheck.rs010064400007670000024000000013001344013434500155110ustar0000000000000000extern crate yaml_rust; #[macro_use] extern crate quickcheck; use quickcheck::TestResult; use std::error::Error; use yaml_rust::{Yaml, YamlEmitter, YamlLoader}; quickcheck! { fn test_check_weird_keys(xs: Vec) -> TestResult { let mut out_str = String::new(); let input = Yaml::Array(xs.into_iter().map(Yaml::String).collect()); { let mut emitter = YamlEmitter::new(&mut out_str); emitter.dump(&input).unwrap(); } match YamlLoader::load_from_str(&out_str) { Ok(output) => TestResult::from_bool(output.len() == 1 && input == output[0]), Err(err) => TestResult::error(err.description()), } } } yaml-rust-0.4.3/tests/spec_test.rs010064400007670000024000000071051344013434500154010ustar0000000000000000#![allow(dead_code)] #![allow(non_upper_case_globals)] extern crate yaml_rust; use yaml_rust::parser::{Event, EventReceiver, Parser}; use yaml_rust::scanner::TScalarStyle; // These names match the names used in the C++ test suite. #[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))] #[derive(Clone, PartialEq, PartialOrd, Debug)] enum TestEvent { OnDocumentStart, OnDocumentEnd, OnSequenceStart, OnSequenceEnd, OnMapStart, OnMapEnd, OnScalar, OnAlias, OnNull, } struct YamlChecker { pub evs: Vec, } impl EventReceiver for YamlChecker { fn on_event(&mut self, ev: Event) { let tev = match ev { Event::DocumentStart => TestEvent::OnDocumentStart, Event::DocumentEnd => TestEvent::OnDocumentEnd, Event::SequenceStart(..) => TestEvent::OnSequenceStart, Event::SequenceEnd => TestEvent::OnSequenceEnd, Event::MappingStart(..) => TestEvent::OnMapStart, Event::MappingEnd => TestEvent::OnMapEnd, Event::Scalar(ref v, style, _, _) => { if v == "~" && style == TScalarStyle::Plain { TestEvent::OnNull } else { TestEvent::OnScalar } } Event::Alias(_) => TestEvent::OnAlias, _ => return, // ignore other events }; self.evs.push(tev); } } fn str_to_test_events(docs: &str) -> Vec { let mut p = YamlChecker { evs: Vec::new() }; let mut parser = Parser::new(docs.chars()); parser.load(&mut p, true).unwrap(); p.evs } macro_rules! assert_next { ($v:expr, $p:pat) => { match $v.next().unwrap() { $p => {} e => { panic!("unexpected event: {:?}", e); } } }; } // auto generated from handler_spec_test.cpp include!("specexamples.rs.inc"); include!("spec_test.rs.inc"); // hand-crafted tests //#[test] //fn test_hc_alias() { //} #[test] fn test_mapvec_legal() { use yaml_rust::yaml::{Array, Hash, Yaml}; use yaml_rust::{YamlEmitter, YamlLoader}; // Emitting a `map>, _>` should result in legal yaml that // we can parse. let mut key = Array::new(); key.push(Yaml::Integer(1)); key.push(Yaml::Integer(2)); key.push(Yaml::Integer(3)); let mut keyhash = Hash::new(); keyhash.insert(Yaml::String("key".into()), Yaml::Array(key)); let mut val = Array::new(); val.push(Yaml::Integer(4)); val.push(Yaml::Integer(5)); val.push(Yaml::Integer(6)); let mut hash = Hash::new(); hash.insert(Yaml::Hash(keyhash), Yaml::Array(val)); let mut out_str = String::new(); { let mut emitter = YamlEmitter::new(&mut out_str); emitter.dump(&Yaml::Hash(hash)).unwrap(); } // At this point, we are tempted to naively render like this: // // ```yaml // --- // {key: // - 1 // - 2 // - 3}: // - 4 // - 5 // - 6 // ``` // // However, this doesn't work, because the key sequence [1, 2, 3] is // rendered in block mode, which is not legal (as far as I can tell) // inside the flow mode of the key. We need to either fully render // everything that's in a key in flow mode (which may make for some // long lines), or use the explicit map identifier '?': // // ```yaml // --- // ? // key: // - 1 // - 2 // - 3 // : // - 4 // - 5 // - 6 // ``` YamlLoader::load_from_str(&out_str).unwrap(); } yaml-rust-0.4.3/tests/spec_test.rs.inc010064400007670000024000001545441254427023000161610ustar0000000000000000#[test] fn test_ex2_1_seq_scalars() { let mut v = str_to_test_events(EX2_1).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_2_mapping_scalars_to_scalars() { let mut v = str_to_test_events(EX2_2).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_3_mapping_scalars_to_sequences() { let mut v = str_to_test_events(EX2_3).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_4_sequence_of_mappings() { let mut v = str_to_test_events(EX2_4).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_5_sequence_of_sequences() { let mut v = str_to_test_events(EX2_5).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_6_mapping_of_mappings() { let mut v = str_to_test_events(EX2_6).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_7_two_documents_in_a_stream() { let mut v = str_to_test_events(EX2_7).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_8_play_by_play_feed() { let mut v = str_to_test_events(EX2_8).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_9_single_document_with_two_comments() { let mut v = str_to_test_events(EX2_9).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_10_simple_anchor() { let mut v = str_to_test_events(EX2_10).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnAlias); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_11_mapping_between_sequences() { let mut v = str_to_test_events(EX2_11).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_12_compact_nested_mapping() { let mut v = str_to_test_events(EX2_12).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_13_in_literals_newlines_are_preserved() { let mut v = str_to_test_events(EX2_13).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_14_in_folded_scalars_newlines_become_spaces() { let mut v = str_to_test_events(EX2_14).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_15_folded_newlines_are_preserved_for_more_indented_and_blank_lines() { let mut v = str_to_test_events(EX2_15).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_16_indentation_determines_scope() { let mut v = str_to_test_events(EX2_16).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_17_quoted_scalars() { let mut v = str_to_test_events(EX2_17).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_18_multi_line_flow_scalars() { let mut v = str_to_test_events(EX2_18).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_23_various_explicit_tags() { let mut v = str_to_test_events(EX2_23).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_24_global_tags() { let mut v = str_to_test_events(EX2_24).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnAlias); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnAlias); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_25_unordered_sets() { let mut v = str_to_test_events(EX2_25).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnNull); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnNull); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnNull); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_26_ordered_mappings() { let mut v = str_to_test_events(EX2_26).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_27_invoice() { let mut v = str_to_test_events(EX2_27).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnAlias); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex2_28_log_file() { let mut v = str_to_test_events(EX2_28).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex5_3_block_structure_indicators() { let mut v = str_to_test_events(EX5_3).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex5_4_flow_structure_indicators() { let mut v = str_to_test_events(EX5_4).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex5_6_node_property_indicators() { let mut v = str_to_test_events(EX5_6).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnAlias); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex5_7_block_scalar_indicators() { let mut v = str_to_test_events(EX5_7).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex5_8_quoted_scalar_indicators() { let mut v = str_to_test_events(EX5_8).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex5_11_line_break_characters() { let mut v = str_to_test_events(EX5_11).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex5_12_tabs_and_spaces() { let mut v = str_to_test_events(EX5_12).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex5_13_escaped_characters() { let mut v = str_to_test_events(EX5_13).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_1_indentation_spaces() { let mut v = str_to_test_events(EX6_1).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_2_indentation_indicators() { let mut v = str_to_test_events(EX6_2).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_3_separation_spaces() { let mut v = str_to_test_events(EX6_3).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_4_line_prefixes() { let mut v = str_to_test_events(EX6_4).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_5_empty_lines() { let mut v = str_to_test_events(EX6_5).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_6_line_folding() { let mut v = str_to_test_events(EX6_6).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_7_block_folding() { let mut v = str_to_test_events(EX6_7).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_8_flow_folding() { let mut v = str_to_test_events(EX6_8).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_9_separated_comment() { let mut v = str_to_test_events(EX6_9).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_12_separation_spaces_ii() { let mut v = str_to_test_events(EX6_12).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_13_reserved_directives() { let mut v = str_to_test_events(EX6_13).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_14_yaml_directive() { let mut v = str_to_test_events(EX6_14).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_16_tag_directive() { let mut v = str_to_test_events(EX6_16).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_18_primary_tag_handle() { let mut v = str_to_test_events(EX6_18).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_19_secondary_tag_handle() { let mut v = str_to_test_events(EX6_19).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_20_tag_handles() { let mut v = str_to_test_events(EX6_20).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_21_local_tag_prefix() { let mut v = str_to_test_events(EX6_21).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_22_global_tag_prefix() { let mut v = str_to_test_events(EX6_22).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_23_node_properties() { let mut v = str_to_test_events(EX6_23).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnAlias); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_24_verbatim_tags() { let mut v = str_to_test_events(EX6_24).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_26_tag_shorthands() { let mut v = str_to_test_events(EX6_26).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_28_non_specific_tags() { let mut v = str_to_test_events(EX6_28).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex6_29_node_anchors() { let mut v = str_to_test_events(EX6_29).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnAlias); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_1_alias_nodes() { let mut v = str_to_test_events(EX7_1).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnAlias); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnAlias); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[allow(dead_code)] fn test_ex7_2_empty_nodes() { let mut v = str_to_test_events(EX7_2).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_3_completely_empty_nodes() { let mut v = str_to_test_events(EX7_3).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnNull); assert_next!(v, TestEvent::OnNull); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_4_double_quoted_implicit_keys() { let mut v = str_to_test_events(EX7_4).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_5_double_quoted_line_breaks() { let mut v = str_to_test_events(EX7_5).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_6_double_quoted_lines() { let mut v = str_to_test_events(EX7_6).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_7_single_quoted_characters() { let mut v = str_to_test_events(EX7_7).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_8_single_quoted_implicit_keys() { let mut v = str_to_test_events(EX7_8).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_9_single_quoted_lines() { let mut v = str_to_test_events(EX7_9).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[allow(dead_code)] fn test_ex7_10_plain_characters() { let mut v = str_to_test_events(EX7_10).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_11_plain_implicit_keys() { let mut v = str_to_test_events(EX7_11).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_12_plain_lines() { let mut v = str_to_test_events(EX7_12).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_13_flow_sequence() { let mut v = str_to_test_events(EX7_13).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_14_flow_sequence_entries() { let mut v = str_to_test_events(EX7_14).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_15_flow_mappings() { let mut v = str_to_test_events(EX7_15).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_16_flow_mapping_entries() { let mut v = str_to_test_events(EX7_16).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnNull); assert_next!(v, TestEvent::OnNull); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[allow(dead_code)] fn test_ex7_17_flow_mapping_separate_values() { let mut v = str_to_test_events(EX7_17).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnNull); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnNull); assert_next!(v, TestEvent::OnNull); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_18_flow_mapping_adjacent_values() { let mut v = str_to_test_events(EX7_18).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnNull); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_19_single_pair_flow_mappings() { let mut v = str_to_test_events(EX7_19).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_20_single_pair_explicit_entry() { let mut v = str_to_test_events(EX7_20).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[allow(dead_code)] fn test_ex7_21_single_pair_implicit_entries() { let mut v = str_to_test_events(EX7_21).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnNull); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_23_flow_content() { let mut v = str_to_test_events(EX7_23).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex7_24_flow_nodes() { let mut v = str_to_test_events(EX7_24).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnAlias); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex8_1_block_scalar_header() { let mut v = str_to_test_events(EX8_1).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[allow(dead_code)] fn test_ex8_2_block_indentation_header() { let mut v = str_to_test_events(EX8_2).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex8_4_chomping_final_line_break() { let mut v = str_to_test_events(EX8_4).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex8_6_empty_scalar_chomping() { let mut v = str_to_test_events(EX8_6).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex8_7_literal_scalar() { let mut v = str_to_test_events(EX8_7).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex8_8_literal_content() { let mut v = str_to_test_events(EX8_8).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex8_9_folded_scalar() { let mut v = str_to_test_events(EX8_9).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex8_10_folded_lines() { let mut v = str_to_test_events(EX8_10).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex8_11_more_indented_lines() { let mut v = str_to_test_events(EX8_11).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex8_12_empty_separation_lines() { let mut v = str_to_test_events(EX8_12).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex8_13_final_empty_lines() { let mut v = str_to_test_events(EX8_13).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex8_14_block_sequence() { let mut v = str_to_test_events(EX8_14).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex8_15_block_sequence_entry_types() { let mut v = str_to_test_events(EX8_15).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnNull); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex8_16_block_mappings() { let mut v = str_to_test_events(EX8_16).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex8_17_explicit_block_mapping_entries() { let mut v = str_to_test_events(EX8_17).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnNull); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex8_18_implicit_block_mapping_entries() { let mut v = str_to_test_events(EX8_18).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnNull); assert_next!(v, TestEvent::OnNull); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex8_19_compact_block_mappings() { let mut v = str_to_test_events(EX8_19).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex8_20_block_node_types() { let mut v = str_to_test_events(EX8_20).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnDocumentEnd); } #[test] fn test_ex8_22_block_collection_nodes() { let mut v = str_to_test_events(EX8_22).into_iter(); assert_next!(v, TestEvent::OnDocumentStart); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnSequenceEnd); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapStart); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnScalar); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnMapEnd); assert_next!(v, TestEvent::OnDocumentEnd); } yaml-rust-0.4.3/tests/specexamples.rs.inc010064400007670000024000000330241254427023000166460ustar0000000000000000const EX2_1 : &'static str = "- Mark McGwire\n- Sammy Sosa\n- Ken Griffey"; const EX2_2 : &'static str = "hr: 65 # Home runs\navg: 0.278 # Batting average\nrbi: 147 # Runs Batted In"; const EX2_3 : &'static str = "american:\n- Boston Red Sox\n- Detroit Tigers\n- New York Yankees\nnational:\n- New York Mets\n- Chicago Cubs\n- Atlanta Braves"; const EX2_4 : &'static str = "-\n name: Mark McGwire\n hr: 65\n avg: 0.278\n-\n name: Sammy Sosa\n hr: 63\n avg: 0.288"; const EX2_5 : &'static str = "- [name , hr, avg ]\n- [Mark McGwire, 65, 0.278]\n- [Sammy Sosa , 63, 0.288]"; const EX2_6 : &'static str = "Mark McGwire: {hr: 65, avg: 0.278}\nSammy Sosa: {\n hr: 63,\n avg: 0.288\n }"; const EX2_7 : &'static str = "# Ranking of 1998 home runs\n---\n- Mark McGwire\n- Sammy Sosa\n- Ken Griffey\n\n# Team ranking\n---\n- Chicago Cubs\n- St Louis Cardinals"; const EX2_8 : &'static str = "---\ntime: 20:03:20\nplayer: Sammy Sosa\naction: strike (miss)\n...\n---\ntime: 20:03:47\nplayer: Sammy Sosa\naction: grand slam\n..."; const EX2_9 : &'static str = "---\nhr: # 1998 hr ranking\n - Mark McGwire\n - Sammy Sosa\nrbi:\n # 1998 rbi ranking\n - Sammy Sosa\n - Ken Griffey"; const EX2_10 : &'static str = "---\nhr:\n - Mark McGwire\n # Following node labeled SS\n - &SS Sammy Sosa\nrbi:\n - *SS # Subsequent occurrence\n - Ken Griffey"; const EX2_11 : &'static str = "? - Detroit Tigers\n - Chicago cubs\n:\n - 2001-07-23\n\n? [ New York Yankees,\n Atlanta Braves ]\n: [ 2001-07-02, 2001-08-12,\n 2001-08-14 ]"; const EX2_12 : &'static str = "---\n# Products purchased\n- item : Super Hoop\n quantity: 1\n- item : Basketball\n quantity: 4\n- item : Big Shoes\n quantity: 1"; const EX2_13 : &'static str = "# ASCII Art\n--- |\n \\//||\\/||\n // || ||__"; const EX2_14 : &'static str = "--- >\n Mark McGwire's\n year was crippled\n by a knee injury."; const EX2_15 : &'static str = ">\n Sammy Sosa completed another\n fine season with great stats.\n \n 63 Home Runs\n 0.288 Batting Average\n \n What a year!"; const EX2_16 : &'static str = "name: Mark McGwire\naccomplishment: >\n Mark set a major league\n home run record in 1998.\nstats: |\n 65 Home Runs\n 0.278 Batting Average\n"; const EX2_17 : &'static str = "unicode: \"Sosa did fine.\\u263A\"\ncontrol: \"\\b1998\\t1999\\t2000\\n\"\nhex esc: \"\\x0d\\x0a is \\r\\n\"\n\nsingle: '\"Howdy!\" he cried.'\nquoted: ' # Not a ''comment''.'\ntie-fighter: '|\\-*-/|'"; const EX2_18 : &'static str = "plain:\n This unquoted scalar\n spans many lines.\n\nquoted: \"So does this\n quoted scalar.\\n\""; // TODO: 2.19 - 2.22 schema tags const EX2_23 : &'static str = "---\nnot-date: !!str 2002-04-28\n\npicture: !!binary |\n R0lGODlhDAAMAIQAAP//9/X\n 17unp5WZmZgAAAOfn515eXv\n Pz7Y6OjuDg4J+fn5OTk6enp\n 56enmleECcgggoBADs=\n\napplication specific tag: !something |\n The semantics of the tag\n above may be different for\n different documents."; const EX2_24 : &'static str = "%TAG ! tag:clarkevans.com,2002:\n--- !shape\n # Use the ! handle for presenting\n # tag:clarkevans.com,2002:circle\n- !circle\n center: &ORIGIN {x: 73, y: 129}\n radius: 7\n- !line\n start: *ORIGIN\n finish: { x: 89, y: 102 }\n- !label\n start: *ORIGIN\n color: 0xFFEEBB\n text: Pretty vector drawing."; const EX2_25 : &'static str = "# Sets are represented as a\n# Mapping where each key is\n# associated with a null value\n--- !!set\n? Mark McGwire\n? Sammy Sosa\n? Ken Griffey"; const EX2_26 : &'static str = "# Ordered maps are represented as\n# A sequence of mappings, with\n# each mapping having one key\n--- !!omap\n- Mark McGwire: 65\n- Sammy Sosa: 63\n- Ken Griffey: 58"; const EX2_27 : &'static str = "--- !\ninvoice: 34843\ndate : 2001-01-23\nbill-to: &id001\n given : Chris\n family : Dumars\n address:\n lines: |\n 458 Walkman Dr.\n Suite #292\n city : Royal Oak\n state : MI\n postal : 48046\nship-to: *id001\nproduct:\n - sku : BL394D\n quantity : 4\n description : Basketball\n price : 450.00\n - sku : BL4438H\n quantity : 1\n description : Super Hoop\n price : 2392.00\ntax : 251.42\ntotal: 4443.52\ncomments:\n Late afternoon is best.\n Backup contact is Nancy\n Billsmer @ 338-4338."; const EX2_28 : &'static str = "---\nTime: 2001-11-23 15:01:42 -5\nUser: ed\nWarning:\n This is an error message\n for the log file\n---\nTime: 2001-11-23 15:02:31 -5\nUser: ed\nWarning:\n A slightly different error\n message.\n---\nDate: 2001-11-23 15:03:17 -5\nUser: ed\nFatal:\n Unknown variable \"bar\"\nStack:\n - file: TopClass.py\n line: 23\n code: |\n x = MoreObject(\"345\\n\")\n - file: MoreClass.py\n line: 58\n code: |-\n foo = bar"; // TODO: 5.1 - 5.2 BOM const EX5_3 : &'static str = "sequence:\n- one\n- two\nmapping:\n ? sky\n : blue\n sea : green"; const EX5_4 : &'static str = "sequence: [ one, two, ]\nmapping: { sky: blue, sea: green }"; const EX5_5 : &'static str = "# Comment only."; const EX5_6 : &'static str = "anchored: !local &anchor value\nalias: *anchor"; const EX5_7 : &'static str = "literal: |\n some\n text\nfolded: >\n some\n text\n"; const EX5_8 : &'static str = "single: 'text'\ndouble: \"text\""; // TODO: 5.9 directive // TODO: 5.10 reserved indicator const EX5_11 : &'static str = "|\n Line break (no glyph)\n Line break (glyphed)\n"; const EX5_12 : &'static str = "# Tabs and spaces\nquoted: \"Quoted\t\"\nblock: |\n void main() {\n \tprintf(\"Hello, world!\\n\");\n }"; const EX5_13 : &'static str = "\"Fun with \\\\\n\\\" \\a \\b \\e \\f \\\n\\n \\r \\t \\v \\0 \\\n\\ \\_ \\N \\L \\P \\\n\\x41 \\u0041 \\U00000041\""; const EX5_14 : &'static str = "Bad escapes:\n \"\\c\n \\xq-\""; const EX6_1 : &'static str = " # Leading comment line spaces are\n # neither content nor indentation.\n \nNot indented:\n By one space: |\n By four\n spaces\n Flow style: [ # Leading spaces\n By two, # in flow style\n Also by two, # are neither\n \tStill by two # content nor\n ] # indentation."; const EX6_2 : &'static str = "? a\n: -\tb\n - -\tc\n - d"; const EX6_3 : &'static str = "- foo:\t bar\n- - baz\n -\tbaz"; const EX6_4 : &'static str = "plain: text\n lines\nquoted: \"text\n \tlines\"\nblock: |\n text\n \tlines\n"; const EX6_5 : &'static str = "Folding:\n \"Empty line\n \t\n as a line feed\"\nChomping: |\n Clipped empty lines\n "; const EX6_6 : &'static str = ">-\n trimmed\n \n \n\n as\n space"; const EX6_7 : &'static str = ">\n foo \n \n \t bar\n\n baz\n"; const EX6_8 : &'static str = "\"\n foo \n \n \t bar\n\n baz\n\""; const EX6_9 : &'static str = "key: # Comment\n value"; const EX6_10 : &'static str = " # Comment\n \n\n"; const EX6_11 : &'static str = "key: # Comment\n # lines\n value\n\n"; const EX6_12 : &'static str = "{ first: Sammy, last: Sosa }:\n# Statistics:\n hr: # Home runs\n 65\n avg: # Average\n 0.278"; const EX6_13 : &'static str = "%FOO bar baz # Should be ignored\n # with a warning.\n--- \"foo\""; const EX6_14 : &'static str = "%YAML 1.3 # Attempt parsing\n # with a warning\n---\n\"foo\""; const EX6_15 : &'static str = "%YAML 1.2\n%YAML 1.1\nfoo"; const EX6_16 : &'static str = "%TAG !yaml! tag:yaml.org,2002:\n---\n!yaml!str \"foo\""; const EX6_17 : &'static str = "%TAG ! !foo\n%TAG ! !foo\nbar"; const EX6_18 : &'static str = "# Private\n!foo \"bar\"\n...\n# Global\n%TAG ! tag:example.com,2000:app/\n---\n!foo \"bar\""; const EX6_19 : &'static str = "%TAG !! tag:example.com,2000:app/\n---\n!!int 1 - 3 # Interval, not integer"; const EX6_20 : &'static str = "%TAG !e! tag:example.com,2000:app/\n---\n!e!foo \"bar\""; const EX6_21 : &'static str = "%TAG !m! !my-\n--- # Bulb here\n!m!light fluorescent\n...\n%TAG !m! !my-\n--- # Color here\n!m!light green"; const EX6_22 : &'static str = "%TAG !e! tag:example.com,2000:app/\n---\n- !e!foo \"bar\""; const EX6_23 : &'static str = "!!str &a1 \"foo\":\n !!str bar\n&a2 baz : *a1"; const EX6_24 : &'static str = "! foo :\n ! baz"; const EX6_25 : &'static str = "- ! foo\n- !<$:?> bar\n"; const EX6_26 : &'static str = "%TAG !e! tag:example.com,2000:app/\n---\n- !local foo\n- !!str bar\n- !e!tag%21 baz\n"; const EX6_27a : &'static str = "%TAG !e! tag:example,2000:app/\n---\n- !e! foo"; const EX6_27b : &'static str = "%TAG !e! tag:example,2000:app/\n---\n- !h!bar baz"; const EX6_28 : &'static str = "# Assuming conventional resolution:\n- \"12\"\n- 12\n- ! 12"; const EX6_29 : &'static str = "First occurrence: &anchor Value\nSecond occurrence: *anchor"; const EX7_1 : &'static str = "First occurrence: &anchor Foo\nSecond occurrence: *anchor\nOverride anchor: &anchor Bar\nReuse anchor: *anchor"; const EX7_2 : &'static str = "{\n foo : !!str,\n !!str : bar,\n}"; const EX7_3 : &'static str = "{\n ? foo :,\n : bar,\n}\n"; const EX7_4 : &'static str = "\"implicit block key\" : [\n \"implicit flow key\" : value,\n ]"; const EX7_5 : &'static str = "\"folded \nto a space,\t\n \nto a line feed, or \t\\\n \\ \tnon-content\""; const EX7_6 : &'static str = "\" 1st non-empty\n\n 2nd non-empty \n\t3rd non-empty \""; const EX7_7 : &'static str = " 'here''s to \"quotes\"'"; const EX7_8 : &'static str = "'implicit block key' : [\n 'implicit flow key' : value,\n ]"; const EX7_9 : &'static str = "' 1st non-empty\n\n 2nd non-empty \n\t3rd non-empty '"; const EX7_10 : &'static str = "# Outside flow collection:\n- ::vector\n- \": - ()\"\n- Up, up, and away!\n- -123\n- http://example.com/foo#bar\n# Inside flow collection:\n- [ ::vector,\n \": - ()\",\n \"Up, up, and away!\",\n -123,\n http://example.com/foo#bar ]"; const EX7_11 : &'static str = "implicit block key : [\n implicit flow key : value,\n ]"; const EX7_12 : &'static str = "1st non-empty\n\n 2nd non-empty \n\t3rd non-empty"; const EX7_13 : &'static str = "- [ one, two, ]\n- [three ,four]"; const EX7_14 : &'static str = "[\n\"double\n quoted\", 'single\n quoted',\nplain\n text, [ nested ],\nsingle: pair,\n]"; const EX7_15 : &'static str = "- { one : two , three: four , }\n- {five: six,seven : eight}"; const EX7_16 : &'static str = "{\n? explicit: entry,\nimplicit: entry,\n?\n}"; const EX7_17 : &'static str = "{\nunquoted : \"separate\",\nhttp://foo.com,\nomitted value:,\n: omitted key,\n}"; const EX7_18 : &'static str = "{\n\"adjacent\":value,\n\"readable\":value,\n\"empty\":\n}"; const EX7_19 : &'static str = "[\nfoo: bar\n]"; const EX7_20 : &'static str = "[\n? foo\n bar : baz\n]"; const EX7_21 : &'static str = "- [ YAML : separate ]\n- [ : empty key entry ]\n- [ {JSON: like}:adjacent ]"; const EX7_22 : &'static str = "[ foo\n bar: invalid,"; // Note: we don't check (on purpose) the >1K chars for an // implicit key const EX7_23 : &'static str = "- [ a, b ]\n- { a: b }\n- \"a\"\n- 'b'\n- c"; const EX7_24 : &'static str = "- !!str \"a\"\n- 'b'\n- &anchor \"c\"\n- *anchor\n- !!str"; const EX8_1 : &'static str = "- | # Empty header\n literal\n- >1 # Indentation indicator\n folded\n- |+ # Chomping indicator\n keep\n\n- >1- # Both indicators\n strip\n"; const EX8_2 : &'static str = "- |\n detected\n- >\n \n \n # detected\n- |1\n explicit\n- >\n \t\n detected\n"; const EX8_3a : &'static str = "- |\n \n text"; const EX8_3b : &'static str = "- >\n text\n text"; const EX8_3c : &'static str = "- |2\n text"; const EX8_4 : &'static str = "strip: |-\n text\nclip: |\n text\nkeep: |+\n text\n"; const EX8_5 : &'static str = " # Strip\n # Comments:\nstrip: |-\n # text\n \n # Clip\n # comments:\n\nclip: |\n # text\n \n # Keep\n # comments:\n\nkeep: |+\n # text\n\n # Trail\n # Comments\n"; const EX8_6 : &'static str = "strip: >-\n\nclip: >\n\nkeep: |+\n\n"; const EX8_7 : &'static str = "|\n literal\n \ttext\n\n"; const EX8_8 : &'static str = "|\n \n \n literal\n \n \n text\n\n # Comment\n"; const EX8_9 : &'static str = ">\n folded\n text\n\n"; const EX8_10 : &'static str = ">\n\n folded\n line\n\n next\n line\n * bullet\n\n * list\n * lines\n\n last\n line\n\n# Comment\n"; const EX8_11 : &'static str = EX8_10; const EX8_12 : &'static str = EX8_10; const EX8_13 : &'static str = EX8_10; const EX8_14 : &'static str = "block sequence:\n - one\n - two : three\n"; const EX8_15 : &'static str = "- # Empty\n- |\n block node\n- - one # Compact\n - two # sequence\n- one: two # Compact mapping\n"; const EX8_16 : &'static str = "block mapping:\n key: value\n"; const EX8_17 : &'static str = "? explicit key # Empty value\n? |\n block key\n: - one # Explicit compact\n - two # block value\n"; // XXX libyaml failed this test const EX8_18 : &'static str = "plain key: in-line value\n: # Both empty\n\"quoted key\":\n- entry\n"; const EX8_19 : &'static str = "- sun: yellow\n- ? earth: blue\n : moon: white\n"; const EX8_20 : &'static str = "-\n \"flow in block\"\n- >\n Block scalar\n- !!map # Block collection\n foo : bar\n"; const EX8_21 : &'static str = "literal: |2\n value\nfolded:\n !foo\n >1\n value\n"; const EX8_22 : &'static str = "sequence: !!seq\n- entry\n- !!seq\n - nested\nmapping: !!map\n foo: bar\n"; yaml-rust-0.4.3/tests/specs/cpp2rust.rb010075500007670000024000000026501254427023000162670ustar0000000000000000#!/usr/bin/env ruby TEST_REGEX = /TEST_F\([a-zA-Z0-9_]+,\s+([a-zA-Z0-9_]+)\)/ DISABLED_TESTS = %w( test_ex7_10_plain_characters test_ex7_17_flow_mapping_separate_values test_ex7_21_single_pair_implicit_entries test_ex7_2_empty_nodes test_ex8_2_block_indentation_header ) class Context attr_accessor :name, :ev, :src def initialize @name = "" @src = "" @ev = [] end end class String def snakecase self .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') .gsub(/([a-z\d])([A-Z])/, '\1_\2') .tr('-', '_') .gsub(/\s/, '_') .gsub(/__+/, '_') .downcase end end ctx = nil tests = [] IO.foreach(ARGV[0]) do |line| line.strip! if ctx fail "unexpected TEST_F" if line =~ TEST_REGEX if line =~ /^}/ tests << ctx ctx = nil end if line =~ /^EXPECT_CALL/ fail 'not end with ;' unless line[-1] == ';' v = line.gsub('(', ' ').gsub(')', ' ').split ctx.ev << v[2] end else next unless line =~ TEST_REGEX name = $1 next unless name =~ /^(Ex\d+_\d+)/ str = $1.upcase $stderr.puts "found #{name}" ctx = Context.new ctx.name = "test_#{name.snakecase}" ctx.src = str end end # code gen tests.each do |t| next if t.ev.size == 0 if DISABLED_TESTS.include? t.name puts "#[allow(dead_code)]" else puts "#[test]" end puts "fn #{t.name}() {" puts " let mut v = str_to_test_events(#{t.src}).into_iter();" t.ev.each do |e| puts " assert_next!(v, TestEvent::#{e});" end puts "}" puts end yaml-rust-0.4.3/tests/specs/handler_spec_test.cpp010064400007670000024000002036311254427023000203510ustar0000000000000000#include "handler_test.h" #include "specexamples.h" // IWYU pragma: keep #include "yaml-cpp/yaml.h" // IWYU pragma: keep #include "gmock/gmock.h" #include "gtest/gtest.h" using ::testing::_; #define EXPECT_THROW_PARSER_EXCEPTION(statement, message) \ ASSERT_THROW(statement, ParserException); \ try { \ statement; \ } catch (const ParserException& e) { \ EXPECT_EQ(e.msg, message); \ } namespace YAML { namespace { typedef HandlerTest HandlerSpecTest; TEST_F(HandlerSpecTest, Ex2_1_SeqScalars) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Mark McGwire")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Sammy Sosa")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Ken Griffey")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_1); } TEST_F(HandlerSpecTest, Ex2_2_MappingScalarsToScalars) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "hr")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "65")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "avg")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "0.278")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "rbi")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "147")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_2); } TEST_F(HandlerSpecTest, Ex2_3_MappingScalarsToSequences) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "american")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Boston Red Sox")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Detroit Tigers")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "New York Yankees")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnScalar(_, "?", 0, "national")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "New York Mets")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Chicago Cubs")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Atlanta Braves")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_3); } TEST_F(HandlerSpecTest, Ex2_4_SequenceOfMappings) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "name")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Mark McGwire")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "hr")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "65")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "avg")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "0.278")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "name")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Sammy Sosa")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "hr")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "63")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "avg")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "0.288")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_4); } TEST_F(HandlerSpecTest, Ex2_5_SequenceOfSequences) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "name")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "hr")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "avg")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Mark McGwire")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "65")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "0.278")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Sammy Sosa")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "63")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "0.288")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_5); } TEST_F(HandlerSpecTest, Ex2_6_MappingOfMappings) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Mark McGwire")); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "hr")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "65")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "avg")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "0.278")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Sammy Sosa")); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "hr")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "63")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "avg")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "0.288")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_6); } TEST_F(HandlerSpecTest, Ex2_7_TwoDocumentsInAStream) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Mark McGwire")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Sammy Sosa")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Ken Griffey")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Chicago Cubs")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "St Louis Cardinals")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_7); } TEST_F(HandlerSpecTest, Ex2_8_PlayByPlayFeed) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "time")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "20:03:20")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "player")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Sammy Sosa")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "action")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "strike (miss)")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "time")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "20:03:47")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "player")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Sammy Sosa")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "action")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "grand slam")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_8); } TEST_F(HandlerSpecTest, Ex2_9_SingleDocumentWithTwoComments) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "hr")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Mark McGwire")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Sammy Sosa")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnScalar(_, "?", 0, "rbi")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Sammy Sosa")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Ken Griffey")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_9); } TEST_F(HandlerSpecTest, Ex2_10_SimpleAnchor) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "hr")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Mark McGwire")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "Sammy Sosa")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnScalar(_, "?", 0, "rbi")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnAlias(_, 1)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Ken Griffey")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_10); } TEST_F(HandlerSpecTest, Ex2_11_MappingBetweenSequences) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Detroit Tigers")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Chicago cubs")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "2001-07-23")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "New York Yankees")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Atlanta Braves")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "2001-07-02")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "2001-08-12")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "2001-08-14")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_11); } TEST_F(HandlerSpecTest, Ex2_12_CompactNestedMapping) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "item")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Super Hoop")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "quantity")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "1")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "item")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Basketball")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "quantity")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "4")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "item")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Big Shoes")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "quantity")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "1")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_12); } TEST_F(HandlerSpecTest, Ex2_13_InLiteralsNewlinesArePreserved) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "\\//||\\/||\n// || ||__")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_13); } TEST_F(HandlerSpecTest, Ex2_14_InFoldedScalarsNewlinesBecomeSpaces) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "Mark McGwire's year was crippled by a knee injury.")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_14); } TEST_F(HandlerSpecTest, Ex2_15_FoldedNewlinesArePreservedForMoreIndentedAndBlankLines) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "Sammy Sosa completed another fine season with great stats.\n\n 63 Home Runs\n 0.288 Batting Average\n\nWhat a year!")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_15); } TEST_F(HandlerSpecTest, Ex2_16_IndentationDeterminesScope) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "name")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Mark McGwire")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "accomplishment")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "Mark set a major league home run record in 1998.\n")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "stats")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "65 Home Runs\n0.278 Batting Average\n")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_16); } TEST_F(HandlerSpecTest, Ex2_17_QuotedScalars) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "unicode")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "Sosa did fine.\xE2\x98\xBA")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "control")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "\b1998\t1999\t2000\n")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "hex esc")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "\x0d\x0a is \r\n")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "single")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "\"Howdy!\" he cried.")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "quoted")); EXPECT_CALL(handler, OnScalar(_, "!", 0, " # Not a 'comment'.")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "tie-fighter")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "|\\-*-/|")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_17); } TEST_F(HandlerSpecTest, Ex2_18_MultiLineFlowScalars) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "plain")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "This unquoted scalar spans many lines.")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "quoted")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "So does this quoted scalar.\n")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_18); } // TODO: 2.19 - 2.22 schema tags TEST_F(HandlerSpecTest, Ex2_23_VariousExplicitTags) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "not-date")); EXPECT_CALL(handler, OnScalar(_, "tag:yaml.org,2002:str", 0, "2002-04-28")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "picture")); EXPECT_CALL(handler, OnScalar(_, "tag:yaml.org,2002:binary", 0, "R0lGODlhDAAMAIQAAP//9/X\n17unp5WZmZgAAAOfn515eXv\nPz7Y6OjuDg4J+fn5OTk6enp\n56enmleECcgggoBADs=\n")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "application specific tag")); EXPECT_CALL(handler, OnScalar(_, "!something", 0, "The semantics of the tag\nabove may be different for\ndifferent documents.")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_23); } TEST_F(HandlerSpecTest, Ex2_24_GlobalTags) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "tag:clarkevans.com,2002:shape", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnMapStart(_, "tag:clarkevans.com,2002:circle", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "center")); EXPECT_CALL(handler, OnMapStart(_, "?", 1, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "x")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "73")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "y")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "129")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnScalar(_, "?", 0, "radius")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "7")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapStart(_, "tag:clarkevans.com,2002:line", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "start")); EXPECT_CALL(handler, OnAlias(_, 1)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "finish")); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "x")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "89")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "y")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "102")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapStart(_, "tag:clarkevans.com,2002:label", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "start")); EXPECT_CALL(handler, OnAlias(_, 1)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "color")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "0xFFEEBB")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "text")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Pretty vector drawing.")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_24); } TEST_F(HandlerSpecTest, Ex2_25_UnorderedSets) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "tag:yaml.org,2002:set", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Mark McGwire")); EXPECT_CALL(handler, OnNull(_, 0)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Sammy Sosa")); EXPECT_CALL(handler, OnNull(_, 0)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Ken Griffey")); EXPECT_CALL(handler, OnNull(_, 0)); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_25); } TEST_F(HandlerSpecTest, Ex2_26_OrderedMappings) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "tag:yaml.org,2002:omap", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Mark McGwire")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "65")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Sammy Sosa")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "63")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Ken Griffey")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "58")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_26); } TEST_F(HandlerSpecTest, Ex2_27_Invoice) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "tag:clarkevans.com,2002:invoice", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "invoice")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "34843")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "date")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "2001-01-23")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "bill-to")); EXPECT_CALL(handler, OnMapStart(_, "?", 1, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "given")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Chris")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "family")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Dumars")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "address")); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "lines")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "458 Walkman Dr.\nSuite #292\n")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "city")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Royal Oak")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "state")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "MI")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "postal")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "48046")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnScalar(_, "?", 0, "ship-to")); EXPECT_CALL(handler, OnAlias(_, 1)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "product")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "sku")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "BL394D")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "quantity")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "4")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "description")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Basketball")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "price")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "450.00")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "sku")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "BL4438H")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "quantity")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "1")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "description")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Super Hoop")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "price")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "2392.00")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnScalar(_, "?", 0, "tax")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "251.42")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "total")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "4443.52")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "comments")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_27); } TEST_F(HandlerSpecTest, Ex2_28_LogFile) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Time")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "2001-11-23 15:01:42 -5")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "User")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "ed")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Warning")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "This is an error message for the log file")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Time")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "2001-11-23 15:02:31 -5")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "User")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "ed")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Warning")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "A slightly different error message.")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Date")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "2001-11-23 15:03:17 -5")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "User")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "ed")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Fatal")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Unknown variable \"bar\"")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Stack")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "file")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "TopClass.py")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "line")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "23")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "code")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "x = MoreObject(\"345\\n\")\n")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "file")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "MoreClass.py")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "line")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "58")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "code")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "foo = bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex2_28); } // TODO: 5.1 - 5.2 BOM TEST_F(HandlerSpecTest, Ex5_3_BlockStructureIndicators) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "sequence")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "one")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "two")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnScalar(_, "?", 0, "mapping")); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "sky")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "blue")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "sea")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "green")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex5_3); } TEST_F(HandlerSpecTest, Ex5_4_FlowStructureIndicators) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "sequence")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "one")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "two")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnScalar(_, "?", 0, "mapping")); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "sky")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "blue")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "sea")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "green")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex5_4); } TEST_F(HandlerSpecTest, Ex5_6_NodePropertyIndicators) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "anchored")); EXPECT_CALL(handler, OnScalar(_, "!local", 1, "value")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "alias")); EXPECT_CALL(handler, OnAlias(_, 1)); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex5_6); } TEST_F(HandlerSpecTest, Ex5_7_BlockScalarIndicators) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "literal")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "some\ntext\n")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "folded")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "some text\n")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex5_7); } TEST_F(HandlerSpecTest, Ex5_8_QuotedScalarIndicators) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "single")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "text")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "double")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "text")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex5_8); } // TODO: 5.9 directive // TODO: 5.10 reserved indicator TEST_F(HandlerSpecTest, Ex5_11_LineBreakCharacters) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "Line break (no glyph)\nLine break (glyphed)\n")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex5_11); } TEST_F(HandlerSpecTest, Ex5_12_TabsAndSpaces) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "quoted")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "Quoted\t")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "block")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "void main() {\n\tprintf(\"Hello, world!\\n\");\n}")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex5_12); } TEST_F(HandlerSpecTest, Ex5_13_EscapedCharacters) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "Fun with \x5C \x22 \x07 \x08 \x1B \x0C \x0A \x0D \x09 \x0B \x00 \x20 \xA0 \x85 \xe2\x80\xa8 \xe2\x80\xa9 A A A")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex5_13); } TEST_F(HandlerSpecTest, Ex5_14_InvalidEscapedCharacters) { EXPECT_THROW_PARSER_EXCEPTION(IgnoreParse(ex5_14), std::string(ErrorMsg::INVALID_ESCAPE) + "c"); } TEST_F(HandlerSpecTest, Ex6_1_IndentationSpaces) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Not indented")); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "By one space")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "By four\n spaces\n")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Flow style")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "By two")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Also by two")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Still by two")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_1); } TEST_F(HandlerSpecTest, Ex6_2_IndentationIndicators) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "a")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "b")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "c")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "d")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_2); } TEST_F(HandlerSpecTest, Ex6_3_SeparationSpaces) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "foo")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "baz")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "baz")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_3); } TEST_F(HandlerSpecTest, Ex6_4_LinePrefixes) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "plain")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "text lines")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "quoted")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "text lines")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "block")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "text\n \tlines\n")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_4); } TEST_F(HandlerSpecTest, Ex6_5_EmptyLines) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Folding")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "Empty line\nas a line feed")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Chomping")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "Clipped empty lines\n")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_5); } TEST_F(HandlerSpecTest, Ex6_6_LineFolding) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "trimmed\n\n\nas space")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_6); } TEST_F(HandlerSpecTest, Ex6_7_BlockFolding) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "foo \n\n\t bar\n\nbaz\n")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_7); } TEST_F(HandlerSpecTest, Ex6_8_FlowFolding) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, " foo\nbar\nbaz ")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_8); } TEST_F(HandlerSpecTest, Ex6_9_SeparatedComment) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "key")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "value")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_9); } TEST_F(HandlerSpecTest, _MultiLineComments) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "key")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "value")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_11); } TEST_F(HandlerSpecTest, Ex6_12_SeparationSpacesII) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "first")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Sammy")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "last")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Sosa")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "hr")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "65")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "avg")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "0.278")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_12); } TEST_F(HandlerSpecTest, Ex6_13_ReservedDirectives) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_13); } TEST_F(HandlerSpecTest, Ex6_14_YAMLDirective) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_14); } TEST_F(HandlerSpecTest, Ex6_15_InvalidRepeatedYAMLDirective) { EXPECT_THROW_PARSER_EXCEPTION(IgnoreParse(ex6_15), ErrorMsg::REPEATED_YAML_DIRECTIVE); } TEST_F(HandlerSpecTest, Ex6_16_TagDirective) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "tag:yaml.org,2002:str", 0, "foo")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_16); } TEST_F(HandlerSpecTest, Ex6_17_InvalidRepeatedTagDirective) { EXPECT_THROW_PARSER_EXCEPTION(IgnoreParse(ex6_17), ErrorMsg::REPEATED_TAG_DIRECTIVE); } TEST_F(HandlerSpecTest, Ex6_18_PrimaryTagHandle) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!foo", 0, "bar")); EXPECT_CALL(handler, OnDocumentEnd()); EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "tag:example.com,2000:app/foo", 0, "bar")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_18); } TEST_F(HandlerSpecTest, Ex6_19_SecondaryTagHandle) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "tag:example.com,2000:app/int", 0, "1 - 3")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_19); } TEST_F(HandlerSpecTest, Ex6_20_TagHandles) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "tag:example.com,2000:app/foo", 0, "bar")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_20); } TEST_F(HandlerSpecTest, Ex6_21_LocalTagPrefix) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!my-light", 0, "fluorescent")); EXPECT_CALL(handler, OnDocumentEnd()); EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!my-light", 0, "green")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_21); } TEST_F(HandlerSpecTest, Ex6_22_GlobalTagPrefix) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "tag:example.com,2000:app/foo", 0, "bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_22); } TEST_F(HandlerSpecTest, Ex6_23_NodeProperties) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "tag:yaml.org,2002:str", 1, "foo")); EXPECT_CALL(handler, OnScalar(_, "tag:yaml.org,2002:str", 0, "bar")); EXPECT_CALL(handler, OnScalar(_, "?", 2, "baz")); EXPECT_CALL(handler, OnAlias(_, 1)); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_23); } TEST_F(HandlerSpecTest, Ex6_24_VerbatimTags) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "tag:yaml.org,2002:str", 0, "foo")); EXPECT_CALL(handler, OnScalar(_, "!bar", 0, "baz")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_24); } // TODO: Implement TEST_F(HandlerSpecTest, DISABLED_Ex6_25_InvalidVerbatimTags) { Parse(ex6_25); FAIL() << "not implemented yet"; } TEST_F(HandlerSpecTest, Ex6_26_TagShorthands) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "!local", 0, "foo")); EXPECT_CALL(handler, OnScalar(_, "tag:yaml.org,2002:str", 0, "bar")); EXPECT_CALL(handler, OnScalar(_, "tag:example.com,2000:app/tag%21", 0, "baz")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_26); } TEST_F(HandlerSpecTest, Ex6_27a_InvalidTagShorthands) { EXPECT_THROW_PARSER_EXCEPTION(IgnoreParse(ex6_27a), ErrorMsg::TAG_WITH_NO_SUFFIX); } // TODO: should we reject this one (since !h! is not declared)? TEST_F(HandlerSpecTest, DISABLED_Ex6_27b_InvalidTagShorthands) { Parse(ex6_27b); FAIL() << "not implemented yet"; } TEST_F(HandlerSpecTest, Ex6_28_NonSpecificTags) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "12")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "12")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "12")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_28); } TEST_F(HandlerSpecTest, Ex6_29_NodeAnchors) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "First occurrence")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "Value")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Second occurrence")); EXPECT_CALL(handler, OnAlias(_, 1)); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex6_29); } TEST_F(HandlerSpecTest, Ex7_1_AliasNodes) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "First occurrence")); EXPECT_CALL(handler, OnScalar(_, "?", 1, "Foo")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Second occurrence")); EXPECT_CALL(handler, OnAlias(_, 1)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Override anchor")); EXPECT_CALL(handler, OnScalar(_, "?", 2, "Bar")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Reuse anchor")); EXPECT_CALL(handler, OnAlias(_, 2)); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_1); } TEST_F(HandlerSpecTest, Ex7_2_EmptyNodes) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "foo")); EXPECT_CALL(handler, OnScalar(_, "tag:yaml.org,2002:str", 0, "")); EXPECT_CALL(handler, OnScalar(_, "tag:yaml.org,2002:str", 0, "")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_2); } TEST_F(HandlerSpecTest, Ex7_3_CompletelyEmptyNodes) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "foo")); EXPECT_CALL(handler, OnNull(_, 0)); EXPECT_CALL(handler, OnNull(_, 0)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_3); } TEST_F(HandlerSpecTest, Ex7_4_DoubleQuotedImplicitKeys) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "implicit block key")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "implicit flow key")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "value")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_4); } TEST_F(HandlerSpecTest, Ex7_5_DoubleQuotedLineBreaks) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "folded to a space,\nto a line feed, or \t \tnon-content")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_5); } TEST_F(HandlerSpecTest, Ex7_6_DoubleQuotedLines) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, " 1st non-empty\n2nd non-empty 3rd non-empty ")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_6); } TEST_F(HandlerSpecTest, Ex7_7_SingleQuotedCharacters) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "here's to \"quotes\"")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_7); } TEST_F(HandlerSpecTest, Ex7_8_SingleQuotedImplicitKeys) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "implicit block key")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "implicit flow key")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "value")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_8); } TEST_F(HandlerSpecTest, Ex7_9_SingleQuotedLines) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, " 1st non-empty\n2nd non-empty 3rd non-empty ")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_9); } TEST_F(HandlerSpecTest, Ex7_10_PlainCharacters) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "::vector")); EXPECT_CALL(handler, OnScalar(_, "!", 0, ": - ()")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "Up, up, and away!")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "-123")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "http://example.com/foo#bar")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "::vector")); EXPECT_CALL(handler, OnScalar(_, "!", 0, ": - ()")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "Up, up, and away!")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "-123")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "http://example.com/foo#bar")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_10); } TEST_F(HandlerSpecTest, Ex7_11_PlainImplicitKeys) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "implicit block key")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "implicit flow key")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "value")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_11); } TEST_F(HandlerSpecTest, Ex7_12_PlainLines) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "1st non-empty\n2nd non-empty 3rd non-empty")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_12); } TEST_F(HandlerSpecTest, Ex7_13_FlowSequence) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "one")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "two")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "three")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "four")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_13); } TEST_F(HandlerSpecTest, Ex7_14_FlowSequenceEntries) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "double quoted")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "single quoted")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "plain text")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "nested")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "single")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "pair")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_14); } TEST_F(HandlerSpecTest, Ex7_15_FlowMappings) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "one")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "two")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "three")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "four")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "five")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "six")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "seven")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "eight")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_15); } TEST_F(HandlerSpecTest, Ex7_16_FlowMappingEntries) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "explicit")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "entry")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "implicit")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "entry")); EXPECT_CALL(handler, OnNull(_, 0)); EXPECT_CALL(handler, OnNull(_, 0)); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_16); } TEST_F(HandlerSpecTest, Ex7_17_FlowMappingSeparateValues) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "unquoted")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "separate")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "http://foo.com")); EXPECT_CALL(handler, OnNull(_, 0)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "omitted value")); EXPECT_CALL(handler, OnNull(_, 0)); EXPECT_CALL(handler, OnNull(_, 0)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "omitted key")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_17); } TEST_F(HandlerSpecTest, Ex7_18_FlowMappingAdjacentValues) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "adjacent")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "value")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "readable")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "value")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "empty")); EXPECT_CALL(handler, OnNull(_, 0)); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_18); } TEST_F(HandlerSpecTest, Ex7_19_SinglePairFlowMappings) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "foo")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_19); } TEST_F(HandlerSpecTest, Ex7_20_SinglePairExplicitEntry) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "foo bar")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "baz")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_20); } TEST_F(HandlerSpecTest, Ex7_21_SinglePairImplicitEntries) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "YAML")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "separate")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Default)); EXPECT_CALL(handler, OnNull(_, 0)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "empty key entry")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "JSON")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "like")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnScalar(_, "?", 0, "adjacent")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_21); } TEST_F(HandlerSpecTest, Ex7_22_InvalidImplicitKeys) { EXPECT_THROW_PARSER_EXCEPTION(IgnoreParse(ex7_22), ErrorMsg::END_OF_SEQ_FLOW); } TEST_F(HandlerSpecTest, Ex7_23_FlowContent) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "a")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "b")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Flow)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "a")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "b")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnScalar(_, "!", 0, "a")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "b")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "c")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_23); } TEST_F(HandlerSpecTest, Ex7_24_FlowNodes) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "tag:yaml.org,2002:str", 0, "a")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "b")); EXPECT_CALL(handler, OnScalar(_, "!", 1, "c")); EXPECT_CALL(handler, OnAlias(_, 1)); EXPECT_CALL(handler, OnScalar(_, "tag:yaml.org,2002:str", 0, "")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex7_24); } TEST_F(HandlerSpecTest, Ex8_1_BlockScalarHeader) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "literal\n")); EXPECT_CALL(handler, OnScalar(_, "!", 0, " folded\n")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "keep\n\n")); EXPECT_CALL(handler, OnScalar(_, "!", 0, " strip")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_1); } TEST_F(HandlerSpecTest, Ex8_2_BlockIndentationHeader) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "detected\n")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "\n\n# detected\n")); EXPECT_CALL(handler, OnScalar(_, "!", 0, " explicit\n")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "\t\ndetected\n")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_2); } TEST_F(HandlerSpecTest, Ex8_3a_InvalidBlockScalarIndentationIndicators) { EXPECT_THROW_PARSER_EXCEPTION(IgnoreParse(ex8_3a), ErrorMsg::END_OF_SEQ); } TEST_F(HandlerSpecTest, Ex8_3b_InvalidBlockScalarIndentationIndicators) { EXPECT_THROW_PARSER_EXCEPTION(IgnoreParse(ex8_3b), ErrorMsg::END_OF_SEQ); } TEST_F(HandlerSpecTest, Ex8_3c_InvalidBlockScalarIndentationIndicators) { EXPECT_THROW_PARSER_EXCEPTION(IgnoreParse(ex8_3c), ErrorMsg::END_OF_SEQ); } TEST_F(HandlerSpecTest, Ex8_4_ChompingFinalLineBreak) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "strip")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "text")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "clip")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "text\n")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "keep")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "text\n")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_4); } TEST_F(HandlerSpecTest, DISABLED_Ex8_5_ChompingTrailingLines) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "strip")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "# text")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "clip")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "# text\n")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "keep")); // NOTE: I believe this is a bug in the YAML spec - // it should be "# text\n\n" EXPECT_CALL(handler, OnScalar(_, "!", 0, "# text\n")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_5); } TEST_F(HandlerSpecTest, Ex8_6_EmptyScalarChomping) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "strip")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "clip")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "keep")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "\n")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_6); } TEST_F(HandlerSpecTest, Ex8_7_LiteralScalar) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "literal\n\ttext\n")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_7); } TEST_F(HandlerSpecTest, Ex8_8_LiteralContent) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "\n\nliteral\n \n\ntext\n")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_8); } TEST_F(HandlerSpecTest, Ex8_9_FoldedScalar) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "folded text\n")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_9); } TEST_F(HandlerSpecTest, Ex8_10_FoldedLines) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "\nfolded line\nnext line\n * bullet\n\n * list\n * lines\n\nlast line\n")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_10); } TEST_F(HandlerSpecTest, Ex8_11_MoreIndentedLines) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "\nfolded line\nnext line\n * bullet\n\n * list\n * lines\n\nlast line\n")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_11); } TEST_F(HandlerSpecTest, Ex8_12_EmptySeparationLines) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "\nfolded line\nnext line\n * bullet\n\n * list\n * lines\n\nlast line\n")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_12); } TEST_F(HandlerSpecTest, Ex8_13_FinalEmptyLines) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "\nfolded line\nnext line\n * bullet\n\n * list\n * lines\n\nlast line\n")); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_13); } TEST_F(HandlerSpecTest, Ex8_14_BlockSequence) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "block sequence")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "one")); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "two")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "three")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_14); } TEST_F(HandlerSpecTest, Ex8_15_BlockSequenceEntryTypes) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnNull(_, 0)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "block node\n")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "one")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "two")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "one")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "two")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_15); } TEST_F(HandlerSpecTest, Ex8_16_BlockMappings) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "block mapping")); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "key")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "value")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_16); } TEST_F(HandlerSpecTest, Ex8_17_ExplicitBlockMappingEntries) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "explicit key")); EXPECT_CALL(handler, OnNull(_, 0)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "block key\n")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "one")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "two")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_17); } TEST_F(HandlerSpecTest, Ex8_18_ImplicitBlockMappingEntries) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "plain key")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "in-line value")); EXPECT_CALL(handler, OnNull(_, 0)); EXPECT_CALL(handler, OnNull(_, 0)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "quoted key")); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "entry")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_18); } TEST_F(HandlerSpecTest, Ex8_19_CompactBlockMappings) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "sun")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "yellow")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "earth")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "blue")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "moon")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "white")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_19); } TEST_F(HandlerSpecTest, Ex8_20_BlockNodeTypes) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnSequenceStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "!", 0, "flow in block")); EXPECT_CALL(handler, OnScalar(_, "!", 0, "Block scalar\n")); EXPECT_CALL(handler, OnMapStart(_, "tag:yaml.org,2002:map", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "foo")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_20); } TEST_F(HandlerSpecTest, DISABLED_Ex8_21_BlockScalarNodes) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "literal")); // NOTE: I believe this is a bug in the YAML spec // - it should be "value\n" EXPECT_CALL(handler, OnScalar(_, "!", 0, "value")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "folded")); EXPECT_CALL(handler, OnScalar(_, "!foo", 0, "value")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_21); } TEST_F(HandlerSpecTest, Ex8_22_BlockCollectionNodes) { EXPECT_CALL(handler, OnDocumentStart(_)); EXPECT_CALL(handler, OnMapStart(_, "?", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "sequence")); EXPECT_CALL(handler, OnSequenceStart(_, "tag:yaml.org,2002:seq", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "entry")); EXPECT_CALL(handler, OnSequenceStart(_, "tag:yaml.org,2002:seq", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "nested")); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnSequenceEnd()); EXPECT_CALL(handler, OnScalar(_, "?", 0, "mapping")); EXPECT_CALL(handler, OnMapStart(_, "tag:yaml.org,2002:map", 0, EmitterStyle::Block)); EXPECT_CALL(handler, OnScalar(_, "?", 0, "foo")); EXPECT_CALL(handler, OnScalar(_, "?", 0, "bar")); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnMapEnd()); EXPECT_CALL(handler, OnDocumentEnd()); Parse(ex8_22); } } } yaml-rust-0.4.3/tests/specs/libyaml_fail-01.yaml010064400007670000024000000001141254427023000176740ustar0000000000000000# Ex 8.18 plain key: in-line value : # Both empty "quoted key": - entry yaml-rust-0.4.3/tests/specs/libyaml_fail-02.yaml010064400007670000024000000001231254427023000176750ustar0000000000000000# Ex 7.17 { unqoted : "separate", http://foo.com, omitted value:, : omitted key, } yaml-rust-0.4.3/tests/specs/libyaml_fail-03.yaml010064400007670000024000000000671254427023000177050ustar0000000000000000# ex 7.2 { foo : !!str, !!str : bar, } yaml-rust-0.4.3/tests/test_round_trip.rs010064400007670000024000000010611344013434500166270ustar0000000000000000extern crate yaml_rust; use yaml_rust::{Yaml, YamlEmitter, YamlLoader}; fn test_round_trip(original: &Yaml) { let mut out = String::new(); YamlEmitter::new(&mut out).dump(original).unwrap(); let documents = YamlLoader::load_from_str(&out).unwrap(); assert_eq!(documents.len(), 1); assert_eq!(documents[0], *original); } #[test] fn test_escape_character() { let y = Yaml::String("\x1b".to_owned()); test_round_trip(&y); } #[test] fn test_colon_in_string() { let y = Yaml::String("x: %".to_owned()); test_round_trip(&y); } yaml-rust-0.4.3/.cargo_vcs_info.json0000644000000001120000000000000130260ustar00{ "git": { "sha1": "1d29d211e9214f2fe0efaf9379efd998fafdb2de" } }