Bug 1336540 part 2 - Vendor toml. r=froydnj

MozReview-Commit-ID: LmZgzyxTLwc

--HG--
extra : rebase_source : 54498689cdcf28c58b6ee1922e057ffc8a50da45
This commit is contained in:
Xidorn Quan 2017-05-18 18:17:19 +10:00
Родитель 029693f013
Коммит 013d14243b
151 изменённых файлов: 6888 добавлений и 0 удалений

1
third_party/rust/toml/.cargo-checksum.json поставляемый Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

0
third_party/rust/toml/.cargo-ok поставляемый Normal file
Просмотреть файл

2
third_party/rust/toml/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,2 @@
target
Cargo.lock

31
third_party/rust/toml/.travis.yml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,31 @@
language: rust
rust:
- stable
- beta
- nightly
sudo: false
before_script:
- pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
script:
- cargo build --verbose
- cargo build --verbose --no-default-features
- cargo build --verbose --features serde --no-default-features
- cargo test --verbose --features serde
- cargo test --verbose --manifest-path serde-tests/Cargo.toml
- rustdoc --test README.md -L target
- cargo doc --no-deps
after_success:
- travis-cargo --only nightly doc-upload
- travis-cargo coveralls --no-sudo
env:
global:
secure: LZMkQQJT5LqLQQ8JyakjvHNqqMPy8lm/SyC+H5cKUVI/xk7xRuti4eKY937N8uSmbff2m9ZYlG6cNwIOfk/nWn8YsqxA8Wg/xugubWzqGuqu+NQ4IZVa7INT2Fiqyk5SPCh8B5fo2x7OBJ24SCkWb2p8bEWAuW8XdZZOdmi3H2I=
notifications:
email:
on_success: never
addons:
apt:
packages:
- libcurl4-openssl-dev
- libelf-dev
- libdw-dev

26
third_party/rust/toml/Cargo.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,26 @@
[package]
name = "toml"
version = "0.2.1"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
license = "MIT/Apache-2.0"
readme = "README.md"
keywords = ["encoding"]
repository = "https://github.com/alexcrichton/toml-rs"
homepage = "https://github.com/alexcrichton/toml-rs"
documentation = "http://alexcrichton.com/toml-rs"
description = """
A native Rust encoder and decoder of TOML-formatted files and streams. Provides
implementations of the standard Encodable/Decodable traits for TOML data to
facilitate deserializing and serializing Rust structures.
"""
[dependencies]
rustc-serialize = { optional = true, version = "0.3.0" }
serde = { optional = true, version = "0.8" }
[features]
default = ["rustc-serialize"]
[dev-dependencies]
rustc-serialize = "0.3"

201
third_party/rust/toml/LICENSE-APACHE поставляемый Normal file
Просмотреть файл

@ -0,0 +1,201 @@
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.

25
third_party/rust/toml/LICENSE-MIT поставляемый Normal file
Просмотреть файл

@ -0,0 +1,25 @@
Copyright (c) 2014 Alex Crichton
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.

26
third_party/rust/toml/README.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,26 @@
# toml-rs
[![Build Status](https://travis-ci.org/alexcrichton/toml-rs.svg?branch=master)](https://travis-ci.org/alexcrichton/toml-rs)
[![Coverage Status](https://coveralls.io/repos/alexcrichton/toml-rs/badge.svg?branch=master&service=github)](https://coveralls.io/github/alexcrichton/toml-rs?branch=master)
[Documentation](http://alexcrichton.com/toml-rs)
A [TOML][toml] decoder and encoder for Rust. This library is currently compliant with
the v0.4.0 version of TOML. This library will also likely continue to stay up to
date with the TOML specification as changes happen.
[toml]: https://github.com/toml-lang/toml
```toml
# Cargo.toml
[dependencies]
toml = "0.2"
```
# License
`toml-rs` is primarily distributed under the terms of both the MIT license and
the Apache License (Version 2.0), with portions covered by various BSD-like
licenses.
See LICENSE-APACHE, and LICENSE-MIT for details.

57
third_party/rust/toml/examples/toml2json.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,57 @@
#![deny(warnings)]
extern crate toml;
extern crate rustc_serialize;
use std::fs::File;
use std::env;
use std::io;
use std::io::prelude::*;
use toml::Value;
use rustc_serialize::json::Json;
fn main() {
let mut args = env::args();
let mut input = String::new();
let filename = if args.len() > 1 {
let name = args.nth(1).unwrap();
File::open(&name).and_then(|mut f| {
f.read_to_string(&mut input)
}).unwrap();
name
} else {
io::stdin().read_to_string(&mut input).unwrap();
"<stdin>".to_string()
};
let mut parser = toml::Parser::new(&input);
let toml = match parser.parse() {
Some(toml) => toml,
None => {
for err in &parser.errors {
let (loline, locol) = parser.to_linecol(err.lo);
let (hiline, hicol) = parser.to_linecol(err.hi);
println!("{}:{}:{}-{}:{} error: {}",
filename, loline, locol, hiline, hicol, err.desc);
}
return
}
};
let json = convert(Value::Table(toml));
println!("{}", json.pretty());
}
fn convert(toml: Value) -> Json {
match toml {
Value::String(s) => Json::String(s),
Value::Integer(i) => Json::I64(i),
Value::Float(f) => Json::F64(f),
Value::Boolean(b) => Json::Boolean(b),
Value::Array(arr) => Json::Array(arr.into_iter().map(convert).collect()),
Value::Table(table) => Json::Object(table.into_iter().map(|(k, v)| {
(k, convert(v))
}).collect()),
Value::Datetime(dt) => Json::String(dt),
}
}

240
third_party/rust/toml/src/decoder/mod.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,240 @@
use std::error;
use std::fmt;
use std::collections::{btree_map, BTreeMap};
use std::iter::Peekable;
use Value;
use self::DecodeErrorKind::*;
#[cfg(feature = "rustc-serialize")] mod rustc_serialize;
#[cfg(feature = "serde")] mod serde;
/// A structure to transform TOML values into Rust values.
///
/// This decoder implements the serialization `Decoder` interface, allowing
/// `Decodable` types to be generated by this decoder. The input is any
/// arbitrary TOML value.
pub struct Decoder {
/// The TOML value left over after decoding. This can be used to inspect
/// whether fields were decoded or not.
pub toml: Option<Value>,
cur_field: Option<String>,
// These aren't used if serde is in use
#[cfg_attr(feature = "serde", allow(dead_code))]
cur_map: Peekable<btree_map::IntoIter<String, Value>>,
#[cfg_attr(feature = "serde", allow(dead_code))]
leftover_map: ::Table,
}
/// Description for errors which can occur while decoding a type.
#[derive(PartialEq, Debug)]
pub struct DecodeError {
/// Field that this error applies to.
pub field: Option<String>,
/// The type of error which occurred while decoding,
pub kind: DecodeErrorKind,
}
/// Enumeration of possible errors which can occur while decoding a structure.
#[derive(PartialEq, Debug)]
pub enum DecodeErrorKind {
/// An error flagged by the application, e.g. value out of range
ApplicationError(String),
/// A field was expected, but none was found.
ExpectedField(/* type */ Option<&'static str>),
/// A field was found, but it was not an expected one.
UnknownField,
/// A field was found, but it had the wrong type.
ExpectedType(/* expected */ &'static str, /* found */ &'static str),
/// The nth map key was expected, but none was found.
ExpectedMapKey(usize),
/// The nth map element was expected, but none was found.
ExpectedMapElement(usize),
/// An enum decoding was requested, but no variants were supplied
NoEnumVariants,
/// The unit type was being decoded, but a non-zero length string was found
NilTooLong,
/// There was an error with the syntactical structure of the TOML.
SyntaxError,
/// A custom error was generated when decoding.
CustomError(String),
/// The end of the TOML input was reached too soon
EndOfStream,
/// Produced by serde ...
InvalidType(&'static str),
}
/// Decodes a TOML value into a decodable type.
///
/// This function will consume the given TOML value and attempt to decode it
/// into the type specified. If decoding fails, `None` will be returned. If a
/// finer-grained error is desired, then it is recommended to use `Decodable`
/// directly.
#[cfg(feature = "rustc-serialize")]
pub fn decode<T: ::rustc_serialize::Decodable>(toml: Value) -> Option<T> {
::rustc_serialize::Decodable::decode(&mut Decoder::new(toml)).ok()
}
/// Decodes a TOML value into a decodable type.
///
/// This function will consume the given TOML value and attempt to decode it
/// into the type specified. If decoding fails, `None` will be returned. If a
/// finer-grained error is desired, then it is recommended to use `Decodable`
/// directly.
#[cfg(all(not(feature = "rustc-serialize"), feature = "serde"))]
pub fn decode<T: ::serde::Deserialize>(toml: Value) -> Option<T> {
::serde::Deserialize::deserialize(&mut Decoder::new(toml)).ok()
}
/// Decodes a string into a toml-encoded value.
///
/// This function will parse the given string into a TOML value, and then parse
/// the TOML value into the desired type. If any error occurs, `None` is
/// returned.
///
/// If more fine-grained errors are desired, these steps should be driven
/// manually.
#[cfg(feature = "rustc-serialize")]
pub fn decode_str<T: ::rustc_serialize::Decodable>(s: &str) -> Option<T> {
::Parser::new(s).parse().and_then(|t| decode(Value::Table(t)))
}
/// Decodes a string into a toml-encoded value.
///
/// This function will parse the given string into a TOML value, and then parse
/// the TOML value into the desired type. If any error occurs, `None` is
/// returned.
///
/// If more fine-grained errors are desired, these steps should be driven
/// manually.
#[cfg(all(not(feature = "rustc-serialize"), feature = "serde"))]
pub fn decode_str<T: ::serde::Deserialize>(s: &str) -> Option<T> {
::Parser::new(s).parse().and_then(|t| decode(Value::Table(t)))
}
impl Decoder {
/// Creates a new decoder, consuming the TOML value to decode.
///
/// This decoder can be passed to the `Decodable` methods or driven
/// manually.
pub fn new(toml: Value) -> Decoder {
Decoder::new_empty(Some(toml), None)
}
fn sub_decoder(&self, toml: Option<Value>, field: &str) -> Decoder {
let cur_field = if field.is_empty() {
self.cur_field.clone()
} else {
match self.cur_field {
None => Some(field.to_string()),
Some(ref s) => Some(format!("{}.{}", s, field))
}
};
Decoder::new_empty(toml, cur_field)
}
fn new_empty(toml: Option<Value>, cur_field: Option<String>) -> Decoder {
Decoder {
toml: toml,
cur_field: cur_field,
leftover_map: BTreeMap::new(),
cur_map: BTreeMap::new().into_iter().peekable(),
}
}
fn err(&self, kind: DecodeErrorKind) -> DecodeError {
DecodeError {
field: self.cur_field.clone(),
kind: kind,
}
}
fn mismatch(&self, expected: &'static str,
found: &Option<Value>) -> DecodeError{
match *found {
Some(ref val) => self.err(ExpectedType(expected, val.type_str())),
None => self.err(ExpectedField(Some(expected))),
}
}
}
impl fmt::Display for DecodeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(match self.kind {
ApplicationError(ref err) => {
write!(f, "{}", err)
}
ExpectedField(expected_type) => {
match expected_type {
Some("table") => write!(f, "expected a section"),
Some(e) => write!(f, "expected a value of type `{}`", e),
None => write!(f, "expected a value"),
}
}
UnknownField => write!(f, "unknown field"),
ExpectedType(expected, found) => {
fn humanize(s: &str) -> String {
if s == "section" {
"a section".to_string()
} else {
format!("a value of type `{}`", s)
}
}
write!(f, "expected {}, but found {}",
humanize(expected),
humanize(found))
}
ExpectedMapKey(idx) => {
write!(f, "expected at least {} keys", idx + 1)
}
ExpectedMapElement(idx) => {
write!(f, "expected at least {} elements", idx + 1)
}
NoEnumVariants => {
write!(f, "expected an enum variant to decode to")
}
NilTooLong => {
write!(f, "expected 0-length string")
}
SyntaxError => {
write!(f, "syntax error")
}
EndOfStream => {
write!(f, "end of stream")
}
InvalidType(s) => {
write!(f, "invalid type: {}", s)
}
CustomError(ref s) => {
write!(f, "custom error: {}", s)
}
});
match self.field {
Some(ref s) => {
write!(f, " for the key `{}`", s)
}
None => Ok(())
}
}
}
impl error::Error for DecodeError {
fn description(&self) -> &str {
match self.kind {
ApplicationError(ref s) => &**s,
ExpectedField(..) => "expected a field",
UnknownField => "found an unknown field",
ExpectedType(..) => "expected a type",
ExpectedMapKey(..) => "expected a map key",
ExpectedMapElement(..) => "expected a map element",
NoEnumVariants => "no enum variants to decode to",
NilTooLong => "nonzero length string representing nil",
SyntaxError => "syntax error",
EndOfStream => "end of stream",
InvalidType(..) => "invalid type",
CustomError(..) => "custom error",
}
}
}

371
third_party/rust/toml/src/decoder/rustc_serialize.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,371 @@
use rustc_serialize;
use std::mem;
use std::collections::BTreeMap;
use super::{Decoder, DecodeError};
use super::DecodeErrorKind::*;
use Value;
impl rustc_serialize::Decoder for Decoder {
type Error = DecodeError;
fn read_nil(&mut self) -> Result<(), DecodeError> {
match self.toml {
Some(Value::String(ref s)) if s.is_empty() => {}
Some(Value::String(..)) => return Err(self.err(NilTooLong)),
ref found => return Err(self.mismatch("string", found)),
}
self.toml.take();
Ok(())
}
fn read_usize(&mut self) -> Result<usize, DecodeError> {
self.read_i64().map(|i| i as usize)
}
fn read_u64(&mut self) -> Result<u64, DecodeError> {
self.read_i64().map(|i| i as u64)
}
fn read_u32(&mut self) -> Result<u32, DecodeError> {
self.read_i64().map(|i| i as u32)
}
fn read_u16(&mut self) -> Result<u16, DecodeError> {
self.read_i64().map(|i| i as u16)
}
fn read_u8(&mut self) -> Result<u8, DecodeError> {
self.read_i64().map(|i| i as u8)
}
fn read_isize(&mut self) -> Result<isize, DecodeError> {
self.read_i64().map(|i| i as isize)
}
fn read_i64(&mut self) -> Result<i64, DecodeError> {
match self.toml {
Some(Value::Integer(i)) => { self.toml.take(); Ok(i) }
ref found => Err(self.mismatch("integer", found)),
}
}
fn read_i32(&mut self) -> Result<i32, DecodeError> {
self.read_i64().map(|i| i as i32)
}
fn read_i16(&mut self) -> Result<i16, DecodeError> {
self.read_i64().map(|i| i as i16)
}
fn read_i8(&mut self) -> Result<i8, DecodeError> {
self.read_i64().map(|i| i as i8)
}
fn read_bool(&mut self) -> Result<bool, DecodeError> {
match self.toml {
Some(Value::Boolean(b)) => { self.toml.take(); Ok(b) }
ref found => Err(self.mismatch("bool", found)),
}
}
fn read_f64(&mut self) -> Result<f64, DecodeError> {
match self.toml {
Some(Value::Float(f)) => { self.toml.take(); Ok(f) },
ref found => Err(self.mismatch("float", found)),
}
}
fn read_f32(&mut self) -> Result<f32, DecodeError> {
self.read_f64().map(|f| f as f32)
}
fn read_char(&mut self) -> Result<char, DecodeError> {
let ch = match self.toml {
Some(Value::String(ref s)) if s.chars().count() == 1 =>
s.chars().next().unwrap(),
ref found => return Err(self.mismatch("string", found)),
};
self.toml.take();
Ok(ch)
}
fn read_str(&mut self) -> Result<String, DecodeError> {
match self.toml.take() {
Some(Value::String(s)) => Ok(s),
found => {
let err = Err(self.mismatch("string", &found));
self.toml = found;
err
}
}
}
// Compound types:
fn read_enum<T, F>(&mut self, _name: &str, f: F)
-> Result<T, DecodeError>
where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
{
f(self)
}
fn read_enum_variant<T, F>(&mut self, names: &[&str], mut f: F)
-> Result<T, DecodeError>
where F: FnMut(&mut Decoder, usize) -> Result<T, DecodeError>
{
// When decoding enums, this crate takes the strategy of trying to
// decode the current TOML as all of the possible variants, returning
// success on the first one that succeeds.
//
// Note that fidelity of the errors returned here is a little nebulous,
// but we try to return the error that had the relevant field as the
// longest field. This way we hopefully match an error against what was
// most likely being written down without losing too much info.
let mut first_error = None::<DecodeError>;
for i in 0..names.len() {
let mut d = self.sub_decoder(self.toml.clone(), "");
match f(&mut d, i) {
Ok(t) => {
self.toml = d.toml;
return Ok(t)
}
Err(e) => {
if let Some(ref first) = first_error {
let my_len = e.field.as_ref().map(|s| s.len());
let first_len = first.field.as_ref().map(|s| s.len());
if my_len <= first_len {
continue
}
}
first_error = Some(e);
}
}
}
Err(first_error.unwrap_or_else(|| self.err(NoEnumVariants)))
}
fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, f: F)
-> Result<T, DecodeError>
where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
{
f(self)
}
fn read_enum_struct_variant<T, F>(&mut self, _names: &[&str], _f: F)
-> Result<T, DecodeError>
where F: FnMut(&mut Decoder, usize) -> Result<T, DecodeError>
{
panic!()
}
fn read_enum_struct_variant_field<T, F>(&mut self,
_f_name: &str,
_f_idx: usize,
_f: F)
-> Result<T, DecodeError>
where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
{
panic!()
}
fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, f: F)
-> Result<T, DecodeError>
where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
{
match self.toml {
Some(Value::Table(..)) => {
let ret = try!(f(self));
match self.toml {
Some(Value::Table(ref t)) if t.is_empty() => {}
_ => return Ok(ret)
}
self.toml.take();
Ok(ret)
}
ref found => Err(self.mismatch("table", found)),
}
}
fn read_struct_field<T, F>(&mut self, f_name: &str, _f_idx: usize, f: F)
-> Result<T, DecodeError>
where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
{
let field = f_name.to_string();
let toml = match self.toml {
Some(Value::Table(ref mut table)) => {
table.remove(&field)
.or_else(|| table.remove(&f_name.replace("_", "-")))
},
ref found => return Err(self.mismatch("table", found)),
};
let mut d = self.sub_decoder(toml, f_name);
let ret = try!(f(&mut d));
if let Some(value) = d.toml {
if let Some(Value::Table(ref mut table)) = self.toml {
table.insert(field, value);
}
}
Ok(ret)
}
fn read_tuple<T, F>(&mut self, tuple_len: usize, f: F)
-> Result<T, DecodeError>
where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
{
self.read_seq(move |d, len| {
assert!(len == tuple_len,
"expected tuple of length `{}`, found tuple \
of length `{}`", tuple_len, len);
f(d)
})
}
fn read_tuple_arg<T, F>(&mut self, a_idx: usize, f: F)
-> Result<T, DecodeError>
where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
{
self.read_seq_elt(a_idx, f)
}
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F)
-> Result<T, DecodeError>
where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
{
panic!()
}
fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F)
-> Result<T, DecodeError>
where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
{
panic!()
}
// Specialized types:
fn read_option<T, F>(&mut self, mut f: F)
-> Result<T, DecodeError>
where F: FnMut(&mut Decoder, bool) -> Result<T, DecodeError>
{
match self.toml {
Some(..) => f(self, true),
None => f(self, false),
}
}
fn read_seq<T, F>(&mut self, f: F) -> Result<T, DecodeError>
where F: FnOnce(&mut Decoder, usize) -> Result<T, DecodeError>
{
let len = match self.toml {
Some(Value::Array(ref arr)) => arr.len(),
None => 0,
ref found => return Err(self.mismatch("array", found)),
};
let ret = try!(f(self, len));
match self.toml {
Some(Value::Array(ref mut arr)) => {
arr.retain(|slot| slot.as_integer() != Some(0));
if !arr.is_empty() { return Ok(ret) }
}
_ => return Ok(ret)
}
self.toml.take();
Ok(ret)
}
fn read_seq_elt<T, F>(&mut self, idx: usize, f: F)
-> Result<T, DecodeError>
where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
{
let toml = match self.toml {
Some(Value::Array(ref mut arr)) => {
mem::replace(&mut arr[idx], Value::Integer(0))
}
ref found => return Err(self.mismatch("array", found)),
};
let mut d = self.sub_decoder(Some(toml), "");
let ret = try!(f(&mut d));
if let Some(toml) = d.toml {
if let Some(Value::Array(ref mut arr)) = self.toml {
arr[idx] = toml;
}
}
Ok(ret)
}
fn read_map<T, F>(&mut self, f: F)
-> Result<T, DecodeError>
where F: FnOnce(&mut Decoder, usize) -> Result<T, DecodeError>
{
let map = match self.toml.take() {
Some(Value::Table(table)) => table,
found => {
self.toml = found;
return Err(self.mismatch("table", &self.toml))
}
};
let amt = map.len();
let prev_iter = mem::replace(&mut self.cur_map,
map.into_iter().peekable());
let prev_map = mem::replace(&mut self.leftover_map, BTreeMap::new());
let ret = try!(f(self, amt));
let leftover = mem::replace(&mut self.leftover_map, prev_map);
self.cur_map = prev_iter;
if !leftover.is_empty() {
self.toml = Some(Value::Table(leftover));
}
Ok(ret)
}
fn read_map_elt_key<T, F>(&mut self, idx: usize, f: F)
-> Result<T, DecodeError>
where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
{
let key = match self.cur_map.peek().map(|p| p.0.clone()) {
Some(k) => k,
None => return Err(self.err(ExpectedMapKey(idx))),
};
let val = Value::String(key.clone());
f(&mut self.sub_decoder(Some(val), &key))
}
fn read_map_elt_val<T, F>(&mut self, idx: usize, f: F)
-> Result<T, DecodeError>
where F: FnOnce(&mut Decoder) -> Result<T, DecodeError>
{
match self.cur_map.next() {
Some((key, value)) => {
let mut d = self.sub_decoder(Some(value), &key);
let ret = f(&mut d);
if let Some(toml) = d.toml.take() {
self.leftover_map.insert(key, toml);
}
ret
}
None => Err(self.err(ExpectedMapElement(idx))),
}
}
fn error(&mut self, err: &str) -> DecodeError {
DecodeError {
field: self.cur_field.clone(),
kind: ApplicationError(err.to_string())
}
}
}
#[cfg(test)]
mod tests {
use rustc_serialize::Decodable;
use std::collections::HashMap;
use {Parser, Decoder, Value};
#[test]
fn bad_enum_chooses_longest_error() {
#[derive(RustcDecodable)]
#[allow(dead_code)]
struct Foo {
wut: HashMap<String, Bar>,
}
#[derive(RustcDecodable)]
enum Bar {
Simple(String),
Detailed(Baz),
}
#[derive(RustcDecodable, Debug)]
struct Baz {
features: Vec<String>,
}
let s = r#"
[wut]
a = { features = "" }
"#;
let v = Parser::new(s).parse().unwrap();
let mut d = Decoder::new(Value::Table(v));
let err = match Foo::decode(&mut d) {
Ok(_) => panic!("expected error"),
Err(e) => e,
};
assert_eq!(err.field.as_ref().unwrap(), "wut.a.features");
}
}

773
third_party/rust/toml/src/decoder/serde.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,773 @@
use serde::de;
use Value;
use super::{Decoder, DecodeError, DecodeErrorKind};
use std::collections::BTreeMap;
macro_rules! forward_to_deserialize {
($(
$name:ident ( $( $arg:ident : $ty:ty ),* );
)*) => {
$(
forward_to_deserialize!{
func: $name ( $( $arg: $ty ),* );
}
)*
};
(func: deserialize_enum ( $( $arg:ident : $ty:ty ),* );) => {
fn deserialize_enum<V>(
&mut self,
$(_: $ty,)*
_visitor: V,
) -> ::std::result::Result<V::Value, Self::Error>
where V: ::serde::de::EnumVisitor
{
Err(::serde::de::Error::invalid_type(::serde::de::Type::Enum))
}
};
(func: $name:ident ( $( $arg:ident : $ty:ty ),* );) => {
#[inline]
fn $name<V>(
&mut self,
$(_: $ty,)*
visitor: V,
) -> ::std::result::Result<V::Value, Self::Error>
where V: ::serde::de::Visitor
{
self.deserialize(visitor)
}
};
}
impl de::Deserializer for Decoder {
type Error = DecodeError;
fn deserialize<V>(&mut self, mut visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor
{
match self.toml.take() {
Some(Value::String(s)) => visitor.visit_string(s),
Some(Value::Integer(i)) => visitor.visit_i64(i),
Some(Value::Float(f)) => visitor.visit_f64(f),
Some(Value::Boolean(b)) => visitor.visit_bool(b),
Some(Value::Datetime(s)) => visitor.visit_string(s),
Some(Value::Array(a)) => {
let len = a.len();
let iter = a.into_iter();
visitor.visit_seq(SeqDeserializer::new(iter, len, &mut self.toml))
}
Some(Value::Table(t)) => {
visitor.visit_map(MapVisitor {
iter: t.into_iter(),
de: self,
key: None,
value: None,
})
}
None => Err(self.err(DecodeErrorKind::EndOfStream)),
}
}
fn deserialize_bool<V>(&mut self, mut visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor
{
match self.toml.take() {
Some(Value::Boolean(b)) => visitor.visit_bool(b),
ref found => Err(self.mismatch("bool", found)),
}
}
fn deserialize_i8<V>(&mut self, visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor
{
self.deserialize_i64(visitor)
}
fn deserialize_i16<V>(&mut self, visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor
{
self.deserialize_i64(visitor)
}
fn deserialize_i32<V>(&mut self, visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor
{
self.deserialize_i64(visitor)
}
fn deserialize_i64<V>(&mut self, mut visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor
{
match self.toml.take() {
Some(Value::Integer(f)) => visitor.visit_i64(f),
ref found => Err(self.mismatch("integer", found)),
}
}
fn deserialize_isize<V>(&mut self, visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor
{
self.deserialize_i64(visitor)
}
fn deserialize_u8<V>(&mut self, visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor
{
self.deserialize_i64(visitor)
}
fn deserialize_u16<V>(&mut self, visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor
{
self.deserialize_i64(visitor)
}
fn deserialize_u32<V>(&mut self, visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor
{
self.deserialize_i64(visitor)
}
fn deserialize_u64<V>(&mut self, visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor
{
self.deserialize_i64(visitor)
}
fn deserialize_usize<V>(&mut self, visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor
{
self.deserialize_i64(visitor)
}
fn deserialize_f32<V>(&mut self, visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor
{
self.deserialize_f64(visitor)
}
fn deserialize_f64<V>(&mut self, mut visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor
{
match self.toml.take() {
Some(Value::Float(f)) => visitor.visit_f64(f),
ref found => Err(self.mismatch("float", found)),
}
}
fn deserialize_str<V>(&mut self, mut visitor: V)
-> Result<V::Value, Self::Error>
where V: de::Visitor,
{
match self.toml.take() {
Some(Value::String(s)) => visitor.visit_string(s),
ref found => Err(self.mismatch("string", found)),
}
}
fn deserialize_string<V>(&mut self, visitor: V)
-> Result<V::Value, Self::Error>
where V: de::Visitor,
{
self.deserialize_str(visitor)
}
fn deserialize_char<V>(&mut self, mut visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor
{
match self.toml.take() {
Some(Value::String(ref s)) if s.chars().count() == 1 => {
visitor.visit_char(s.chars().next().unwrap())
}
ref found => return Err(self.mismatch("string", found)),
}
}
fn deserialize_option<V>(&mut self, mut visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor
{
if self.toml.is_none() {
visitor.visit_none()
} else {
visitor.visit_some(self)
}
}
fn deserialize_seq<V>(&mut self, mut visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor,
{
if self.toml.is_none() {
let iter = None::<i32>.into_iter();
visitor.visit_seq(de::value::SeqDeserializer::new(iter, 0))
} else {
self.deserialize(visitor)
}
}
fn deserialize_map<V>(&mut self, mut visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor,
{
match self.toml.take() {
Some(Value::Table(t)) => {
visitor.visit_map(MapVisitor {
iter: t.into_iter(),
de: self,
key: None,
value: None,
})
}
ref found => Err(self.mismatch("table", found)),
}
}
fn deserialize_enum<V>(&mut self,
_enum: &str,
variants: &[&str],
mut visitor: V) -> Result<V::Value, DecodeError>
where V: de::EnumVisitor,
{
// When decoding enums, this crate takes the strategy of trying to
// decode the current TOML as all of the possible variants, returning
// success on the first one that succeeds.
//
// Note that fidelity of the errors returned here is a little nebulous,
// but we try to return the error that had the relevant field as the
// longest field. This way we hopefully match an error against what was
// most likely being written down without losing too much info.
let mut first_error = None::<DecodeError>;
for variant in 0..variants.len() {
let mut de = VariantVisitor {
de: self.sub_decoder(self.toml.clone(), ""),
variant: variant,
};
match visitor.visit(&mut de) {
Ok(value) => {
self.toml = de.de.toml;
return Ok(value);
}
Err(e) => {
if let Some(ref first) = first_error {
let my_len = e.field.as_ref().map(|s| s.len());
let first_len = first.field.as_ref().map(|s| s.len());
if my_len <= first_len {
continue
}
}
first_error = Some(e);
}
}
}
Err(first_error.unwrap_or_else(|| self.err(DecodeErrorKind::NoEnumVariants)))
}
// When #[derive(Deserialize)] encounters an unknown struct field it will
// call this method (somehow), and we want to preserve all unknown struct
// fields to return them upwards (to warn about unused keys), so we override
// that here to not tamper with our own internal state.
fn deserialize_ignored_any<V>(&mut self, visitor: V)
-> Result<V::Value, Self::Error>
where V: de::Visitor
{
use serde::de::value::ValueDeserializer;
let mut d = <() as ValueDeserializer<Self::Error>>::into_deserializer(());
d.deserialize(visitor)
}
fn deserialize_bytes<V>(&mut self, visitor: V)
-> Result<V::Value, Self::Error>
where V: de::Visitor
{
self.deserialize_seq(visitor)
}
fn deserialize_seq_fixed_size<V>(&mut self, _len: usize, visitor: V)
-> Result<V::Value, Self::Error>
where V: de::Visitor
{
self.deserialize_seq(visitor)
}
fn deserialize_newtype_struct<V>(&mut self, _name: &'static str, visitor: V)
-> Result<V::Value, Self::Error>
where V: de::Visitor
{
self.deserialize_seq(visitor)
}
fn deserialize_tuple_struct<V>(&mut self,
_name: &'static str,
_len: usize,
visitor: V)
-> Result<V::Value, Self::Error>
where V: de::Visitor
{
self.deserialize_seq(visitor)
}
fn deserialize_struct<V>(&mut self,
_name: &'static str,
_fields: &'static [&'static str],
visitor: V)
-> Result<V::Value, Self::Error>
where V: de::Visitor
{
self.deserialize_map(visitor)
}
fn deserialize_tuple<V>(&mut self,
_len: usize,
visitor: V)
-> Result<V::Value, Self::Error>
where V: de::Visitor
{
self.deserialize_seq(visitor)
}
forward_to_deserialize!{
deserialize_unit();
deserialize_unit_struct(name: &'static str);
deserialize_struct_field();
}
}
struct VariantVisitor {
de: Decoder,
variant: usize,
}
impl de::VariantVisitor for VariantVisitor {
type Error = DecodeError;
fn visit_variant<V>(&mut self) -> Result<V, DecodeError>
where V: de::Deserialize
{
use serde::de::value::ValueDeserializer;
let mut de = self.variant.into_deserializer();
de::Deserialize::deserialize(&mut de)
}
fn visit_unit(&mut self) -> Result<(), DecodeError> {
de::Deserialize::deserialize(&mut self.de)
}
fn visit_newtype<T>(&mut self) -> Result<T, DecodeError>
where T: de::Deserialize,
{
de::Deserialize::deserialize(&mut self.de)
}
fn visit_tuple<V>(&mut self,
_len: usize,
visitor: V) -> Result<V::Value, DecodeError>
where V: de::Visitor,
{
de::Deserializer::deserialize(&mut self.de, visitor)
}
fn visit_struct<V>(&mut self,
_fields: &'static [&'static str],
visitor: V) -> Result<V::Value, DecodeError>
where V: de::Visitor,
{
de::Deserializer::deserialize(&mut self.de, visitor)
}
}
struct SeqDeserializer<'a, I> {
iter: I,
len: usize,
toml: &'a mut Option<Value>,
}
impl<'a, I> SeqDeserializer<'a, I> where I: Iterator<Item=Value> {
fn new(iter: I, len: usize, toml: &'a mut Option<Value>) -> Self {
SeqDeserializer {
iter: iter,
len: len,
toml: toml,
}
}
fn put_value_back(&mut self, v: Value) {
*self.toml = self.toml.take().or(Some(Value::Array(Vec::new())));
match self.toml.as_mut().unwrap() {
&mut Value::Array(ref mut a) => {
a.push(v);
},
_ => unreachable!(),
}
}
}
impl<'a, I> de::Deserializer for SeqDeserializer<'a, I>
where I: Iterator<Item=Value>,
{
type Error = DecodeError;
fn deserialize<V>(&mut self, mut visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor,
{
visitor.visit_seq(self)
}
forward_to_deserialize!{
deserialize_bool();
deserialize_usize();
deserialize_u8();
deserialize_u16();
deserialize_u32();
deserialize_u64();
deserialize_isize();
deserialize_i8();
deserialize_i16();
deserialize_i32();
deserialize_i64();
deserialize_f32();
deserialize_f64();
deserialize_char();
deserialize_str();
deserialize_string();
deserialize_unit();
deserialize_option();
deserialize_seq();
deserialize_seq_fixed_size(len: usize);
deserialize_bytes();
deserialize_map();
deserialize_unit_struct(name: &'static str);
deserialize_newtype_struct(name: &'static str);
deserialize_tuple_struct(name: &'static str, len: usize);
deserialize_struct(name: &'static str, fields: &'static [&'static str]);
deserialize_struct_field();
deserialize_tuple(len: usize);
deserialize_enum(name: &'static str, variants: &'static [&'static str]);
deserialize_ignored_any();
}
}
impl<'a, I> de::SeqVisitor for SeqDeserializer<'a, I>
where I: Iterator<Item=Value>
{
type Error = DecodeError;
fn visit<V>(&mut self) -> Result<Option<V>, DecodeError>
where V: de::Deserialize
{
match self.iter.next() {
Some(value) => {
self.len -= 1;
let mut de = Decoder::new(value);
let v = try!(de::Deserialize::deserialize(&mut de));
if let Some(t) = de.toml {
self.put_value_back(t);
}
Ok(Some(v))
}
None => Ok(None),
}
}
fn end(&mut self) -> Result<(), DecodeError> {
if self.len == 0 {
Ok(())
} else {
Err(de::Error::end_of_stream())
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl de::Error for DecodeError {
fn custom<T: Into<String>>(msg: T) -> DecodeError {
DecodeError {
field: None,
kind: DecodeErrorKind::CustomError(msg.into()),
}
}
fn end_of_stream() -> DecodeError {
DecodeError { field: None, kind: DecodeErrorKind::EndOfStream }
}
fn missing_field(name: &'static str) -> DecodeError {
DecodeError {
field: Some(name.to_string()),
kind: DecodeErrorKind::ExpectedField(None),
}
}
fn unknown_field(name: &str) -> DecodeError {
DecodeError {
field: Some(name.to_string()),
kind: DecodeErrorKind::UnknownField,
}
}
fn invalid_type(ty: de::Type) -> Self {
DecodeError {
field: None,
kind: DecodeErrorKind::InvalidType(match ty {
de::Type::Bool => "bool",
de::Type::Usize |
de::Type::U8 |
de::Type::U16 |
de::Type::U32 |
de::Type::U64 |
de::Type::Isize |
de::Type::I8 |
de::Type::I16 |
de::Type::I32 |
de::Type::I64 => "integer",
de::Type::F32 |
de::Type::F64 => "float",
de::Type::Char |
de::Type::Str |
de::Type::String => "string",
de::Type::Seq => "array",
de::Type::Struct |
de::Type::Map => "table",
de::Type::Unit => "Unit",
de::Type::Option => "Option",
de::Type::UnitStruct => "UnitStruct",
de::Type::NewtypeStruct => "NewtypeStruct",
de::Type::TupleStruct => "TupleStruct",
de::Type::FieldName => "FieldName",
de::Type::Tuple => "Tuple",
de::Type::Enum => "Enum",
de::Type::VariantName => "VariantName",
de::Type::StructVariant => "StructVariant",
de::Type::TupleVariant => "TupleVariant",
de::Type::UnitVariant => "UnitVariant",
de::Type::Bytes => "Bytes",
})
}
}
}
struct MapVisitor<'a, I> {
iter: I,
de: &'a mut Decoder,
key: Option<String>,
value: Option<Value>,
}
impl<'a, I> MapVisitor<'a, I> {
fn put_value_back(&mut self, v: Value) {
self.de.toml = self.de.toml.take().or_else(|| {
Some(Value::Table(BTreeMap::new()))
});
match self.de.toml.as_mut().unwrap() {
&mut Value::Table(ref mut t) => {
t.insert(self.key.take().unwrap(), v);
},
_ => unreachable!(),
}
}
}
impl<'a, I> de::MapVisitor for MapVisitor<'a, I>
where I: Iterator<Item=(String, Value)>
{
type Error = DecodeError;
fn visit_key<K>(&mut self) -> Result<Option<K>, DecodeError>
where K: de::Deserialize
{
while let Some((k, v)) = self.iter.next() {
let mut dec = self.de.sub_decoder(Some(Value::String(k.clone())), &k);
self.key = Some(k);
match de::Deserialize::deserialize(&mut dec) {
Ok(val) => {
self.value = Some(v);
return Ok(Some(val))
}
// If this was an unknown field, then we put the toml value
// back into the map and keep going.
Err(DecodeError {kind: DecodeErrorKind::UnknownField, ..}) => {
self.put_value_back(v);
}
Err(e) => return Err(e),
}
}
Ok(None)
}
fn visit_value<V>(&mut self) -> Result<V, DecodeError>
where V: de::Deserialize
{
match self.value.take() {
Some(t) => {
let mut dec = {
// Borrowing the key here because Rust doesn't have
// non-lexical borrows yet.
let key = match self.key {
Some(ref key) => &**key,
None => ""
};
self.de.sub_decoder(Some(t), key)
};
let v = try!(de::Deserialize::deserialize(&mut dec));
if let Some(t) = dec.toml {
self.put_value_back(t);
}
Ok(v)
},
None => Err(de::Error::end_of_stream())
}
}
fn end(&mut self) -> Result<(), DecodeError> {
if let Some(v) = self.value.take() {
self.put_value_back(v);
}
while let Some((k, v)) = self.iter.next() {
self.key = Some(k);
self.put_value_back(v);
}
Ok(())
}
fn missing_field<V>(&mut self, field_name: &'static str)
-> Result<V, DecodeError> where V: de::Deserialize {
// See if the type can deserialize from a unit.
match de::Deserialize::deserialize(&mut UnitDeserializer) {
Err(DecodeError {
kind: DecodeErrorKind::InvalidType(..),
field,
}) => Err(DecodeError {
field: field.or(Some(field_name.to_string())),
kind: DecodeErrorKind::ExpectedField(None),
}),
v => v,
}
}
}
struct UnitDeserializer;
impl de::Deserializer for UnitDeserializer {
type Error = DecodeError;
fn deserialize<V>(&mut self, mut visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor,
{
visitor.visit_unit()
}
fn deserialize_option<V>(&mut self, mut visitor: V)
-> Result<V::Value, DecodeError>
where V: de::Visitor,
{
visitor.visit_none()
}
forward_to_deserialize!{
deserialize_bool();
deserialize_usize();
deserialize_u8();
deserialize_u16();
deserialize_u32();
deserialize_u64();
deserialize_isize();
deserialize_i8();
deserialize_i16();
deserialize_i32();
deserialize_i64();
deserialize_f32();
deserialize_f64();
deserialize_char();
deserialize_str();
deserialize_string();
deserialize_unit();
deserialize_seq();
deserialize_seq_fixed_size(len: usize);
deserialize_bytes();
deserialize_map();
deserialize_unit_struct(name: &'static str);
deserialize_newtype_struct(name: &'static str);
deserialize_tuple_struct(name: &'static str, len: usize);
deserialize_struct(name: &'static str, fields: &'static [&'static str]);
deserialize_struct_field();
deserialize_tuple(len: usize);
deserialize_enum(name: &'static str, variants: &'static [&'static str]);
deserialize_ignored_any();
}
}
impl de::Deserialize for Value {
fn deserialize<D>(deserializer: &mut D) -> Result<Value, D::Error>
where D: de::Deserializer
{
struct ValueVisitor;
impl de::Visitor for ValueVisitor {
type Value = Value;
fn visit_bool<E>(&mut self, value: bool) -> Result<Value, E> {
Ok(Value::Boolean(value))
}
fn visit_i64<E>(&mut self, value: i64) -> Result<Value, E> {
Ok(Value::Integer(value))
}
fn visit_f64<E>(&mut self, value: f64) -> Result<Value, E> {
Ok(Value::Float(value))
}
fn visit_str<E>(&mut self, value: &str) -> Result<Value, E> {
Ok(Value::String(value.into()))
}
fn visit_string<E>(&mut self, value: String) -> Result<Value, E> {
Ok(Value::String(value))
}
fn visit_seq<V>(&mut self, visitor: V) -> Result<Value, V::Error>
where V: de::SeqVisitor
{
let values = try!(de::impls::VecVisitor::new().visit_seq(visitor));
Ok(Value::Array(values))
}
fn visit_map<V>(&mut self, visitor: V) -> Result<Value, V::Error>
where V: de::MapVisitor
{
let mut v = de::impls::BTreeMapVisitor::new();
let values = try!(v.visit_map(visitor));
Ok(Value::Table(values))
}
}
deserializer.deserialize(ValueVisitor)
}
}

209
third_party/rust/toml/src/display.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,209 @@
use std::fmt;
use Table as TomlTable;
use Value::{self, String, Integer, Float, Boolean, Datetime, Array, Table};
struct Printer<'a, 'b:'a> {
output: &'a mut fmt::Formatter<'b>,
stack: Vec<&'a str>,
}
struct Key<'a>(&'a [&'a str]);
impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
String(ref s) => write_str(f, s),
Integer(i) => write!(f, "{}", i),
Float(fp) => {
try!(write!(f, "{}", fp));
if fp % 1.0 == 0.0 { try!(write!(f, ".0")) }
Ok(())
}
Boolean(b) => write!(f, "{}", b),
Datetime(ref s) => write!(f, "{}", s),
Table(ref t) => {
let mut p = Printer { output: f, stack: Vec::new() };
p.print(t)
}
Array(ref a) => {
try!(write!(f, "["));
for (i, v) in a.iter().enumerate() {
if i != 0 { try!(write!(f, ", ")); }
try!(write!(f, "{}", v));
}
write!(f, "]")
}
}
}
}
fn write_str(f: &mut fmt::Formatter, s: &str) -> fmt::Result {
try!(write!(f, "\""));
for ch in s.chars() {
match ch {
'\u{8}' => try!(write!(f, "\\b")),
'\u{9}' => try!(write!(f, "\\t")),
'\u{a}' => try!(write!(f, "\\n")),
'\u{c}' => try!(write!(f, "\\f")),
'\u{d}' => try!(write!(f, "\\r")),
'\u{22}' => try!(write!(f, "\\\"")),
'\u{5c}' => try!(write!(f, "\\\\")),
ch => try!(write!(f, "{}", ch)),
}
}
write!(f, "\"")
}
impl<'a, 'b> Printer<'a, 'b> {
fn print(&mut self, table: &'a TomlTable) -> fmt::Result {
let mut space_out_first = false;
for (k, v) in table.iter() {
match *v {
Table(..) => continue,
Array(ref a) => {
if let Some(&Table(..)) = a.first() {
continue;
}
}
_ => {}
}
space_out_first = true;
try!(writeln!(self.output, "{} = {}", Key(&[k]), v));
}
for (i, (k, v)) in table.iter().enumerate() {
match *v {
Table(ref inner) => {
self.stack.push(k);
if space_out_first || i != 0 {
try!(write!(self.output, "\n"));
}
try!(writeln!(self.output, "[{}]", Key(&self.stack)));
try!(self.print(inner));
self.stack.pop();
}
Array(ref inner) => {
match inner.first() {
Some(&Table(..)) => {}
_ => continue
}
self.stack.push(k);
for (j, inner) in inner.iter().enumerate() {
if space_out_first || i != 0 || j != 0 {
try!(write!(self.output, "\n"));
}
try!(writeln!(self.output, "[[{}]]", Key(&self.stack)));
match *inner {
Table(ref inner) => try!(self.print(inner)),
_ => panic!("non-heterogeneous toml array"),
}
}
self.stack.pop();
}
_ => {},
}
}
Ok(())
}
}
impl<'a> fmt::Display for Key<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for (i, part) in self.0.iter().enumerate() {
if i != 0 { try!(write!(f, ".")); }
let ok = part.chars().all(|c| {
match c {
'a' ... 'z' |
'A' ... 'Z' |
'0' ... '9' |
'-' | '_' => true,
_ => false,
}
});
if ok {
try!(write!(f, "{}", part));
} else {
try!(write_str(f, part));
}
}
Ok(())
}
}
#[cfg(test)]
#[allow(warnings)]
mod tests {
use Value;
use Value::{String, Integer, Float, Boolean, Datetime, Array, Table};
use std::collections::BTreeMap;
macro_rules! map( ($($k:expr => $v:expr),*) => ({
let mut _m = BTreeMap::new();
$(_m.insert($k.to_string(), $v);)*
_m
}) );
#[test]
fn simple_show() {
assert_eq!(String("foo".to_string()).to_string(),
"\"foo\"");
assert_eq!(Integer(10).to_string(),
"10");
assert_eq!(Float(10.0).to_string(),
"10.0");
assert_eq!(Float(2.4).to_string(),
"2.4");
assert_eq!(Boolean(true).to_string(),
"true");
assert_eq!(Datetime("test".to_string()).to_string(),
"test");
assert_eq!(Array(vec![]).to_string(),
"[]");
assert_eq!(Array(vec![Integer(1), Integer(2)]).to_string(),
"[1, 2]");
}
#[test]
fn table() {
assert_eq!(Table(map! { }).to_string(),
"");
assert_eq!(Table(map! { "test" => Integer(2) }).to_string(),
"test = 2\n");
assert_eq!(Table(map! {
"test" => Integer(2),
"test2" => Table(map! {
"test" => String("wut".to_string())
})
}).to_string(),
"test = 2\n\
\n\
[test2]\n\
test = \"wut\"\n");
assert_eq!(Table(map! {
"test" => Integer(2),
"test2" => Table(map! {
"test" => String("wut".to_string())
})
}).to_string(),
"test = 2\n\
\n\
[test2]\n\
test = \"wut\"\n");
assert_eq!(Table(map! {
"test" => Integer(2),
"test2" => Array(vec![Table(map! {
"test" => String("wut".to_string())
})])
}).to_string(),
"test = 2\n\
\n\
[[test2]]\n\
test = \"wut\"\n");
assert_eq!(Table(map! {
"foo.bar" => Integer(2),
"foo\"bar" => Integer(2)
}).to_string(),
"\"foo\\\"bar\" = 2\n\
\"foo.bar\" = 2\n");
}
}

203
third_party/rust/toml/src/encoder/mod.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,203 @@
use std::collections::BTreeMap;
use std::error;
use std::fmt;
use std::mem;
use {Value, Table};
#[cfg(feature = "rustc-serialize")] mod rustc_serialize;
#[cfg(feature = "serde")] mod serde;
/// A structure to transform Rust values into TOML values.
///
/// This encoder implements the serialization `Encoder` interface, allowing
/// `Encodable` rust types to be fed into the encoder. The output of this
/// encoder is a TOML `Table` structure. The resulting TOML can be stringified
/// if necessary.
///
/// # Example
///
/// ```
/// extern crate rustc_serialize;
/// extern crate toml;
///
/// # fn main() {
/// use toml::{Encoder, Value};
/// use rustc_serialize::Encodable;
///
/// #[derive(RustcEncodable)]
/// struct MyStruct { foo: isize, bar: String }
/// let my_struct = MyStruct { foo: 4, bar: "hello!".to_string() };
///
/// let mut e = Encoder::new();
/// my_struct.encode(&mut e).unwrap();
///
/// assert_eq!(e.toml.get(&"foo".to_string()), Some(&Value::Integer(4)))
/// # }
/// ```
#[derive(Default, Debug)]
pub struct Encoder {
/// Output TOML that is emitted. The current version of this encoder forces
/// the top-level representation of a structure to be a table.
///
/// This field can be used to extract the return value after feeding a value
/// into this `Encoder`.
pub toml: Table,
state: State,
}
/// Enumeration of errors which can occur while encoding a rust value into a
/// TOML value.
#[allow(missing_copy_implementations)]
#[derive(Debug)]
pub enum Error {
/// Indication that a key was needed when a value was emitted, but no key
/// was previously emitted.
NeedsKey,
/// Indication that a key was emitted, but no value was emitted.
NoValue,
/// Indicates that a map key was attempted to be emitted at an invalid
/// location.
InvalidMapKeyLocation,
/// Indicates that a type other than a string was attempted to be used as a
/// map key type.
InvalidMapKeyType,
/// A custom error type was generated
Custom(String),
}
/// Internal state of the encoder when encoding transitions
#[derive(Debug)]
pub struct EncoderState {
inner: State,
}
#[derive(PartialEq, Debug)]
enum State {
Start,
NextKey(String),
NextArray(Vec<Value>),
NextMapKey,
}
impl Default for State {
fn default() -> State { State::Start }
}
impl Encoder {
/// Constructs a new encoder which will emit to the given output stream.
pub fn new() -> Encoder {
Encoder { state: State::Start, toml: BTreeMap::new() }
}
fn emit_value(&mut self, v: Value) -> Result<(), Error> {
match mem::replace(&mut self.state, State::Start) {
State::NextKey(key) => { self.toml.insert(key, v); Ok(()) }
State::NextArray(mut vec) => {
// TODO: validate types
vec.push(v);
self.state = State::NextArray(vec);
Ok(())
}
State::NextMapKey => {
match v {
Value::String(s) => { self.state = State::NextKey(s); Ok(()) }
_ => Err(Error::InvalidMapKeyType)
}
}
_ => Err(Error::NeedsKey)
}
}
fn emit_none(&mut self) -> Result<(), Error> {
match mem::replace(&mut self.state, State::Start) {
State::Start => unreachable!(),
State::NextKey(_) => Ok(()),
State::NextArray(..) => panic!("how to encode None in an array?"),
State::NextMapKey => Err(Error::InvalidMapKeyLocation),
}
}
fn seq_begin(&mut self) -> Result<State, Error> {
Ok(mem::replace(&mut self.state, State::NextArray(Vec::new())))
}
fn seq_end(&mut self, old: State) -> Result<(), Error> {
match mem::replace(&mut self.state, old) {
State::NextArray(v) => self.emit_value(Value::Array(v)),
_ => unreachable!(),
}
}
fn table_key<F>(&mut self, f: F) -> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
match mem::replace(&mut self.state, State::NextMapKey) {
State::Start => {}
_ => return Err(Error::InvalidMapKeyLocation),
}
try!(f(self));
match self.state {
State::NextKey(_) => Ok(()),
_ => Err(Error::InvalidMapKeyLocation),
}
}
}
/// Encodes an encodable value into a TOML value.
///
/// This function expects the type given to represent a TOML table in some form.
/// If encoding encounters an error, then this function will fail the task.
#[cfg(feature = "rustc-serialize")]
pub fn encode<T: ::rustc_serialize::Encodable>(t: &T) -> Value {
let mut e = Encoder::new();
t.encode(&mut e).unwrap();
Value::Table(e.toml)
}
/// Encodes an encodable value into a TOML value.
///
/// This function expects the type given to represent a TOML table in some form.
/// If encoding encounters an error, then this function will fail the task.
#[cfg(all(not(feature = "rustc-serialize"), feature = "serde"))]
pub fn encode<T: ::serde::Serialize>(t: &T) -> Value {
let mut e = Encoder::new();
t.serialize(&mut e).unwrap();
Value::Table(e.toml)
}
/// Encodes an encodable value into a TOML string.
///
/// This function expects the type given to represent a TOML table in some form.
/// If encoding encounters an error, then this function will fail the task.
#[cfg(feature = "rustc-serialize")]
pub fn encode_str<T: ::rustc_serialize::Encodable>(t: &T) -> String {
encode(t).to_string()
}
/// Encodes an encodable value into a TOML string.
///
/// This function expects the type given to represent a TOML table in some form.
/// If encoding encounters an error, then this function will fail the task.
#[cfg(all(not(feature = "rustc-serialize"), feature = "serde"))]
pub fn encode_str<T: ::serde::Serialize>(t: &T) -> String {
encode(t).to_string()
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::NeedsKey => write!(f, "need a key to encode"),
Error::NoValue => write!(f, "no value to emit for a previous key"),
Error::InvalidMapKeyLocation => write!(f, "a map cannot be emitted \
at this location"),
Error::InvalidMapKeyType => write!(f, "only strings can be used as \
key types"),
Error::Custom(ref s) => write!(f, "custom error: {}", s),
}
}
}
impl error::Error for Error {
fn description(&self) -> &str { "TOML encoding error" }
}

748
third_party/rust/toml/src/encoder/rustc_serialize.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,748 @@
use std::mem;
use rustc_serialize;
use Value;
use super::{Encoder, Error, State};
use super::Error::*;
impl Encoder {
fn table<F>(&mut self, f: F) -> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
match mem::replace(&mut self.state, State::Start) {
State::NextKey(key) => {
let mut nested = Encoder::new();
try!(f(&mut nested));
self.toml.insert(key, Value::Table(nested.toml));
Ok(())
}
State::NextArray(mut arr) => {
let mut nested = Encoder::new();
try!(f(&mut nested));
arr.push(Value::Table(nested.toml));
self.state = State::NextArray(arr);
Ok(())
}
State::Start => f(self),
State::NextMapKey => Err(Error::InvalidMapKeyLocation),
}
}
fn seq<F>(&mut self, f: F) -> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
let old = try!(self.seq_begin());
try!(f(self));
self.seq_end(old)
}
}
impl rustc_serialize::Encoder for Encoder {
type Error = Error;
fn emit_nil(&mut self) -> Result<(), Error> { Ok(()) }
fn emit_usize(&mut self, v: usize) -> Result<(), Error> {
self.emit_i64(v as i64)
}
fn emit_u8(&mut self, v: u8) -> Result<(), Error> {
self.emit_i64(v as i64)
}
fn emit_u16(&mut self, v: u16) -> Result<(), Error> {
self.emit_i64(v as i64)
}
fn emit_u32(&mut self, v: u32) -> Result<(), Error> {
self.emit_i64(v as i64)
}
fn emit_u64(&mut self, v: u64) -> Result<(), Error> {
self.emit_i64(v as i64)
}
fn emit_isize(&mut self, v: isize) -> Result<(), Error> {
self.emit_i64(v as i64)
}
fn emit_i8(&mut self, v: i8) -> Result<(), Error> {
self.emit_i64(v as i64)
}
fn emit_i16(&mut self, v: i16) -> Result<(), Error> {
self.emit_i64(v as i64)
}
fn emit_i32(&mut self, v: i32) -> Result<(), Error> {
self.emit_i64(v as i64)
}
fn emit_i64(&mut self, v: i64) -> Result<(), Error> {
self.emit_value(Value::Integer(v))
}
fn emit_bool(&mut self, v: bool) -> Result<(), Error> {
self.emit_value(Value::Boolean(v))
}
fn emit_f32(&mut self, v: f32) -> Result<(), Error> { self.emit_f64(v as f64) }
fn emit_f64(&mut self, v: f64) -> Result<(), Error> {
self.emit_value(Value::Float(v))
}
fn emit_char(&mut self, v: char) -> Result<(), Error> {
self.emit_str(&v.to_string())
}
fn emit_str(&mut self, v: &str) -> Result<(), Error> {
self.emit_value(Value::String(v.to_string()))
}
fn emit_enum<F>(&mut self, _name: &str, f: F)
-> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
f(self)
}
fn emit_enum_variant<F>(&mut self, _v_name: &str, _v_id: usize,
_len: usize, f: F) -> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
f(self)
}
fn emit_enum_variant_arg<F>(&mut self, _a_idx: usize, f: F)
-> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
f(self)
}
fn emit_enum_struct_variant<F>(&mut self, _v_name: &str, _v_id: usize,
_len: usize,
_f: F)
-> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
panic!()
}
fn emit_enum_struct_variant_field<F>(&mut self,
_f_name: &str,
_f_idx: usize,
_f: F)
-> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
panic!()
}
fn emit_struct<F>(&mut self, _name: &str, _len: usize, f: F)
-> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
self.table(f)
}
fn emit_struct_field<F>(&mut self, f_name: &str, _f_idx: usize, f: F)
-> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
let old = mem::replace(&mut self.state,
State::NextKey(f_name.to_string()));
try!(f(self));
if self.state != State::Start {
return Err(NoValue)
}
self.state = old;
Ok(())
}
fn emit_tuple<F>(&mut self, len: usize, f: F)
-> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
self.emit_seq(len, f)
}
fn emit_tuple_arg<F>(&mut self, idx: usize, f: F)
-> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
self.emit_seq_elt(idx, f)
}
fn emit_tuple_struct<F>(&mut self, _name: &str, _len: usize, _f: F)
-> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
unimplemented!()
}
fn emit_tuple_struct_arg<F>(&mut self, _f_idx: usize, _f: F)
-> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
unimplemented!()
}
fn emit_option<F>(&mut self, f: F)
-> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
f(self)
}
fn emit_option_none(&mut self) -> Result<(), Error> {
self.emit_none()
}
fn emit_option_some<F>(&mut self, f: F) -> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
f(self)
}
fn emit_seq<F>(&mut self, _len: usize, f: F)
-> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
self.seq(f)
}
fn emit_seq_elt<F>(&mut self, _idx: usize, f: F)
-> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
f(self)
}
fn emit_map<F>(&mut self, len: usize, f: F)
-> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
self.emit_struct("foo", len, f)
}
fn emit_map_elt_key<F>(&mut self, _idx: usize, f: F) -> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
self.table_key(f)
}
fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> Result<(), Error>
where F: FnOnce(&mut Encoder) -> Result<(), Error>
{
f(self)
}
}
impl rustc_serialize::Encodable for Value {
fn encode<E>(&self, e: &mut E) -> Result<(), E::Error>
where E: rustc_serialize::Encoder
{
match *self {
Value::String(ref s) => e.emit_str(s),
Value::Integer(i) => e.emit_i64(i),
Value::Float(f) => e.emit_f64(f),
Value::Boolean(b) => e.emit_bool(b),
Value::Datetime(ref s) => e.emit_str(s),
Value::Array(ref a) => {
e.emit_seq(a.len(), |e| {
for item in a {
try!(item.encode(e));
}
Ok(())
})
}
Value::Table(ref t) => {
e.emit_map(t.len(), |e| {
for (i, (key, value)) in t.iter().enumerate() {
try!(e.emit_map_elt_key(i, |e| e.emit_str(key)));
try!(e.emit_map_elt_val(i, |e| value.encode(e)));
}
Ok(())
})
}
}
}
}
#[cfg(test)]
mod tests {
use std::collections::{BTreeMap, HashSet};
use rustc_serialize::{self, Encodable, Decodable};
use {Encoder, Decoder, DecodeError};
use Value;
use Value::{Table, Integer, Array, Float};
macro_rules! encode( ($t:expr) => ({
let mut e = Encoder::new();
$t.encode(&mut e).unwrap();
e.toml
}) );
macro_rules! decode( ($t:expr) => ({
let mut d = Decoder::new($t);
Decodable::decode(&mut d).unwrap()
}) );
macro_rules! map( ($($k:ident, $v:expr),*) => ({
let mut _m = BTreeMap::new();
$(_m.insert(stringify!($k).to_string(), $v);)*
_m
}) );
#[test]
fn smoke() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { a: isize }
let v = Foo { a: 2 };
assert_eq!(encode!(v), map! { a, Integer(2) });
assert_eq!(v, decode!(Table(encode!(v))));
}
#[test]
fn smoke_hyphen() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { a_b: isize }
let v = Foo { a_b: 2 };
assert_eq!(encode!(v), map! { a_b, Integer(2) });
assert_eq!(v, decode!(Table(encode!(v))));
let mut m = BTreeMap::new();
m.insert("a-b".to_string(), Integer(2));
assert_eq!(v, decode!(Table(encode!(v))));
}
#[test]
fn nested() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { a: isize, b: Bar }
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Bar { a: String }
let v = Foo { a: 2, b: Bar { a: "test".to_string() } };
assert_eq!(encode!(v),
map! {
a, Integer(2),
b, Table(map! {
a, Value::String("test".to_string())
})
});
assert_eq!(v, decode!(Table(encode!(v))));
}
#[test]
fn application_decode_error() {
#[derive(PartialEq, Debug)]
struct Range10(usize);
impl Decodable for Range10 {
fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<Range10, D::Error> {
let x: usize = try!(Decodable::decode(d));
if x > 10 {
Err(d.error("Value out of range!"))
} else {
Ok(Range10(x))
}
}
}
let mut d_good = Decoder::new(Integer(5));
let mut d_bad1 = Decoder::new(Value::String("not an isize".to_string()));
let mut d_bad2 = Decoder::new(Integer(11));
assert_eq!(Ok(Range10(5)), Decodable::decode(&mut d_good));
let err1: Result<Range10, _> = Decodable::decode(&mut d_bad1);
assert!(err1.is_err());
let err2: Result<Range10, _> = Decodable::decode(&mut d_bad2);
assert!(err2.is_err());
}
#[test]
fn array() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { a: Vec<isize> }
let v = Foo { a: vec![1, 2, 3, 4] };
assert_eq!(encode!(v),
map! {
a, Array(vec![
Integer(1),
Integer(2),
Integer(3),
Integer(4)
])
});
assert_eq!(v, decode!(Table(encode!(v))));
}
#[test]
fn tuple() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { a: (isize, isize, isize, isize) }
let v = Foo { a: (1, 2, 3, 4) };
assert_eq!(encode!(v),
map! {
a, Array(vec![
Integer(1),
Integer(2),
Integer(3),
Integer(4)
])
});
assert_eq!(v, decode!(Table(encode!(v))));
}
#[test]
fn inner_structs_with_options() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo {
a: Option<Box<Foo>>,
b: Bar,
}
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Bar {
a: String,
b: f64,
}
let v = Foo {
a: Some(Box::new(Foo {
a: None,
b: Bar { a: "foo".to_string(), b: 4.5 },
})),
b: Bar { a: "bar".to_string(), b: 1.0 },
};
assert_eq!(encode!(v),
map! {
a, Table(map! {
b, Table(map! {
a, Value::String("foo".to_string()),
b, Float(4.5)
})
}),
b, Table(map! {
a, Value::String("bar".to_string()),
b, Float(1.0)
})
});
assert_eq!(v, decode!(Table(encode!(v))));
}
#[test]
fn hashmap() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo {
map: BTreeMap<String, isize>,
set: HashSet<char>,
}
let v = Foo {
map: {
let mut m = BTreeMap::new();
m.insert("foo".to_string(), 10);
m.insert("bar".to_string(), 4);
m
},
set: {
let mut s = HashSet::new();
s.insert('a');
s
},
};
assert_eq!(encode!(v),
map! {
map, Table(map! {
foo, Integer(10),
bar, Integer(4)
}),
set, Array(vec![Value::String("a".to_string())])
}
);
assert_eq!(v, decode!(Table(encode!(v))));
}
#[test]
fn tuple_struct() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo(isize, String, f64);
let v = Foo(1, "foo".to_string(), 4.5);
assert_eq!(
encode!(v),
map! {
_field0, Integer(1),
_field1, Value::String("foo".to_string()),
_field2, Float(4.5)
}
);
assert_eq!(v, decode!(Table(encode!(v))));
}
#[test]
fn table_array() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { a: Vec<Bar>, }
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Bar { a: isize }
let v = Foo { a: vec![Bar { a: 1 }, Bar { a: 2 }] };
assert_eq!(
encode!(v),
map! {
a, Array(vec![
Table(map!{ a, Integer(1) }),
Table(map!{ a, Integer(2) }),
])
}
);
assert_eq!(v, decode!(Table(encode!(v))));
}
#[test]
fn type_errors() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { bar: isize }
let mut d = Decoder::new(Table(map! {
bar, Float(1.0)
}));
let a: Result<Foo, DecodeError> = Decodable::decode(&mut d);
match a {
Ok(..) => panic!("should not have decoded"),
Err(e) => {
assert_eq!(e.to_string(),
"expected a value of type `integer`, but \
found a value of type `float` for the key `bar`");
}
}
}
#[test]
fn missing_errors() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { bar: isize }
let mut d = Decoder::new(Table(map! {
}));
let a: Result<Foo, DecodeError> = Decodable::decode(&mut d);
match a {
Ok(..) => panic!("should not have decoded"),
Err(e) => {
assert_eq!(e.to_string(),
"expected a value of type `integer` for the key `bar`");
}
}
}
#[test]
fn parse_enum() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { a: E }
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
enum E {
Bar(isize),
Baz(f64),
Last(Foo2),
}
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo2 {
test: String,
}
let v = Foo { a: E::Bar(10) };
assert_eq!(
encode!(v),
map! { a, Integer(10) }
);
assert_eq!(v, decode!(Table(encode!(v))));
let v = Foo { a: E::Baz(10.2) };
assert_eq!(
encode!(v),
map! { a, Float(10.2) }
);
assert_eq!(v, decode!(Table(encode!(v))));
let v = Foo { a: E::Last(Foo2 { test: "test".to_string() }) };
assert_eq!(
encode!(v),
map! { a, Table(map! { test, Value::String("test".to_string()) }) }
);
assert_eq!(v, decode!(Table(encode!(v))));
}
#[test]
fn unused_fields() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { a: isize }
let v = Foo { a: 2 };
let mut d = Decoder::new(Table(map! {
a, Integer(2),
b, Integer(5)
}));
assert_eq!(v, Decodable::decode(&mut d).unwrap());
assert_eq!(d.toml, Some(Table(map! {
b, Integer(5)
})));
}
#[test]
fn unused_fields2() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { a: Bar }
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Bar { a: isize }
let v = Foo { a: Bar { a: 2 } };
let mut d = Decoder::new(Table(map! {
a, Table(map! {
a, Integer(2),
b, Integer(5)
})
}));
assert_eq!(v, Decodable::decode(&mut d).unwrap());
assert_eq!(d.toml, Some(Table(map! {
a, Table(map! {
b, Integer(5)
})
})));
}
#[test]
fn unused_fields3() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { a: Bar }
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Bar { a: isize }
let v = Foo { a: Bar { a: 2 } };
let mut d = Decoder::new(Table(map! {
a, Table(map! {
a, Integer(2)
})
}));
assert_eq!(v, Decodable::decode(&mut d).unwrap());
assert_eq!(d.toml, None);
}
#[test]
fn unused_fields4() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { a: BTreeMap<String, String> }
let v = Foo { a: map! { a, "foo".to_string() } };
let mut d = Decoder::new(Table(map! {
a, Table(map! {
a, Value::String("foo".to_string())
})
}));
assert_eq!(v, Decodable::decode(&mut d).unwrap());
assert_eq!(d.toml, None);
}
#[test]
fn unused_fields5() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { a: Vec<String> }
let v = Foo { a: vec!["a".to_string()] };
let mut d = Decoder::new(Table(map! {
a, Array(vec![Value::String("a".to_string())])
}));
assert_eq!(v, Decodable::decode(&mut d).unwrap());
assert_eq!(d.toml, None);
}
#[test]
fn unused_fields6() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { a: Option<Vec<String>> }
let v = Foo { a: Some(vec![]) };
let mut d = Decoder::new(Table(map! {
a, Array(vec![])
}));
assert_eq!(v, Decodable::decode(&mut d).unwrap());
assert_eq!(d.toml, None);
}
#[test]
fn unused_fields7() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { a: Vec<Bar> }
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Bar { a: isize }
let v = Foo { a: vec![Bar { a: 1 }] };
let mut d = Decoder::new(Table(map! {
a, Array(vec![Table(map! {
a, Integer(1),
b, Integer(2)
})])
}));
assert_eq!(v, Decodable::decode(&mut d).unwrap());
assert_eq!(d.toml, Some(Table(map! {
a, Array(vec![Table(map! {
b, Integer(2)
})])
})));
}
#[test]
fn unused_fields8() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { a: BTreeMap<String, Bar> }
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Bar { a: isize }
let v = Foo { a: map! { a, Bar { a: 2 } } };
let mut d = Decoder::new(Table(map! {
a, Table(map! {
a, Table(map! {
a, Integer(2),
b, Integer(2)
})
})
}));
assert_eq!(v, Decodable::decode(&mut d).unwrap());
assert_eq!(d.toml, Some(Table(map! {
a, Table(map! {
a, Table(map! {
b, Integer(2)
})
})
})));
}
#[test]
fn empty_arrays() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { a: Vec<Bar> }
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Bar;
let v = Foo { a: vec![] };
let mut d = Decoder::new(Table(map! {}));
assert_eq!(v, Decodable::decode(&mut d).unwrap());
}
#[test]
fn empty_arrays2() {
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Foo { a: Option<Vec<Bar>> }
#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
struct Bar;
let v = Foo { a: None };
let mut d = Decoder::new(Table(map! {}));
assert_eq!(v, Decodable::decode(&mut d).unwrap());
let v = Foo { a: Some(vec![]) };
let mut d = Decoder::new(Table(map! {
a, Array(vec![])
}));
assert_eq!(v, Decodable::decode(&mut d).unwrap());
}
#[test]
fn round_trip() {
let toml = r#"
[test]
foo = "bar"
[[values]]
foo = "baz"
[[values]]
foo = "qux"
"#;
let value: Value = toml.parse().unwrap();
let val2 = ::encode_str(&value).parse().unwrap();
assert_eq!(value, val2);
}
}

339
third_party/rust/toml/src/encoder/serde.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,339 @@
use std::mem;
use serde::ser;
use Value;
use super::{Encoder, Error, EncoderState, State};
impl Encoder {
fn table_begin(&mut self) -> Result<Self, Error> {
match self.state {
State::NextMapKey => Err(Error::InvalidMapKeyLocation),
_ => Ok(mem::replace(self, Encoder::new()))
}
}
fn table_end(&mut self, mut state: Self) -> Result<(), Error> {
match state.state {
State::NextKey(key) => {
mem::swap(&mut self.toml, &mut state.toml);
self.toml.insert(key, Value::Table(state.toml));
},
State::NextArray(mut arr) => {
mem::swap(&mut self.toml, &mut state.toml);
arr.push(Value::Table(state.toml));
self.state = State::NextArray(arr);
},
State::Start => {},
State::NextMapKey => unreachable!(),
}
Ok(())
}
}
impl ser::Serializer for Encoder {
type Error = Error;
type MapState = Self;
type StructState = Self;
type StructVariantState = Self;
type SeqState = EncoderState;
type TupleState = EncoderState;
type TupleStructState = EncoderState;
type TupleVariantState = EncoderState;
fn serialize_bool(&mut self, v: bool) -> Result<(), Error> {
self.emit_value(Value::Boolean(v))
}
fn serialize_i64(&mut self, v: i64) -> Result<(), Error> {
self.emit_value(Value::Integer(v))
}
// TODO: checked casts
fn serialize_u64(&mut self, v: u64) -> Result<(), Error> {
self.serialize_i64(v as i64)
}
fn serialize_isize(&mut self, v: isize) -> Result<(), Error> {
self.serialize_i64(v as i64)
}
fn serialize_usize(&mut self, v: usize) -> Result<(), Error> {
self.serialize_i64(v as i64)
}
fn serialize_i8(&mut self, v: i8) -> Result<(), Error> {
self.serialize_i64(v as i64)
}
fn serialize_u8(&mut self, v: u8) -> Result<(), Error> {
self.serialize_i64(v as i64)
}
fn serialize_i16(&mut self, v: i16) -> Result<(), Error> {
self.serialize_i64(v as i64)
}
fn serialize_u16(&mut self, v: u16) -> Result<(), Error> {
self.serialize_i64(v as i64)
}
fn serialize_i32(&mut self, v: i32) -> Result<(), Error> {
self.serialize_i64(v as i64)
}
fn serialize_u32(&mut self, v: u32) -> Result<(), Error> {
self.serialize_i64(v as i64)
}
fn serialize_f32(&mut self, v: f32) -> Result<(), Error> {
self.serialize_f64(v as f64)
}
fn serialize_f64(&mut self, v: f64) -> Result<(), Error> {
self.emit_value(Value::Float(v))
}
fn serialize_str(&mut self, value: &str) -> Result<(), Error> {
self.emit_value(Value::String(value.to_string()))
}
fn serialize_unit_struct(&mut self, _name: &'static str) -> Result<(), Error> {
Ok(())
}
fn serialize_unit(&mut self) -> Result<(), Error> {
Ok(())
}
fn serialize_none(&mut self) -> Result<(), Error> {
self.emit_none()
}
fn serialize_char(&mut self, c: char) -> Result<(), Error> {
self.serialize_str(&c.to_string())
}
fn serialize_some<V>(&mut self, value: V) -> Result<(), Error>
where V: ser::Serialize
{
value.serialize(self)
}
fn serialize_bytes(&mut self, v: &[u8]) -> Result<(), Error> {
let mut state = try!(self.serialize_seq(Some(v.len())));
for c in v {
try!(self.serialize_seq_elt(&mut state, c));
}
self.serialize_seq_end(state)
}
fn serialize_seq_fixed_size(&mut self, len: usize)
-> Result<EncoderState, Error> {
self.serialize_seq(Some(len))
}
fn serialize_seq(&mut self, _len: Option<usize>)
-> Result<EncoderState, Error> {
self.seq_begin().map(|s| EncoderState { inner: s })
}
fn serialize_seq_elt<T>(&mut self,
_state: &mut EncoderState,
value: T) -> Result<(), Error>
where T: ser::Serialize
{
value.serialize(self)
}
fn serialize_seq_end(&mut self, state: EncoderState) -> Result<(), Error> {
self.seq_end(state.inner)
}
fn serialize_tuple(&mut self, len: usize)
-> Result<EncoderState, Error> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_elt<T>(&mut self,
state: &mut EncoderState,
value: T) -> Result<(), Error>
where T: ser::Serialize
{
self.serialize_seq_elt(state, value)
}
fn serialize_tuple_end(&mut self, state: EncoderState) -> Result<(), Error> {
self.serialize_seq_end(state)
}
fn serialize_tuple_struct(&mut self,
_name: &'static str,
len: usize) -> Result<EncoderState, Error> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_struct_elt<T>(&mut self,
state: &mut EncoderState,
value: T) -> Result<(), Error>
where T: ser::Serialize
{
self.serialize_seq_elt(state, value)
}
fn serialize_tuple_struct_end(&mut self, state: EncoderState)
-> Result<(), Error> {
self.serialize_seq_end(state)
}
fn serialize_tuple_variant(&mut self,
_name: &'static str,
_id: usize,
_variant: &'static str,
len: usize) -> Result<EncoderState, Error> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_variant_elt<T>(&mut self,
state: &mut EncoderState,
value: T) -> Result<(), Error>
where T: ser::Serialize
{
self.serialize_seq_elt(state, value)
}
fn serialize_tuple_variant_end(&mut self, state: EncoderState)
-> Result<(), Error> {
self.serialize_seq_end(state)
}
fn serialize_map(&mut self, _len: Option<usize>) -> Result<Self, Error> {
self.table_begin()
}
fn serialize_map_key<K>(&mut self,
_state: &mut Encoder,
key: K) -> Result<(), Error>
where K: ser::Serialize
{
self.table_key(|me| key.serialize(me))
}
fn serialize_map_value<V>(&mut self,
_state: &mut Encoder,
value: V) -> Result<(), Error>
where V: ser::Serialize
{
value.serialize(self)
}
fn serialize_map_end(&mut self, state: Self) -> Result<(), Error> {
self.table_end(state)
}
fn serialize_struct(&mut self,
_name: &'static str,
len: usize) -> Result<Self, Error> {
self.serialize_map(Some(len))
}
fn serialize_struct_elt<V>(&mut self,
state: &mut Encoder,
key: &'static str,
value: V) -> Result<(), Error>
where V: ser::Serialize
{
try!(self.serialize_map_key(state, key));
self.serialize_map_value(state, value)
}
fn serialize_struct_end(&mut self, state: Self) -> Result<(), Error> {
self.serialize_map_end(state)
}
fn serialize_struct_variant(&mut self,
_name: &'static str,
_id: usize,
_variant: &'static str,
len: usize) -> Result<Self, Error> {
self.serialize_map(Some(len))
}
fn serialize_struct_variant_elt<V>(&mut self,
state: &mut Encoder,
key: &'static str,
value: V) -> Result<(), Error>
where V: ser::Serialize
{
try!(self.serialize_map_key(state, key));
self.serialize_map_value(state, value)
}
fn serialize_struct_variant_end(&mut self, state: Self) -> Result<(), Error> {
self.serialize_map_end(state)
}
fn serialize_newtype_struct<T>(&mut self,
_name: &'static str,
value: T) -> Result<(), Self::Error>
where T: ser::Serialize,
{
// Don't serialize the newtype struct in a tuple.
value.serialize(self)
}
fn serialize_newtype_variant<T>(&mut self,
_name: &'static str,
_variant_index: usize,
_variant: &'static str,
value: T) -> Result<(), Self::Error>
where T: ser::Serialize,
{
// Don't serialize the newtype struct variant in a tuple.
value.serialize(self)
}
fn serialize_unit_variant(&mut self,
_name: &'static str,
_variant_index: usize,
_variant: &'static str,
) -> Result<(), Self::Error>
{
Ok(())
}
}
impl ser::Serialize for Value {
fn serialize<E>(&self, e: &mut E) -> Result<(), E::Error>
where E: ser::Serializer
{
match *self {
Value::String(ref s) => e.serialize_str(s),
Value::Integer(i) => e.serialize_i64(i),
Value::Float(f) => e.serialize_f64(f),
Value::Boolean(b) => e.serialize_bool(b),
Value::Datetime(ref s) => e.serialize_str(s),
Value::Array(ref a) => {
let mut state = try!(e.serialize_seq(Some(a.len())));
for el in a.iter() {
try!(e.serialize_seq_elt(&mut state, el));
}
e.serialize_seq_end(state)
}
Value::Table(ref t) => {
let mut state = try!(e.serialize_map(Some(t.len())));
for (k, v) in t.iter() {
try!(e.serialize_map_key(&mut state, k));
try!(e.serialize_map_value(&mut state, v));
}
e.serialize_map_end(state)
}
}
}
}
impl ser::Error for Error {
fn custom<T: Into<String>>(msg: T) -> Error {
Error::Custom(msg.into())
}
}

492
third_party/rust/toml/src/lib.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,492 @@
//! A TOML-parsing library
//!
//! This library is an implementation in Rust of a parser for TOML configuration
//! files [1]. It is focused around high quality errors including specific spans
//! and detailed error messages when things go wrong.
//!
//! This implementation currently passes the language agnostic [test suite][2].
//!
//! # Example
//!
//! ```
//! let toml = r#"
//! [test]
//! foo = "bar"
//! "#;
//!
//! let value = toml::Parser::new(toml).parse().unwrap();
//! println!("{:?}", value);
//! ```
//!
//! # Conversions
//!
//! This library also supports using the standard `Encodable` and `Decodable`
//! traits with TOML values. This library provides the following conversion
//! capabilities:
//!
//! * `String` => `toml::Value` - via `Parser`
//! * `toml::Value` => `String` - via `Display`
//! * `toml::Value` => rust object - via `Decoder`
//! * rust object => `toml::Value` - via `Encoder`
//!
//! Convenience functions for performing multiple conversions at a time are also
//! provided.
//!
//! [1]: https://github.com/mojombo/toml
//! [2]: https://github.com/BurntSushi/toml-test
#![doc(html_root_url = "http://alexcrichton.com/toml-rs")]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]
#[cfg(feature = "rustc-serialize")] extern crate rustc_serialize;
#[cfg(feature = "serde")] extern crate serde;
use std::collections::BTreeMap;
use std::str::FromStr;
pub use parser::{Parser, ParserError};
#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
pub use self::encoder::{Encoder, Error, EncoderState, encode, encode_str};
#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
pub use self::decoder::{Decoder, DecodeError, DecodeErrorKind, decode, decode_str};
mod parser;
mod display;
#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
mod encoder;
#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
mod decoder;
/// Representation of a TOML value.
#[derive(PartialEq, Clone, Debug)]
#[allow(missing_docs)]
pub enum Value {
String(String),
Integer(i64),
Float(f64),
Boolean(bool),
Datetime(String),
Array(Array),
Table(Table),
}
/// Type representing a TOML array, payload of the `Value::Array` variant
pub type Array = Vec<Value>;
/// Type representing a TOML table, payload of the `Value::Table` variant
pub type Table = BTreeMap<String, Value>;
impl Value {
/// Tests whether this and another value have the same type.
pub fn same_type(&self, other: &Value) -> bool {
match (self, other) {
(&Value::String(..), &Value::String(..)) |
(&Value::Integer(..), &Value::Integer(..)) |
(&Value::Float(..), &Value::Float(..)) |
(&Value::Boolean(..), &Value::Boolean(..)) |
(&Value::Datetime(..), &Value::Datetime(..)) |
(&Value::Array(..), &Value::Array(..)) |
(&Value::Table(..), &Value::Table(..)) => true,
_ => false,
}
}
/// Returns a human-readable representation of the type of this value.
pub fn type_str(&self) -> &'static str {
match *self {
Value::String(..) => "string",
Value::Integer(..) => "integer",
Value::Float(..) => "float",
Value::Boolean(..) => "boolean",
Value::Datetime(..) => "datetime",
Value::Array(..) => "array",
Value::Table(..) => "table",
}
}
/// Extracts the string of this value if it is a string.
pub fn as_str(&self) -> Option<&str> {
match *self { Value::String(ref s) => Some(&**s), _ => None }
}
/// Extracts the integer value if it is an integer.
pub fn as_integer(&self) -> Option<i64> {
match *self { Value::Integer(i) => Some(i), _ => None }
}
/// Extracts the float value if it is a float.
pub fn as_float(&self) -> Option<f64> {
match *self { Value::Float(f) => Some(f), _ => None }
}
/// Extracts the boolean value if it is a boolean.
pub fn as_bool(&self) -> Option<bool> {
match *self { Value::Boolean(b) => Some(b), _ => None }
}
/// Extracts the datetime value if it is a datetime.
///
/// Note that a parsed TOML value will only contain ISO 8601 dates. An
/// example date is:
///
/// ```notrust
/// 1979-05-27T07:32:00Z
/// ```
pub fn as_datetime(&self) -> Option<&str> {
match *self { Value::Datetime(ref s) => Some(&**s), _ => None }
}
/// Extracts the array value if it is an array.
pub fn as_slice(&self) -> Option<&[Value]> {
match *self { Value::Array(ref s) => Some(&**s), _ => None }
}
/// Extracts the table value if it is a table.
pub fn as_table(&self) -> Option<&Table> {
match *self { Value::Table(ref s) => Some(s), _ => None }
}
/// Lookups for value at specified path.
///
/// Uses '.' as a path separator.
///
/// Note: arrays have zero-based indexes.
///
/// Note: empty path returns self.
///
/// ```
/// # #![allow(unstable)]
/// let toml = r#"
/// [test]
/// foo = "bar"
///
/// [[values]]
/// foo = "baz"
///
/// [[values]]
/// foo = "qux"
/// "#;
/// let value: toml::Value = toml.parse().unwrap();
///
/// let foo = value.lookup("test.foo").unwrap();
/// assert_eq!(foo.as_str().unwrap(), "bar");
///
/// let foo = value.lookup("values.1.foo").unwrap();
/// assert_eq!(foo.as_str().unwrap(), "qux");
///
/// let no_bar = value.lookup("test.bar");
/// assert_eq!(no_bar.is_none(), true);
/// ```
pub fn lookup(&self, path: &str) -> Option<&Value> {
let ref path = match Parser::new(path).lookup() {
Some(path) => path,
None => return None,
};
let mut cur_value = self;
if path.is_empty() {
return Some(cur_value)
}
for key in path {
match *cur_value {
Value::Table(ref hm) => {
match hm.get(key) {
Some(v) => cur_value = v,
None => return None
}
},
Value::Array(ref v) => {
match key.parse::<usize>().ok() {
Some(idx) if idx < v.len() => cur_value = &v[idx],
_ => return None
}
},
_ => return None
}
};
Some(cur_value)
}
/// Lookups for mutable value at specified path.
///
/// Uses '.' as a path separator.
///
/// Note: arrays have zero-based indexes.
///
/// Note: empty path returns self.
///
/// ```
/// # #![allow(unstable)]
/// let toml = r#"
/// [test]
/// foo = "bar"
///
/// [[values]]
/// foo = "baz"
///
/// [[values]]
/// foo = "qux"
/// "#;
/// let mut value: toml::Value = toml.parse().unwrap();
/// {
/// let string = value.lookup_mut("test.foo").unwrap();
/// assert_eq!(string, &mut toml::Value::String(String::from("bar")));
/// *string = toml::Value::String(String::from("foo"));
/// }
/// let result = value.lookup_mut("test.foo").unwrap();
/// assert_eq!(result.as_str().unwrap(), "foo");
/// ```
pub fn lookup_mut(&mut self, path: &str) -> Option<&mut Value> {
let ref path = match Parser::new(path).lookup() {
Some(path) => path,
None => return None,
};
let mut cur = self;
if path.is_empty() {
return Some(cur)
}
for key in path {
let tmp = cur;
match *tmp {
Value::Table(ref mut hm) => {
match hm.get_mut(key) {
Some(v) => cur = v,
None => return None
}
}
Value::Array(ref mut v) => {
match key.parse::<usize>().ok() {
Some(idx) if idx < v.len() => cur = &mut v[idx],
_ => return None
}
}
_ => return None
}
}
Some(cur)
}
}
impl FromStr for Value {
type Err = Vec<ParserError>;
fn from_str(s: &str) -> Result<Value, Vec<ParserError>> {
let mut p = Parser::new(s);
match p.parse().map(Value::Table) {
Some(n) => Ok(n),
None => Err(p.errors),
}
}
}
#[cfg(test)]
mod tests {
use super::Value;
#[test]
fn lookup_mut_change() {
let toml = r#"
[test]
foo = "bar"
[[values]]
foo = "baz"
[[values]]
foo = "qux"
"#;
let mut value: Value = toml.parse().unwrap();
{
let foo = value.lookup_mut("values.0.foo").unwrap();
*foo = Value::String(String::from("bar"));
}
let foo = value.lookup("values.0.foo").unwrap();
assert_eq!(foo.as_str().unwrap(), "bar");
}
#[test]
fn lookup_mut_valid() {
let toml = r#"
[test]
foo = "bar"
[[values]]
foo = "baz"
[[values]]
foo = "qux"
"#;
let mut value: Value = toml.parse().unwrap();
{
let test_foo = value.lookup_mut("test.foo").unwrap();
assert_eq!(test_foo.as_str().unwrap(), "bar");
}
{
let foo1 = value.lookup_mut("values.1.foo").unwrap();
assert_eq!(foo1.as_str().unwrap(), "qux");
}
assert!(value.lookup_mut("test.bar").is_none());
assert!(value.lookup_mut("test.foo.bar").is_none());
}
#[test]
fn lookup_mut_invalid_index() {
let toml = r#"
[[values]]
foo = "baz"
"#;
let mut value: Value = toml.parse().unwrap();
{
let foo = value.lookup_mut("test.foo");
assert!(foo.is_none());
}
{
let foo = value.lookup_mut("values.100.foo");
assert!(foo.is_none());
}
{
let foo = value.lookup_mut("values.str.foo");
assert!(foo.is_none());
}
}
#[test]
fn lookup_mut_self() {
let mut value: Value = r#"foo = "bar""#.parse().unwrap();
{
let foo = value.lookup_mut("foo").unwrap();
assert_eq!(foo.as_str().unwrap(), "bar");
}
let foo = value.lookup_mut("").unwrap();
assert!(foo.as_table().is_some());
let baz = foo.lookup_mut("foo").unwrap();
assert_eq!(baz.as_str().unwrap(), "bar");
}
#[test]
fn lookup_valid() {
let toml = r#"
[test]
foo = "bar"
[[values]]
foo = "baz"
[[values]]
foo = "qux"
"#;
let value: Value = toml.parse().unwrap();
let test_foo = value.lookup("test.foo").unwrap();
assert_eq!(test_foo.as_str().unwrap(), "bar");
let foo1 = value.lookup("values.1.foo").unwrap();
assert_eq!(foo1.as_str().unwrap(), "qux");
assert!(value.lookup("test.bar").is_none());
assert!(value.lookup("test.foo.bar").is_none());
}
#[test]
fn lookup_invalid_index() {
let toml = r#"
[[values]]
foo = "baz"
"#;
let value: Value = toml.parse().unwrap();
let foo = value.lookup("test.foo");
assert!(foo.is_none());
let foo = value.lookup("values.100.foo");
assert!(foo.is_none());
let foo = value.lookup("values.str.foo");
assert!(foo.is_none());
}
#[test]
fn lookup_self() {
let value: Value = r#"foo = "bar""#.parse().unwrap();
let foo = value.lookup("foo").unwrap();
assert_eq!(foo.as_str().unwrap(), "bar");
let foo = value.lookup("").unwrap();
assert!(foo.as_table().is_some());
let baz = foo.lookup("foo").unwrap();
assert_eq!(baz.as_str().unwrap(), "bar");
}
#[test]
fn lookup_advanced() {
let value: Value = "[table]\n\"value\" = 0".parse().unwrap();
let looked = value.lookup("table.\"value\"").unwrap();
assert_eq!(*looked, Value::Integer(0));
}
#[test]
fn lookup_advanced_table() {
let value: Value = "[table.\"name.other\"]\nvalue = \"my value\"".parse().unwrap();
let looked = value.lookup(r#"table."name.other".value"#).unwrap();
assert_eq!(*looked, Value::String(String::from("my value")));
}
#[test]
fn lookup_mut_advanced() {
let mut value: Value = "[table]\n\"value\" = [0, 1, 2]".parse().unwrap();
let looked = value.lookup_mut("table.\"value\".1").unwrap();
assert_eq!(*looked, Value::Integer(1));
}
#[test]
fn single_dot() {
let value: Value = "[table]\n\"value\" = [0, 1, 2]".parse().unwrap();
assert_eq!(None, value.lookup("."));
}
#[test]
fn array_dot() {
let value: Value = "[table]\n\"value\" = [0, 1, 2]".parse().unwrap();
assert_eq!(None, value.lookup("0."));
}
#[test]
fn dot_inside() {
let value: Value = "[table]\n\"value\" = [0, 1, 2]".parse().unwrap();
assert_eq!(None, value.lookup("table.\"value.0\""));
}
#[test]
fn table_with_quotes() {
let value: Value = "[table.\"element\"]\n\"value\" = [0, 1, 2]".parse().unwrap();
assert_eq!(None, value.lookup("\"table.element\".\"value\".0"));
}
#[test]
fn table_with_quotes_2() {
let value: Value = "[table.\"element\"]\n\"value\" = [0, 1, 2]".parse().unwrap();
assert_eq!(Value::Integer(0), *value.lookup("table.\"element\".\"value\".0").unwrap());
}
}

1627
third_party/rust/toml/src/parser.rs поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

1
third_party/rust/toml/tests/README.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
Tests are from https://github.com/BurntSushi/toml-test

52
third_party/rust/toml/tests/formatting.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,52 @@
extern crate rustc_serialize;
extern crate toml;
use toml::encode_str;
#[derive(Debug, Clone, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)]
struct User {
pub name: String,
pub surname: String,
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)]
struct Users {
pub user: Vec<User>,
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)]
struct TwoUsers {
pub user0: User,
pub user1: User,
}
#[test]
fn no_unnecessary_newlines_array() {
assert!(!encode_str(&Users {
user: vec![
User {
name: "John".to_string(),
surname: "Doe".to_string(),
},
User {
name: "Jane".to_string(),
surname: "Dough".to_string(),
},
],
})
.starts_with("\n"));
}
#[test]
fn no_unnecessary_newlines_table() {
assert!(!encode_str(&TwoUsers {
user0: User {
name: "John".to_string(),
surname: "Doe".to_string(),
},
user1: User {
name: "Jane".to_string(),
surname: "Dough".to_string(),
},
})
.starts_with("\n"));
}

Просмотреть файл

@ -0,0 +1,15 @@
{
"ints-and-floats": {
"type": "array",
"value": [
{
"type": "integer",
"value": "1"
},
{
"type": "float",
"value": "1.1"
}
]
}
}

108
third_party/rust/toml/tests/invalid.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,108 @@
extern crate toml;
use toml::{Parser};
fn run(toml: &str) {
let mut p = Parser::new(toml);
let table = p.parse();
assert!(table.is_none());
assert!(p.errors.len() > 0);
// test Parser::to_linecol with the generated error offsets
for error in &p.errors {
p.to_linecol(error.lo);
p.to_linecol(error.hi);
}
}
macro_rules! test( ($name:ident, $toml:expr) => (
#[test]
fn $name() { run($toml); }
) );
test!(array_mixed_types_arrays_and_ints,
include_str!("invalid/array-mixed-types-arrays-and-ints.toml"));
test!(array_mixed_types_ints_and_floats,
include_str!("invalid/array-mixed-types-ints-and-floats.toml"));
test!(array_mixed_types_strings_and_ints,
include_str!("invalid/array-mixed-types-strings-and-ints.toml"));
test!(datetime_malformed_no_leads,
include_str!("invalid/datetime-malformed-no-leads.toml"));
test!(datetime_malformed_no_secs,
include_str!("invalid/datetime-malformed-no-secs.toml"));
test!(datetime_malformed_no_t,
include_str!("invalid/datetime-malformed-no-t.toml"));
test!(datetime_malformed_no_z,
include_str!("invalid/datetime-malformed-no-z.toml"));
test!(datetime_malformed_with_milli,
include_str!("invalid/datetime-malformed-with-milli.toml"));
test!(duplicate_keys,
include_str!("invalid/duplicate-keys.toml"));
test!(duplicate_key_table,
include_str!("invalid/duplicate-key-table.toml"));
test!(duplicate_tables,
include_str!("invalid/duplicate-tables.toml"));
test!(empty_implicit_table,
include_str!("invalid/empty-implicit-table.toml"));
test!(empty_table,
include_str!("invalid/empty-table.toml"));
test!(float_no_leading_zero,
include_str!("invalid/float-no-leading-zero.toml"));
test!(float_no_trailing_digits,
include_str!("invalid/float-no-trailing-digits.toml"));
test!(key_after_array,
include_str!("invalid/key-after-array.toml"));
test!(key_after_table,
include_str!("invalid/key-after-table.toml"));
test!(key_empty,
include_str!("invalid/key-empty.toml"));
test!(key_hash,
include_str!("invalid/key-hash.toml"));
test!(key_newline,
include_str!("invalid/key-newline.toml"));
test!(key_open_bracket,
include_str!("invalid/key-open-bracket.toml"));
test!(key_single_open_bracket,
include_str!("invalid/key-single-open-bracket.toml"));
test!(key_space,
include_str!("invalid/key-space.toml"));
test!(key_start_bracket,
include_str!("invalid/key-start-bracket.toml"));
test!(key_two_equals,
include_str!("invalid/key-two-equals.toml"));
test!(string_bad_byte_escape,
include_str!("invalid/string-bad-byte-escape.toml"));
test!(string_bad_escape,
include_str!("invalid/string-bad-escape.toml"));
test!(string_byte_escapes,
include_str!("invalid/string-byte-escapes.toml"));
test!(string_no_close,
include_str!("invalid/string-no-close.toml"));
test!(table_array_implicit,
include_str!("invalid/table-array-implicit.toml"));
test!(table_array_malformed_bracket,
include_str!("invalid/table-array-malformed-bracket.toml"));
test!(table_array_malformed_empty,
include_str!("invalid/table-array-malformed-empty.toml"));
test!(table_empty,
include_str!("invalid/table-empty.toml"));
test!(table_nested_brackets_close,
include_str!("invalid/table-nested-brackets-close.toml"));
test!(table_nested_brackets_open,
include_str!("invalid/table-nested-brackets-open.toml"));
test!(table_whitespace,
include_str!("invalid/table-whitespace.toml"));
test!(table_with_pound,
include_str!("invalid/table-with-pound.toml"));
test!(text_after_array_entries,
include_str!("invalid/text-after-array-entries.toml"));
test!(text_after_integer,
include_str!("invalid/text-after-integer.toml"));
test!(text_after_string,
include_str!("invalid/text-after-string.toml"));
test!(text_after_table,
include_str!("invalid/text-after-table.toml"));
test!(text_before_array_separator,
include_str!("invalid/text-before-array-separator.toml"));
test!(text_in_array,
include_str!("invalid/text-in-array.toml"));

Просмотреть файл

@ -0,0 +1 @@
arrays-and-ints = [1, ["Arrays are not integers."]]

Просмотреть файл

@ -0,0 +1 @@
ints-and-floats = [1, 1.1]

Просмотреть файл

@ -0,0 +1 @@
strings-and-ints = ["hi", 42]

Просмотреть файл

@ -0,0 +1 @@
no-leads = 1987-7-05T17:45:00Z

Просмотреть файл

@ -0,0 +1 @@
no-secs = 1987-07-05T17:45Z

Просмотреть файл

@ -0,0 +1 @@
no-t = 1987-07-0517:45:00Z

Просмотреть файл

@ -0,0 +1 @@
no-z = 1987-07-05T17:45:00

Просмотреть файл

@ -0,0 +1 @@
with-milli = 1987-07-5T17:45:00.12Z

5
third_party/rust/toml/tests/invalid/duplicate-key-table.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,5 @@
[fruit]
type = "apple"
[fruit.type]
apple = "yes"

2
third_party/rust/toml/tests/invalid/duplicate-keys.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,2 @@
dupe = false
dupe = true

2
third_party/rust/toml/tests/invalid/duplicate-tables.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,2 @@
[a]
[a]

1
third_party/rust/toml/tests/invalid/empty-implicit-table.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
[naughty..naughty]

1
third_party/rust/toml/tests/invalid/empty-table.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
[]

Просмотреть файл

@ -0,0 +1,2 @@
answer = .12345
neganswer = -.12345

Просмотреть файл

@ -0,0 +1,2 @@
answer = 1.
neganswer = -1.

1
third_party/rust/toml/tests/invalid/key-after-array.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
[[agencies]] owner = "S Cjelli"

1
third_party/rust/toml/tests/invalid/key-after-table.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
[history] guard = "sleeping"

1
third_party/rust/toml/tests/invalid/key-empty.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
= 1

1
third_party/rust/toml/tests/invalid/key-hash.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
a# = 1

2
third_party/rust/toml/tests/invalid/key-newline.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,2 @@
a
= 1

1
third_party/rust/toml/tests/invalid/key-open-bracket.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
[abc = 1

Просмотреть файл

@ -0,0 +1 @@
[

1
third_party/rust/toml/tests/invalid/key-space.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
a b = 1

3
third_party/rust/toml/tests/invalid/key-start-bracket.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,3 @@
[a]
[xyz = 5
[b]

1
third_party/rust/toml/tests/invalid/key-two-equals.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
key= = 1

Просмотреть файл

@ -0,0 +1 @@
naughty = "\xAg"

1
third_party/rust/toml/tests/invalid/string-bad-escape.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
invalid-escape = "This string has a bad \a escape character."

1
third_party/rust/toml/tests/invalid/string-byte-escapes.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
answer = "\x33"

1
third_party/rust/toml/tests/invalid/string-no-close.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
no-ending-quote = "One time, at band camp

14
third_party/rust/toml/tests/invalid/table-array-implicit.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,14 @@
# This test is a bit tricky. It should fail because the first use of
# `[[albums.songs]]` without first declaring `albums` implies that `albums`
# must be a table. The alternative would be quite weird. Namely, it wouldn't
# comply with the TOML spec: "Each double-bracketed sub-table will belong to
# the most *recently* defined table element *above* it."
#
# This is in contrast to the *valid* test, table-array-implicit where
# `[[albums.songs]]` works by itself, so long as `[[albums]]` isn't declared
# later. (Although, `[albums]` could be.)
[[albums.songs]]
name = "Glory Days"
[[albums]]
name = "Born in the USA"

Просмотреть файл

@ -0,0 +1,2 @@
[[albums]
name = "Born to Run"

Просмотреть файл

@ -0,0 +1,2 @@
[[]]
name = "Born to Run"

1
third_party/rust/toml/tests/invalid/table-empty.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
[]

Просмотреть файл

@ -0,0 +1,2 @@
[a]b]
zyx = 42

Просмотреть файл

@ -0,0 +1,2 @@
[a[b]
zyx = 42

1
third_party/rust/toml/tests/invalid/table-whitespace.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
[invalid key]

2
third_party/rust/toml/tests/invalid/table-with-pound.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,2 @@
[key#group]
answer = 42

Просмотреть файл

@ -0,0 +1,4 @@
array = [
"Is there life after an array separator?", No
"Entry"
]

1
third_party/rust/toml/tests/invalid/text-after-integer.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
answer = 42 the ultimate answer?

1
third_party/rust/toml/tests/invalid/text-after-string.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
string = "Is there life after strings?" No.

1
third_party/rust/toml/tests/invalid/text-after-table.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
[error] this shouldn't be here

Просмотреть файл

@ -0,0 +1,4 @@
array = [
"Is there life before an array separator?" No,
"Entry"
]

5
third_party/rust/toml/tests/invalid/text-in-array.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,5 @@
array = [
"Entry 1",
I don't belong,
"Entry 2",
]

195
third_party/rust/toml/tests/valid.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,195 @@
extern crate rustc_serialize;
extern crate toml;
use std::collections::BTreeMap;
use rustc_serialize::json::Json;
use toml::{Parser, Value};
use toml::Value::{Table, Integer, Float, Boolean, Datetime, Array};
fn to_json(toml: Value) -> Json {
fn doit(s: &str, json: Json) -> Json {
let mut map = BTreeMap::new();
map.insert(format!("{}", "type"), Json::String(format!("{}", s)));
map.insert(format!("{}", "value"), json);
Json::Object(map)
}
match toml {
Value::String(s) => doit("string", Json::String(s)),
Integer(i) => doit("integer", Json::String(format!("{}", i))),
Float(f) => doit("float", Json::String({
let s = format!("{:.15}", f);
let s = format!("{}", s.trim_right_matches('0'));
if s.ends_with(".") {format!("{}0", s)} else {s}
})),
Boolean(b) => doit("bool", Json::String(format!("{}", b))),
Datetime(s) => doit("datetime", Json::String(s)),
Array(arr) => {
let is_table = match arr.first() {
Some(&Table(..)) => true,
_ => false,
};
let json = Json::Array(arr.into_iter().map(to_json).collect());
if is_table {json} else {doit("array", json)}
}
Table(table) => Json::Object(table.into_iter().map(|(k, v)| {
(k, to_json(v))
}).collect()),
}
}
fn run(toml: &str, json: &str) {
let mut p = Parser::new(toml);
let table = p.parse();
assert!(p.errors.len() == 0, "had_errors: {:?}",
p.errors.iter().map(|e| {
(e.desc.clone(), &toml[e.lo - 5..e.hi + 5])
}).collect::<Vec<(String, &str)>>());
assert!(table.is_some());
let toml = Table(table.unwrap());
let toml_string = format!("{}", toml);
let json = Json::from_str(json).unwrap();
let toml_json = to_json(toml.clone());
assert!(json == toml_json,
"expected\n{}\ngot\n{}\n",
json.pretty(),
toml_json.pretty());
let table2 = Parser::new(&toml_string).parse().unwrap();
// floats are a little lossy
if table2.values().any(|v| v.as_float().is_some()) { return }
assert_eq!(toml, Table(table2));
}
macro_rules! test( ($name:ident, $toml:expr, $json:expr) => (
#[test]
fn $name() { run($toml, $json); }
) );
test!(array_empty,
include_str!("valid/array-empty.toml"),
include_str!("valid/array-empty.json"));
test!(array_nospaces,
include_str!("valid/array-nospaces.toml"),
include_str!("valid/array-nospaces.json"));
test!(arrays_hetergeneous,
include_str!("valid/arrays-hetergeneous.toml"),
include_str!("valid/arrays-hetergeneous.json"));
test!(arrays,
include_str!("valid/arrays.toml"),
include_str!("valid/arrays.json"));
test!(arrays_nested,
include_str!("valid/arrays-nested.toml"),
include_str!("valid/arrays-nested.json"));
test!(empty,
include_str!("valid/empty.toml"),
include_str!("valid/empty.json"));
test!(bool,
include_str!("valid/bool.toml"),
include_str!("valid/bool.json"));
test!(datetime,
include_str!("valid/datetime.toml"),
include_str!("valid/datetime.json"));
test!(example,
include_str!("valid/example.toml"),
include_str!("valid/example.json"));
test!(float,
include_str!("valid/float.toml"),
include_str!("valid/float.json"));
test!(implicit_and_explicit_after,
include_str!("valid/implicit-and-explicit-after.toml"),
include_str!("valid/implicit-and-explicit-after.json"));
test!(implicit_and_explicit_before,
include_str!("valid/implicit-and-explicit-before.toml"),
include_str!("valid/implicit-and-explicit-before.json"));
test!(implicit_groups,
include_str!("valid/implicit-groups.toml"),
include_str!("valid/implicit-groups.json"));
test!(integer,
include_str!("valid/integer.toml"),
include_str!("valid/integer.json"));
test!(key_equals_nospace,
include_str!("valid/key-equals-nospace.toml"),
include_str!("valid/key-equals-nospace.json"));
test!(key_space,
include_str!("valid/key-space.toml"),
include_str!("valid/key-space.json"));
test!(key_special_chars,
include_str!("valid/key-special-chars.toml"),
include_str!("valid/key-special-chars.json"));
test!(key_with_pound,
include_str!("valid/key-with-pound.toml"),
include_str!("valid/key-with-pound.json"));
test!(long_float,
include_str!("valid/long-float.toml"),
include_str!("valid/long-float.json"));
test!(long_integer,
include_str!("valid/long-integer.toml"),
include_str!("valid/long-integer.json"));
test!(multiline_string,
include_str!("valid/multiline-string.toml"),
include_str!("valid/multiline-string.json"));
test!(raw_multiline_string,
include_str!("valid/raw-multiline-string.toml"),
include_str!("valid/raw-multiline-string.json"));
test!(raw_string,
include_str!("valid/raw-string.toml"),
include_str!("valid/raw-string.json"));
test!(string_empty,
include_str!("valid/string-empty.toml"),
include_str!("valid/string-empty.json"));
test!(string_escapes,
include_str!("valid/string-escapes.toml"),
include_str!("valid/string-escapes.json"));
test!(string_simple,
include_str!("valid/string-simple.toml"),
include_str!("valid/string-simple.json"));
test!(string_with_pound,
include_str!("valid/string-with-pound.toml"),
include_str!("valid/string-with-pound.json"));
test!(table_array_implicit,
include_str!("valid/table-array-implicit.toml"),
include_str!("valid/table-array-implicit.json"));
test!(table_array_many,
include_str!("valid/table-array-many.toml"),
include_str!("valid/table-array-many.json"));
test!(table_array_nest,
include_str!("valid/table-array-nest.toml"),
include_str!("valid/table-array-nest.json"));
test!(table_array_one,
include_str!("valid/table-array-one.toml"),
include_str!("valid/table-array-one.json"));
test!(table_empty,
include_str!("valid/table-empty.toml"),
include_str!("valid/table-empty.json"));
test!(table_sub_empty,
include_str!("valid/table-sub-empty.toml"),
include_str!("valid/table-sub-empty.json"));
test!(table_whitespace,
include_str!("valid/table-whitespace.toml"),
include_str!("valid/table-whitespace.json"));
test!(table_with_pound,
include_str!("valid/table-with-pound.toml"),
include_str!("valid/table-with-pound.json"));
test!(unicode_escape,
include_str!("valid/unicode-escape.toml"),
include_str!("valid/unicode-escape.json"));
test!(unicode_literal,
include_str!("valid/unicode-literal.toml"),
include_str!("valid/unicode-literal.json"));
test!(hard_example,
include_str!("valid/hard_example.toml"),
include_str!("valid/hard_example.json"));
test!(example2,
include_str!("valid/example2.toml"),
include_str!("valid/example2.json"));
test!(example3,
include_str!("valid/example-v0.3.0.toml"),
include_str!("valid/example-v0.3.0.json"));
test!(example4,
include_str!("valid/example-v0.4.0.toml"),
include_str!("valid/example-v0.4.0.json"));
test!(example_bom,
include_str!("valid/example-bom.toml"),
include_str!("valid/example.json"));

11
third_party/rust/toml/tests/valid/array-empty.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,11 @@
{
"thevoid": { "type": "array", "value": [
{"type": "array", "value": [
{"type": "array", "value": [
{"type": "array", "value": [
{"type": "array", "value": []}
]}
]}
]}
]}
}

1
third_party/rust/toml/tests/valid/array-empty.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
thevoid = [[[[[]]]]]

10
third_party/rust/toml/tests/valid/array-nospaces.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,10 @@
{
"ints": {
"type": "array",
"value": [
{"type": "integer", "value": "1"},
{"type": "integer", "value": "2"},
{"type": "integer", "value": "3"}
]
}
}

1
third_party/rust/toml/tests/valid/array-nospaces.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
ints = [1,2,3]

19
third_party/rust/toml/tests/valid/arrays-hetergeneous.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,19 @@
{
"mixed": {
"type": "array",
"value": [
{"type": "array", "value": [
{"type": "integer", "value": "1"},
{"type": "integer", "value": "2"}
]},
{"type": "array", "value": [
{"type": "string", "value": "a"},
{"type": "string", "value": "b"}
]},
{"type": "array", "value": [
{"type": "float", "value": "1.1"},
{"type": "float", "value": "2.1"}
]}
]
}
}

1
third_party/rust/toml/tests/valid/arrays-hetergeneous.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
mixed = [[1, 2], ["a", "b"], [1.1, 2.1]]

13
third_party/rust/toml/tests/valid/arrays-nested.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,13 @@
{
"nest": {
"type": "array",
"value": [
{"type": "array", "value": [
{"type": "string", "value": "a"}
]},
{"type": "array", "value": [
{"type": "string", "value": "b"}
]}
]
}
}

1
third_party/rust/toml/tests/valid/arrays-nested.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
nest = [["a"], ["b"]]

34
third_party/rust/toml/tests/valid/arrays.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,34 @@
{
"ints": {
"type": "array",
"value": [
{"type": "integer", "value": "1"},
{"type": "integer", "value": "2"},
{"type": "integer", "value": "3"}
]
},
"floats": {
"type": "array",
"value": [
{"type": "float", "value": "1.1"},
{"type": "float", "value": "2.1"},
{"type": "float", "value": "3.1"}
]
},
"strings": {
"type": "array",
"value": [
{"type": "string", "value": "a"},
{"type": "string", "value": "b"},
{"type": "string", "value": "c"}
]
},
"dates": {
"type": "array",
"value": [
{"type": "datetime", "value": "1987-07-05T17:45:00Z"},
{"type": "datetime", "value": "1979-05-27T07:32:00Z"},
{"type": "datetime", "value": "2006-06-01T11:00:00Z"}
]
}
}

8
third_party/rust/toml/tests/valid/arrays.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,8 @@
ints = [1, 2, 3]
floats = [1.1, 2.1, 3.1]
strings = ["a", "b", "c"]
dates = [
1987-07-05T17:45:00Z,
1979-05-27T07:32:00Z,
2006-06-01T11:00:00Z,
]

4
third_party/rust/toml/tests/valid/bool.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,4 @@
{
"f": {"type": "bool", "value": "false"},
"t": {"type": "bool", "value": "true"}
}

2
third_party/rust/toml/tests/valid/bool.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,2 @@
t = true
f = false

12
third_party/rust/toml/tests/valid/comments-everywhere.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,12 @@
{
"group": {
"answer": {"type": "integer", "value": "42"},
"more": {
"type": "array",
"value": [
{"type": "integer", "value": "42"},
{"type": "integer", "value": "42"}
]
}
}
}

24
third_party/rust/toml/tests/valid/comments-everywhere.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,24 @@
# Top comment.
# Top comment.
# Top comment.
# [no-extraneous-groups-please]
[group] # Comment
answer = 42 # Comment
# no-extraneous-keys-please = 999
# Inbetween comment.
more = [ # Comment
# What about multiple # comments?
# Can you handle it?
#
# Evil.
# Evil.
42, 42, # Comments within arrays are fun.
# What about multiple # comments?
# Can you handle it?
#
# Evil.
# Evil.
# ] Did I fool you?
] # Hopefully not.

3
third_party/rust/toml/tests/valid/datetime.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,3 @@
{
"bestdayever": {"type": "datetime", "value": "1987-07-05T17:45:00Z"}
}

1
third_party/rust/toml/tests/valid/datetime.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
bestdayever = 1987-07-05T17:45:00Z

1
third_party/rust/toml/tests/valid/empty.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
{}

0
third_party/rust/toml/tests/valid/empty.toml поставляемый Normal file
Просмотреть файл

5
third_party/rust/toml/tests/valid/example-bom.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,5 @@
best-day-ever = 1987-07-05T17:45:00Z
[numtheory]
boring = false
perfection = [6, 28, 496]

1
third_party/rust/toml/tests/valid/example-v0.3.0.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
{"Array":{"key1":{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"},{"type":"integer","value":"3"}]},"key2":{"type":"array","value":[{"type":"string","value":"red"},{"type":"string","value":"yellow"},{"type":"string","value":"green"}]},"key3":{"type":"array","value":[{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"}]},{"type":"array","value":[{"type":"integer","value":"3"},{"type":"integer","value":"4"},{"type":"integer","value":"5"}]}]},"key4":{"type":"array","value":[{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"}]},{"type":"array","value":[{"type":"string","value":"a"},{"type":"string","value":"b"},{"type":"string","value":"c"}]}]},"key5":{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"},{"type":"integer","value":"3"}]},"key6":{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"}]}},"Booleans":{"False":{"type":"bool","value":"false"},"True":{"type":"bool","value":"true"}},"Datetime":{"key1":{"type":"datetime","value":"1979-05-27T07:32:00Z"}},"Float":{"both":{},"exponent":{},"fractional":{"key1":{"type":"float","value":"1.0"},"key2":{"type":"float","value":"3.1415"},"key3":{"type":"float","value":"-0.01"}}},"Integer":{"key1":{"type":"integer","value":"99"},"key2":{"type":"integer","value":"42"},"key3":{"type":"integer","value":"0"},"key4":{"type":"integer","value":"-17"}},"String":{"Literal":{"Multiline":{"lines":{"type":"string","value":"The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n"},"regex2":{"type":"string","value":"I [dw]on't need \\d{2} apples"}},"quoted":{"type":"string","value":"Tom \"Dubs\" Preston-Werner"},"regex":{"type":"string","value":"\u003c\\i\\c*\\s*\u003e"},"winpath":{"type":"string","value":"C:\\Users\\nodejs\\templates"},"winpath2":{"type":"string","value":"\\\\ServerX\\admin$\\system32\\"}},"Multiline":{"key1":{"type":"string","value":"One\nTwo"},"key2":{"type":"string","value":"One\nTwo"},"key3":{"type":"string","value":"One\nTwo"}},"Multilined":{"Singleline":{"key1":{"type":"string","value":"The quick brown fox jumps over the lazy dog."},"key2":{"type":"string","value":"The quick brown fox jumps over the lazy dog."},"key3":{"type":"string","value":"The quick brown fox jumps over the lazy dog."}}},"basic":{"type":"string","value":"I'm a string. \"You can quote me\". Name\u0009José\nLocation\u0009SF."}},"Table":{"key":{"type":"string","value":"value"}},"dog":{"tater":{"type":{"type":"string","value":"pug"}}},"fruit":[{"name":{"type":"string","value":"apple"},"physical":{"color":{"type":"string","value":"red"},"shape":{"type":"string","value":"round"}},"variety":[{"name":{"type":"string","value":"red delicious"}},{"name":{"type":"string","value":"granny smith"}}]},{"name":{"type":"string","value":"banana"},"variety":[{"name":{"type":"string","value":"plantain"}}]}],"products":[{"name":{"type":"string","value":"Hammer"},"sku":{"type":"integer","value":"738594937"}},{},{"color":{"type":"string","value":"gray"},"name":{"type":"string","value":"Nail"},"sku":{"type":"integer","value":"284758393"}}],"x":{"y":{"z":{"w":{}}}}}

182
third_party/rust/toml/tests/valid/example-v0.3.0.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,182 @@
# Comment
# I am a comment. Hear me roar. Roar.
# Table
# Tables (also known as hash tables or dictionaries) are collections of key/value pairs.
# They appear in square brackets on a line by themselves.
[Table]
key = "value" # Yeah, you can do this.
# Nested tables are denoted by table names with dots in them. Name your tables whatever crap you please, just don't use #, ., [ or ].
[dog.tater]
type = "pug"
# You don't need to specify all the super-tables if you don't want to. TOML knows how to do it for you.
# [x] you
# [x.y] don't
# [x.y.z] need these
[x.y.z.w] # for this to work
# String
# There are four ways to express strings: basic, multi-line basic, literal, and multi-line literal.
# All strings must contain only valid UTF-8 characters.
[String]
basic = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
[String.Multiline]
# The following strings are byte-for-byte equivalent:
key1 = "One\nTwo"
key2 = """One\nTwo"""
key3 = """
One
Two"""
[String.Multilined.Singleline]
# The following strings are byte-for-byte equivalent:
key1 = "The quick brown fox jumps over the lazy dog."
key2 = """
The quick brown \
fox jumps over \
the lazy dog."""
key3 = """\
The quick brown \
fox jumps over \
the lazy dog.\
"""
[String.Literal]
# What you see is what you get.
winpath = 'C:\Users\nodejs\templates'
winpath2 = '\\ServerX\admin$\system32\'
quoted = 'Tom "Dubs" Preston-Werner'
regex = '<\i\c*\s*>'
[String.Literal.Multiline]
regex2 = '''I [dw]on't need \d{2} apples'''
lines = '''
The first newline is
trimmed in raw strings.
All other whitespace
is preserved.
'''
# Integer
# Integers are whole numbers. Positive numbers may be prefixed with a plus sign.
# Negative numbers are prefixed with a minus sign.
[Integer]
key1 = +99
key2 = 42
key3 = 0
key4 = -17
# Float
# A float consists of an integer part (which may be prefixed with a plus or minus sign)
# followed by a fractional part and/or an exponent part.
[Float.fractional]
# fractional
key1 = +1.0
key2 = 3.1415
key3 = -0.01
[Float.exponent]
# exponent
#key1 = 5e+22
#key2 = 1e6
#key3 = -2E-2
[Float.both]
# both
#key = 6.626e-34
# Boolean
# Booleans are just the tokens you're used to. Always lowercase.
[Booleans]
True = true
False = false
# Datetime
# Datetimes are RFC 3339 dates.
[Datetime]
key1 = 1979-05-27T07:32:00Z
#key2 = 1979-05-27T00:32:00-07:00
#key3 = 1979-05-27T00:32:00.999999-07:00
# Array
# Arrays are square brackets with other primitives inside. Whitespace is ignored. Elements are separated by commas. Data types may not be mixed.
[Array]
key1 = [ 1, 2, 3 ]
key2 = [ "red", "yellow", "green" ]
key3 = [ [ 1, 2 ], [3, 4, 5] ]
key4 = [ [ 1, 2 ], ["a", "b", "c"] ] # this is ok
#Arrays can also be multiline. So in addition to ignoring whitespace, arrays also ignore newlines between the brackets.
# Terminating commas are ok before the closing bracket.
key5 = [
1, 2, 3
]
key6 = [
1,
2, # this is ok
]
# Array of Tables
# These can be expressed by using a table name in double brackets.
# Each table with the same double bracketed name will be an element in the array.
# The tables are inserted in the order encountered.
[[products]]
name = "Hammer"
sku = 738594937
[[products]]
[[products]]
name = "Nail"
sku = 284758393
color = "gray"
# You can create nested arrays of tables as well.
[[fruit]]
name = "apple"
[fruit.physical]
color = "red"
shape = "round"
[[fruit.variety]]
name = "red delicious"
[[fruit.variety]]
name = "granny smith"
[[fruit]]
name = "banana"
[[fruit.variety]]
name = "plantain"

1
third_party/rust/toml/tests/valid/example-v0.4.0.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
{"array":{"key1":{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"},{"type":"integer","value":"3"}]},"key2":{"type":"array","value":[{"type":"string","value":"red"},{"type":"string","value":"yellow"},{"type":"string","value":"green"}]},"key3":{"type":"array","value":[{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"}]},{"type":"array","value":[{"type":"integer","value":"3"},{"type":"integer","value":"4"},{"type":"integer","value":"5"}]}]},"key4":{"type":"array","value":[{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"}]},{"type":"array","value":[{"type":"string","value":"a"},{"type":"string","value":"b"},{"type":"string","value":"c"}]}]},"key5":{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"},{"type":"integer","value":"3"}]},"key6":{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"}]}},"boolean":{"False":{"type":"bool","value":"false"},"True":{"type":"bool","value":"true"}},"datetime":{},"float":{"both":{},"exponent":{},"fractional":{"key1":{"type":"float","value":"1.0"},"key2":{"type":"float","value":"3.1415"},"key3":{"type":"float","value":"-0.01"}},"underscores":{}},"fruit":[{"name":{"type":"string","value":"apple"},"physical":{"color":{"type":"string","value":"red"},"shape":{"type":"string","value":"round"}},"variety":[{"name":{"type":"string","value":"red delicious"}},{"name":{"type":"string","value":"granny smith"}}]},{"name":{"type":"string","value":"banana"},"variety":[{"name":{"type":"string","value":"plantain"}}]}],"integer":{"key1":{"type":"integer","value":"99"},"key2":{"type":"integer","value":"42"},"key3":{"type":"integer","value":"0"},"key4":{"type":"integer","value":"-17"},"underscores":{"key1":{"type":"integer","value":"1000"},"key2":{"type":"integer","value":"5349221"},"key3":{"type":"integer","value":"12345"}}},"products":[{"name":{"type":"string","value":"Hammer"},"sku":{"type":"integer","value":"738594937"}},{},{"color":{"type":"string","value":"gray"},"name":{"type":"string","value":"Nail"},"sku":{"type":"integer","value":"284758393"}}],"string":{"basic":{"basic":{"type":"string","value":"I'm a string. \"You can quote me\". Name\u0009José\nLocation\u0009SF."}},"literal":{"multiline":{"lines":{"type":"string","value":"The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n"},"regex2":{"type":"string","value":"I [dw]on't need \\d{2} apples"}},"quoted":{"type":"string","value":"Tom \"Dubs\" Preston-Werner"},"regex":{"type":"string","value":"\u003c\\i\\c*\\s*\u003e"},"winpath":{"type":"string","value":"C:\\Users\\nodejs\\templates"},"winpath2":{"type":"string","value":"\\\\ServerX\\admin$\\system32\\"}},"multiline":{"continued":{"key1":{"type":"string","value":"The quick brown fox jumps over the lazy dog."},"key2":{"type":"string","value":"The quick brown fox jumps over the lazy dog."},"key3":{"type":"string","value":"The quick brown fox jumps over the lazy dog."}},"key1":{"type":"string","value":"One\nTwo"},"key2":{"type":"string","value":"One\nTwo"},"key3":{"type":"string","value":"One\nTwo"}}},"table":{"inline":{"name":{"first":{"type":"string","value":"Tom"},"last":{"type":"string","value":"Preston-Werner"}},"point":{"x":{"type":"integer","value":"1"},"y":{"type":"integer","value":"2"}}},"key":{"type":"string","value":"value"},"subtable":{"key":{"type":"string","value":"another value"}}},"x":{"y":{"z":{"w":{}}}}}

235
third_party/rust/toml/tests/valid/example-v0.4.0.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,235 @@
################################################################################
## Comment
# Speak your mind with the hash symbol. They go from the symbol to the end of
# the line.
################################################################################
## Table
# Tables (also known as hash tables or dictionaries) are collections of
# key/value pairs. They appear in square brackets on a line by themselves.
[table]
key = "value" # Yeah, you can do this.
# Nested tables are denoted by table names with dots in them. Name your tables
# whatever crap you please, just don't use #, ., [ or ].
[table.subtable]
key = "another value"
# You don't need to specify all the super-tables if you don't want to. TOML
# knows how to do it for you.
# [x] you
# [x.y] don't
# [x.y.z] need these
[x.y.z.w] # for this to work
################################################################################
## Inline Table
# Inline tables provide a more compact syntax for expressing tables. They are
# especially useful for grouped data that can otherwise quickly become verbose.
# Inline tables are enclosed in curly braces `{` and `}`. No newlines are
# allowed between the curly braces unless they are valid within a value.
[table.inline]
name = { first = "Tom", last = "Preston-Werner" }
point = { x = 1, y = 2 }
################################################################################
## String
# There are four ways to express strings: basic, multi-line basic, literal, and
# multi-line literal. All strings must contain only valid UTF-8 characters.
[string.basic]
basic = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
[string.multiline]
# The following strings are byte-for-byte equivalent:
key1 = "One\nTwo"
key2 = """One\nTwo"""
key3 = """
One
Two"""
[string.multiline.continued]
# The following strings are byte-for-byte equivalent:
key1 = "The quick brown fox jumps over the lazy dog."
key2 = """
The quick brown \
fox jumps over \
the lazy dog."""
key3 = """\
The quick brown \
fox jumps over \
the lazy dog.\
"""
[string.literal]
# What you see is what you get.
winpath = 'C:\Users\nodejs\templates'
winpath2 = '\\ServerX\admin$\system32\'
quoted = 'Tom "Dubs" Preston-Werner'
regex = '<\i\c*\s*>'
[string.literal.multiline]
regex2 = '''I [dw]on't need \d{2} apples'''
lines = '''
The first newline is
trimmed in raw strings.
All other whitespace
is preserved.
'''
################################################################################
## Integer
# Integers are whole numbers. Positive numbers may be prefixed with a plus sign.
# Negative numbers are prefixed with a minus sign.
[integer]
key1 = +99
key2 = 42
key3 = 0
key4 = -17
[integer.underscores]
# For large numbers, you may use underscores to enhance readability. Each
# underscore must be surrounded by at least one digit.
key1 = 1_000
key2 = 5_349_221
key3 = 1_2_3_4_5 # valid but inadvisable
################################################################################
## Float
# A float consists of an integer part (which may be prefixed with a plus or
# minus sign) followed by a fractional part and/or an exponent part.
[float.fractional]
key1 = +1.0
key2 = 3.1415
key3 = -0.01
[float.exponent]
[float.both]
[float.underscores]
################################################################################
## Boolean
# Booleans are just the tokens you're used to. Always lowercase.
[boolean]
True = true
False = false
################################################################################
## Datetime
# Datetimes are RFC 3339 dates.
[datetime]
#key1 = 1979-05-27T07:32:00Z
#key2 = 1979-05-27T00:32:00-07:00
#key3 = 1979-05-27T00:32:00.999999-07:00
################################################################################
## Array
# Arrays are square brackets with other primitives inside. Whitespace is
# ignored. Elements are separated by commas. Data types may not be mixed.
[array]
key1 = [ 1, 2, 3 ]
key2 = [ "red", "yellow", "green" ]
key3 = [ [ 1, 2 ], [3, 4, 5] ]
key4 = [ [ 1, 2 ], ["a", "b", "c"] ] # this is ok
# Arrays can also be multiline. So in addition to ignoring whitespace, arrays
# also ignore newlines between the brackets. Terminating commas are ok before
# the closing bracket.
key5 = [
1, 2, 3
]
key6 = [
1,
2, # this is ok
]
################################################################################
## Array of Tables
# These can be expressed by using a table name in double brackets. Each table
# with the same double bracketed name will be an element in the array. The
# tables are inserted in the order encountered.
[[products]]
name = "Hammer"
sku = 738594937
[[products]]
[[products]]
name = "Nail"
sku = 284758393
color = "gray"
# You can create nested arrays of tables as well.
[[fruit]]
name = "apple"
[fruit.physical]
color = "red"
shape = "round"
[[fruit.variety]]
name = "red delicious"
[[fruit.variety]]
name = "granny smith"
[[fruit]]
name = "banana"
[[fruit.variety]]
name = "plantain"

14
third_party/rust/toml/tests/valid/example.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,14 @@
{
"best-day-ever": {"type": "datetime", "value": "1987-07-05T17:45:00Z"},
"numtheory": {
"boring": {"type": "bool", "value": "false"},
"perfection": {
"type": "array",
"value": [
{"type": "integer", "value": "6"},
{"type": "integer", "value": "28"},
{"type": "integer", "value": "496"}
]
}
}
}

5
third_party/rust/toml/tests/valid/example.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,5 @@
best-day-ever = 1987-07-05T17:45:00Z
[numtheory]
boring = false
perfection = [6, 28, 496]

1
third_party/rust/toml/tests/valid/example2.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
{"clients":{"data":{"type":"array","value":[{"type":"array","value":[{"type":"string","value":"gamma"},{"type":"string","value":"delta"}]},{"type":"array","value":[{"type":"integer","value":"1"},{"type":"integer","value":"2"}]}]},"hosts":{"type":"array","value":[{"type":"string","value":"alpha"},{"type":"string","value":"omega"}]}},"database":{"connection_max":{"type":"integer","value":"5000"},"enabled":{"type":"bool","value":"true"},"ports":{"type":"array","value":[{"type":"integer","value":"8001"},{"type":"integer","value":"8001"},{"type":"integer","value":"8002"}]},"server":{"type":"string","value":"192.168.1.1"}},"owner":{"bio":{"type":"string","value":"GitHub Cofounder \u0026 CEO\nLikes tater tots and beer."},"dob":{"type":"datetime","value":"1979-05-27T07:32:00Z"},"name":{"type":"string","value":"Tom Preston-Werner"},"organization":{"type":"string","value":"GitHub"}},"products":[{"name":{"type":"string","value":"Hammer"},"sku":{"type":"integer","value":"738594937"}},{"color":{"type":"string","value":"gray"},"name":{"type":"string","value":"Nail"},"sku":{"type":"integer","value":"284758393"}}],"servers":{"alpha":{"dc":{"type":"string","value":"eqdc10"},"ip":{"type":"string","value":"10.0.0.1"}},"beta":{"country":{"type":"string","value":"中国"},"dc":{"type":"string","value":"eqdc10"},"ip":{"type":"string","value":"10.0.0.2"}}},"title":{"type":"string","value":"TOML Example"}}

47
third_party/rust/toml/tests/valid/example2.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,47 @@
# This is a TOML document. Boom.
title = "TOML Example"
[owner]
name = "Tom Preston-Werner"
organization = "GitHub"
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
dob = 1979-05-27T07:32:00Z # First class dates? Why not?
[database]
server = "192.168.1.1"
ports = [ 8001, 8001, 8002 ]
connection_max = 5000
enabled = true
[servers]
# You can indent as you please. Tabs or spaces. TOML don't care.
[servers.alpha]
ip = "10.0.0.1"
dc = "eqdc10"
[servers.beta]
ip = "10.0.0.2"
dc = "eqdc10"
country = "中国" # This should be parsed as UTF-8
[clients]
data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it
# Line breaks are OK when inside arrays
hosts = [
"alpha",
"omega"
]
# Products
[[products]]
name = "Hammer"
sku = 738594937
[[products]]
name = "Nail"
sku = 284758393
color = "gray"

4
third_party/rust/toml/tests/valid/float.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,4 @@
{
"pi": {"type": "float", "value": "3.14"},
"negpi": {"type": "float", "value": "-3.14"}
}

2
third_party/rust/toml/tests/valid/float.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,2 @@
pi = 3.14
negpi = -3.14

1
third_party/rust/toml/tests/valid/hard_example.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
{"the":{"hard":{"another_test_string":{"type":"string","value":" Same thing, but with a string #"},"bit#":{"multi_line_array":{"type":"array","value":[{"type":"string","value":"]"}]},"what?":{"type":"string","value":"You don't think some user won't do that?"}},"harder_test_string":{"type":"string","value":" And when \"'s are in the string, along with # \""},"test_array":{"type":"array","value":[{"type":"string","value":"] "},{"type":"string","value":" # "}]},"test_array2":{"type":"array","value":[{"type":"string","value":"Test #11 ]proved that"},{"type":"string","value":"Experiment #9 was a success"}]}},"test_string":{"type":"string","value":"You'll hate me after this - #"}}}

33
third_party/rust/toml/tests/valid/hard_example.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,33 @@
# Test file for TOML
# Only this one tries to emulate a TOML file written by a user of the kind of parser writers probably hate
# This part you'll really hate
[the]
test_string = "You'll hate me after this - #" # " Annoying, isn't it?
[the.hard]
test_array = [ "] ", " # "] # ] There you go, parse this!
test_array2 = [ "Test #11 ]proved that", "Experiment #9 was a success" ]
# You didn't think it'd as easy as chucking out the last #, did you?
another_test_string = " Same thing, but with a string #"
harder_test_string = " And when \"'s are in the string, along with # \"" # "and comments are there too"
# Things will get harder
[the.hard."bit#"]
"what?" = "You don't think some user won't do that?"
multi_line_array = [
"]",
# ] Oh yes I did
]
# Each of the following keygroups/key value pairs should produce an error. Uncomment to them to test
#[error] if you didn't catch this, your parser is broken
#string = "Anything other than tabs, spaces and newline after a keygroup or key value pair has ended should produce an error unless it is a comment" like this
#array = [
# "This might most likely happen in multiline arrays",
# Like here,
# "or here,
# and here"
# ] End of array comment, forgot the #
#number = 3.14 pi <--again forgot the #

Просмотреть файл

@ -0,0 +1,10 @@
{
"a": {
"better": {"type": "integer", "value": "43"},
"b": {
"c": {
"answer": {"type": "integer", "value": "42"}
}
}
}
}

Просмотреть файл

@ -0,0 +1,5 @@
[a.b.c]
answer = 42
[a]
better = 43

Просмотреть файл

@ -0,0 +1,10 @@
{
"a": {
"better": {"type": "integer", "value": "43"},
"b": {
"c": {
"answer": {"type": "integer", "value": "42"}
}
}
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше