Bug 1396821 - Update vendored Rust crates. r=ato

MozReview-Commit-ID: D8W2mtdAmpb

--HG--
rename : third_party/rust/rustc-serialize/LICENSE-APACHE => third_party/rust/serde_json/LICENSE-APACHE
rename : third_party/rust/rustc-serialize/LICENSE-MIT => third_party/rust/serde_json/LICENSE-MIT
extra : rebase_source : 5e5054596543e501434ecde199c055548fd62271
This commit is contained in:
Henrik Skupin 2018-08-20 17:49:11 +02:00
parent 1fc0887dc1
commit 0be64a7b29
59 changed files with 15680 additions and 6904 deletions

34
Cargo.lock generated
View File

@ -806,6 +806,7 @@ dependencies = [
name = "geckodriver"
version = "0.21.0"
dependencies = [
"base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
@ -815,7 +816,9 @@ dependencies = [
"mozrunner 0.7.0",
"mozversion 0.1.3",
"regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.66 (git+https://github.com/servo/serde?branch=deserialize_from_enums8)",
"serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"webdriver 0.36.0",
"zip 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1836,11 +1839,6 @@ name = "rustc-demangle"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-serialize"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc_version"
version = "0.2.1"
@ -1849,6 +1847,11 @@ dependencies = [
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ryu"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "safemem"
version = "0.2.0"
@ -1928,6 +1931,16 @@ dependencies = [
"syn 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_json"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "servo_arc"
version = "0.1.1"
@ -2412,11 +2425,15 @@ dependencies = [
name = "webdriver"
version = "0.36.0"
dependencies = [
"base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cookie 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.66 (git+https://github.com/servo/serde?branch=deserialize_from_enums8)",
"serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2795,8 +2812,8 @@ dependencies = [
"checksum runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d79b4b604167921892e84afbbaad9d5ad74e091bf6c511d9dbfb0593f09fabd"
"checksum rust-ini 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8a654c5bda722c699be6b0fe4c0d90de218928da5b724c3e467fc48865c37263"
"checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69"
"checksum ryu 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0568787116e13c652377b6846f5931454a363a8fdf8ae50463ee40935b278b"
"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f"
"checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
@ -2806,6 +2823,7 @@ dependencies = [
"checksum serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)" = "e9a2d9a9ac5120e0f768801ca2b58ad6eec929dc9d1d616c162f208869c2ce95"
"checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3"
"checksum serde_derive 1.0.66 (git+https://github.com/servo/serde?branch=deserialize_from_enums8)" = "<none>"
"checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae"
"checksum simd 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ed3686dd9418ebcc3a26a0c0ae56deab0681e53fe899af91f5bbcee667ebffb1"
"checksum siphasher 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ffc669b726f2bc9a3bcff66e5e23b56ba6bf70e22a34c3d7b6d0b3450b65b84"
"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"

View File

@ -1 +0,0 @@
{"files":{".travis.yml":"03dcea6dcd54625b42d91176e86718626dfd911744a343dee3edefa001e87dc5","Cargo.toml":"01199fa6ca6337a7513e9ef8951268b8882347e5affaa50e710ac4960d9c65e0","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"0aebc3beb6fc32d6073582d5fea170761689a2c83cddb5436aa26e57b7d04e7b","appveyor.yml":"da991211b72fa6f231af7adb84c9fb72f5a9131d1c0a3d47b8ceffe5a82c8542","benches/base64.rs":"96f7d0c7d260362e41b8cefb4839f1e1b3c18c2f10344f6ccafac7c434f99ca9","benches/hex.rs":"057821307b4b7de02f2c267f9248457386035382916c5afe4b72d6f2e905062c","benches/json.rs":"659f2ae2e1ad5ed022fafce6418d17dfe09c3dcb3f054857dce0effc907da850","src/base64.rs":"57649c590c1fba643ff955910f1d4427feda43414bb0863cd279bea56c3ff178","src/collection_impls.rs":"8ae6bc0d61a4777d834c2b24fa987550cb13c570e1564f87ee32eceff3cb2d5b","src/hex.rs":"a2ba86cf47035b5d9cbf4adf8dc3e941d4e0a6ce1a61a29cbb14ea1fdabac6bb","src/json.rs":"75a788a46612c73bfd14af20fb48855dc8c930747c5255a288d2d09de25ea960","src/lib.rs":"a0e4a368a609f019434e7584f54448cf33ebf3e37e3fb1dd5537d300088184b1","src/serialize.rs":"7ddcc3c32843850e30d05b82a8cda8ae63ec0016e2b0bfbcc46a03ea3ea986e8"},"package":"dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"}

View File

@ -1,24 +0,0 @@
language: rust
rust:
- 1.0.0
- 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 test --verbose
- cargo doc --no-deps
after_success:
- travis-cargo --only nightly doc-upload
env:
global:
secure: "kJnqqAXRl0C7Afx0c8Y3vA6TAEZsxlasu7eIZMdCbNS4N1+Rwh0jNTa2jy2D3CQCrzW5OCefnkpkPTu8mADrAjedM4p/9X5UXZi0sgg2lzCgfGwrRzitTnyPDkdYidiu4QeC/r0WPC8lYZKHkJXYhF8bZgchB9ypnZ6LAHCcDkA="
notifications:
email:
on_success: never

View File

@ -1,18 +0,0 @@
[package]
name = "rustc-serialize"
version = "0.3.24"
authors = ["The Rust Project Developers"]
license = "MIT/Apache-2.0"
readme = "README.md"
repository = "https://github.com/rust-lang/rustc-serialize"
homepage = "https://github.com/rust-lang/rustc-serialize"
documentation = "https://doc.rust-lang.org/rustc-serialize"
description = """
Generic serialization/deserialization support corresponding to the
`derive(RustcEncodable, RustcDecodable)` mode in the compiler. Also includes
support for hex, base64, and json encoding and decoding.
"""
[dev-dependencies]
rand = "0.3"

View File

@ -1,31 +0,0 @@
# rustc-serialize
> **NOTE**: This crate is deprecated in favor of [`serde`]. No new feature
> development will happen in this crate, although bug fixes proposed through PRs
> will still be merged. It is very highly recommended by the Rust Library Team
> that you use [`serde`], not this crate.
[`serde`]: https://serde.rs
Serialization and deserialization support provided by the compiler in the form
of `derive(RustcEncodable, RustcDecodable)`.
[![Linux Build Status](https://travis-ci.org/rust-lang-nursery/rustc-serialize.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rustc-serialize)
[![Windows Build Status](https://ci.appveyor.com/api/projects/status/ka194de75aapwpft?svg=true)](https://ci.appveyor.com/project/alexcrichton/rustc-serialize)
[Documentation](https://doc.rust-lang.org/rustc-serialize)
## Usage
Add this to your `Cargo.toml`:
```toml
[dependencies]
rustc-serialize = "0.3"
```
and this to your crate root:
```rust
extern crate rustc_serialize;
```

View File

@ -1,17 +0,0 @@
environment:
matrix:
- TARGET: x86_64-pc-windows-msvc
- TARGET: i686-pc-windows-msvc
- TARGET: i686-pc-windows-gnu
install:
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe"
- rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
- SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
- SET PATH=%PATH%;C:\MinGW\bin
- rustc -V
- cargo -V
build: false
test_script:
- cargo test --verbose

View File

@ -1,48 +0,0 @@
#![feature(test)]
extern crate test;
extern crate rustc_serialize;
use rustc_serialize::base64::{FromBase64, ToBase64, STANDARD};
use test::Bencher;
#[bench]
fn bench_to_base64(b: &mut Bencher) {
let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
";
b.iter(|| {
s.as_bytes().to_base64(STANDARD);
});
b.bytes = s.len() as u64;
}
#[bench]
fn bench_from_base64(b: &mut Bencher) {
let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
";
let sb = s.as_bytes().to_base64(STANDARD);
b.iter(|| {
sb.from_base64().unwrap();
});
b.bytes = sb.len() as u64;
}
#[bench]
fn bench_to_base64_large(b: &mut Bencher) {
let s: Vec<_> = (0..10000).map(|i| ((i as u32 * 12345) % 256) as u8).collect();
b.iter(|| {
s.to_base64(STANDARD);
});
b.bytes = s.len() as u64;
}
#[bench]
fn bench_from_base64_large(b: &mut Bencher) {
let s: Vec<_> = (0..10000).map(|i| ((i as u32 * 12345) % 256) as u8).collect();
let sb = s.to_base64(STANDARD);
b.iter(|| {
sb.from_base64().unwrap();
});
b.bytes = sb.len() as u64;
}

View File

@ -1,28 +0,0 @@
#![feature(test)]
extern crate test;
extern crate rustc_serialize;
use test::Bencher;
use rustc_serialize::hex::{FromHex, ToHex};
#[bench]
fn bench_to_hex(b: &mut Bencher) {
let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
";
b.iter(|| {
s.as_bytes().to_hex();
});
b.bytes = s.len() as u64;
}
#[bench]
fn bench_from_hex(b: &mut Bencher) {
let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
";
let sb = s.as_bytes().to_hex();
b.iter(|| {
sb.from_hex().unwrap();
});
b.bytes = sb.len() as u64;
}

View File

@ -1,84 +0,0 @@
#![feature(test)]
extern crate test;
extern crate rustc_serialize;
use std::string;
use rustc_serialize::json::{Json, Parser};
use test::Bencher;
#[bench]
fn bench_streaming_small(b: &mut Bencher) {
b.iter( || {
let mut parser = Parser::new(
r#"{
"a": 1.0,
"b": [
true,
"foo\nbar",
{ "c": {"d": null} }
]
}"#.chars()
);
loop {
match parser.next() {
None => return,
_ => {}
}
}
});
}
#[bench]
fn bench_small(b: &mut Bencher) {
b.iter( || {
let _ = Json::from_str(r#"{
"a": 1.0,
"b": [
true,
"foo\nbar",
{ "c": {"d": null} }
]
}"#);
});
}
#[bench]
fn bench_decode_hex_escape(b: &mut Bencher) {
let mut src = "\"".to_string();
for _ in 0..10 {
src.push_str("\\uF975\\uf9bc\\uF9A0\\uF9C4\\uF975\\uf9bc\\uF9A0\\uF9C4");
}
src.push_str("\"");
b.iter( || {
let _ = Json::from_str(&src);
});
}
fn big_json() -> string::String {
let mut src = "[\n".to_string();
for _ in 0..500 {
src.push_str(r#"{ "a": true, "b": null, "c":3.1415, "d": "Hello world", "e": \
[1,2,3]},"#);
}
src.push_str("{}]");
return src;
}
#[bench]
fn bench_streaming_large(b: &mut Bencher) {
let src = big_json();
b.iter( || {
let mut parser = Parser::new(src.chars());
loop {
match parser.next() {
None => return,
_ => {}
}
}
});
}
#[bench]
fn bench_large(b: &mut Bencher) {
let src = big_json();
b.iter( || { let _ = Json::from_str(&src); });
}

View File

@ -1,489 +0,0 @@
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// ignore-lexer-test FIXME #15679
//! Base64 binary-to-text encoding
pub use self::FromBase64Error::*;
pub use self::CharacterSet::*;
use std::fmt;
use std::error;
/// Available encoding character sets
#[derive(Clone, Copy, Debug)]
pub enum CharacterSet {
/// The standard character set (uses `+` and `/`)
Standard,
/// The URL safe character set (uses `-` and `_`)
UrlSafe
}
/// Available newline types
#[derive(Clone, Copy, Debug)]
pub enum Newline {
/// A linefeed (i.e. Unix-style newline)
LF,
/// A carriage return and a linefeed (i.e. Windows-style newline)
CRLF
}
/// Contains configuration parameters for `to_base64`.
#[derive(Clone, Copy, Debug)]
pub struct Config {
/// Character set to use
pub char_set: CharacterSet,
/// Newline to use
pub newline: Newline,
/// True to pad output with `=` characters
pub pad: bool,
/// `Some(len)` to wrap lines at `len`, `None` to disable line wrapping
pub line_length: Option<usize>
}
/// Configuration for RFC 4648 standard base64 encoding
pub static STANDARD: Config =
Config {char_set: Standard, newline: Newline::CRLF, pad: true, line_length: None};
/// Configuration for RFC 4648 base64url encoding
pub static URL_SAFE: Config =
Config {char_set: UrlSafe, newline: Newline::CRLF, pad: false, line_length: None};
/// Configuration for RFC 2045 MIME base64 encoding
pub static MIME: Config =
Config {char_set: Standard, newline: Newline::CRLF, pad: true, line_length: Some(76)};
static STANDARD_CHARS: &'static[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz\
0123456789+/";
static URLSAFE_CHARS: &'static[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz\
0123456789-_";
/// A trait for converting a value to base64 encoding.
pub trait ToBase64 {
/// Converts the value of `self` to a base64 value following the specified
/// format configuration, returning the owned string.
fn to_base64(&self, config: Config) -> String;
}
impl ToBase64 for [u8] {
/// Turn a vector of `u8` bytes into a base64 string.
///
/// # Example
///
/// ```rust
/// extern crate rustc_serialize;
/// use rustc_serialize::base64::{ToBase64, STANDARD};
///
/// fn main () {
/// let str = [52,32].to_base64(STANDARD);
/// println!("base 64 output: {:?}", str);
/// }
/// ```
fn to_base64(&self, config: Config) -> String {
let bytes = match config.char_set {
Standard => STANDARD_CHARS,
UrlSafe => URLSAFE_CHARS
};
let len = self.len();
let newline = match config.newline {
Newline::LF => "\n",
Newline::CRLF => "\r\n",
};
// Preallocate memory.
let mut prealloc_len = (len + 2) / 3 * 4;
if let Some(line_length) = config.line_length {
let num_lines = match prealloc_len {
0 => 0,
n => (n - 1) / line_length
};
prealloc_len += num_lines * newline.bytes().count();
}
let mut out_bytes = vec![b'='; prealloc_len];
// Deal with padding bytes
let mod_len = len % 3;
// Use iterators to reduce branching
{
let mut cur_length = 0;
let mut s_in = self[..len - mod_len].iter().map(|&x| x as u32);
let mut s_out = out_bytes.iter_mut();
// Convenient shorthand
let enc = |val| bytes[val as usize];
let mut write = |val| *s_out.next().unwrap() = val;
// Iterate though blocks of 4
while let (Some(first), Some(second), Some(third)) =
(s_in.next(), s_in.next(), s_in.next()) {
// Line break if needed
if let Some(line_length) = config.line_length {
if cur_length >= line_length {
for b in newline.bytes() { write(b) };
cur_length = 0;
}
}
let n = first << 16 | second << 8 | third;
// This 24-bit number gets separated into four 6-bit numbers.
write(enc((n >> 18) & 63));
write(enc((n >> 12) & 63));
write(enc((n >> 6 ) & 63));
write(enc((n >> 0 ) & 63));
cur_length += 4;
}
// Line break only needed if padding is required
if mod_len != 0 {
if let Some(line_length) = config.line_length {
if cur_length >= line_length {
for b in newline.bytes() { write(b) };
}
}
}
// Heh, would be cool if we knew this was exhaustive
// (the dream of bounded integer types)
match mod_len {
0 => (),
1 => {
let n = (self[len-1] as u32) << 16;
write(enc((n >> 18) & 63));
write(enc((n >> 12) & 63));
}
2 => {
let n = (self[len-2] as u32) << 16 |
(self[len-1] as u32) << 8;
write(enc((n >> 18) & 63));
write(enc((n >> 12) & 63));
write(enc((n >> 6 ) & 63));
}
_ => panic!("Algebra is broken, please alert the math police")
}
}
// We get padding for "free", so only have to drop it if unwanted.
if !config.pad {
while let Some(&b'=') = out_bytes.last() {
out_bytes.pop();
}
}
unsafe { String::from_utf8_unchecked(out_bytes) }
}
}
impl<'a, T: ?Sized + ToBase64> ToBase64 for &'a T {
fn to_base64(&self, config: Config) -> String {
(**self).to_base64(config)
}
}
/// A trait for converting from base64 encoded values.
pub trait FromBase64 {
/// Converts the value of `self`, interpreted as base64 encoded data, into
/// an owned vector of bytes, returning the vector.
fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error>;
}
/// Errors that can occur when decoding a base64 encoded string
#[derive(Clone, Copy)]
pub enum FromBase64Error {
/// The input contained a character not part of the base64 format
InvalidBase64Byte(u8, usize),
/// The input had an invalid length
InvalidBase64Length,
}
impl fmt::Debug for FromBase64Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
InvalidBase64Byte(ch, idx) =>
write!(f, "Invalid character '{}' at position {}", ch, idx),
InvalidBase64Length => write!(f, "Invalid length"),
}
}
}
impl error::Error for FromBase64Error {
fn description(&self) -> &str {
match *self {
InvalidBase64Byte(_, _) => "invalid character",
InvalidBase64Length => "invalid length",
}
}
}
impl fmt::Display for FromBase64Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self, f)
}
}
impl FromBase64 for str {
/// Convert any base64 encoded string (literal, `@`, `&`, or `~`)
/// to the byte values it encodes.
///
/// You can use the `String::from_utf8` function to turn a `Vec<u8>` into a
/// string with characters corresponding to those values.
///
/// # Example
///
/// This converts a string literal to base64 and back.
///
/// ```rust
/// extern crate rustc_serialize;
/// use rustc_serialize::base64::{ToBase64, FromBase64, STANDARD};
///
/// fn main () {
/// let hello_str = b"Hello, World".to_base64(STANDARD);
/// println!("base64 output: {}", hello_str);
/// let res = hello_str.from_base64();
/// if res.is_ok() {
/// let opt_bytes = String::from_utf8(res.unwrap());
/// if opt_bytes.is_ok() {
/// println!("decoded from base64: {:?}", opt_bytes.unwrap());
/// }
/// }
/// }
/// ```
#[inline]
fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error> {
self.as_bytes().from_base64()
}
}
impl FromBase64 for [u8] {
fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error> {
let mut r = Vec::with_capacity(self.len());
let mut buf: u32 = 0;
let mut modulus = 0;
let mut it = self.iter();
for byte in it.by_ref() {
let code = DECODE_TABLE[*byte as usize];
if code >= SPECIAL_CODES_START {
match code {
NEWLINE_CODE => continue,
EQUALS_CODE => break,
INVALID_CODE => return Err(InvalidBase64Byte(
*byte, (byte as *const _ as usize) - self.as_ptr() as usize)),
_ => unreachable!(),
}
}
buf = (buf | code as u32) << 6;
modulus += 1;
if modulus == 4 {
modulus = 0;
r.push((buf >> 22) as u8);
r.push((buf >> 14) as u8);
r.push((buf >> 6 ) as u8);
}
}
for byte in it {
match *byte {
b'=' | b'\r' | b'\n' => continue,
_ => return Err(InvalidBase64Byte(
*byte, (byte as *const _ as usize) - self.as_ptr() as usize)),
}
}
match modulus {
2 => {
r.push((buf >> 10) as u8);
}
3 => {
r.push((buf >> 16) as u8);
r.push((buf >> 8 ) as u8);
}
0 => (),
_ => return Err(InvalidBase64Length),
}
Ok(r)
}
}
impl<'a, T: ?Sized + FromBase64> FromBase64 for &'a T {
fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error> {
(**self).from_base64()
}
}
/// Base64 decoding lookup table, generated using:
///
/// ```
/// let mut ch = 0u8;
/// for ch in 0..255 {
/// let mut ch = ch as u8;
/// let code = match ch {
/// b'A'...b'Z' => ch - 0x41,
/// b'a'...b'z' => ch - 0x47,
/// b'0'...b'9' => ch + 0x04,
/// b'+' | b'-' => 0x3E,
/// b'/' | b'_' => 0x3F,
/// b'=' => 0xFE,
/// b'\r' | b'\n' => 0xFD,
/// _ => 0xFF,
/// };
/// print!("0x{:02X}, ", code);
/// if ch % 16 == 15 { println!(""); }
/// else if ch == 0xFF { break; }
/// ch += 1;
/// }
/// println!("");
/// ```
const DECODE_TABLE: [u8; 256] = [
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0x3E, 0xFF, 0x3F,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF,
0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F,
0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
];
const INVALID_CODE: u8 = 0xFF;
const EQUALS_CODE: u8 = 0xFE;
const NEWLINE_CODE: u8 = 0xFD;
const SPECIAL_CODES_START: u8 = NEWLINE_CODE;
#[cfg(test)]
mod tests {
use base64::{Config, Newline, FromBase64, ToBase64, STANDARD, URL_SAFE};
#[test]
fn test_to_base64_basic() {
assert_eq!("".as_bytes().to_base64(STANDARD), "");
assert_eq!("f".as_bytes().to_base64(STANDARD), "Zg==");
assert_eq!("fo".as_bytes().to_base64(STANDARD), "Zm8=");
assert_eq!("foo".as_bytes().to_base64(STANDARD), "Zm9v");
assert_eq!("foob".as_bytes().to_base64(STANDARD), "Zm9vYg==");
assert_eq!("fooba".as_bytes().to_base64(STANDARD), "Zm9vYmE=");
assert_eq!("foobar".as_bytes().to_base64(STANDARD), "Zm9vYmFy");
}
#[test]
fn test_to_base64_crlf_line_break() {
assert!(![0; 1000].to_base64(Config {line_length: None, ..STANDARD})
.contains("\r\n"));
assert_eq!(b"foobar".to_base64(Config {line_length: Some(4),
..STANDARD}),
"Zm9v\r\nYmFy");
}
#[test]
fn test_to_base64_lf_line_break() {
assert!(![0; 1000].to_base64(Config {line_length: None,
newline: Newline::LF,
..STANDARD})
.contains("\n"));
assert_eq!(b"foobar".to_base64(Config {line_length: Some(4),
newline: Newline::LF,
..STANDARD}),
"Zm9v\nYmFy");
}
#[test]
fn test_to_base64_padding() {
assert_eq!("f".as_bytes().to_base64(Config {pad: false, ..STANDARD}), "Zg");
assert_eq!("fo".as_bytes().to_base64(Config {pad: false, ..STANDARD}), "Zm8");
}
#[test]
fn test_to_base64_url_safe() {
assert_eq!([251, 255].to_base64(URL_SAFE), "-_8");
assert_eq!([251, 255].to_base64(STANDARD), "+/8=");
}
#[test]
fn test_to_base64_empty_line_length() {
[].to_base64(Config {line_length: Some(72), ..STANDARD});
}
#[test]
fn test_from_base64_basic() {
assert_eq!("".from_base64().unwrap(), b"");
assert_eq!("Zg==".from_base64().unwrap(), b"f");
assert_eq!("Zm8=".from_base64().unwrap(), b"fo");
assert_eq!("Zm9v".from_base64().unwrap(), b"foo");
assert_eq!("Zm9vYg==".from_base64().unwrap(), b"foob");
assert_eq!("Zm9vYmE=".from_base64().unwrap(), b"fooba");
assert_eq!("Zm9vYmFy".from_base64().unwrap(), b"foobar");
}
#[test]
fn test_from_base64_bytes() {
assert_eq!(b"Zm9vYmFy".from_base64().unwrap(), b"foobar");
}
#[test]
fn test_from_base64_newlines() {
assert_eq!("Zm9v\r\nYmFy".from_base64().unwrap(),
b"foobar");
assert_eq!("Zm9vYg==\r\n".from_base64().unwrap(),
b"foob");
assert_eq!("Zm9v\nYmFy".from_base64().unwrap(),
b"foobar");
assert_eq!("Zm9vYg==\n".from_base64().unwrap(),
b"foob");
}
#[test]
fn test_from_base64_urlsafe() {
assert_eq!("-_8".from_base64().unwrap(), "+/8=".from_base64().unwrap());
}
#[test]
fn test_from_base64_invalid_char() {
assert!("Zm$=".from_base64().is_err());
assert!("Zg==$".from_base64().is_err());
}
#[test]
fn test_from_base64_invalid_padding() {
assert!("Z===".from_base64().is_err());
}
#[test]
fn test_base64_random() {
use rand::{thread_rng, Rng};
for _ in 0..1000 {
let times = thread_rng().gen_range(1, 100);
let v = thread_rng().gen_iter::<u8>().take(times)
.collect::<Vec<_>>();
assert_eq!(v.to_base64(STANDARD)
.from_base64()
.unwrap(),
v);
}
}
}

View File

@ -1,186 +0,0 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Implementations of serialization for structures found in libcollections
use std::hash::Hash;
use {Decodable, Encodable, Decoder, Encoder, cap_capacity};
use std::collections::{LinkedList, VecDeque, BTreeMap, BTreeSet, HashMap, HashSet};
impl<
T: Encodable
> Encodable for LinkedList<T> {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
try!(s.emit_seq_elt(i, |s| e.encode(s)));
}
Ok(())
})
}
}
impl<T:Decodable> Decodable for LinkedList<T> {
fn decode<D: Decoder>(d: &mut D) -> Result<LinkedList<T>, D::Error> {
d.read_seq(|d, len| {
let mut list = LinkedList::new();
for i in 0..len {
list.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
}
Ok(list)
})
}
}
impl<T: Encodable> Encodable for VecDeque<T> {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
try!(s.emit_seq_elt(i, |s| e.encode(s)));
}
Ok(())
})
}
}
impl<T:Decodable> Decodable for VecDeque<T> {
fn decode<D: Decoder>(d: &mut D) -> Result<VecDeque<T>, D::Error> {
d.read_seq(|d, len| {
let mut deque: VecDeque<T> = VecDeque::new();
for i in 0..len {
deque.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
}
Ok(deque)
})
}
}
impl<
K: Encodable + Ord,
V: Encodable
> Encodable for BTreeMap<K, V> {
fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
e.emit_map(self.len(), |e| {
let mut i = 0;
for (key, val) in self.iter() {
try!(e.emit_map_elt_key(i, |e| key.encode(e)));
try!(e.emit_map_elt_val(i, |e| val.encode(e)));
i += 1;
}
Ok(())
})
}
}
impl<
K: Decodable + Ord,
V: Decodable
> Decodable for BTreeMap<K, V> {
fn decode<D: Decoder>(d: &mut D) -> Result<BTreeMap<K, V>, D::Error> {
d.read_map(|d, len| {
let mut map = BTreeMap::new();
for i in 0..len {
let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
map.insert(key, val);
}
Ok(map)
})
}
}
impl<
T: Encodable + Ord
> Encodable for BTreeSet<T> {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_seq(self.len(), |s| {
let mut i = 0;
for e in self.iter() {
try!(s.emit_seq_elt(i, |s| e.encode(s)));
i += 1;
}
Ok(())
})
}
}
impl<
T: Decodable + Ord
> Decodable for BTreeSet<T> {
fn decode<D: Decoder>(d: &mut D) -> Result<BTreeSet<T>, D::Error> {
d.read_seq(|d, len| {
let mut set = BTreeSet::new();
for i in 0..len {
set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
}
Ok(set)
})
}
}
impl<K, V> Encodable for HashMap<K, V>
where K: Encodable + Hash + Eq,
V: Encodable,
{
fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
e.emit_map(self.len(), |e| {
let mut i = 0;
for (key, val) in self.iter() {
try!(e.emit_map_elt_key(i, |e| key.encode(e)));
try!(e.emit_map_elt_val(i, |e| val.encode(e)));
i += 1;
}
Ok(())
})
}
}
impl<K, V> Decodable for HashMap<K, V>
where K: Decodable + Hash + Eq,
V: Decodable,
{
fn decode<D: Decoder>(d: &mut D) -> Result<HashMap<K, V>, D::Error> {
d.read_map(|d, len| {
let mut map = HashMap::with_capacity(cap_capacity::<(K, V)>(len));
for i in 0..len {
let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
map.insert(key, val);
}
Ok(map)
})
}
}
impl<T> Encodable for HashSet<T> where T: Encodable + Hash + Eq {
fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
s.emit_seq(self.len(), |s| {
let mut i = 0;
for e in self.iter() {
try!(s.emit_seq_elt(i, |s| e.encode(s)));
i += 1;
}
Ok(())
})
}
}
impl<T> Decodable for HashSet<T> where T: Decodable + Hash + Eq, {
fn decode<D: Decoder>(d: &mut D) -> Result<HashSet<T>, D::Error> {
d.read_seq(|d, len| {
let mut set = HashSet::with_capacity(cap_capacity::<T>(len));
for i in 0..len {
set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
}
Ok(set)
})
}
}

View File

@ -1,221 +0,0 @@
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// ignore-lexer-test FIXME #15679
//! Hex binary-to-text encoding
pub use self::FromHexError::*;
use std::fmt;
use std::error;
/// A trait for converting a value to hexadecimal encoding
pub trait ToHex {
/// Converts the value of `self` to a hex value, returning the owned
/// string.
fn to_hex(&self) -> String;
}
static CHARS: &'static[u8] = b"0123456789abcdef";
impl ToHex for [u8] {
/// Turn a vector of `u8` bytes into a hexadecimal string.
///
/// # Example
///
/// ```rust
/// extern crate rustc_serialize;
/// use rustc_serialize::hex::ToHex;
///
/// fn main () {
/// let str = [52,32].to_hex();
/// println!("{}", str);
/// }
/// ```
fn to_hex(&self) -> String {
let mut v = Vec::with_capacity(self.len() * 2);
for &byte in self.iter() {
v.push(CHARS[(byte >> 4) as usize]);
v.push(CHARS[(byte & 0xf) as usize]);
}
unsafe {
String::from_utf8_unchecked(v)
}
}
}
impl<'a, T: ?Sized + ToHex> ToHex for &'a T {
fn to_hex(&self) -> String {
(**self).to_hex()
}
}
/// A trait for converting hexadecimal encoded values
pub trait FromHex {
/// Converts the value of `self`, interpreted as hexadecimal encoded data,
/// into an owned vector of bytes, returning the vector.
fn from_hex(&self) -> Result<Vec<u8>, FromHexError>;
}
/// Errors that can occur when decoding a hex encoded string
#[derive(Clone, Copy)]
pub enum FromHexError {
/// The input contained a character not part of the hex format
InvalidHexCharacter(char, usize),
/// The input had an invalid length
InvalidHexLength,
}
impl fmt::Debug for FromHexError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
InvalidHexCharacter(ch, idx) =>
write!(f, "Invalid character '{}' at position {}", ch, idx),
InvalidHexLength => write!(f, "Invalid input length"),
}
}
}
impl error::Error for FromHexError {
fn description(&self) -> &str {
match *self {
InvalidHexCharacter(_, _) => "invalid character",
InvalidHexLength => "invalid length",
}
}
}
impl fmt::Display for FromHexError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self, f)
}
}
impl FromHex for str {
/// Convert any hexadecimal encoded string (literal, `@`, `&`, or `~`)
/// to the byte values it encodes.
///
/// You can use the `String::from_utf8` function to turn a
/// `Vec<u8>` into a string with characters corresponding to those values.
///
/// # Example
///
/// This converts a string literal to hexadecimal and back.
///
/// ```rust
/// extern crate rustc_serialize;
/// use rustc_serialize::hex::{FromHex, ToHex};
///
/// fn main () {
/// let hello_str = "Hello, World".as_bytes().to_hex();
/// println!("{}", hello_str);
/// let bytes = hello_str.from_hex().unwrap();
/// println!("{:?}", bytes);
/// let result_str = String::from_utf8(bytes).unwrap();
/// println!("{}", result_str);
/// }
/// ```
fn from_hex(&self) -> Result<Vec<u8>, FromHexError> {
// This may be an overestimate if there is any whitespace
let mut b = Vec::with_capacity(self.len() / 2);
let mut modulus = 0;
let mut buf = 0;
for (idx, byte) in self.bytes().enumerate() {
buf <<= 4;
match byte {
b'A'...b'F' => buf |= byte - b'A' + 10,
b'a'...b'f' => buf |= byte - b'a' + 10,
b'0'...b'9' => buf |= byte - b'0',
b' '|b'\r'|b'\n'|b'\t' => {
buf >>= 4;
continue
}
_ => {
let ch = self[idx..].chars().next().unwrap();
return Err(InvalidHexCharacter(ch, idx))
}
}
modulus += 1;
if modulus == 2 {
modulus = 0;
b.push(buf);
}
}
match modulus {
0 => Ok(b.into_iter().collect()),
_ => Err(InvalidHexLength),
}
}
}
impl<'a, T: ?Sized + FromHex> FromHex for &'a T {
fn from_hex(&self) -> Result<Vec<u8>, FromHexError> {
(**self).from_hex()
}
}
#[cfg(test)]
mod tests {
use hex::{FromHex, ToHex};
#[test]
pub fn test_to_hex() {
assert_eq!("foobar".as_bytes().to_hex(), "666f6f626172");
}
#[test]
pub fn test_from_hex_okay() {
assert_eq!("666f6f626172".from_hex().unwrap(),
b"foobar");
assert_eq!("666F6F626172".from_hex().unwrap(),
b"foobar");
}
#[test]
pub fn test_from_hex_odd_len() {
assert!("666".from_hex().is_err());
assert!("66 6".from_hex().is_err());
}
#[test]
pub fn test_from_hex_invalid_char() {
assert!("66y6".from_hex().is_err());
}
#[test]
pub fn test_from_hex_ignores_whitespace() {
assert_eq!("666f 6f6\r\n26172 ".from_hex().unwrap(),
b"foobar");
}
#[test]
pub fn test_to_hex_all_bytes() {
for i in 0..256 {
assert_eq!([i as u8].to_hex(), format!("{:02x}", i));
}
}
#[test]
pub fn test_from_hex_all_bytes() {
for i in 0..256 {
let ii: &[u8] = &[i as u8];
assert_eq!(format!("{:02x}", i).from_hex().unwrap(),
ii);
assert_eq!(format!("{:02X}", i).from_hex().unwrap(),
ii);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,79 +0,0 @@
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Support code for encoding and decoding types.
//!
//! > **NOTE**: This crate is deprecated in favor of [`serde`]. No new feature
//! > development will happen in this crate, although bug fixes proposed through
//! > PRs will still be merged. It is very highly recommended by the Rust
//! > Library Team that you use [`serde`], not this crate.
//!
//! [`serde`]: https://serde.rs
//!
//! # Usage
//!
//! This crate is [on crates.io](https://crates.io/crates/rustc-serialize) and
//! can be used by adding `rustc-serialize` to the dependencies in your
//! project's `Cargo.toml`.
//!
//! ```toml
//! [dependencies]
//! rustc-serialize = "0.3"
//! ```
//!
//! and this to your crate root:
//!
//! ```rust
//! extern crate rustc_serialize;
//! ```
#![cfg_attr(rustbuild, feature(staged_api, rustc_private))]
#![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/rustc-serialize/")]
#![cfg_attr(test, deny(warnings))]
#![allow(trivial_numeric_casts)]
#![cfg_attr(rust_build, feature(staged_api))]
#![cfg_attr(rust_build, staged_api)]
#![cfg_attr(rust_build,
unstable(feature = "rustc_private",
reason = "use the crates.io `rustc-serialize` library instead"))]
#[cfg(test)] extern crate rand;
pub use self::serialize::{Decoder, Encoder, Decodable, Encodable,
DecoderHelpers, EncoderHelpers};
// Limit collections from allocating more than
// 1 MB for calls to `with_capacity`.
fn cap_capacity<T>(given_len: usize) -> usize {
use std::cmp::min;
use std::mem::size_of;
const PRE_ALLOCATE_CAP: usize = 0x100000;
match size_of::<T>() {
0 => min(given_len, PRE_ALLOCATE_CAP),
n => min(given_len, PRE_ALLOCATE_CAP / n)
}
}
mod serialize;
mod collection_impls;
pub mod base64;
pub mod hex;
pub mod json;
mod rustc_serialize {
pub use serialize::*;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
{"files":{".travis.yml":"f73b83dfd8c84e2af27d780e93441a071507c8c2d981a73844558fe72717448e","Cargo.toml":"a97493cb1e3f170d30a5f8d92ae65185103083baf408eb5c0bd8f64a7ffdf007","LICENSE-APACHE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","README.md":"d150ab564033cacab1e6e806b13e78bb241818e950ffa4bf2623e6bd3bc64fb3","benchmark/benchmark.rs":"5ee2d5f68f6fa93f24e3828c9e8e269c22ce3ea96c0804def61b0b3026ad021f","build.rs":"96e9308d3a7a23a4c222892be8f29f45b13bffaed751f2e5b0b247230b65f360","src/buffer/mod.rs":"bcdc3db1c97b36c04c4445c4a7fba768be7a8b16e0f8bc7bab86ac06256a9750","src/common.rs":"f165881b718867b7801044bd29fa7f4322ebfc63d45d462d4a703253f8812a3e","src/d2s.rs":"35e0982e83d8c46f4304148d0454957b62be5f17480ad417d893521d578ad86e","src/d2s_full_table.rs":"7f7e475c54ae69d834574603bde9dcbe9f0d7cb09cfc3cda025319c903996bf8","src/d2s_small_table.rs":"f1bc5b328be636f100315ba818545e7d3c125cacec8487ed12f59f50d70b945e","src/digit_table.rs":"02351ca54cb8cb3679f635115dd094f32fd91750e9f66103c1ee9ec3db507072","src/f2s.rs":"2a59cc3ea57244ef4e926d98284a33363fb67452e20f24141395312173698e32","src/lib.rs":"268d75e445101f1edc0ced93852941ab9b150f1faea642490a03e8a613a33589","src/mulshift128.rs":"b539411c08b7cde489b876addc346a061e3594ed707fe577a3cdff6d26b0e1f8","src/pretty/exponent.rs":"15fd163fdb81573d331f24fda37f5403931512ffb08715a2695f0a0256b69b84","src/pretty/mantissa.rs":"7b0ea97069ee597f3bc0c8f2f3354c75be93d01c6a8135104ae82cd83df318e0","src/pretty/mod.rs":"f691267e66ce6f13d6db17ca6b93065e50a669e73916cbd22c8bfb3e33ad85fe","tests/d2s_table_test.rs":"57b541dc08c54c83979f18a20f8895daac3ad32628b140c66b09f42bce7f2691","tests/d2s_test.rs":"9abea253a30d96815688a34f20e2b3eff40c9d8b9a1209d7e927ba5a63efd74a","tests/exhaustive.rs":"0e01491936cb6b5ae68d92e50b6f7cebb26362774e860df103695ecc1f71fa7b","tests/f2s_test.rs":"7fa9dd515ed42947f570243a6d0656b6e2861c1399f679d96317dc109018d59b","tests/macros/mod.rs":"45eed20e9a3d8d9b673f504e8194f762223346adec46a6fbf1e0717eaeee85bc"},"package":"fd0568787116e13c652377b6846f5931454a363a8fdf8ae50463ee40935b278b"}

13
third_party/rust/ryu/.travis.yml vendored Normal file
View File

@ -0,0 +1,13 @@
language: rust
rust:
- nightly
- beta
- stable
matrix:
include:
- rust: 1.15.0
script:
- cargo build
- cargo build --features small

39
third_party/rust/ryu/Cargo.toml vendored Normal file
View File

@ -0,0 +1,39 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g. crates.io) dependencies
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
[package]
name = "ryu"
version = "0.2.4"
authors = ["David Tolnay <dtolnay@gmail.com>"]
build = "build.rs"
description = "Fast floating point to string conversion"
documentation = "https://docs.rs/ryu"
readme = "README.md"
license = "Apache-2.0"
repository = "https://github.com/dtolnay/ryu"
[[example]]
name = "benchmark"
path = "benchmark/benchmark.rs"
[dependencies.no-panic]
version = "0.1"
optional = true
[dev-dependencies.num_cpus]
version = "1.8"
[dev-dependencies.rand]
version = "0.5"
[features]
small = []
[badges.travis-ci]
repository = "dtolnay/ryu"

201
third_party/rust/ryu/LICENSE-APACHE vendored Normal file
View 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.

74
third_party/rust/ryu/README.md vendored Normal file
View File

@ -0,0 +1,74 @@
# Ryū
[![Build Status](https://api.travis-ci.org/dtolnay/ryu.svg?branch=master)](https://travis-ci.org/dtolnay/ryu)
[![Latest Version](https://img.shields.io/crates/v/ryu.svg)](https://crates.io/crates/ryu)
[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/ryu)
[![Rustc Version 1.15+](https://img.shields.io/badge/rustc-1.15+-lightgray.svg)](https://blog.rust-lang.org/2017/02/02/Rust-1.15.html)
Pure Rust implementation of Ryū, an algorithm to quickly convert floating point
numbers to decimal strings.
The PLDI'18 paper [*Ryū: fast float-to-string conversion*][paper] by Ulf Adams
includes a complete correctness proof of the algorithm. The paper is available
under the creative commons CC-BY-SA license.
This Rust implementation is a line-by-line port of Ulf Adams' implementation in
C, [https://github.com/ulfjack/ryu][upstream]. The `ryu::raw` module exposes
exactly the API and formatting of the C implementation as unsafe pure Rust
functions. There is additionally a safe API as demonstrated in the example code
below. The safe API uses the same underlying Ryū algorithm but diverges from the
formatting of the C implementation to produce more human-readable output, for
example `0.3` rather than `3E-1`.
*Requirements: this crate supports any compiler version back to rustc 1.15; it
uses nothing from the Rust standard library so is usable from no_std crates.*
[paper]: https://dl.acm.org/citation.cfm?id=3192369
[upstream]: https://github.com/ulfjack/ryu/tree/4ffc2b759e4b0a431b35dbfbfd6e0e85fdd15a69
```toml
[dependencies]
ryu = "0.2"
```
## Examples
```rust
extern crate ryu;
fn main() {
let mut buffer = ryu::Buffer::new();
let printed = buffer.format(1.234);
assert_eq!(printed, "1.234");
}
```
## Performance
You can run upstream's benchmarks with:
```console
$ git clone https://github.com/ulfjack/ryu c-ryu
$ cd c-ryu
$ bazel run -c opt //ryu/benchmark
```
And our benchmarks with:
```console
$ git clone https://github.com/ulfjack/ryu rust-ryu
$ cd rust-ryu
$ cargo run --example benchmark --release
```
These benchmarks measure the average time to print a 32-bit float and average
time to print a 64-bit float, where the inputs are distributed as uniform random
bit patterns 32 and 64 bits wide.
The upstream C code, the unsafe direct Rust port, and the safe pretty Rust API
all perform the same, taking around 21 nanoseconds to format a 32-bit float and
31 nanoseconds to format a 64-bit float.
## License
Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)

View File

@ -0,0 +1,86 @@
extern crate rand;
extern crate ryu;
use rand::{Rng, SeedableRng};
const SAMPLES: usize = 10000;
const ITERATIONS: usize = 1000;
struct MeanAndVariance {
n: i64,
mean: f64,
m2: f64,
}
impl MeanAndVariance {
fn new() -> Self {
MeanAndVariance {
n: 0,
mean: 0.0,
m2: 0.0,
}
}
fn update(&mut self, x: f64) {
self.n += 1;
let d = x - self.mean;
self.mean += d / self.n as f64;
let d2 = x - self.mean;
self.m2 += d * d2;
}
fn variance(&self) -> f64 {
self.m2 / (self.n - 1) as f64
}
fn stddev(&self) -> f64 {
self.variance().sqrt()
}
}
macro_rules! benchmark {
($name:ident, $ty:ident) => {
fn $name() -> usize {
let mut rng = rand::prng::XorShiftRng::from_seed([123u8; 16]);
let mut mv = MeanAndVariance::new();
let mut throwaway = 0;
for _ in 0..SAMPLES {
let f = loop {
let f = $ty::from_bits(rng.gen());
if f.is_finite() {
break f;
}
};
let t1 = std::time::SystemTime::now();
for _ in 0..ITERATIONS {
throwaway += ryu::Buffer::new().format(f).len();
}
let duration = t1.elapsed().unwrap();
let nanos = duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as u64;
mv.update(nanos as f64 / ITERATIONS as f64);
}
println!(
"{:12} {:8.3} {:8.3}",
concat!(stringify!($name), ":"),
mv.mean,
mv.stddev(),
);
throwaway
}
};
}
benchmark!(pretty32, f32);
benchmark!(pretty64, f64);
fn main() {
println!("{:>20}{:>9}", "Average", "Stddev");
let mut throwaway = 0;
throwaway += pretty32();
throwaway += pretty64();
if std::env::var_os("ryu-benchmark").is_some() {
// Prevent the compiler from optimizing the code away.
println!("{}", throwaway);
}
}

54
third_party/rust/ryu/build.rs vendored Normal file
View File

@ -0,0 +1,54 @@
use std::env;
use std::process::Command;
use std::str::{self, FromStr};
// The rustc-cfg strings below are *not* public API. Please let us know by
// opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script.
fn main() {
let minor = match rustc_minor_version() {
Some(minor) => minor,
None => return,
};
// 128-bit integers stabilized in Rust 1.26:
// https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
if minor >= 26 {
println!("cargo:rustc-cfg=integer128");
}
// #[must_use] on functions stabilized in Rust 1.27:
// https://blog.rust-lang.org/2018/06/21/Rust-1.27.html
if minor >= 27 {
println!("cargo:rustc-cfg=must_use_return");
}
}
fn rustc_minor_version() -> Option<u32> {
let rustc = match env::var_os("RUSTC") {
Some(rustc) => rustc,
None => return None,
};
let output = match Command::new(rustc).arg("--version").output() {
Ok(output) => output,
Err(_) => return None,
};
let version = match str::from_utf8(&output.stdout) {
Ok(version) => version,
Err(_) => return None,
};
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return None;
}
let next = match pieces.next() {
Some(next) => next,
None => return None,
};
u32::from_str(next).ok()
}

97
third_party/rust/ryu/src/buffer/mod.rs vendored Normal file
View File

@ -0,0 +1,97 @@
use core::{mem, slice, str};
use pretty;
#[cfg(feature = "no-panic")]
use no_panic::no_panic;
/// Safe API for formatting floating point numbers to text.
///
/// ## Example
///
/// ```rust
/// let mut buffer = ryu::Buffer::new();
/// let printed = buffer.format(1.234);
/// assert_eq!(printed, "1.234");
/// ```
#[derive(Copy, Clone)]
pub struct Buffer {
bytes: [u8; 24],
}
impl Buffer {
/// This is a cheap operation; you don't need to worry about reusing buffers
/// for efficiency.
#[inline]
#[cfg_attr(feature = "no-panic", no_panic)]
pub fn new() -> Self {
Buffer {
bytes: unsafe { mem::uninitialized() },
}
}
/// Print a floating point number into this buffer and return a reference to
/// its string representation within the buffer.
///
/// # Special cases
///
/// This function **does not** check for NaN or infinity. If the input
/// number is not a finite float, the printed representation will be some
/// correctly formatted but unspecified numerical value.
///
/// Please check [`is_finite`] yourself before calling this function, or
/// check [`is_nan`] and [`is_infinite`] and handle those cases yourself.
///
/// [`is_finite`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_finite
/// [`is_nan`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_nan
/// [`is_infinite`]: https://doc.rust-lang.org/std/primitive.f64.html#method.is_infinite
#[inline]
#[cfg_attr(feature = "no-panic", no_panic)]
pub fn format<F: Float>(&mut self, f: F) -> &str {
unsafe {
let n = f.write_to_ryu_buffer(&mut self.bytes[0]);
debug_assert!(n <= self.bytes.len());
let slice = slice::from_raw_parts(&self.bytes[0], n);
str::from_utf8_unchecked(slice)
}
}
}
impl Default for Buffer {
#[inline]
#[cfg_attr(feature = "no-panic", no_panic)]
fn default() -> Self {
Buffer::new()
}
}
/// A floating point number, f32 or f64, that can be written into a
/// [`ryu::Buffer`][Buffer].
///
/// This trait is sealed and cannot be implemented for types outside of the
/// `ryu` crate.
pub trait Float: Sealed {
// Not public API.
#[doc(hidden)]
unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize;
}
impl Float for f32 {
#[inline]
#[cfg_attr(feature = "no-panic", no_panic)]
unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize {
pretty::f2s_buffered_n(self, result)
}
}
impl Float for f64 {
#[inline]
#[cfg_attr(feature = "no-panic", no_panic)]
unsafe fn write_to_ryu_buffer(self, result: *mut u8) -> usize {
pretty::d2s_buffered_n(self, result)
}
}
pub trait Sealed {}
impl Sealed for f32 {}
impl Sealed for f64 {}

72
third_party/rust/ryu/src/common.rs vendored Normal file
View File

@ -0,0 +1,72 @@
// Translated from C to Rust. The original C code can be found at
// https://github.com/ulfjack/ryu and carries the following license:
//
// Copyright 2018 Ulf Adams
//
// The contents of this file may be used under the terms of the Apache License,
// Version 2.0.
//
// (See accompanying file LICENSE-Apache or copy at
// http://www.apache.org/licenses/LICENSE-2.0)
//
// Alternatively, the contents of this file may be used under the terms of
// the Boost Software License, Version 1.0.
// (See accompanying file LICENSE-Boost or copy at
// https://www.boost.org/LICENSE_1_0.txt)
//
// Unless required by applicable law or agreed to in writing, this software
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
use core::ptr;
// Returns e == 0 ? 1 : ceil(log_2(5^e)).
#[cfg_attr(feature = "no-panic", inline)]
pub fn pow5bits(e: i32) -> u32 {
// This approximation works up to the point that the multiplication overflows at e = 3529.
// If the multiplication were done in 64 bits, it would fail at 5^4004 which is just greater
// than 2^9297.
debug_assert!(e >= 0);
debug_assert!(e <= 3528);
((e as u32 * 1217359) >> 19) + 1
}
// Returns floor(log_10(2^e)).
#[cfg_attr(feature = "no-panic", inline)]
pub fn log10_pow2(e: i32) -> i32 {
// The first value this approximation fails for is 2^1651 which is just greater than 10^297.
debug_assert!(e >= 0);
debug_assert!(e <= 1650);
((e as u32 * 78913) >> 18) as i32
}
// Returns floor(log_10(5^e)).
#[cfg_attr(feature = "no-panic", inline)]
pub fn log10_pow5(e: i32) -> i32 {
// The first value this approximation fails for is 5^2621 which is just greater than 10^1832.
debug_assert!(e >= 0);
debug_assert!(e <= 2620);
((e as u32 * 732923) >> 20) as i32
}
#[cfg_attr(feature = "no-panic", inline)]
pub unsafe fn copy_special_str(
result: *mut u8,
sign: bool,
exponent: bool,
mantissa: bool,
) -> usize {
if mantissa {
ptr::copy_nonoverlapping(b"NaN".as_ptr(), result, 3);
return 3;
}
if sign {
*result = b'-';
}
if exponent {
ptr::copy_nonoverlapping(b"Infinity".as_ptr(), result.offset(sign as isize), 8);
return sign as usize + 8;
}
ptr::copy_nonoverlapping(b"0E0".as_ptr(), result.offset(sign as isize), 3);
sign as usize + 3
}

553
third_party/rust/ryu/src/d2s.rs vendored Normal file
View File

@ -0,0 +1,553 @@
// Translated from C to Rust. The original C code can be found at
// https://github.com/ulfjack/ryu and carries the following license:
//
// Copyright 2018 Ulf Adams
//
// The contents of this file may be used under the terms of the Apache License,
// Version 2.0.
//
// (See accompanying file LICENSE-Apache or copy at
// http://www.apache.org/licenses/LICENSE-2.0)
//
// Alternatively, the contents of this file may be used under the terms of
// the Boost Software License, Version 1.0.
// (See accompanying file LICENSE-Boost or copy at
// https://www.boost.org/LICENSE_1_0.txt)
//
// Unless required by applicable law or agreed to in writing, this software
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
use core::{mem, ptr};
use common::*;
#[cfg(not(feature = "small"))]
use d2s_full_table::*;
#[cfg(feature = "small")]
use d2s_small_table::*;
use digit_table::*;
#[cfg(not(integer128))]
use mulshift128::*;
#[cfg(feature = "no-panic")]
use no_panic::no_panic;
pub const DOUBLE_MANTISSA_BITS: u32 = 52;
pub const DOUBLE_EXPONENT_BITS: u32 = 11;
const DOUBLE_POW5_INV_BITCOUNT: i32 = 122;
const DOUBLE_POW5_BITCOUNT: i32 = 121;
#[cfg_attr(feature = "no-panic", inline)]
fn pow5_factor(mut value: u64) -> u32 {
let mut count = 0u32;
loop {
debug_assert!(value != 0);
let q = value / 5;
let r = value % 5;
if r != 0 {
break;
}
value = q;
count += 1;
}
count
}
// Returns true if value is divisible by 5^p.
#[cfg_attr(feature = "no-panic", inline)]
fn multiple_of_power_of_5(value: u64, p: u32) -> bool {
// I tried a case distinction on p, but there was no performance difference.
pow5_factor(value) >= p
}
// Returns true if value is divisible by 2^p.
#[cfg_attr(feature = "no-panic", inline)]
fn multiple_of_power_of_2(value: u64, p: u32) -> bool {
// return __builtin_ctzll(value) >= p;
(value & ((1u64 << p) - 1)) == 0
}
#[cfg(integer128)]
#[cfg_attr(feature = "no-panic", inline)]
fn mul_shift(m: u64, mul: &(u64, u64), j: u32) -> u64 {
let b0 = m as u128 * mul.0 as u128;
let b2 = m as u128 * mul.1 as u128;
(((b0 >> 64) + b2) >> (j - 64)) as u64
}
#[cfg(integer128)]
#[cfg_attr(feature = "no-panic", inline)]
fn mul_shift_all(
m: u64,
mul: &(u64, u64),
j: u32,
vp: &mut u64,
vm: &mut u64,
mm_shift: u32,
) -> u64 {
*vp = mul_shift(4 * m + 2, mul, j);
*vm = mul_shift(4 * m - 1 - mm_shift as u64, mul, j);
mul_shift(4 * m, mul, j)
}
#[cfg(not(integer128))]
#[cfg_attr(feature = "no-panic", inline)]
fn mul_shift_all(
mut m: u64,
mul: &(u64, u64),
j: u32,
vp: &mut u64,
vm: &mut u64,
mm_shift: u32,
) -> u64 {
m <<= 1;
// m is maximum 55 bits
let (lo, tmp) = umul128(m, mul.0);
let (mut mid, mut hi) = umul128(m, mul.1);
mid = mid.wrapping_add(tmp);
hi = hi.wrapping_add((mid < tmp) as u64); // overflow into hi
let lo2 = lo.wrapping_add(mul.0);
let mid2 = mid.wrapping_add(mul.1).wrapping_add((lo2 < lo) as u64);
let hi2 = hi.wrapping_add((mid2 < mid) as u64);
*vp = shiftright128(mid2, hi2, j - 64 - 1);
if mm_shift == 1 {
let lo3 = lo.wrapping_sub(mul.0);
let mid3 = mid.wrapping_sub(mul.1).wrapping_sub((lo3 > lo) as u64);
let hi3 = hi.wrapping_sub((mid3 > mid) as u64);
*vm = shiftright128(mid3, hi3, j - 64 - 1);
} else {
let lo3 = lo + lo;
let mid3 = mid.wrapping_add(mid).wrapping_add((lo3 < lo) as u64);
let hi3 = hi.wrapping_add(hi).wrapping_add((mid3 < mid) as u64);
let lo4 = lo3.wrapping_sub(mul.0);
let mid4 = mid3.wrapping_sub(mul.1).wrapping_sub((lo4 > lo3) as u64);
let hi4 = hi3.wrapping_sub((mid4 > mid3) as u64);
*vm = shiftright128(mid4, hi4, j - 64);
}
shiftright128(mid, hi, j - 64 - 1)
}
#[cfg_attr(feature = "no-panic", inline)]
pub fn decimal_length(v: u64) -> u32 {
// This is slightly faster than a loop.
// The average output length is 16.38 digits, so we check high-to-low.
// Function precondition: v is not an 18, 19, or 20-digit number.
// (17 digits are sufficient for round-tripping.)
debug_assert!(v < 100000000000000000);
if v >= 10000000000000000 {
17
} else if v >= 1000000000000000 {
16
} else if v >= 100000000000000 {
15
} else if v >= 10000000000000 {
14
} else if v >= 1000000000000 {
13
} else if v >= 100000000000 {
12
} else if v >= 10000000000 {
11
} else if v >= 1000000000 {
10
} else if v >= 100000000 {
9
} else if v >= 10000000 {
8
} else if v >= 1000000 {
7
} else if v >= 100000 {
6
} else if v >= 10000 {
5
} else if v >= 1000 {
4
} else if v >= 100 {
3
} else if v >= 10 {
2
} else {
1
}
}
// A floating decimal representing m * 10^e.
pub struct FloatingDecimal64 {
pub mantissa: u64,
pub exponent: i32,
}
#[cfg_attr(feature = "no-panic", inline)]
pub fn d2d(ieee_mantissa: u64, ieee_exponent: u32) -> FloatingDecimal64 {
let bias = (1u32 << (DOUBLE_EXPONENT_BITS - 1)) - 1;
let (e2, m2) = if ieee_exponent == 0 {
(
// We subtract 2 so that the bounds computation has 2 additional bits.
1 - bias as i32 - DOUBLE_MANTISSA_BITS as i32 - 2,
ieee_mantissa,
)
} else {
(
ieee_exponent as i32 - bias as i32 - DOUBLE_MANTISSA_BITS as i32 - 2,
(1u64 << DOUBLE_MANTISSA_BITS) | ieee_mantissa,
)
};
let even = (m2 & 1) == 0;
let accept_bounds = even;
// Step 2: Determine the interval of legal decimal representations.
let mv = 4 * m2;
// Implicit bool -> int conversion. True is 1, false is 0.
let mm_shift = (ieee_mantissa != 0 || ieee_exponent <= 1) as u32;
// We would compute mp and mm like this:
// uint64_t mp = 4 * m2 + 2;
// uint64_t mm = mv - 1 - mm_shift;
// Step 3: Convert to a decimal power base using 128-bit arithmetic.
let mut vr: u64;
let mut vp: u64 = unsafe { mem::uninitialized() };
let mut vm: u64 = unsafe { mem::uninitialized() };
let e10: i32;
let mut vm_is_trailing_zeros = false;
let mut vr_is_trailing_zeros = false;
if e2 >= 0 {
// I tried special-casing q == 0, but there was no effect on performance.
// This expression is slightly faster than max(0, log10_pow2(e2) - 1).
let q = (log10_pow2(e2) - (e2 > 3) as i32) as u32;
e10 = q as i32;
let k = DOUBLE_POW5_INV_BITCOUNT + pow5bits(q as i32) as i32 - 1;
let i = -e2 + q as i32 + k;
vr = mul_shift_all(
m2,
#[cfg(feature = "small")]
unsafe {
&compute_inv_pow5(q)
},
#[cfg(not(feature = "small"))]
unsafe {
debug_assert!(q < DOUBLE_POW5_INV_SPLIT.len() as u32);
DOUBLE_POW5_INV_SPLIT.get_unchecked(q as usize)
},
i as u32,
&mut vp,
&mut vm,
mm_shift,
);
if q <= 21 {
// This should use q <= 22, but I think 21 is also safe. Smaller values
// may still be safe, but it's more difficult to reason about them.
// Only one of mp, mv, and mm can be a multiple of 5, if any.
if mv % 5 == 0 {
vr_is_trailing_zeros = multiple_of_power_of_5(mv, q);
} else if accept_bounds {
// Same as min(e2 + (~mm & 1), pow5_factor(mm)) >= q
// <=> e2 + (~mm & 1) >= q && pow5_factor(mm) >= q
// <=> true && pow5_factor(mm) >= q, since e2 >= q.
vm_is_trailing_zeros = multiple_of_power_of_5(mv - 1 - mm_shift as u64, q);
} else {
// Same as min(e2 + 1, pow5_factor(mp)) >= q.
vp -= multiple_of_power_of_5(mv + 2, q) as u64;
}
}
} else {
// This expression is slightly faster than max(0, log10_pow5(-e2) - 1).
let q = (log10_pow5(-e2) - (-e2 > 1) as i32) as u32;
e10 = q as i32 + e2;
let i = -e2 - q as i32;
let k = pow5bits(i) as i32 - DOUBLE_POW5_BITCOUNT;
let j = q as i32 - k;
vr = mul_shift_all(
m2,
#[cfg(feature = "small")]
unsafe {
&compute_pow5(i as u32)
},
#[cfg(not(feature = "small"))]
unsafe {
debug_assert!(i < DOUBLE_POW5_SPLIT.len() as i32);
DOUBLE_POW5_SPLIT.get_unchecked(i as usize)
},
j as u32,
&mut vp,
&mut vm,
mm_shift,
);
if q <= 1 {
// {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q trailing 0 bits.
// mv = 4 * m2, so it always has at least two trailing 0 bits.
vr_is_trailing_zeros = true;
if accept_bounds {
// mm = mv - 1 - mm_shift, so it has 1 trailing 0 bit iff mm_shift == 1.
vm_is_trailing_zeros = mm_shift == 1;
} else {
// mp = mv + 2, so it always has at least one trailing 0 bit.
vp -= 1;
}
} else if q < 63 {
// TODO(ulfjack): Use a tighter bound here.
// We need to compute min(ntz(mv), pow5_factor(mv) - e2) >= q - 1
// <=> ntz(mv) >= q - 1 && pow5_factor(mv) - e2 >= q - 1
// <=> ntz(mv) >= q - 1 (e2 is negative and -e2 >= q)
// <=> (mv & ((1 << (q - 1)) - 1)) == 0
// We also need to make sure that the left shift does not overflow.
vr_is_trailing_zeros = multiple_of_power_of_2(mv, q - 1);
}
}
// Step 4: Find the shortest decimal representation in the interval of legal representations.
let mut removed = 0u32;
let mut last_removed_digit = 0u8;
// On average, we remove ~2 digits.
let output = if vm_is_trailing_zeros || vr_is_trailing_zeros {
// General case, which happens rarely (~0.7%).
while vp / 10 > vm / 10 {
vm_is_trailing_zeros &= vm - (vm / 10) * 10 == 0;
vr_is_trailing_zeros &= last_removed_digit == 0;
last_removed_digit = (vr % 10) as u8;
vr /= 10;
vp /= 10;
vm /= 10;
removed += 1;
}
if vm_is_trailing_zeros {
while vm % 10 == 0 {
vr_is_trailing_zeros &= last_removed_digit == 0;
last_removed_digit = (vr % 10) as u8;
vr /= 10;
vp /= 10;
vm /= 10;
removed += 1;
}
}
if vr_is_trailing_zeros && last_removed_digit == 5 && vr % 2 == 0 {
// Round even if the exact number is .....50..0.
last_removed_digit = 4;
}
// We need to take vr + 1 if vr is outside bounds or we need to round up.
vr + ((vr == vm && (!accept_bounds || !vm_is_trailing_zeros)) || last_removed_digit >= 5)
as u64
} else {
// Specialized for the common case (~99.3%). Percentages below are relative to this.
let mut round_up = false;
// Optimization: remove two digits at a time (~86.2%).
if vp / 100 > vm / 100 {
round_up = vr % 100 >= 50;
vr /= 100;
vp /= 100;
vm /= 100;
removed += 2;
}
// Loop iterations below (approximately), without optimization above:
// 0: 0.03%, 1: 13.8%, 2: 70.6%, 3: 14.0%, 4: 1.40%, 5: 0.14%, 6+: 0.02%
// Loop iterations below (approximately), with optimization above:
// 0: 70.6%, 1: 27.8%, 2: 1.40%, 3: 0.14%, 4+: 0.02%
while vp / 10 > vm / 10 {
round_up = vr % 10 >= 5;
vr /= 10;
vp /= 10;
vm /= 10;
removed += 1;
}
// We need to take vr + 1 if vr is outside bounds or we need to round up.
vr + (vr == vm || round_up) as u64
};
let exp = e10 + removed as i32;
FloatingDecimal64 {
exponent: exp,
mantissa: output,
}
}
#[cfg_attr(feature = "no-panic", inline)]
unsafe fn to_chars(v: FloatingDecimal64, sign: bool, result: *mut u8) -> usize {
// Step 5: Print the decimal representation.
let mut index = 0isize;
if sign {
*result.offset(index) = b'-';
index += 1;
}
let mut output = v.mantissa;
let olength = decimal_length(output);
// Print the decimal digits.
// The following code is equivalent to:
// for (uint32_t i = 0; i < olength - 1; ++i) {
// const uint32_t c = output % 10; output /= 10;
// result[index + olength - i] = (char) ('0' + c);
// }
// result[index] = '0' + output % 10;
let mut i = 0isize;
// We prefer 32-bit operations, even on 64-bit platforms.
// We have at most 17 digits, and uint32_t can store 9 digits.
// If output doesn't fit into uint32_t, we cut off 8 digits,
// so the rest will fit into uint32_t.
if (output >> 32) != 0 {
// Expensive 64-bit division.
let mut output2 = (output - 100000000 * (output / 100000000)) as u32;
output /= 100000000;
let c = output2 % 10000;
output2 /= 10000;
let d = output2 % 10000;
let c0 = (c % 100) << 1;
let c1 = (c / 100) << 1;
let d0 = (d % 100) << 1;
let d1 = (d / 100) << 1;
ptr::copy_nonoverlapping(
DIGIT_TABLE.get_unchecked(c0 as usize),
result.offset(index + olength as isize - i - 1),
2,
);
ptr::copy_nonoverlapping(
DIGIT_TABLE.get_unchecked(c1 as usize),
result.offset(index + olength as isize - i - 3),
2,
);
ptr::copy_nonoverlapping(
DIGIT_TABLE.get_unchecked(d0 as usize),
result.offset(index + olength as isize - i - 5),
2,
);
ptr::copy_nonoverlapping(
DIGIT_TABLE.get_unchecked(d1 as usize),
result.offset(index + olength as isize - i - 7),
2,
);
i += 8;
}
let mut output2 = output as u32;
while output2 >= 10000 {
let c = (output2 - 10000 * (output2 / 10000)) as u32;
output2 /= 10000;
let c0 = (c % 100) << 1;
let c1 = (c / 100) << 1;
ptr::copy_nonoverlapping(
DIGIT_TABLE.get_unchecked(c0 as usize),
result.offset(index + olength as isize - i - 1),
2,
);
ptr::copy_nonoverlapping(
DIGIT_TABLE.get_unchecked(c1 as usize),
result.offset(index + olength as isize - i - 3),
2,
);
i += 4;
}
if output2 >= 100 {
let c = ((output2 % 100) << 1) as u32;
output2 /= 100;
ptr::copy_nonoverlapping(
DIGIT_TABLE.get_unchecked(c as usize),
result.offset(index + olength as isize - i - 1),
2,
);
i += 2;
}
if output2 >= 10 {
let c = (output2 << 1) as u32;
// We can't use memcpy here: the decimal dot goes between these two digits.
*result.offset(index + olength as isize - i) = *DIGIT_TABLE.get_unchecked(c as usize + 1);
*result.offset(index) = *DIGIT_TABLE.get_unchecked(c as usize);
} else {
*result.offset(index) = b'0' + output2 as u8;
}
// Print decimal point if needed.
if olength > 1 {
*result.offset(index + 1) = b'.';
index += olength as isize + 1;
} else {
index += 1;
}
// Print the exponent.
*result.offset(index) = b'E';
index += 1;
let mut exp = v.exponent as i32 + olength as i32 - 1;
if exp < 0 {
*result.offset(index) = b'-';
index += 1;
exp = -exp;
}
if exp >= 100 {
let c = exp % 10;
ptr::copy_nonoverlapping(
DIGIT_TABLE.get_unchecked((2 * (exp / 10)) as usize),
result.offset(index),
2,
);
*result.offset(index + 2) = b'0' + c as u8;
index += 3;
} else if exp >= 10 {
ptr::copy_nonoverlapping(
DIGIT_TABLE.get_unchecked((2 * exp) as usize),
result.offset(index),
2,
);
index += 2;
} else {
*result.offset(index) = b'0' + exp as u8;
index += 1;
}
debug_assert!(index <= 24);
index as usize
}
/// Print f64 to the given buffer and return number of bytes written.
///
/// At most 24 bytes will be written.
///
/// ## Special cases
///
/// This function represents any NaN as `NaN`, positive infinity as `Infinity`,
/// and negative infinity as `-Infinity`.
///
/// ## Safety
///
/// The `result` pointer argument must point to sufficiently many writable bytes
/// to hold Ryū's representation of `f`.
///
/// ## Example
///
/// ```rust
/// let f = 1.234f64;
///
/// unsafe {
/// let mut buffer: [u8; 24] = std::mem::uninitialized();
/// let n = ryu::raw::d2s_buffered_n(f, &mut buffer[0]);
/// let s = std::str::from_utf8_unchecked(&buffer[..n]);
/// assert_eq!(s, "1.234E0");
/// }
/// ```
#[cfg_attr(must_use_return, must_use)]
#[cfg_attr(feature = "no-panic", no_panic)]
pub unsafe fn d2s_buffered_n(f: f64, result: *mut u8) -> usize {
// Step 1: Decode the floating-point number, and unify normalized and subnormal cases.
let bits = mem::transmute::<f64, u64>(f);
// Decode bits into sign, mantissa, and exponent.
let ieee_sign = ((bits >> (DOUBLE_MANTISSA_BITS + DOUBLE_EXPONENT_BITS)) & 1) != 0;
let ieee_mantissa = bits & ((1u64 << DOUBLE_MANTISSA_BITS) - 1);
let ieee_exponent =
(bits >> DOUBLE_MANTISSA_BITS) as u32 & ((1u32 << DOUBLE_EXPONENT_BITS) - 1);
// Case distinction; exit early for the easy cases.
if ieee_exponent == ((1u32 << DOUBLE_EXPONENT_BITS) - 1)
|| (ieee_exponent == 0 && ieee_mantissa == 0)
{
return copy_special_str(result, ieee_sign, ieee_exponent != 0, ieee_mantissa != 0);
}
let v = d2d(ieee_mantissa, ieee_exponent);
to_chars(v, ieee_sign, result)
}

View File

@ -0,0 +1,643 @@
// Translated from C to Rust. The original C code can be found at
// https://github.com/ulfjack/ryu and carries the following license:
//
// Copyright 2018 Ulf Adams
//
// The contents of this file may be used under the terms of the Apache License,
// Version 2.0.
//
// (See accompanying file LICENSE-Apache or copy at
// http://www.apache.org/licenses/LICENSE-2.0)
//
// Alternatively, the contents of this file may be used under the terms of
// the Boost Software License, Version 1.0.
// (See accompanying file LICENSE-Boost or copy at
// https://www.boost.org/LICENSE_1_0.txt)
//
// Unless required by applicable law or agreed to in writing, this software
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
pub static DOUBLE_POW5_INV_SPLIT: [(u64, u64); 292] = [
(1, 288230376151711744),
(3689348814741910324, 230584300921369395),
(2951479051793528259, 184467440737095516),
(17118578500402463900, 147573952589676412),
(12632330341676300947, 236118324143482260),
(10105864273341040758, 188894659314785808),
(15463389048156653253, 151115727451828646),
(17362724847566824558, 241785163922925834),
(17579528692795369969, 193428131138340667),
(6684925324752475329, 154742504910672534),
(18074578149087781173, 247588007857076054),
(18149011334012135262, 198070406285660843),
(3451162622983977240, 158456325028528675),
(5521860196774363583, 253530120045645880),
(4417488157419490867, 202824096036516704),
(7223339340677503017, 162259276829213363),
(7867994130342094503, 259614842926741381),
(2605046489531765280, 207691874341393105),
(2084037191625412224, 166153499473114484),
(10713157136084480204, 265845599156983174),
(12259874523609494487, 212676479325586539),
(13497248433629505913, 170141183460469231),
(14216899864323388813, 272225893536750770),
(11373519891458711051, 217780714829400616),
(5409467098425058518, 174224571863520493),
(4965798542738183305, 278759314981632789),
(7661987648932456967, 223007451985306231),
(2440241304404055250, 178405961588244985),
(3904386087046488400, 285449538541191976),
(17880904128604832013, 228359630832953580),
(14304723302883865611, 182687704666362864),
(15133127457049002812, 146150163733090291),
(16834306301794583852, 233840261972944466),
(9778096226693756759, 187072209578355573),
(15201174610838826053, 149657767662684458),
(2185786488890659746, 239452428260295134),
(5437978005854438120, 191561942608236107),
(15418428848909281466, 153249554086588885),
(6222742084545298729, 245199286538542217),
(16046240111861969953, 196159429230833773),
(1768945645263844993, 156927543384667019),
(10209010661905972635, 251084069415467230),
(8167208529524778108, 200867255532373784),
(10223115638361732810, 160693804425899027),
(1599589762411131202, 257110087081438444),
(4969020624670815285, 205688069665150755),
(3975216499736652228, 164550455732120604),
(13739044029062464211, 263280729171392966),
(7301886408508061046, 210624583337114373),
(13220206756290269483, 168499666669691498),
(17462981995322520850, 269599466671506397),
(6591687966774196033, 215679573337205118),
(12652048002903177473, 172543658669764094),
(9175230360419352987, 276069853871622551),
(3650835473593572067, 220855883097298041),
(17678063637842498946, 176684706477838432),
(13527506561580357021, 282695530364541492),
(3443307619780464970, 226156424291633194),
(6443994910566282300, 180925139433306555),
(5155195928453025840, 144740111546645244),
(15627011115008661990, 231584178474632390),
(12501608892006929592, 185267342779705912),
(2622589484121723027, 148213874223764730),
(4196143174594756843, 237142198758023568),
(10735612169159626121, 189713759006418854),
(12277838550069611220, 151771007205135083),
(15955192865369467629, 242833611528216133),
(1696107848069843133, 194266889222572907),
(12424932722681605476, 155413511378058325),
(1433148282581017146, 248661618204893321),
(15903913885032455010, 198929294563914656),
(9033782293284053685, 159143435651131725),
(14454051669254485895, 254629497041810760),
(11563241335403588716, 203703597633448608),
(16629290697806691620, 162962878106758886),
(781423413297334329, 260740604970814219),
(4314487545379777786, 208592483976651375),
(3451590036303822229, 166873987181321100),
(5522544058086115566, 266998379490113760),
(4418035246468892453, 213598703592091008),
(10913125826658934609, 170878962873672806),
(10082303693170474728, 273406340597876490),
(8065842954536379782, 218725072478301192),
(17520720807854834795, 174980057982640953),
(5897060404116273733, 279968092772225526),
(1028299508551108663, 223974474217780421),
(15580034865808528224, 179179579374224336),
(17549358155809824511, 286687326998758938),
(2971440080422128639, 229349861599007151),
(17134547323305344204, 183479889279205720),
(13707637858644275364, 146783911423364576),
(14553522944347019935, 234854258277383322),
(4264120725993795302, 187883406621906658),
(10789994210278856888, 150306725297525326),
(9885293106962350374, 240490760476040522),
(529536856086059653, 192392608380832418),
(7802327114352668369, 153914086704665934),
(1415676938738538420, 246262538727465495),
(1132541550990830736, 197010030981972396),
(15663428499760305882, 157608024785577916),
(17682787970132668764, 252172839656924666),
(10456881561364224688, 201738271725539733),
(15744202878575200397, 161390617380431786),
(17812026976236499989, 258224987808690858),
(3181575136763469022, 206579990246952687),
(13613306553636506187, 165263992197562149),
(10713244041592678929, 264422387516099439),
(12259944048016053467, 211537910012879551),
(6118606423670932450, 169230328010303641),
(2411072648389671274, 270768524816485826),
(16686253377679378312, 216614819853188660),
(13349002702143502650, 173291855882550928),
(17669055508687693916, 277266969412081485),
(14135244406950155133, 221813575529665188),
(240149081334393137, 177450860423732151),
(11452284974360759988, 283921376677971441),
(5472479164746697667, 227137101342377153),
(11756680961281178780, 181709681073901722),
(2026647139541122378, 145367744859121378),
(18000030682233437097, 232588391774594204),
(18089373360528660001, 186070713419675363),
(3403452244197197031, 148856570735740291),
(16513570034941246220, 238170513177184465),
(13210856027952996976, 190536410541747572),
(3189987192878576934, 152429128433398058),
(1414630693863812771, 243886605493436893),
(8510402184574870864, 195109284394749514),
(10497670562401807014, 156087427515799611),
(9417575270359070576, 249739884025279378),
(14912757845771077107, 199791907220223502),
(4551508647133041040, 159833525776178802),
(10971762650154775986, 255733641241886083),
(16156107749607641435, 204586912993508866),
(9235537384944202825, 163669530394807093),
(11087511001168814197, 261871248631691349),
(12559357615676961681, 209496998905353079),
(13736834907283479668, 167597599124282463),
(18289587036911657145, 268156158598851941),
(10942320814787415393, 214524926879081553),
(16132554281313752961, 171619941503265242),
(11054691591134363444, 274591906405224388),
(16222450902391311402, 219673525124179510),
(12977960721913049122, 175738820099343608),
(17075388340318968271, 281182112158949773),
(2592264228029443648, 224945689727159819),
(5763160197165465241, 179956551781727855),
(9221056315464744386, 287930482850764568),
(14755542681855616155, 230344386280611654),
(15493782960226403247, 184275509024489323),
(1326979923955391628, 147420407219591459),
(9501865507812447252, 235872651551346334),
(11290841220991868125, 188698121241077067),
(1653975347309673853, 150958496992861654),
(10025058185179298811, 241533595188578646),
(4330697733401528726, 193226876150862917),
(14532604630946953951, 154581500920690333),
(1116074521063664381, 247330401473104534),
(4582208431592841828, 197864321178483627),
(14733813189500004432, 158291456942786901),
(16195403473716186445, 253266331108459042),
(5577625149489128510, 202613064886767234),
(8151448934333213131, 162090451909413787),
(16731667109675051333, 259344723055062059),
(17074682502481951390, 207475778444049647),
(6281048372501740465, 165980622755239718),
(6360328581260874421, 265568996408383549),
(8777611679750609860, 212455197126706839),
(10711438158542398211, 169964157701365471),
(9759603424184016492, 271942652322184754),
(11497031554089123517, 217554121857747803),
(16576322872755119460, 174043297486198242),
(11764721337440549842, 278469275977917188),
(16790474699436260520, 222775420782333750),
(13432379759549008416, 178220336625867000),
(3045063541568861850, 285152538601387201),
(17193446092222730773, 228122030881109760),
(13754756873778184618, 182497624704887808),
(18382503128506368341, 145998099763910246),
(3586563302416817083, 233596959622256395),
(2869250641933453667, 186877567697805116),
(17052795772514404226, 149502054158244092),
(12527077977055405469, 239203286653190548),
(17400360011128145022, 191362629322552438),
(2852241564676785048, 153090103458041951),
(15631632947708587046, 244944165532867121),
(8815957543424959314, 195955332426293697),
(18120812478965698421, 156764265941034957),
(14235904707377476180, 250822825505655932),
(4010026136418160298, 200658260404524746),
(17965416168102169531, 160526608323619796),
(2919224165770098987, 256842573317791675),
(2335379332616079190, 205474058654233340),
(1868303466092863352, 164379246923386672),
(6678634360490491686, 263006795077418675),
(5342907488392393349, 210405436061934940),
(4274325990713914679, 168324348849547952),
(10528270399884173809, 269318958159276723),
(15801313949391159694, 215455166527421378),
(1573004715287196786, 172364133221937103),
(17274202803427156150, 275782613155099364),
(17508711057483635243, 220626090524079491),
(10317620031244997871, 176500872419263593),
(12818843235250086271, 282401395870821749),
(13944423402941979340, 225921116696657399),
(14844887537095493795, 180736893357325919),
(15565258844418305359, 144589514685860735),
(6457670077359736959, 231343223497377177),
(16234182506113520537, 185074578797901741),
(9297997190148906106, 148059663038321393),
(11187446689496339446, 236895460861314229),
(12639306166338981880, 189516368689051383),
(17490142562555006151, 151613094951241106),
(2158786396894637579, 242580951921985771),
(16484424376483351356, 194064761537588616),
(9498190686444770762, 155251809230070893),
(11507756283569722895, 248402894768113429),
(12895553841597688639, 198722315814490743),
(17695140702761971558, 158977852651592594),
(17244178680193423523, 254364564242548151),
(10105994129412828495, 203491651394038521),
(4395446488788352473, 162793321115230817),
(10722063196803274280, 260469313784369307),
(1198952927958798777, 208375451027495446),
(15716557601334680315, 166700360821996356),
(17767794532651667857, 266720577315194170),
(14214235626121334286, 213376461852155336),
(7682039686155157106, 170701169481724269),
(1223217053622520399, 273121871170758831),
(15735968901865657612, 218497496936607064),
(16278123936234436413, 174797997549285651),
(219556594781725998, 279676796078857043),
(7554342905309201445, 223741436863085634),
(9732823138989271479, 178993149490468507),
(815121763415193074, 286389039184749612),
(11720143854957885429, 229111231347799689),
(13065463898708218666, 183288985078239751),
(6763022304224664610, 146631188062591801),
(3442138057275642729, 234609900900146882),
(13821756890046245153, 187687920720117505),
(11057405512036996122, 150150336576094004),
(6623802375033462826, 240240538521750407),
(16367088344252501231, 192192430817400325),
(13093670675402000985, 153753944653920260),
(2503129006933649959, 246006311446272417),
(13070549649772650937, 196805049157017933),
(17835137349301941396, 157444039325614346),
(2710778055689733971, 251910462920982955),
(2168622444551787177, 201528370336786364),
(5424246770383340065, 161222696269429091),
(1300097203129523457, 257956314031086546),
(15797473021471260058, 206365051224869236),
(8948629602435097724, 165092040979895389),
(3249760919670425388, 264147265567832623),
(9978506365220160957, 211317812454266098),
(15361502721659949412, 169054249963412878),
(2442311466204457120, 270486799941460606),
(16711244431931206989, 216389439953168484),
(17058344360286875914, 173111551962534787),
(12535955717491360170, 276978483140055660),
(10028764573993088136, 221582786512044528),
(15401709288678291155, 177266229209635622),
(9885339602917624555, 283625966735416996),
(4218922867592189321, 226900773388333597),
(14443184738299482427, 181520618710666877),
(4175850161155765295, 145216494968533502),
(10370709072591134795, 232346391949653603),
(15675264887556728482, 185877113559722882),
(5161514280561562140, 148701690847778306),
(879725219414678777, 237922705356445290),
(703780175531743021, 190338164285156232),
(11631070584651125387, 152270531428124985),
(162968861732249003, 243632850284999977),
(11198421533611530172, 194906280227999981),
(5269388412147313814, 155925024182399985),
(8431021459435702103, 249480038691839976),
(3055468352806651359, 199584030953471981),
(17201769941212962380, 159667224762777584),
(16454785461715008838, 255467559620444135),
(13163828369372007071, 204374047696355308),
(17909760324981426303, 163499238157084246),
(2830174816776909822, 261598781051334795),
(2264139853421527858, 209279024841067836),
(16568707141704863579, 167423219872854268),
(4373838538276319787, 267877151796566830),
(3499070830621055830, 214301721437253464),
(6488605479238754987, 171441377149802771),
(3003071137298187333, 274306203439684434),
(6091805724580460189, 219444962751747547),
(15941491023890099121, 175555970201398037),
(10748990379256517301, 280889552322236860),
(8599192303405213841, 224711641857789488),
(14258051472207991719, 179769313486231590),
];
pub static DOUBLE_POW5_SPLIT: [(u64, u64); 326] = [
(0, 72057594037927936),
(0, 90071992547409920),
(0, 112589990684262400),
(0, 140737488355328000),
(0, 87960930222080000),
(0, 109951162777600000),
(0, 137438953472000000),
(0, 85899345920000000),
(0, 107374182400000000),
(0, 134217728000000000),
(0, 83886080000000000),
(0, 104857600000000000),
(0, 131072000000000000),
(0, 81920000000000000),
(0, 102400000000000000),
(0, 128000000000000000),
(0, 80000000000000000),
(0, 100000000000000000),
(0, 125000000000000000),
(0, 78125000000000000),
(0, 97656250000000000),
(0, 122070312500000000),
(0, 76293945312500000),
(0, 95367431640625000),
(0, 119209289550781250),
(4611686018427387904, 74505805969238281),
(10376293541461622784, 93132257461547851),
(8358680908399640576, 116415321826934814),
(612489549322387456, 72759576141834259),
(14600669991935148032, 90949470177292823),
(13639151471491547136, 113686837721616029),
(3213881284082270208, 142108547152020037),
(4314518811765112832, 88817841970012523),
(781462496279003136, 111022302462515654),
(10200200157203529728, 138777878078144567),
(13292654125893287936, 86736173798840354),
(7392445620511834112, 108420217248550443),
(4628871007212404736, 135525271560688054),
(16728102434789916672, 84703294725430033),
(7075069988205232128, 105879118406787542),
(18067209522111315968, 132348898008484427),
(8986162942105878528, 82718061255302767),
(6621017659204960256, 103397576569128459),
(3664586055578812416, 129246970711410574),
(16125424340018921472, 80779356694631608),
(1710036351314100224, 100974195868289511),
(15972603494424788992, 126217744835361888),
(9982877184015493120, 78886090522101180),
(12478596480019366400, 98607613152626475),
(10986559581596820096, 123259516440783094),
(2254913720070624656, 77037197775489434),
(12042014186943056628, 96296497219361792),
(15052517733678820785, 120370621524202240),
(9407823583549262990, 75231638452626400),
(11759779479436578738, 94039548065783000),
(14699724349295723422, 117549435082228750),
(4575641699882439235, 73468396926392969),
(10331238143280436948, 91835496157991211),
(8302361660673158281, 114794370197489014),
(1154580038986672043, 143492962746861268),
(9944984561221445835, 89683101716788292),
(12431230701526807293, 112103877145985365),
(1703980321626345405, 140129846432481707),
(17205888765512323542, 87581154020301066),
(12283988920035628619, 109476442525376333),
(1519928094762372062, 136845553156720417),
(12479170105294952299, 85528470722950260),
(15598962631618690374, 106910588403687825),
(5663645234241199255, 133638235504609782),
(17374836326682913246, 83523897190381113),
(7883487353071477846, 104404871487976392),
(9854359191339347308, 130506089359970490),
(10770660513014479971, 81566305849981556),
(13463325641268099964, 101957882312476945),
(2994098996302961243, 127447352890596182),
(15706369927971514489, 79654595556622613),
(5797904354682229399, 99568244445778267),
(2635694424925398845, 124460305557222834),
(6258995034005762182, 77787690973264271),
(3212057774079814824, 97234613716580339),
(17850130272881932242, 121543267145725423),
(18073860448192289507, 75964541966078389),
(8757267504958198172, 94955677457597987),
(6334898362770359811, 118694596821997484),
(13182683513586250689, 74184123013748427),
(11866668373555425458, 92730153767185534),
(5609963430089506015, 115912692208981918),
(17341285199088104971, 72445432630613698),
(12453234462005355406, 90556790788267123),
(10954857059079306353, 113195988485333904),
(13693571323849132942, 141494985606667380),
(17781854114260483896, 88434366004167112),
(3780573569116053255, 110542957505208891),
(114030942967678664, 138178696881511114),
(4682955357782187069, 86361685550944446),
(15077066234082509644, 107952106938680557),
(5011274737320973344, 134940133673350697),
(14661261756894078100, 84337583545844185),
(4491519140835433913, 105421979432305232),
(5614398926044292391, 131777474290381540),
(12732371365632458552, 82360921431488462),
(6692092170185797382, 102951151789360578),
(17588487249587022536, 128688939736700722),
(15604490549419276989, 80430587335437951),
(14893927168346708332, 100538234169297439),
(14005722942005997511, 125672792711621799),
(15671105866394830300, 78545495444763624),
(1142138259283986260, 98181869305954531),
(15262730879387146537, 122727336632443163),
(7233363790403272633, 76704585395276977),
(13653390756431478696, 95880731744096221),
(3231680390257184658, 119850914680120277),
(4325643253124434363, 74906821675075173),
(10018740084832930858, 93633527093843966),
(3300053069186387764, 117041908867304958),
(15897591223523656064, 73151193042065598),
(10648616992549794273, 91438991302581998),
(4087399203832467033, 114298739128227498),
(14332621041645359599, 142873423910284372),
(18181260187883125557, 89295889943927732),
(4279831161144355331, 111619862429909666),
(14573160988285219972, 139524828037387082),
(13719911636105650386, 87203017523366926),
(7926517508277287175, 109003771904208658),
(684774848491833161, 136254714880260823),
(7345513307948477581, 85159196800163014),
(18405263671790372785, 106448996000203767),
(18394893571310578077, 133061245000254709),
(13802651491282805250, 83163278125159193),
(3418256308821342851, 103954097656448992),
(4272820386026678563, 129942622070561240),
(2670512741266674102, 81214138794100775),
(17173198981865506339, 101517673492625968),
(3019754653622331308, 126897091865782461),
(4193189667727651020, 79310682416114038),
(14464859121514339583, 99138353020142547),
(13469387883465536574, 123922941275178184),
(8418367427165960359, 77451838296986365),
(15134645302384838353, 96814797871232956),
(471562554271496325, 121018497339041196),
(9518098633274461011, 75636560836900747),
(7285937273165688360, 94545701046125934),
(18330793628311886258, 118182126307657417),
(4539216990053847055, 73863828942285886),
(14897393274422084627, 92329786177857357),
(4786683537745442072, 115412232722321697),
(14520892257159371055, 72132645451451060),
(18151115321449213818, 90165806814313825),
(8853836096529353561, 112707258517892282),
(1843923083806916143, 140884073147365353),
(12681666973447792349, 88052545717103345),
(2017025661527576725, 110065682146379182),
(11744654113764246714, 137582102682973977),
(422879793461572340, 85988814176858736),
(528599741826965425, 107486017721073420),
(660749677283706782, 134357522151341775),
(7330497575943398595, 83973451344588609),
(13774807988356636147, 104966814180735761),
(3383451930163631472, 131208517725919702),
(15949715511634433382, 82005323578699813),
(6102086334260878016, 102506654473374767),
(3015921899398709616, 128133318091718459),
(18025852251620051174, 80083323807324036),
(4085571240815512351, 100104154759155046),
(14330336087874166247, 125130193448943807),
(15873989082562435760, 78206370905589879),
(15230800334775656796, 97757963631987349),
(5203442363187407284, 122197454539984187),
(946308467778435600, 76373409087490117),
(5794571603150432404, 95466761359362646),
(16466586540792816313, 119333451699203307),
(7985773578781816244, 74583407312002067),
(5370530955049882401, 93229259140002584),
(6713163693812353001, 116536573925003230),
(18030785363914884337, 72835358703127018),
(13315109668038829614, 91044198378908773),
(2808829029766373305, 113805247973635967),
(17346094342490130344, 142256559967044958),
(6229622945628943561, 88910349979403099),
(3175342663608791547, 111137937474253874),
(13192550366365765242, 138922421842817342),
(3633657960551215372, 86826513651760839),
(18377130505971182927, 108533142064701048),
(4524669058754427043, 135666427580876311),
(9745447189362598758, 84791517238047694),
(2958436949848472639, 105989396547559618),
(12921418224165366607, 132486745684449522),
(12687572408530742033, 82804216052780951),
(11247779492236039638, 103505270065976189),
(224666310012885835, 129381587582470237),
(2446259452971747599, 80863492239043898),
(12281196353069460307, 101079365298804872),
(15351495441336825384, 126349206623506090),
(14206370669262903769, 78968254139691306),
(8534591299723853903, 98710317674614133),
(15279925143082205283, 123387897093267666),
(14161639232853766206, 77117435683292291),
(13090363022639819853, 96396794604115364),
(16362953778299774816, 120495993255144205),
(12532689120651053212, 75309995784465128),
(15665861400813816515, 94137494730581410),
(10358954714162494836, 117671868413226763),
(4168503687137865320, 73544917758266727),
(598943590494943747, 91931147197833409),
(5360365506546067587, 114913933997291761),
(11312142901609972388, 143642417496614701),
(9375932322719926695, 89776510935384188),
(11719915403399908368, 112220638669230235),
(10038208235822497557, 140275798336537794),
(10885566165816448877, 87672373960336121),
(18218643725697949000, 109590467450420151),
(18161618638695048346, 136988084313025189),
(13656854658398099168, 85617552695640743),
(12459382304570236056, 107021940869550929),
(1739169825430631358, 133777426086938662),
(14922039196176308311, 83610891304336663),
(14040862976792997485, 104513614130420829),
(3716020665709083144, 130642017663026037),
(4628355925281870917, 81651261039391273),
(10397130925029726550, 102064076299239091),
(8384727637859770284, 127580095374048864),
(5240454773662356427, 79737559608780540),
(6550568467077945534, 99671949510975675),
(3576524565420044014, 124589936888719594),
(6847013871814915412, 77868710555449746),
(17782139376623420074, 97335888194312182),
(13004302183924499284, 121669860242890228),
(17351060901807587860, 76043662651806392),
(3242082053549933210, 95054578314757991),
(17887660622219580224, 118818222893447488),
(11179787888887237640, 74261389308404680),
(13974734861109047050, 92826736635505850),
(8245046539531533005, 116033420794382313),
(16682369133275677888, 72520887996488945),
(7017903361312433648, 90651109995611182),
(17995751238495317868, 113313887494513977),
(8659630992836983623, 141642359368142472),
(5412269370523114764, 88526474605089045),
(11377022731581281359, 110658093256361306),
(4997906377621825891, 138322616570451633),
(14652906532082110942, 86451635356532270),
(9092761128247862869, 108064544195665338),
(2142579373455052779, 135080680244581673),
(12868327154477877747, 84425425152863545),
(2250350887815183471, 105531781441079432),
(2812938609768979339, 131914726801349290),
(6369772649532999991, 82446704250843306),
(17185587848771025797, 103058380313554132),
(3035240737254230630, 128822975391942666),
(6508711479211282048, 80514359619964166),
(17359261385868878368, 100642949524955207),
(17087390713908710056, 125803686906194009),
(3762090168551861929, 78627304316371256),
(4702612710689827411, 98284130395464070),
(15101637925217060072, 122855162994330087),
(16356052730901744401, 76784476871456304),
(1998321839917628885, 95980596089320381),
(7109588318324424010, 119975745111650476),
(13666864735807540814, 74984840694781547),
(12471894901332038114, 93731050868476934),
(6366496589810271835, 117163813585596168),
(3979060368631419896, 73227383490997605),
(9585511479216662775, 91534229363747006),
(2758517312166052660, 114417786704683758),
(12671518677062341634, 143022233380854697),
(1002170145522881665, 89388895863034186),
(10476084718758377889, 111736119828792732),
(13095105898447972362, 139670149785990915),
(5878598177316288774, 87293843616244322),
(16571619758500136775, 109117304520305402),
(11491152661270395161, 136396630650381753),
(264441385652915120, 85247894156488596),
(330551732066143900, 106559867695610745),
(5024875683510067779, 133199834619513431),
(10058076329834874218, 83249896637195894),
(3349223375438816964, 104062370796494868),
(4186529219298521205, 130077963495618585),
(14145795808130045513, 81298727184761615),
(13070558741735168987, 101623408980952019),
(11726512408741573330, 127029261226190024),
(7329070255463483331, 79393288266368765),
(13773023837756742068, 99241610332960956),
(17216279797195927585, 124052012916201195),
(8454331864033760789, 77532508072625747),
(5956228811614813082, 96915635090782184),
(7445286014518516353, 121144543863477730),
(9264989777501460624, 75715339914673581),
(16192923240304213684, 94644174893341976),
(1794409976670715490, 118305218616677471),
(8039035263060279037, 73940761635423419),
(5437108060397960892, 92425952044279274),
(16019757112352226923, 115532440055349092),
(788976158365366019, 72207775034593183),
(14821278253238871236, 90259718793241478),
(9303225779693813237, 112824648491551848),
(11629032224617266546, 141030810614439810),
(11879831158813179495, 88144256634024881),
(1014730893234310657, 110180320792531102),
(10491785653397664129, 137725400990663877),
(8863209042587234033, 86078375619164923),
(6467325284806654637, 107597969523956154),
(17307528642863094104, 134497461904945192),
(10817205401789433815, 84060913690590745),
(18133192770664180173, 105076142113238431),
(18054804944902837312, 131345177641548039),
(18201782118205355176, 82090736025967524),
(4305483574047142354, 102613420032459406),
(14605226504413703751, 128266775040574257),
(2210737537617482988, 80166734400358911),
(16598479977304017447, 100208418000448638),
(11524727934775246001, 125260522500560798),
(2591268940807140847, 78287826562850499),
(17074144231291089770, 97859783203563123),
(16730994270686474309, 122324729004453904),
(10456871419179046443, 76452955627783690),
(3847717237119032246, 95566194534729613),
(9421332564826178211, 119457743168412016),
(5888332853016361382, 74661089480257510),
(16583788103125227536, 93326361850321887),
(16118049110479146516, 116657952312902359),
(16991309721690548428, 72911220195563974),
(12015765115258409727, 91139025244454968),
(15019706394073012159, 113923781555568710),
(9551260955736489391, 142404726944460888),
(5969538097335305869, 89002954340288055),
(2850236603241744433, 111253692925360069),
];

View File

@ -0,0 +1,206 @@
// Translated from C to Rust. The original C code can be found at
// https://github.com/ulfjack/ryu and carries the following license:
//
// Copyright 2018 Ulf Adams
//
// The contents of this file may be used under the terms of the Apache License,
// Version 2.0.
//
// (See accompanying file LICENSE-Apache or copy at
// http://www.apache.org/licenses/LICENSE-2.0)
//
// Alternatively, the contents of this file may be used under the terms of
// the Boost Software License, Version 1.0.
// (See accompanying file LICENSE-Boost or copy at
// https://www.boost.org/LICENSE_1_0.txt)
//
// Unless required by applicable law or agreed to in writing, this software
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
use common::*;
#[cfg(not(integer128))]
use mulshift128::*;
pub static DOUBLE_POW5_TABLE: [u64; 26] = [
1,
5,
25,
125,
625,
3125,
15625,
78125,
390625,
1953125,
9765625,
48828125,
244140625,
1220703125,
6103515625,
30517578125,
152587890625,
762939453125,
3814697265625,
19073486328125,
95367431640625,
476837158203125,
2384185791015625,
11920928955078125,
59604644775390625,
298023223876953125,
];
pub static DOUBLE_POW5_SPLIT2: [(u64, u64); 13] = [
(0, 72057594037927936),
(10376293541461622784, 93132257461547851),
(15052517733678820785, 120370621524202240),
(6258995034005762182, 77787690973264271),
(14893927168346708332, 100538234169297439),
(4272820386026678563, 129942622070561240),
(7330497575943398595, 83973451344588609),
(18377130505971182927, 108533142064701048),
(10038208235822497557, 140275798336537794),
(7017903361312433648, 90651109995611182),
(6366496589810271835, 117163813585596168),
(9264989777501460624, 75715339914673581),
(17074144231291089770, 97859783203563123),
];
// Unfortunately, the results are sometimes off by one. We use an additional
// lookup table to store those cases and adjust the result.
pub static POW5_OFFSETS: [u32; 13] = [
0x00000000, 0x00000000, 0x00000000, 0x033c55be, 0x03db77d8, 0x0265ffb2, 0x00000800, 0x01a8ff56,
0x00000000, 0x0037a200, 0x00004000, 0x03fffffc, 0x00003ffe,
];
pub static DOUBLE_POW5_INV_SPLIT2: [(u64, u64); 13] = [
(1, 288230376151711744),
(7661987648932456967, 223007451985306231),
(12652048002903177473, 172543658669764094),
(5522544058086115566, 266998379490113760),
(3181575136763469022, 206579990246952687),
(4551508647133041040, 159833525776178802),
(1116074521063664381, 247330401473104534),
(17400360011128145022, 191362629322552438),
(9297997190148906106, 148059663038321393),
(11720143854957885429, 229111231347799689),
(15401709288678291155, 177266229209635622),
(3003071137298187333, 274306203439684434),
(17516772882021341108, 212234145163966538),
];
pub static POW5_INV_OFFSETS: [u32; 20] = [
0x51505404, 0x55054514, 0x45555545, 0x05511411, 0x00505010, 0x00000004, 0x00000000, 0x00000000,
0x55555040, 0x00505051, 0x00050040, 0x55554000, 0x51659559, 0x00001000, 0x15000010, 0x55455555,
0x41404051, 0x00001010, 0x00000014, 0x00000000,
];
// Computes 5^i in the form required by Ryu.
#[cfg(integer128)]
#[cfg_attr(feature = "no-panic", inline)]
pub unsafe fn compute_pow5(i: u32) -> (u64, u64) {
let base = i / DOUBLE_POW5_TABLE.len() as u32;
let base2 = base * DOUBLE_POW5_TABLE.len() as u32;
let offset = i - base2;
debug_assert!(base < DOUBLE_POW5_SPLIT2.len() as u32);
let mul = *DOUBLE_POW5_SPLIT2.get_unchecked(base as usize);
if offset == 0 {
return mul;
}
debug_assert!(offset < DOUBLE_POW5_TABLE.len() as u32);
let m = *DOUBLE_POW5_TABLE.get_unchecked(offset as usize);
let b0 = m as u128 * mul.0 as u128;
let b2 = m as u128 * mul.1 as u128;
let delta = pow5bits(i as i32) - pow5bits(base2 as i32);
debug_assert!(base < POW5_OFFSETS.len() as u32);
let shifted_sum = (b0 >> delta)
+ (b2 << (64 - delta))
+ ((*POW5_OFFSETS.get_unchecked(base as usize) >> offset) & 1) as u128;
(shifted_sum as u64, (shifted_sum >> 64) as u64)
}
// Computes 5^-i in the form required by Ryu.
#[cfg(integer128)]
#[cfg_attr(feature = "no-panic", inline)]
pub unsafe fn compute_inv_pow5(i: u32) -> (u64, u64) {
let base = (i + DOUBLE_POW5_TABLE.len() as u32 - 1) / DOUBLE_POW5_TABLE.len() as u32;
let base2 = base * DOUBLE_POW5_TABLE.len() as u32;
let offset = base2 - i;
debug_assert!(base < DOUBLE_POW5_INV_SPLIT2.len() as u32);
let mul = *DOUBLE_POW5_INV_SPLIT2.get_unchecked(base as usize); // 1/5^base2
if offset == 0 {
return mul;
}
debug_assert!(offset < DOUBLE_POW5_TABLE.len() as u32);
let m = *DOUBLE_POW5_TABLE.get_unchecked(offset as usize); // 5^offset
let b0 = m as u128 * (mul.0 - 1) as u128;
let b2 = m as u128 * mul.1 as u128; // 1/5^base2 * 5^offset = 1/5^(base2-offset) = 1/5^i
let delta = pow5bits(base2 as i32) - pow5bits(i as i32);
debug_assert!(base < POW5_INV_OFFSETS.len() as u32);
let shifted_sum = ((b0 >> delta) + (b2 << (64 - delta)))
+ 1
+ ((*POW5_INV_OFFSETS.get_unchecked((i / 16) as usize) >> ((i % 16) << 1)) & 3) as u128;
(shifted_sum as u64, (shifted_sum >> 64) as u64)
}
// Computes 5^i in the form required by Ryu, and stores it in the given pointer.
#[cfg(not(integer128))]
#[cfg_attr(feature = "no-panic", inline)]
pub unsafe fn compute_pow5(i: u32) -> (u64, u64) {
let base = i / DOUBLE_POW5_TABLE.len() as u32;
let base2 = base * DOUBLE_POW5_TABLE.len() as u32;
let offset = i - base2;
debug_assert!(base < DOUBLE_POW5_SPLIT2.len() as u32);
let mul = *DOUBLE_POW5_SPLIT2.get_unchecked(base as usize);
if offset == 0 {
return mul;
}
debug_assert!(offset < DOUBLE_POW5_TABLE.len() as u32);
let m = *DOUBLE_POW5_TABLE.get_unchecked(offset as usize);
let (low1, mut high1) = umul128(m, mul.1);
let (low0, high0) = umul128(m, mul.0);
let sum = high0 + low1;
if sum < high0 {
high1 += 1; // overflow into high1
}
// high1 | sum | low0
let delta = pow5bits(i as i32) - pow5bits(base2 as i32);
debug_assert!(base < POW5_OFFSETS.len() as u32);
(
shiftright128(low0, sum, delta)
+ ((*POW5_OFFSETS.get_unchecked(base as usize) >> offset) & 1) as u64,
shiftright128(sum, high1, delta),
)
}
// Computes 5^-i in the form required by Ryu, and stores it in the given pointer.
#[cfg(not(integer128))]
#[cfg_attr(feature = "no-panic", inline)]
pub unsafe fn compute_inv_pow5(i: u32) -> (u64, u64) {
let base = (i + DOUBLE_POW5_TABLE.len() as u32 - 1) / DOUBLE_POW5_TABLE.len() as u32;
let base2 = base * DOUBLE_POW5_TABLE.len() as u32;
let offset = base2 - i;
debug_assert!(base < DOUBLE_POW5_INV_SPLIT2.len() as u32);
let mul = *DOUBLE_POW5_INV_SPLIT2.get_unchecked(base as usize); // 1/5^base2
if offset == 0 {
return mul;
}
debug_assert!(offset < DOUBLE_POW5_TABLE.len() as u32);
let m = *DOUBLE_POW5_TABLE.get_unchecked(offset as usize);
let (low1, mut high1) = umul128(m, mul.1);
let (low0, high0) = umul128(m, mul.0 - 1);
let sum = high0 + low1;
if sum < high0 {
high1 += 1; // overflow into high1
}
// high1 | sum | low0
let delta = pow5bits(base2 as i32) - pow5bits(i as i32);
debug_assert!(base < POW5_INV_OFFSETS.len() as u32);
(
shiftright128(low0, sum, delta)
+ 1
+ ((*POW5_INV_OFFSETS.get_unchecked((i / 16) as usize) >> ((i % 16) << 1)) & 3) as u64,
shiftright128(sum, high1, delta),
)
}

28
third_party/rust/ryu/src/digit_table.rs vendored Normal file
View File

@ -0,0 +1,28 @@
// Translated from C to Rust. The original C code can be found at
// https://github.com/ulfjack/ryu and carries the following license:
//
// Copyright 2018 Ulf Adams
//
// The contents of this file may be used under the terms of the Apache License,
// Version 2.0.
//
// (See accompanying file LICENSE-Apache or copy at
// http://www.apache.org/licenses/LICENSE-2.0)
//
// Alternatively, the contents of this file may be used under the terms of
// the Boost Software License, Version 1.0.
// (See accompanying file LICENSE-Boost or copy at
// https://www.boost.org/LICENSE_1_0.txt)
//
// Unless required by applicable law or agreed to in writing, this software
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
// A table of all two-digit numbers. This is used to speed up decimal digit
// generation by copying pairs of digits into the final output.
pub static DIGIT_TABLE: [u8; 200] = *b"\
0001020304050607080910111213141516171819\
2021222324252627282930313233343536373839\
4041424344454647484950515253545556575859\
6061626364656667686970717273747576777879\
8081828384858687888990919293949596979899";

494
third_party/rust/ryu/src/f2s.rs vendored Normal file
View File

@ -0,0 +1,494 @@
// Translated from C to Rust. The original C code can be found at
// https://github.com/ulfjack/ryu and carries the following license:
//
// Copyright 2018 Ulf Adams
//
// The contents of this file may be used under the terms of the Apache License,
// Version 2.0.
//
// (See accompanying file LICENSE-Apache or copy at
// http://www.apache.org/licenses/LICENSE-2.0)
//
// Alternatively, the contents of this file may be used under the terms of
// the Boost Software License, Version 1.0.
// (See accompanying file LICENSE-Boost or copy at
// https://www.boost.org/LICENSE_1_0.txt)
//
// Unless required by applicable law or agreed to in writing, this software
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
use core::{mem, ptr};
use common::*;
use digit_table::*;
#[cfg(feature = "no-panic")]
use no_panic::no_panic;
pub const FLOAT_MANTISSA_BITS: u32 = 23;
pub const FLOAT_EXPONENT_BITS: u32 = 8;
const FLOAT_POW5_INV_BITCOUNT: i32 = 59;
const FLOAT_POW5_BITCOUNT: i32 = 61;
// This table is generated by PrintFloatLookupTable.
static FLOAT_POW5_INV_SPLIT: [u64; 32] = [
576460752303423489,
461168601842738791,
368934881474191033,
295147905179352826,
472236648286964522,
377789318629571618,
302231454903657294,
483570327845851670,
386856262276681336,
309485009821345069,
495176015714152110,
396140812571321688,
316912650057057351,
507060240091291761,
405648192073033409,
324518553658426727,
519229685853482763,
415383748682786211,
332306998946228969,
531691198313966350,
425352958651173080,
340282366920938464,
544451787073501542,
435561429658801234,
348449143727040987,
557518629963265579,
446014903970612463,
356811923176489971,
570899077082383953,
456719261665907162,
365375409332725730,
1 << 63,
];
static FLOAT_POW5_SPLIT: [u64; 47] = [
1152921504606846976,
1441151880758558720,
1801439850948198400,
2251799813685248000,
1407374883553280000,
1759218604441600000,
2199023255552000000,
1374389534720000000,
1717986918400000000,
2147483648000000000,
1342177280000000000,
1677721600000000000,
2097152000000000000,
1310720000000000000,
1638400000000000000,
2048000000000000000,
1280000000000000000,
1600000000000000000,
2000000000000000000,
1250000000000000000,
1562500000000000000,
1953125000000000000,
1220703125000000000,
1525878906250000000,
1907348632812500000,
1192092895507812500,
1490116119384765625,
1862645149230957031,
1164153218269348144,
1455191522836685180,
1818989403545856475,
2273736754432320594,
1421085471520200371,
1776356839400250464,
2220446049250313080,
1387778780781445675,
1734723475976807094,
2168404344971008868,
1355252715606880542,
1694065894508600678,
2117582368135750847,
1323488980084844279,
1654361225106055349,
2067951531382569187,
1292469707114105741,
1615587133892632177,
2019483917365790221,
];
#[cfg_attr(feature = "no-panic", inline)]
fn pow5_factor(mut value: u32) -> u32 {
let mut count = 0u32;
loop {
debug_assert!(value != 0);
let q = value / 5;
let r = value % 5;
if r != 0 {
break;
}
value = q;
count += 1;
}
count
}
// Returns true if value is divisible by 5^p.
#[cfg_attr(feature = "no-panic", inline)]
fn multiple_of_power_of_5(value: u32, p: u32) -> bool {
pow5_factor(value) >= p
}
// Returns true if value is divisible by 2^p.
#[cfg_attr(feature = "no-panic", inline)]
fn multiple_of_power_of_2(value: u32, p: u32) -> bool {
// return __builtin_ctz(value) >= p;
(value & ((1u32 << p) - 1)) == 0
}
// It seems to be slightly faster to avoid uint128_t here, although the
// generated code for uint128_t looks slightly nicer.
#[cfg_attr(feature = "no-panic", inline)]
fn mul_shift(m: u32, factor: u64, shift: i32) -> u32 {
debug_assert!(shift > 32);
// The casts here help MSVC to avoid calls to the __allmul library
// function.
let factor_lo = factor as u32;
let factor_hi = (factor >> 32) as u32;
let bits0 = m as u64 * factor_lo as u64;
let bits1 = m as u64 * factor_hi as u64;
let sum = (bits0 >> 32) + bits1;
let shifted_sum = sum >> (shift - 32);
debug_assert!(shifted_sum <= u32::max_value() as u64);
shifted_sum as u32
}
#[cfg_attr(feature = "no-panic", inline)]
fn mul_pow5_inv_div_pow2(m: u32, q: u32, j: i32) -> u32 {
debug_assert!(q < FLOAT_POW5_INV_SPLIT.len() as u32);
unsafe { mul_shift(m, *FLOAT_POW5_INV_SPLIT.get_unchecked(q as usize), j) }
}
#[cfg_attr(feature = "no-panic", inline)]
fn mul_pow5_div_pow2(m: u32, i: u32, j: i32) -> u32 {
debug_assert!(i < FLOAT_POW5_SPLIT.len() as u32);
unsafe { mul_shift(m, *FLOAT_POW5_SPLIT.get_unchecked(i as usize), j) }
}
#[cfg_attr(feature = "no-panic", inline)]
pub fn decimal_length(v: u32) -> u32 {
// Function precondition: v is not a 10-digit number.
// (9 digits are sufficient for round-tripping.)
debug_assert!(v < 1000000000);
if v >= 100000000 {
9
} else if v >= 10000000 {
8
} else if v >= 1000000 {
7
} else if v >= 100000 {
6
} else if v >= 10000 {
5
} else if v >= 1000 {
4
} else if v >= 100 {
3
} else if v >= 10 {
2
} else {
1
}
}
// A floating decimal representing m * 10^e.
pub struct FloatingDecimal32 {
pub mantissa: u32,
pub exponent: i32,
}
#[cfg_attr(feature = "no-panic", inline)]
pub fn f2d(ieee_mantissa: u32, ieee_exponent: u32) -> FloatingDecimal32 {
let bias = (1u32 << (FLOAT_EXPONENT_BITS - 1)) - 1;
let (e2, m2) = if ieee_exponent == 0 {
(
// We subtract 2 so that the bounds computation has 2 additional bits.
1 - bias as i32 - FLOAT_MANTISSA_BITS as i32 - 2,
ieee_mantissa,
)
} else {
(
ieee_exponent as i32 - bias as i32 - FLOAT_MANTISSA_BITS as i32 - 2,
(1u32 << FLOAT_MANTISSA_BITS) | ieee_mantissa,
)
};
let even = (m2 & 1) == 0;
let accept_bounds = even;
// Step 2: Determine the interval of legal decimal representations.
let mv = 4 * m2;
let mp = 4 * m2 + 2;
// Implicit bool -> int conversion. True is 1, false is 0.
let mm_shift = (ieee_mantissa != 0 || ieee_exponent <= 1) as u32;
let mm = 4 * m2 - 1 - mm_shift;
// Step 3: Convert to a decimal power base using 64-bit arithmetic.
let mut vr: u32;
let mut vp: u32;
let mut vm: u32;
let e10: i32;
let mut vm_is_trailing_zeros = false;
let mut vr_is_trailing_zeros = false;
let mut last_removed_digit = 0u8;
if e2 >= 0 {
let q = log10_pow2(e2) as u32;
e10 = q as i32;
let k = FLOAT_POW5_INV_BITCOUNT + pow5bits(q as i32) as i32 - 1;
let i = -e2 + q as i32 + k;
vr = mul_pow5_inv_div_pow2(mv, q, i);
vp = mul_pow5_inv_div_pow2(mp, q, i);
vm = mul_pow5_inv_div_pow2(mm, q, i);
if q != 0 && (vp - 1) / 10 <= vm / 10 {
// We need to know one removed digit even if we are not going to loop below. We could use
// q = X - 1 above, except that would require 33 bits for the result, and we've found that
// 32-bit arithmetic is faster even on 64-bit machines.
let l = FLOAT_POW5_INV_BITCOUNT + pow5bits(q as i32 - 1) as i32 - 1;
last_removed_digit =
(mul_pow5_inv_div_pow2(mv, q - 1, -e2 + q as i32 - 1 + l) % 10) as u8;
}
if q <= 9 {
// The largest power of 5 that fits in 24 bits is 5^10, but q <= 9 seems to be safe as well.
// Only one of mp, mv, and mm can be a multiple of 5, if any.
if mv % 5 == 0 {
vr_is_trailing_zeros = multiple_of_power_of_5(mv, q);
} else if accept_bounds {
vm_is_trailing_zeros = multiple_of_power_of_5(mm, q);
} else {
vp -= multiple_of_power_of_5(mp, q) as u32;
}
}
} else {
let q = log10_pow5(-e2) as u32;
e10 = q as i32 + e2;
let i = -e2 - q as i32;
let k = pow5bits(i) as i32 - FLOAT_POW5_BITCOUNT;
let mut j = q as i32 - k;
vr = mul_pow5_div_pow2(mv, i as u32, j);
vp = mul_pow5_div_pow2(mp, i as u32, j);
vm = mul_pow5_div_pow2(mm, i as u32, j);
if q != 0 && (vp - 1) / 10 <= vm / 10 {
j = q as i32 - 1 - (pow5bits(i + 1) as i32 - FLOAT_POW5_BITCOUNT);
last_removed_digit = (mul_pow5_div_pow2(mv, (i + 1) as u32, j) % 10) as u8;
}
if q <= 1 {
// {vr,vp,vm} is trailing zeros if {mv,mp,mm} has at least q trailing 0 bits.
// mv = 4 * m2, so it always has at least two trailing 0 bits.
vr_is_trailing_zeros = true;
if accept_bounds {
// mm = mv - 1 - mm_shift, so it has 1 trailing 0 bit iff mm_shift == 1.
vm_is_trailing_zeros = mm_shift == 1;
} else {
// mp = mv + 2, so it always has at least one trailing 0 bit.
vp -= 1;
}
} else if q < 31 {
// TODO(ulfjack): Use a tighter bound here.
vr_is_trailing_zeros = multiple_of_power_of_2(mv, q - 1);
}
}
// Step 4: Find the shortest decimal representation in the interval of legal representations.
let mut removed = 0u32;
let output = if vm_is_trailing_zeros || vr_is_trailing_zeros {
// General case, which happens rarely (~4.0%).
while vp / 10 > vm / 10 {
vm_is_trailing_zeros &= vm - (vm / 10) * 10 == 0;
vr_is_trailing_zeros &= last_removed_digit == 0;
last_removed_digit = (vr % 10) as u8;
vr /= 10;
vp /= 10;
vm /= 10;
removed += 1;
}
if vm_is_trailing_zeros {
while vm % 10 == 0 {
vr_is_trailing_zeros &= last_removed_digit == 0;
last_removed_digit = (vr % 10) as u8;
vr /= 10;
vp /= 10;
vm /= 10;
removed += 1;
}
}
if vr_is_trailing_zeros && last_removed_digit == 5 && vr % 2 == 0 {
// Round even if the exact number is .....50..0.
last_removed_digit = 4;
}
// We need to take vr + 1 if vr is outside bounds or we need to round up.
vr + ((vr == vm && (!accept_bounds || !vm_is_trailing_zeros)) || last_removed_digit >= 5)
as u32
} else {
// Specialized for the common case (~96.0%). Percentages below are relative to this.
// Loop iterations below (approximately):
// 0: 13.6%, 1: 70.7%, 2: 14.1%, 3: 1.39%, 4: 0.14%, 5+: 0.01%
while vp / 10 > vm / 10 {
last_removed_digit = (vr % 10) as u8;
vr /= 10;
vp /= 10;
vm /= 10;
removed += 1;
}
// We need to take vr + 1 if vr is outside bounds or we need to round up.
vr + (vr == vm || last_removed_digit >= 5) as u32
};
let exp = e10 + removed as i32;
FloatingDecimal32 {
exponent: exp,
mantissa: output,
}
}
#[cfg_attr(feature = "no-panic", inline)]
unsafe fn to_chars(v: FloatingDecimal32, sign: bool, result: *mut u8) -> usize {
// Step 5: Print the decimal representation.
let mut index = 0isize;
if sign {
*result.offset(index) = b'-';
index += 1;
}
let mut output = v.mantissa;
let olength = decimal_length(output);
// Print the decimal digits.
// The following code is equivalent to:
// for (uint32_t i = 0; i < olength - 1; ++i) {
// const uint32_t c = output % 10; output /= 10;
// result[index + olength - i] = (char) ('0' + c);
// }
// result[index] = '0' + output % 10;
let mut i = 0isize;
while output >= 10000 {
let c = output - 10000 * (output / 10000);
output /= 10000;
let c0 = (c % 100) << 1;
let c1 = (c / 100) << 1;
ptr::copy_nonoverlapping(
DIGIT_TABLE.get_unchecked(c0 as usize),
result.offset(index + olength as isize - i - 1),
2,
);
ptr::copy_nonoverlapping(
DIGIT_TABLE.get_unchecked(c1 as usize),
result.offset(index + olength as isize - i - 3),
2,
);
i += 4;
}
if output >= 100 {
let c = (output % 100) << 1;
output /= 100;
ptr::copy_nonoverlapping(
DIGIT_TABLE.get_unchecked(c as usize),
result.offset(index + olength as isize - i - 1),
2,
);
i += 2;
}
if output >= 10 {
let c = output << 1;
// We can't use memcpy here: the decimal dot goes between these two digits.
*result.offset(index + olength as isize - i) = *DIGIT_TABLE.get_unchecked(c as usize + 1);
*result.offset(index) = *DIGIT_TABLE.get_unchecked(c as usize);
} else {
*result.offset(index) = b'0' + output as u8;
}
// Print decimal point if needed.
if olength > 1 {
*result.offset(index + 1) = b'.';
index += olength as isize + 1;
} else {
index += 1;
}
// Print the exponent.
*result.offset(index) = b'E';
index += 1;
let mut exp = v.exponent + olength as i32 - 1;
if exp < 0 {
*result.offset(index) = b'-';
index += 1;
exp = -exp;
}
if exp >= 10 {
ptr::copy_nonoverlapping(
DIGIT_TABLE.get_unchecked((2 * exp) as usize),
result.offset(index),
2,
);
index += 2;
} else {
*result.offset(index) = b'0' + exp as u8;
index += 1;
}
debug_assert!(index <= 15);
index as usize
}
/// Print f32 to the given buffer and return number of bytes written.
///
/// At most 15 bytes will be written.
///
/// ## Special cases
///
/// This function represents any NaN as `NaN`, positive infinity as `Infinity`,
/// and negative infinity as `-Infinity`.
///
/// ## Safety
///
/// The `result` pointer argument must point to sufficiently many writable bytes
/// to hold Ryū's representation of `f`.
///
/// ## Example
///
/// ```rust
/// let f = 1.234f32;
///
/// unsafe {
/// let mut buffer: [u8; 15] = std::mem::uninitialized();
/// let n = ryu::raw::f2s_buffered_n(f, &mut buffer[0]);
/// let s = std::str::from_utf8_unchecked(&buffer[..n]);
/// assert_eq!(s, "1.234E0");
/// }
/// ```
#[cfg_attr(must_use_return, must_use)]
#[cfg_attr(feature = "no-panic", no_panic)]
pub unsafe fn f2s_buffered_n(f: f32, result: *mut u8) -> usize {
// Step 1: Decode the floating-point number, and unify normalized and subnormal cases.
let bits = mem::transmute::<f32, u32>(f);
// Decode bits into sign, mantissa, and exponent.
let ieee_sign = ((bits >> (FLOAT_MANTISSA_BITS + FLOAT_EXPONENT_BITS)) & 1) != 0;
let ieee_mantissa = bits & ((1u32 << FLOAT_MANTISSA_BITS) - 1);
let ieee_exponent =
((bits >> FLOAT_MANTISSA_BITS) & ((1u32 << FLOAT_EXPONENT_BITS) - 1)) as u32;
// Case distinction; exit early for the easy cases.
if ieee_exponent == ((1u32 << FLOAT_EXPONENT_BITS) - 1)
|| (ieee_exponent == 0 && ieee_mantissa == 0)
{
return copy_special_str(result, ieee_sign, ieee_exponent != 0, ieee_mantissa != 0);
}
let v = f2d(ieee_mantissa, ieee_exponent);
to_chars(v, ieee_sign, result)
}

68
third_party/rust/ryu/src/lib.rs vendored Normal file
View File

@ -0,0 +1,68 @@
//! Pure Rust implementation of Ryū, an algorithm to quickly convert floating
//! point numbers to decimal strings.
//!
//! The PLDI'18 paper [*Ryū: fast float-to-string conversion*][paper] by Ulf
//! Adams includes a complete correctness proof of the algorithm. The paper is
//! available under the creative commons CC-BY-SA license.
//!
//! This Rust implementation is a line-by-line port of Ulf Adams' implementation
//! in C, [https://github.com/ulfjack/ryu][upstream]. The [`ryu::raw`][raw]
//! module exposes exactly the API and formatting of the C implementation as
//! unsafe pure Rust functions. There is additionally a safe API as demonstrated
//! in the example code below. The safe API uses the same underlying Ryū
//! algorithm but diverges from the formatting of the C implementation to
//! produce more human-readable output, for example `0.3` rather than `3E-1`.
//!
//! [paper]: https://dl.acm.org/citation.cfm?id=3192369
//! [upstream]: https://github.com/ulfjack/ryu
//! [raw]: raw/index.html
//!
//! # Examples
//!
//! ```rust
//! extern crate ryu;
//!
//! fn main() {
//! let mut buffer = ryu::Buffer::new();
//! let printed = buffer.format(1.234);
//! assert_eq!(printed, "1.234");
//! }
//! ```
#![no_std]
#![doc(html_root_url = "https://docs.rs/ryu/0.2.4")]
#![cfg_attr(feature = "no-panic", feature(use_extern_macros))]
#![cfg_attr(
feature = "cargo-clippy",
allow(
cast_lossless,
cyclomatic_complexity,
many_single_char_names,
needless_pass_by_value,
unreadable_literal,
)
)]
#[cfg(feature = "no-panic")]
extern crate no_panic;
mod buffer;
mod common;
mod d2s;
#[cfg(not(feature = "small"))]
mod d2s_full_table;
#[cfg(feature = "small")]
mod d2s_small_table;
mod digit_table;
mod f2s;
#[cfg(not(integer128))]
mod mulshift128;
mod pretty;
pub use buffer::{Buffer, Float};
/// Unsafe functions that exactly mirror the API of the C implementation of Ryū.
pub mod raw {
pub use d2s::d2s_buffered_n;
pub use f2s::f2s_buffered_n;
}

57
third_party/rust/ryu/src/mulshift128.rs vendored Normal file
View File

@ -0,0 +1,57 @@
// Translated from C to Rust. The original C code can be found at
// https://github.com/ulfjack/ryu and carries the following license:
//
// Copyright 2018 Ulf Adams
//
// The contents of this file may be used under the terms of the Apache License,
// Version 2.0.
//
// (See accompanying file LICENSE-Apache or copy at
// http://www.apache.org/licenses/LICENSE-2.0)
//
// Alternatively, the contents of this file may be used under the terms of
// the Boost Software License, Version 1.0.
// (See accompanying file LICENSE-Boost or copy at
// https://www.boost.org/LICENSE_1_0.txt)
//
// Unless required by applicable law or agreed to in writing, this software
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
// Returns (lo, hi).
#[cfg_attr(feature = "no-panic", inline)]
pub fn umul128(a: u64, b: u64) -> (u64, u64) {
let a_lo = a as u32;
let a_hi = (a >> 32) as u32;
let b_lo = b as u32;
let b_hi = (b >> 32) as u32;
let b00 = a_lo as u64 * b_lo as u64;
let b01 = a_lo as u64 * b_hi as u64;
let b10 = a_hi as u64 * b_lo as u64;
let b11 = a_hi as u64 * b_hi as u64;
let b00_lo = b00 as u32;
let b00_hi = (b00 >> 32) as u32;
let mid1 = b10 + b00_hi as u64;
let mid1_lo = mid1 as u32;
let mid1_hi = (mid1 >> 32) as u32;
let mid2 = b01 + mid1_lo as u64;
let mid2_lo = mid2 as u32;
let mid2_hi = (mid2 >> 32) as u32;
let p_hi = b11 + mid1_hi as u64 + mid2_hi as u64;
let p_lo = ((mid2_lo as u64) << 32) + b00_lo as u64;
(p_lo, p_hi)
}
#[cfg_attr(feature = "no-panic", inline)]
pub fn shiftright128(lo: u64, hi: u64, dist: u32) -> u64 {
// We don't need to handle the case dist >= 64 here (see above).
debug_assert!(dist > 0);
debug_assert!(dist < 64);
(hi << (64 - dist)) | (lo >> dist)
}

View File

@ -0,0 +1,49 @@
use core::ptr;
use digit_table::*;
#[cfg_attr(feature = "no-panic", inline)]
pub unsafe fn write_exponent3(mut k: isize, mut result: *mut u8) -> usize {
let sign = k < 0;
if sign {
*result = b'-';
result = result.offset(1);
k = -k;
}
debug_assert!(k < 1000);
if k >= 100 {
*result = b'0' + (k / 100) as u8;
k %= 100;
let d = DIGIT_TABLE.get_unchecked(k as usize * 2);
ptr::copy_nonoverlapping(d, result.offset(1), 2);
sign as usize + 3
} else if k >= 10 {
let d = DIGIT_TABLE.get_unchecked(k as usize * 2);
ptr::copy_nonoverlapping(d, result, 2);
sign as usize + 2
} else {
*result = b'0' + k as u8;
sign as usize + 1
}
}
#[cfg_attr(feature = "no-panic", inline)]
pub unsafe fn write_exponent2(mut k: isize, mut result: *mut u8) -> usize {
let sign = k < 0;
if sign {
*result = b'-';
result = result.offset(1);
k = -k;
}
debug_assert!(k < 100);
if k >= 10 {
let d = DIGIT_TABLE.get_unchecked(k as usize * 2);
ptr::copy_nonoverlapping(d, result, 2);
sign as usize + 2
} else {
*result = b'0' + k as u8;
sign as usize + 1
}
}

View File

@ -0,0 +1,51 @@
use core::ptr;
use digit_table::*;
#[cfg_attr(feature = "no-panic", inline)]
pub unsafe fn write_mantissa_long(mut output: u64, mut result: *mut u8) {
if (output >> 32) != 0 {
// One expensive 64-bit division.
let mut output2 = (output - 100_000_000 * (output / 100_000_000)) as u32;
output /= 100_000_000;
let c = output2 % 10_000;
output2 /= 10_000;
let d = output2 % 10_000;
let c0 = (c % 100) << 1;
let c1 = (c / 100) << 1;
let d0 = (d % 100) << 1;
let d1 = (d / 100) << 1;
ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(c0 as usize), result.offset(-2), 2);
ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(c1 as usize), result.offset(-4), 2);
ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(d0 as usize), result.offset(-6), 2);
ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(d1 as usize), result.offset(-8), 2);
result = result.offset(-8);
}
write_mantissa(output as u32, result);
}
#[cfg_attr(feature = "no-panic", inline)]
pub unsafe fn write_mantissa(mut output: u32, mut result: *mut u8) {
while output >= 10_000 {
let c = (output - 10_000 * (output / 10_000)) as u32;
output /= 10_000;
let c0 = (c % 100) << 1;
let c1 = (c / 100) << 1;
ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(c0 as usize), result.offset(-2), 2);
ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(c1 as usize), result.offset(-4), 2);
result = result.offset(-4);
}
if output >= 100 {
let c = ((output % 100) << 1) as u32;
output /= 100;
ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(c as usize), result.offset(-2), 2);
result = result.offset(-2);
}
if output >= 10 {
let c = (output << 1) as u32;
ptr::copy_nonoverlapping(DIGIT_TABLE.get_unchecked(c as usize), result.offset(-2), 2);
} else {
*result.offset(-1) = b'0' + output as u8;
}
}

154
third_party/rust/ryu/src/pretty/mod.rs vendored Normal file
View File

@ -0,0 +1,154 @@
mod exponent;
mod mantissa;
use core::{mem, ptr};
use self::exponent::*;
use self::mantissa::*;
use d2s;
use d2s::*;
use f2s;
use f2s::*;
#[cfg(feature = "no-panic")]
use no_panic::no_panic;
#[cfg_attr(must_use_return, must_use)]
#[cfg_attr(feature = "no-panic", no_panic)]
pub unsafe fn d2s_buffered_n(f: f64, result: *mut u8) -> usize {
let bits = mem::transmute::<f64, u64>(f);
let sign = ((bits >> (DOUBLE_MANTISSA_BITS + DOUBLE_EXPONENT_BITS)) & 1) != 0;
let ieee_mantissa = bits & ((1u64 << DOUBLE_MANTISSA_BITS) - 1);
let ieee_exponent =
(bits >> DOUBLE_MANTISSA_BITS) as u32 & ((1u32 << DOUBLE_EXPONENT_BITS) - 1);
let mut index = 0isize;
if sign {
*result = b'-';
index += 1;
}
if ieee_exponent == 0 && ieee_mantissa == 0 {
ptr::copy_nonoverlapping(b"0.0".as_ptr(), result.offset(index), 3);
return sign as usize + 3;
}
let v = d2d(ieee_mantissa, ieee_exponent);
let length = d2s::decimal_length(v.mantissa) as isize;
let k = v.exponent as isize;
let kk = length + k; // 10^(kk-1) <= v < 10^kk
debug_assert!(k >= -324);
if 0 <= k && kk <= 16 {
// 1234e7 -> 12340000000.0
write_mantissa_long(v.mantissa, result.offset(index + length));
for i in length..kk {
*result.offset(index + i) = b'0';
}
*result.offset(index + kk) = b'.';
*result.offset(index + kk + 1) = b'0';
index as usize + kk as usize + 2
} else if 0 < kk && kk <= 16 {
// 1234e-2 -> 12.34
write_mantissa_long(v.mantissa, result.offset(index + length + 1));
ptr::copy(result.offset(index + 1), result.offset(index), kk as usize);
*result.offset(index + kk) = b'.';
index as usize + length as usize + 1
} else if -5 < kk && kk <= 0 {
// 1234e-6 -> 0.001234
*result.offset(index) = b'0';
*result.offset(index + 1) = b'.';
let offset = 2 - kk;
for i in 2..offset {
*result.offset(index + i) = b'0';
}
write_mantissa_long(v.mantissa, result.offset(index + length + offset));
index as usize + length as usize + offset as usize
} else if length == 1 {
// 1e30
*result.offset(index) = b'0' + v.mantissa as u8;
*result.offset(index + 1) = b'e';
index as usize + 2 + write_exponent3(kk - 1, result.offset(index + 2))
} else {
// 1234e30 -> 1.234e33
write_mantissa_long(v.mantissa, result.offset(index + length + 1));
*result.offset(index) = *result.offset(index + 1);
*result.offset(index + 1) = b'.';
*result.offset(index + length + 1) = b'e';
index as usize
+ length as usize
+ 2
+ write_exponent3(kk - 1, result.offset(index + length + 2))
}
}
#[cfg_attr(must_use_return, must_use)]
#[cfg_attr(feature = "no-panic", no_panic)]
pub unsafe fn f2s_buffered_n(f: f32, result: *mut u8) -> usize {
let bits = mem::transmute::<f32, u32>(f);
let sign = ((bits >> (FLOAT_MANTISSA_BITS + FLOAT_EXPONENT_BITS)) & 1) != 0;
let ieee_mantissa = bits & ((1u32 << FLOAT_MANTISSA_BITS) - 1);
let ieee_exponent =
((bits >> FLOAT_MANTISSA_BITS) & ((1u32 << FLOAT_EXPONENT_BITS) - 1)) as u32;
let mut index = 0isize;
if sign {
*result = b'-';
index += 1;
}
if ieee_exponent == 0 && ieee_mantissa == 0 {
ptr::copy_nonoverlapping(b"0.0".as_ptr(), result.offset(index), 3);
return sign as usize + 3;
}
let v = f2d(ieee_mantissa, ieee_exponent);
let length = f2s::decimal_length(v.mantissa) as isize;
let k = v.exponent as isize;
let kk = length + k; // 10^(kk-1) <= v < 10^kk
debug_assert!(k >= -45);
if 0 <= k && kk <= 13 {
// 1234e7 -> 12340000000.0
write_mantissa(v.mantissa, result.offset(index + length));
for i in length..kk {
*result.offset(index + i) = b'0';
}
*result.offset(index + kk) = b'.';
*result.offset(index + kk + 1) = b'0';
index as usize + kk as usize + 2
} else if 0 < kk && kk <= 13 {
// 1234e-2 -> 12.34
write_mantissa(v.mantissa, result.offset(index + length + 1));
ptr::copy(result.offset(index + 1), result.offset(index), kk as usize);
*result.offset(index + kk) = b'.';
index as usize + length as usize + 1
} else if -6 < kk && kk <= 0 {
// 1234e-6 -> 0.001234
*result.offset(index) = b'0';
*result.offset(index + 1) = b'.';
let offset = 2 - kk;
for i in 2..offset {
*result.offset(index + i) = b'0';
}
write_mantissa(v.mantissa, result.offset(index + length + offset));
index as usize + length as usize + offset as usize
} else if length == 1 {
// 1e30
*result.offset(index) = b'0' + v.mantissa as u8;
*result.offset(index + 1) = b'e';
index as usize + 2 + write_exponent2(kk - 1, result.offset(index + 2))
} else {
// 1234e30 -> 1.234e33
write_mantissa(v.mantissa, result.offset(index + length + 1));
*result.offset(index) = *result.offset(index + 1);
*result.offset(index + 1) = b'.';
*result.offset(index + length + 1) = b'e';
index as usize
+ length as usize
+ 2
+ write_exponent2(kk - 1, result.offset(index + length + 2))
}
}

View File

@ -0,0 +1,52 @@
// Translated from C to Rust. The original C code can be found at
// https://github.com/ulfjack/ryu and carries the following license:
//
// Copyright 2018 Ulf Adams
//
// The contents of this file may be used under the terms of the Apache License,
// Version 2.0.
//
// (See accompanying file LICENSE-Apache or copy at
// http://www.apache.org/licenses/LICENSE-2.0)
//
// Alternatively, the contents of this file may be used under the terms of
// the Boost Software License, Version 1.0.
// (See accompanying file LICENSE-Boost or copy at
// https://www.boost.org/LICENSE_1_0.txt)
//
// Unless required by applicable law or agreed to in writing, this software
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
#![allow(dead_code)]
extern crate core;
#[path = "../src/common.rs"]
mod common;
#[path = "../src/d2s_full_table.rs"]
mod d2s_full_table;
#[path = "../src/d2s_small_table.rs"]
mod d2s_small_table;
#[path = "../src/mulshift128.rs"]
mod mulshift128;
use d2s_full_table::*;
use d2s_small_table::*;
#[test]
fn test_compute_pow5() {
for (i, entry) in DOUBLE_POW5_SPLIT.iter().enumerate() {
assert_eq!(*entry, unsafe { compute_pow5(i as u32) }, "entry {}", i);
}
}
#[test]
fn test_compute_inv_pow5() {
for (i, entry) in DOUBLE_POW5_INV_SPLIT.iter().enumerate() {
assert_eq!(*entry, unsafe { compute_inv_pow5(i as u32) }, "entry {}", i);
}
}

154
third_party/rust/ryu/tests/d2s_test.rs vendored Normal file
View File

@ -0,0 +1,154 @@
// Translated from C to Rust. The original C code can be found at
// https://github.com/ulfjack/ryu and carries the following license:
//
// Copyright 2018 Ulf Adams
//
// The contents of this file may be used under the terms of the Apache License,
// Version 2.0.
//
// (See accompanying file LICENSE-Apache or copy at
// http://www.apache.org/licenses/LICENSE-2.0)
//
// Alternatively, the contents of this file may be used under the terms of
// the Boost Software License, Version 1.0.
// (See accompanying file LICENSE-Boost or copy at
// https://www.boost.org/LICENSE_1_0.txt)
//
// Unless required by applicable law or agreed to in writing, this software
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
extern crate rand;
extern crate ryu;
#[macro_use]
mod macros;
use std::{f64, str};
fn print(f: f64) -> String {
let mut bytes = [0u8; 24];
let n = unsafe { ryu::raw::d2s_buffered_n(f, &mut bytes[0]) };
let s = str::from_utf8(&bytes[..n]).unwrap();
s.to_owned()
}
fn pretty(f: f64) -> String {
ryu::Buffer::new().format(f).to_owned()
}
#[test]
fn test_ryu() {
check!(3E-1, 0.3);
check!(1.234E15, 1234000000000000.0);
check!(1.234E16, 1.234e16);
check!(2.71828E0, 2.71828);
check!(1.1E128, 1.1e128);
check!(1.1E-64, 1.1e-64);
check!(2.718281828459045E0, 2.718281828459045);
check!(5E-324, 5e-324);
check!(1.7976931348623157E308, 1.7976931348623157e308);
}
#[test]
fn test_random() {
let mut bytes = [0u8; 24];
let mut buffer = ryu::Buffer::new();
for _ in 0..1000000 {
let f = rand::random();
let n = unsafe { ryu::raw::d2s_buffered_n(f, &mut bytes[0]) };
assert_eq!(f, str::from_utf8(&bytes[..n]).unwrap().parse().unwrap());
assert_eq!(f, buffer.format(f).parse().unwrap());
}
}
#[test]
fn test_non_finite() {
for i in 0u64..1 << 23 {
let f = f64::from_bits((((1 << 11) - 1) << 52) + (i << 29));
assert!(!f.is_finite(), "f={}", f);
ryu::Buffer::new().format(f);
}
}
#[test]
fn test_basic() {
check!(0E0, 0.0);
check!(-0E0, -0.0);
check!(1E0, 1.0);
check!(-1E0, -1.0);
assert_eq!(print(f64::NAN), "NaN");
assert_eq!(print(f64::INFINITY), "Infinity");
assert_eq!(print(f64::NEG_INFINITY), "-Infinity");
}
#[test]
fn test_switch_to_subnormal() {
check!(2.2250738585072014E-308, 2.2250738585072014e-308);
}
#[test]
fn test_min_and_max() {
assert_eq!(f64::from_bits(0x7fefffffffffffff), 1.7976931348623157e308);
check!(1.7976931348623157E308, 1.7976931348623157e308);
assert_eq!(f64::from_bits(1), 5e-324);
check!(5E-324, 5e-324);
}
#[test]
fn test_lots_of_trailing_zeros() {
check!(2.9802322387695312E-8, 2.9802322387695312e-8);
}
#[test]
fn test_regression() {
check!(-2.109808898695963E16, -2.109808898695963e16);
check!(4.940656E-318, 4.940656e-318);
check!(1.18575755E-316, 1.18575755e-316);
check!(2.989102097996E-312, 2.989102097996e-312);
check!(9.0608011534336E15, 9060801153433600.0);
check!(4.708356024711512E18, 4.708356024711512e18);
check!(9.409340012568248E18, 9.409340012568248e18);
check!(1.2345678E0, 1.2345678);
}
#[test]
fn test_looks_like_pow5() {
// These numbers have a mantissa that is a multiple of the largest power of
// 5 that fits, and an exponent that causes the computation for q to result
// in 22, which is a corner case for Ryu.
assert_eq!(f64::from_bits(0x4830F0CF064DD592), 5.764607523034235e39);
check!(5.764607523034235E39, 5.764607523034235e39);
assert_eq!(f64::from_bits(0x4840F0CF064DD592), 1.152921504606847e40);
check!(1.152921504606847E40, 1.152921504606847e40);
assert_eq!(f64::from_bits(0x4850F0CF064DD592), 2.305843009213694e40);
check!(2.305843009213694E40, 2.305843009213694e40);
}
#[test]
fn test_output_length() {
check!(1E0, 1.0); // already tested in Basic
check!(1.2E0, 1.2);
check!(1.23E0, 1.23);
check!(1.234E0, 1.234);
check!(1.2345E0, 1.2345);
check!(1.23456E0, 1.23456);
check!(1.234567E0, 1.234567);
check!(1.2345678E0, 1.2345678); // already tested in Regression
check!(1.23456789E0, 1.23456789);
check!(1.234567895E0, 1.234567895); // 1.234567890 would be trimmed
check!(1.2345678901E0, 1.2345678901);
check!(1.23456789012E0, 1.23456789012);
check!(1.234567890123E0, 1.234567890123);
check!(1.2345678901234E0, 1.2345678901234);
check!(1.23456789012345E0, 1.23456789012345);
check!(1.234567890123456E0, 1.234567890123456);
check!(1.2345678901234567E0, 1.2345678901234567);
// Test 32-bit chunking
check!(4.294967294E0, 4.294967294); // 2^32 - 2
check!(4.294967295E0, 4.294967295); // 2^32 - 1
check!(4.294967296E0, 4.294967296); // 2^32
check!(4.294967297E0, 4.294967297); // 2^32 + 1
check!(4.294967298E0, 4.294967298); // 2^32 + 2
}

View File

@ -0,0 +1,55 @@
#![cfg(exhaustive)]
extern crate num_cpus;
extern crate ryu;
use std::str;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use std::thread;
#[test]
fn test_exhaustive() {
const BATCH_SIZE: u32 = 1_000_000;
let counter = Arc::new(AtomicUsize::new(0));
let finished = Arc::new(AtomicUsize::new(0));
let mut workers = Vec::new();
for _ in 0..num_cpus::get() {
let counter = counter.clone();
let finished = finished.clone();
workers.push(thread::spawn(move || loop {
let batch = counter.fetch_add(1, Ordering::SeqCst) as u32;
if batch > u32::max_value() / BATCH_SIZE {
return;
}
let min = batch * BATCH_SIZE;
let max = if batch == u32::max_value() / BATCH_SIZE {
u32::max_value()
} else {
min + BATCH_SIZE - 1
};
let mut bytes = [0u8; 24];
let mut buffer = ryu::Buffer::new();
for u in min..=max {
let f = f32::from_bits(u);
if !f.is_finite() {
continue;
}
let n = unsafe { ryu::raw::f2s_buffered_n(f, &mut bytes[0]) };
assert_eq!(Ok(Ok(f)), str::from_utf8(&bytes[..n]).map(str::parse));
assert_eq!(Ok(f), buffer.format(f).parse());
}
let increment = (max - min + 1) as usize;
let update = finished.fetch_add(increment, Ordering::SeqCst);
println!("{}", update + increment);
}));
}
for w in workers {
w.join().unwrap();
}
}

183
third_party/rust/ryu/tests/f2s_test.rs vendored Normal file
View File

@ -0,0 +1,183 @@
// Translated from C to Rust. The original C code can be found at
// https://github.com/ulfjack/ryu and carries the following license:
//
// Copyright 2018 Ulf Adams
//
// The contents of this file may be used under the terms of the Apache License,
// Version 2.0.
//
// (See accompanying file LICENSE-Apache or copy at
// http://www.apache.org/licenses/LICENSE-2.0)
//
// Alternatively, the contents of this file may be used under the terms of
// the Boost Software License, Version 1.0.
// (See accompanying file LICENSE-Boost or copy at
// https://www.boost.org/LICENSE_1_0.txt)
//
// Unless required by applicable law or agreed to in writing, this software
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
extern crate rand;
extern crate ryu;
#[macro_use]
mod macros;
use std::{f32, str};
fn print(f: f32) -> String {
let mut bytes = [0u8; 24];
let n = unsafe { ryu::raw::f2s_buffered_n(f, &mut bytes[0]) };
let s = str::from_utf8(&bytes[..n]).unwrap();
s.to_owned()
}
fn pretty(f: f32) -> String {
ryu::Buffer::new().format(f).to_owned()
}
#[test]
fn test_ryu() {
check!(3E-1, 0.3);
check!(1.234E12, 1234000000000.0);
check!(1.234E13, 1.234e13);
check!(2.71828E0, 2.71828);
check!(1.1E32, 1.1e32);
check!(1.1E-32, 1.1e-32);
check!(2.7182817E0, 2.7182817);
check!(1E-45, 1e-45);
check!(3.4028235E38, 3.4028235e38);
check!(-1.234E-3, -0.001234);
}
#[test]
fn test_random() {
let mut bytes = [0u8; 24];
let mut buffer = ryu::Buffer::new();
for _ in 0..1000000 {
let f = rand::random();
let n = unsafe { ryu::raw::f2s_buffered_n(f, &mut bytes[0]) };
assert_eq!(f, str::from_utf8(&bytes[..n]).unwrap().parse().unwrap());
assert_eq!(f, buffer.format(f).parse().unwrap());
}
}
#[test]
fn test_non_finite() {
for i in 0u32..1 << 23 {
let f = f32::from_bits((((1 << 8) - 1) << 23) + i);
assert!(!f.is_finite(), "f={}", f);
ryu::Buffer::new().format(f);
}
}
#[test]
fn test_basic() {
check!(0E0, 0.0);
check!(-0E0, -0.0);
check!(1E0, 1.0);
check!(-1E0, -1.0);
assert_eq!(print(f32::NAN), "NaN");
assert_eq!(print(f32::INFINITY), "Infinity");
assert_eq!(print(f32::NEG_INFINITY), "-Infinity");
}
#[test]
fn test_switch_to_subnormal() {
check!(1.1754944E-38, 1.1754944e-38);
}
#[test]
fn test_min_and_max() {
assert_eq!(f32::from_bits(0x7f7fffff), 3.4028235e38);
check!(3.4028235E38, 3.4028235e38);
assert_eq!(f32::from_bits(1), 1e-45);
check!(1E-45, 1e-45);
}
// Check that we return the exact boundary if it is the shortest
// representation, but only if the original floating point number is even.
#[test]
fn test_boundary_round_even() {
check!(3.355445E7, 33554450.0);
check!(9E9, 9000000000.0);
check!(3.436672E10, 34366720000.0);
}
// If the exact value is exactly halfway between two shortest representations,
// then we round to even. It seems like this only makes a difference if the
// last two digits are ...2|5 or ...7|5, and we cut off the 5.
#[test]
fn test_exact_value_round_even() {
check!(3.0540412E5, 305404.12);
check!(8.0990312E3, 8099.0312);
}
#[test]
fn test_lots_of_trailing_zeros() {
// Pattern for the first test: 00111001100000000000000000000000
check!(2.4414062E-4, 0.00024414062);
check!(2.4414062E-3, 0.0024414062);
check!(4.3945312E-3, 0.0043945312);
check!(6.3476562E-3, 0.0063476562);
}
#[test]
fn test_regression() {
check!(4.7223665E21, 4.7223665e21);
check!(8.388608E6, 8388608.0);
check!(1.6777216E7, 16777216.0);
check!(3.3554436E7, 33554436.0);
check!(6.7131496E7, 67131496.0);
check!(1.9310392E-38, 1.9310392e-38);
check!(-2.47E-43, -2.47e-43);
check!(1.993244E-38, 1.993244e-38);
check!(4.1039004E3, 4103.9004);
check!(5.3399997E9, 5339999700.0);
check!(6.0898E-39, 6.0898e-39);
check!(1.0310042E-3, 0.0010310042);
check!(2.882326E17, 2.882326e17);
check!(7.038531E-26, 7.038531e-26);
check!(9.223404E17, 9.223404e17);
check!(6.710887E7, 67108870.0);
check!(1E-44, 1e-44);
check!(2.816025E14, 2.816025e14);
check!(9.223372E18, 9.223372e18);
check!(1.5846086E29, 1.5846086e29);
check!(1.1811161E19, 1.1811161e19);
check!(5.368709E18, 5.368709e18);
check!(4.6143166E18, 4.6143166e18);
check!(7.812537E-3, 0.007812537);
check!(1E-45, 1e-45);
check!(1.18697725E20, 1.18697725e20);
check!(1.00014165E-36, 1.00014165e-36);
check!(2E2, 200.0);
check!(3.3554432E7, 33554432.0);
}
#[test]
fn test_looks_like_pow5() {
// These numbers have a mantissa that is the largest power of 5 that fits,
// and an exponent that causes the computation for q to result in 10, which
// is a corner case for Ryu.
assert_eq!(f32::from_bits(0x5D1502F9), 6.7108864e17);
check!(6.7108864E17, 6.7108864e17);
assert_eq!(f32::from_bits(0x5D9502F9), 1.3421773e18);
check!(1.3421773E18, 1.3421773e18);
assert_eq!(f32::from_bits(0x5E1502F9), 2.6843546e18);
check!(2.6843546E18, 2.6843546e18);
}
#[test]
fn test_output_length() {
check!(1E0, 1.0); // already tested in Basic
check!(1.2E0, 1.2);
check!(1.23E0, 1.23);
check!(1.234E0, 1.234);
check!(1.2345E0, 1.2345);
check!(1.23456E0, 1.23456);
check!(1.234567E0, 1.234567);
check!(1.2345678E0, 1.2345678);
check!(1.23456735E-36, 1.23456735e-36);
}

View File

@ -0,0 +1,12 @@
macro_rules! check {
($ryu:tt, $pretty:tt) => {
assert_eq!($ryu, $pretty);
assert_eq!(print($ryu), stringify!($ryu));
assert_eq!(pretty($pretty), stringify!($pretty));
};
(-$ryu:tt, -$pretty:tt) => {
assert_eq!(-$ryu, -$pretty);
assert_eq!(print(-$ryu), concat!("-", stringify!($ryu)));
assert_eq!(pretty(-$pretty), concat!("-", stringify!($pretty)));
};
}

View File

@ -0,0 +1 @@
{"files":{"Cargo.toml":"0265066945da4da5957f3446cef6f2a52e81254be3a9c4e678cc2c1e1160118b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"c4d8690cd2aa2db200ecdf2f2113fc8e3f4ccc88f3dc96da22189f45136932d0","src/de.rs":"42d7aa8cf85baa1b3851180e32af883c11ca2889df6f4eb306670f360af46d3e","src/error.rs":"8ac6d4c861891c133b3359b2a14fccb8a6d463a4b2c13f0d658884c1972186ce","src/iter.rs":"b5c77c5482e45bed1e63bd36a0f991a08f732811546a163228be48303e7f1b4d","src/lib.rs":"698af0adc583d8b5a22f510bb33fbdb35552dd6e0775e038f7ed50f6680580d8","src/macros.rs":"0d9850832f53c8aca337395b2536f1cdaf2d2d2699adc09c9a2001544106a4fc","src/map.rs":"724205f934003c879fb3e48a84b21c54e273e968beec97b85617042911ca88d7","src/number.rs":"47bf5416ca4f8299e98f008bd1bcf7e7311f00d0ce282536a17310fa73788def","src/read.rs":"832bc530dd35ee24df59c1cf648cfbbffc4c2e72e86104b0e186582ae0de545a","src/ser.rs":"d2050d362c23e988141e6c5d08590152b3412ee3464e1a3026b83dda7de0c985","src/value/de.rs":"b25d9192f179f84c0ecb2226216ff663c39ebdde524179f7118718f3202243cf","src/value/from.rs":"13a6c7b0b327f23c2fd899c8390e8ddfd8907bfcfc362e80834b9ae7ddb698e9","src/value/index.rs":"b9a8cc6f37e2a079a5e4ab1bf25fa9ff076c514870e0756a0c88af3ffa0f51a8","src/value/mod.rs":"8d0ac56fcd12aee1c645afdfe0df62b10527cab21d16284fe9f0bd6768457002","src/value/partial_eq.rs":"5924e245408afc8075e2bb9dda479c938c6c8cdd3c18b54697aa2b33fffda57b","src/value/ser.rs":"4bbc3ad0f646464f1e9b9a2c2e48df799d02ef658eacadc35971b897cfe7cd02"},"package":"44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae"}

54
third_party/rust/serde_json/Cargo.toml vendored Normal file
View File

@ -0,0 +1,54 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g. crates.io) dependencies
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
[package]
name = "serde_json"
version = "1.0.26"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
description = "A JSON serialization file format"
documentation = "http://docs.serde.rs/serde_json/"
readme = "README.md"
keywords = ["json", "serde", "serialization"]
categories = ["encoding"]
license = "MIT/Apache-2.0"
repository = "https://github.com/serde-rs/json"
[dependencies.indexmap]
version = "1.0"
optional = true
[dependencies.itoa]
version = "0.4"
[dependencies.ryu]
version = "0.2"
[dependencies.serde]
version = "1.0.60"
[dev-dependencies.compiletest_rs]
version = "0.3"
[dev-dependencies.serde_bytes]
version = "0.10"
[dev-dependencies.serde_derive]
version = "1.0"
[features]
arbitrary_precision = []
default = []
preserve_order = ["indexmap"]
[badges.appveyor]
repository = "serde-rs/json"
[badges.travis-ci]
repository = "serde-rs/json"

365
third_party/rust/serde_json/README.md vendored Normal file
View File

@ -0,0 +1,365 @@
# Serde JSON &emsp; [![Build Status]][travis] [![Latest Version]][crates.io] [![Rustc Version 1.15+]][rustc]
[Build Status]: https://api.travis-ci.org/serde-rs/json.svg?branch=master
[travis]: https://travis-ci.org/serde-rs/json
[Latest Version]: https://img.shields.io/crates/v/serde_json.svg
[crates.io]: https://crates.io/crates/serde\_json
[Rustc Version 1.15+]: https://img.shields.io/badge/rustc-1.15+-lightgray.svg
[rustc]: https://blog.rust-lang.org/2017/02/02/Rust-1.15.html
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
---
```toml
[dependencies]
serde_json = "1.0"
```
You may be looking for:
- [JSON API documentation](https://docs.serde.rs/serde_json/)
- [Serde API documentation](https://docs.serde.rs/serde/)
- [Detailed documentation about Serde](https://serde.rs/)
- [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/codegen.html)
- [Release notes](https://github.com/serde-rs/json/releases)
JSON is a ubiquitous open-standard format that uses human-readable text to
transmit data objects consisting of key-value pairs.
```json,ignore
{
"name": "John Doe",
"age": 43,
"address": {
"street": "10 Downing Street",
"city": "London"
},
"phones": [
"+44 1234567",
"+44 2345678"
]
}
```
There are three common ways that you might find yourself needing to work
with JSON data in Rust.
- **As text data.** An unprocessed string of JSON data that you receive on
an HTTP endpoint, read from a file, or prepare to send to a remote
server.
- **As an untyped or loosely typed representation.** Maybe you want to
check that some JSON data is valid before passing it on, but without
knowing the structure of what it contains. Or you want to do very basic
manipulations like insert a key in a particular spot.
- **As a strongly typed Rust data structure.** When you expect all or most
of your data to conform to a particular structure and want to get real
work done without JSON's loosey-goosey nature tripping you up.
Serde JSON provides efficient, flexible, safe ways of converting data
between each of these representations.
## Operating on untyped JSON values
Any valid JSON data can be manipulated in the following recursive enum
representation. This data structure is [`serde_json::Value`][value].
```rust,ignore
enum Value {
Null,
Bool(bool),
Number(Number),
String(String),
Array(Vec<Value>),
Object(Map<String, Value>),
}
```
A string of JSON data can be parsed into a `serde_json::Value` by the
[`serde_json::from_str`][from_str] function. There is also
[`from_slice`][from_slice] for parsing from a byte slice &[u8] and
[`from_reader`][from_reader] for parsing from any `io::Read` like a File or
a TCP stream.
<a href="http://play.integer32.com/?gist=a266662bc71712e080efbf25ce30f306" target="_blank">
<img align="right" width="50" src="https://raw.githubusercontent.com/serde-rs/serde-rs.github.io/master/img/run.png">
</a>
```rust
extern crate serde_json;
use serde_json::{Value, Error};
fn untyped_example() -> Result<(), Error> {
// Some JSON input data as a &str. Maybe this comes from the user.
let data = r#"{
"name": "John Doe",
"age": 43,
"phones": [
"+44 1234567",
"+44 2345678"
]
}"#;
// Parse the string of data into serde_json::Value.
let v: Value = serde_json::from_str(data)?;
// Access parts of the data by indexing with square brackets.
println!("Please call {} at the number {}", v["name"], v["phones"][0]);
Ok(())
}
```
The result of square bracket indexing like `v["name"]` is a borrow of the data
at that index, so the type is `&Value`. A JSON map can be indexed with string
keys, while a JSON array can be indexed with integer keys. If the type of the
data is not right for the type with which it is being indexed, or if a map does
not contain the key being indexed, or if the index into a vector is out of
bounds, the returned element is `Value::Null`.
When a `Value` is printed, it is printed as a JSON string. So in the code above,
the output looks like `Please call "John Doe" at the number "+44 1234567"`. The
quotation marks appear because `v["name"]` is a `&Value` containing a JSON
string and its JSON representation is `"John Doe"`. Printing as a plain string
without quotation marks involves converting from a JSON string to a Rust string
with [`as_str()`] or avoiding the use of `Value` as described in the following
section.
[`as_str()`]: https://docs.serde.rs/serde_json/enum.Value.html#method.as_str
The `Value` representation is sufficient for very basic tasks but can be tedious
to work with for anything more significant. Error handling is verbose to
implement correctly, for example imagine trying to detect the presence of
unrecognized fields in the input data. The compiler is powerless to help you
when you make a mistake, for example imagine typoing `v["name"]` as `v["nmae"]`
in one of the dozens of places it is used in your code.
## Parsing JSON as strongly typed data structures
Serde provides a powerful way of mapping JSON data into Rust data structures
largely automatically.
<a href="http://play.integer32.com/?gist=cff572b80d3f078c942a2151e6020adc" target="_blank">
<img align="right" width="50" src="https://raw.githubusercontent.com/serde-rs/serde-rs.github.io/master/img/run.png">
</a>
```rust
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
use serde_json::Error;
#[derive(Serialize, Deserialize)]
struct Person {
name: String,
age: u8,
phones: Vec<String>,
}
fn typed_example() -> Result<(), Error> {
// Some JSON input data as a &str. Maybe this comes from the user.
let data = r#"{
"name": "John Doe",
"age": 43,
"phones": [
"+44 1234567",
"+44 2345678"
]
}"#;
// Parse the string of data into a Person object. This is exactly the
// same function as the one that produced serde_json::Value above, but
// now we are asking it for a Person as output.
let p: Person = serde_json::from_str(data)?;
// Do things just like with any other Rust data structure.
println!("Please call {} at the number {}", p.name, p.phones[0]);
Ok(())
}
```
This is the same `serde_json::from_str` function as before, but this time we
assign the return value to a variable of type `Person` so Serde will
automatically interpret the input data as a `Person` and produce informative
error messages if the layout does not conform to what a `Person` is expected
to look like.
Any type that implements Serde's `Deserialize` trait can be deserialized
this way. This includes built-in Rust standard library types like `Vec<T>`
and `HashMap<K, V>`, as well as any structs or enums annotated with
`#[derive(Deserialize)]`.
Once we have `p` of type `Person`, our IDE and the Rust compiler can help us
use it correctly like they do for any other Rust code. The IDE can
autocomplete field names to prevent typos, which was impossible in the
`serde_json::Value` representation. And the Rust compiler can check that
when we write `p.phones[0]`, then `p.phones` is guaranteed to be a
`Vec<String>` so indexing into it makes sense and produces a `String`.
## Constructing JSON values
Serde JSON provides a [`json!` macro][macro] to build `serde_json::Value`
objects with very natural JSON syntax. In order to use this macro,
`serde_json` needs to be imported with the `#[macro_use]` attribute.
<a href="http://play.integer32.com/?gist=c216d6beabd9429a6ac13b8f88938dfe" target="_blank">
<img align="right" width="50" src="https://raw.githubusercontent.com/serde-rs/serde-rs.github.io/master/img/run.png">
</a>
```rust
#[macro_use]
extern crate serde_json;
fn main() {
// The type of `john` is `serde_json::Value`
let john = json!({
"name": "John Doe",
"age": 43,
"phones": [
"+44 1234567",
"+44 2345678"
]
});
println!("first phone number: {}", john["phones"][0]);
// Convert to a string of JSON and print it out
println!("{}", john.to_string());
}
```
The `Value::to_string()` function converts a `serde_json::Value` into a
`String` of JSON text.
One neat thing about the `json!` macro is that variables and expressions can
be interpolated directly into the JSON value as you are building it. Serde
will check at compile time that the value you are interpolating is able to
be represented as JSON.
<a href="http://play.integer32.com/?gist=aae3af4d274bd249d1c8a947076355f2" target="_blank">
<img align="right" width="50" src="https://raw.githubusercontent.com/serde-rs/serde-rs.github.io/master/img/run.png">
</a>
```rust
let full_name = "John Doe";
let age_last_year = 42;
// The type of `john` is `serde_json::Value`
let john = json!({
"name": full_name,
"age": age_last_year + 1,
"phones": [
format!("+44 {}", random_phone())
]
});
```
This is amazingly convenient but we have the problem we had before with
`Value` which is that the IDE and Rust compiler cannot help us if we get it
wrong. Serde JSON provides a better way of serializing strongly-typed data
structures into JSON text.
## Creating JSON by serializing data structures
A data structure can be converted to a JSON string by
[`serde_json::to_string`][to_string]. There is also
[`serde_json::to_vec`][to_vec] which serializes to a `Vec<u8>` and
[`serde_json::to_writer`][to_writer] which serializes to any `io::Write`
such as a File or a TCP stream.
<a href="http://play.integer32.com/?gist=40967ece79921c77fd78ebc8f177c063" target="_blank">
<img align="right" width="50" src="https://raw.githubusercontent.com/serde-rs/serde-rs.github.io/master/img/run.png">
</a>
```rust
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
use serde_json::Error;
#[derive(Serialize, Deserialize)]
struct Address {
street: String,
city: String,
}
fn print_an_address() -> Result<(), Error> {
// Some data structure.
let address = Address {
street: "10 Downing Street".to_owned(),
city: "London".to_owned(),
};
// Serialize it to a JSON string.
let j = serde_json::to_string(&address)?;
// Print, write to a file, or send to an HTTP server.
println!("{}", j);
Ok(())
}
```
Any type that implements Serde's `Serialize` trait can be serialized this
way. This includes built-in Rust standard library types like `Vec<T>` and
`HashMap<K, V>`, as well as any structs or enums annotated with
`#[derive(Serialize)]`.
## Performance
It is fast. You should expect in the ballpark of 500 to 1000 megabytes per
second deserialization and 600 to 900 megabytes per second serialization,
depending on the characteristics of your data. This is competitive with the
fastest C and C++ JSON libraries or even 30% faster for many use cases.
Benchmarks live in the [serde-rs/json-benchmark] repo.
[serde-rs/json-benchmark]: https://github.com/serde-rs/json-benchmark
## Getting help
Serde developers live in the #serde channel on
[`irc.mozilla.org`](https://wiki.mozilla.org/IRC). The #rust channel is also a
good resource with generally faster response time but less specific knowledge
about Serde. If IRC is not your thing, we are happy to respond to [GitHub
issues](https://github.com/serde-rs/json/issues/new) as well.
## No-std support
This crate currently requires the Rust standard library. For JSON support in
Serde without a standard library, please see the [`serde-json-core`] crate.
[`serde-json-core`]: https://japaric.github.io/serde-json-core/serde_json_core/
## License
Serde JSON is licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in Serde JSON by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions.
[value]: https://docs.serde.rs/serde_json/value/enum.Value.html
[from_str]: https://docs.serde.rs/serde_json/de/fn.from_str.html
[from_slice]: https://docs.serde.rs/serde_json/de/fn.from_slice.html
[from_reader]: https://docs.serde.rs/serde_json/de/fn.from_reader.html
[to_string]: https://docs.serde.rs/serde_json/ser/fn.to_string.html
[to_vec]: https://docs.serde.rs/serde_json/ser/fn.to_vec.html
[to_writer]: https://docs.serde.rs/serde_json/ser/fn.to_writer.html
[macro]: https://docs.serde.rs/serde_json/macro.json.html

2265
third_party/rust/serde_json/src/de.rs vendored Normal file

File diff suppressed because it is too large Load Diff

429
third_party/rust/serde_json/src/error.rs vendored Normal file
View File

@ -0,0 +1,429 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! When serializing or deserializing JSON goes wrong.
use std::error;
use std::fmt::{self, Debug, Display};
use std::io;
use std::result;
use serde::de;
use serde::ser;
/// This type represents all possible errors that can occur when serializing or
/// deserializing JSON data.
pub struct Error {
/// This `Box` allows us to keep the size of `Error` as small as possible. A
/// larger `Error` type was substantially slower due to all the functions
/// that pass around `Result<T, Error>`.
err: Box<ErrorImpl>,
}
/// Alias for a `Result` with the error type `serde_json::Error`.
pub type Result<T> = result::Result<T, Error>;
impl Error {
/// One-based line number at which the error was detected.
///
/// Characters in the first line of the input (before the first newline
/// character) are in line 1.
pub fn line(&self) -> usize {
self.err.line
}
/// One-based column number at which the error was detected.
///
/// The first character in the input and any characters immediately
/// following a newline character are in column 1.
///
/// Note that errors may occur in column 0, for example if a read from an IO
/// stream fails immediately following a previously read newline character.
pub fn column(&self) -> usize {
self.err.column
}
/// Categorizes the cause of this error.
///
/// - `Category::Io` - failure to read or write bytes on an IO stream
/// - `Category::Syntax` - input that is not syntactically valid JSON
/// - `Category::Data` - input data that is semantically incorrect
/// - `Category::Eof` - unexpected end of the input data
pub fn classify(&self) -> Category {
match self.err.code {
ErrorCode::Message(_) => Category::Data,
ErrorCode::Io(_) => Category::Io,
ErrorCode::EofWhileParsingList
| ErrorCode::EofWhileParsingObject
| ErrorCode::EofWhileParsingString
| ErrorCode::EofWhileParsingValue => Category::Eof,
ErrorCode::ExpectedColon
| ErrorCode::ExpectedListCommaOrEnd
| ErrorCode::ExpectedObjectCommaOrEnd
| ErrorCode::ExpectedObjectOrArray
| ErrorCode::ExpectedSomeIdent
| ErrorCode::ExpectedSomeValue
| ErrorCode::ExpectedSomeString
| ErrorCode::InvalidEscape
| ErrorCode::InvalidNumber
| ErrorCode::NumberOutOfRange
| ErrorCode::InvalidUnicodeCodePoint
| ErrorCode::ControlCharacterWhileParsingString
| ErrorCode::KeyMustBeAString
| ErrorCode::LoneLeadingSurrogateInHexEscape
| ErrorCode::TrailingComma
| ErrorCode::TrailingCharacters
| ErrorCode::UnexpectedEndOfHexEscape
| ErrorCode::RecursionLimitExceeded => Category::Syntax,
}
}
/// Returns true if this error was caused by a failure to read or write
/// bytes on an IO stream.
pub fn is_io(&self) -> bool {
self.classify() == Category::Io
}
/// Returns true if this error was caused by input that was not
/// syntactically valid JSON.
pub fn is_syntax(&self) -> bool {
self.classify() == Category::Syntax
}
/// Returns true if this error was caused by input data that was
/// semantically incorrect.
///
/// For example, JSON containing a number is semantically incorrect when the
/// type being deserialized into holds a String.
pub fn is_data(&self) -> bool {
self.classify() == Category::Data
}
/// Returns true if this error was caused by prematurely reaching the end of
/// the input data.
///
/// Callers that process streaming input may be interested in retrying the
/// deserialization once more data is available.
pub fn is_eof(&self) -> bool {
self.classify() == Category::Eof
}
}
/// Categorizes the cause of a `serde_json::Error`.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Category {
/// The error was caused by a failure to read or write bytes on an IO
/// stream.
Io,
/// The error was caused by input that was not syntactically valid JSON.
Syntax,
/// The error was caused by input data that was semantically incorrect.
///
/// For example, JSON containing a number is semantically incorrect when the
/// type being deserialized into holds a String.
Data,
/// The error was caused by prematurely reaching the end of the input data.
///
/// Callers that process streaming input may be interested in retrying the
/// deserialization once more data is available.
Eof,
}
#[cfg_attr(feature = "cargo-clippy", allow(fallible_impl_from))]
impl From<Error> for io::Error {
/// Convert a `serde_json::Error` into an `io::Error`.
///
/// JSON syntax and data errors are turned into `InvalidData` IO errors.
/// EOF errors are turned into `UnexpectedEof` IO errors.
///
/// ```rust
/// use std::io;
///
/// enum MyError {
/// Io(io::Error),
/// Json(serde_json::Error),
/// }
///
/// impl From<serde_json::Error> for MyError {
/// fn from(err: serde_json::Error) -> MyError {
/// use serde_json::error::Category;
/// match err.classify() {
/// Category::Io => {
/// MyError::Io(err.into())
/// }
/// Category::Syntax | Category::Data | Category::Eof => {
/// MyError::Json(err)
/// }
/// }
/// }
/// }
/// ```
fn from(j: Error) -> Self {
if let ErrorCode::Io(err) = j.err.code {
err
} else {
match j.classify() {
Category::Io => unreachable!(),
Category::Syntax | Category::Data => io::Error::new(io::ErrorKind::InvalidData, j),
Category::Eof => io::Error::new(io::ErrorKind::UnexpectedEof, j),
}
}
}
}
struct ErrorImpl {
code: ErrorCode,
line: usize,
column: usize,
}
// Not public API. Should be pub(crate).
#[doc(hidden)]
pub enum ErrorCode {
/// Catchall for syntax error messages
Message(Box<str>),
/// Some IO error occurred while serializing or deserializing.
Io(io::Error),
/// EOF while parsing a list.
EofWhileParsingList,
/// EOF while parsing an object.
EofWhileParsingObject,
/// EOF while parsing a string.
EofWhileParsingString,
/// EOF while parsing a JSON value.
EofWhileParsingValue,
/// Expected this character to be a `':'`.
ExpectedColon,
/// Expected this character to be either a `','` or a `']'`.
ExpectedListCommaOrEnd,
/// Expected this character to be either a `','` or a `'}'`.
ExpectedObjectCommaOrEnd,
/// Expected this character to be either a `'{'` or a `'['`.
ExpectedObjectOrArray,
/// Expected to parse either a `true`, `false`, or a `null`.
ExpectedSomeIdent,
/// Expected this character to start a JSON value.
ExpectedSomeValue,
/// Expected this character to start a JSON string.
ExpectedSomeString,
/// Invalid hex escape code.
InvalidEscape,
/// Invalid number.
InvalidNumber,
/// Number is bigger than the maximum value of its type.
NumberOutOfRange,
/// Invalid unicode code point.
InvalidUnicodeCodePoint,
/// Control character found while parsing a string.
ControlCharacterWhileParsingString,
/// Object key is not a string.
KeyMustBeAString,
/// Lone leading surrogate in hex escape.
LoneLeadingSurrogateInHexEscape,
/// JSON has a comma after the last value in an array or map.
TrailingComma,
/// JSON has non-whitespace trailing characters after the value.
TrailingCharacters,
/// Unexpected end of hex excape.
UnexpectedEndOfHexEscape,
/// Encountered nesting of JSON maps and arrays more than 128 layers deep.
RecursionLimitExceeded,
}
impl Error {
// Not public API. Should be pub(crate).
#[doc(hidden)]
#[cold]
pub fn syntax(code: ErrorCode, line: usize, column: usize) -> Self {
Error {
err: Box::new(ErrorImpl {
code: code,
line: line,
column: column,
}),
}
}
// Not public API. Should be pub(crate).
//
// Update `eager_json` crate when this function changes.
#[doc(hidden)]
#[cold]
pub fn io(error: io::Error) -> Self {
Error {
err: Box::new(ErrorImpl {
code: ErrorCode::Io(error),
line: 0,
column: 0,
}),
}
}
// Not public API. Should be pub(crate).
#[doc(hidden)]
#[cold]
pub fn fix_position<F>(self, f: F) -> Self
where
F: FnOnce(ErrorCode) -> Error,
{
if self.err.line == 0 {
f(self.err.code)
} else {
self
}
}
}
impl Display for ErrorCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ErrorCode::Message(ref msg) => f.write_str(msg),
ErrorCode::Io(ref err) => Display::fmt(err, f),
ErrorCode::EofWhileParsingList => f.write_str("EOF while parsing a list"),
ErrorCode::EofWhileParsingObject => f.write_str("EOF while parsing an object"),
ErrorCode::EofWhileParsingString => f.write_str("EOF while parsing a string"),
ErrorCode::EofWhileParsingValue => f.write_str("EOF while parsing a value"),
ErrorCode::ExpectedColon => f.write_str("expected `:`"),
ErrorCode::ExpectedListCommaOrEnd => f.write_str("expected `,` or `]`"),
ErrorCode::ExpectedObjectCommaOrEnd => f.write_str("expected `,` or `}`"),
ErrorCode::ExpectedObjectOrArray => f.write_str("expected `{` or `[`"),
ErrorCode::ExpectedSomeIdent => f.write_str("expected ident"),
ErrorCode::ExpectedSomeValue => f.write_str("expected value"),
ErrorCode::ExpectedSomeString => f.write_str("expected string"),
ErrorCode::InvalidEscape => f.write_str("invalid escape"),
ErrorCode::InvalidNumber => f.write_str("invalid number"),
ErrorCode::NumberOutOfRange => f.write_str("number out of range"),
ErrorCode::InvalidUnicodeCodePoint => f.write_str("invalid unicode code point"),
ErrorCode::ControlCharacterWhileParsingString => {
f.write_str("control character (\\u0000-\\u001F) found while parsing a string")
}
ErrorCode::KeyMustBeAString => f.write_str("key must be a string"),
ErrorCode::LoneLeadingSurrogateInHexEscape => {
f.write_str("lone leading surrogate in hex escape")
}
ErrorCode::TrailingComma => f.write_str("trailing comma"),
ErrorCode::TrailingCharacters => f.write_str("trailing characters"),
ErrorCode::UnexpectedEndOfHexEscape => f.write_str("unexpected end of hex escape"),
ErrorCode::RecursionLimitExceeded => f.write_str("recursion limit exceeded"),
}
}
}
impl error::Error for Error {
fn description(&self) -> &str {
match self.err.code {
ErrorCode::Io(ref err) => error::Error::description(err),
_ => {
// If you want a better message, use Display::fmt or to_string().
"JSON error"
}
}
}
fn cause(&self) -> Option<&error::Error> {
match self.err.code {
ErrorCode::Io(ref err) => Some(err),
_ => None,
}
}
}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&*self.err, f)
}
}
impl Display for ErrorImpl {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.line == 0 {
Display::fmt(&self.code, f)
} else {
write!(
f,
"{} at line {} column {}",
self.code, self.line, self.column
)
}
}
}
// Remove two layers of verbosity from the debug representation. Humans often
// end up seeing this representation because it is what unwrap() shows.
impl Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Error({:?}, line: {}, column: {})",
self.err.code.to_string(),
self.err.line,
self.err.column
)
}
}
impl de::Error for Error {
#[cold]
fn custom<T: Display>(msg: T) -> Error {
Error {
err: Box::new(ErrorImpl {
code: ErrorCode::Message(msg.to_string().into_boxed_str()),
line: 0,
column: 0,
}),
}
}
#[cold]
fn invalid_type(unexp: de::Unexpected, exp: &de::Expected) -> Self {
if let de::Unexpected::Unit = unexp {
Error::custom(format_args!("invalid type: null, expected {}", exp))
} else {
Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
}
}
}
impl ser::Error for Error {
#[cold]
fn custom<T: Display>(msg: T) -> Error {
Error {
err: Box::new(ErrorImpl {
code: ErrorCode::Message(msg.to_string().into_boxed_str()),
line: 0,
column: 0,
}),
}
}
}

78
third_party/rust/serde_json/src/iter.rs vendored Normal file
View File

@ -0,0 +1,78 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::io;
pub struct LineColIterator<I> {
iter: I,
/// Index of the current line. Characters in the first line of the input
/// (before the first newline character) are in line 1.
line: usize,
/// Index of the current column. The first character in the input and any
/// characters immediately following a newline character are in column 1.
/// The column is 0 immediately after a newline character has been read.
col: usize,
/// Byte offset of the start of the current line. This is the sum of lenghts
/// of all previous lines. Keeping track of things this way allows efficient
/// computation of the current line, column, and byte offset while only
/// updating one of the counters in `next()` in the common case.
start_of_line: usize,
}
impl<I> LineColIterator<I>
where
I: Iterator<Item = io::Result<u8>>,
{
pub fn new(iter: I) -> LineColIterator<I> {
LineColIterator {
iter: iter,
line: 1,
col: 0,
start_of_line: 0,
}
}
pub fn line(&self) -> usize {
self.line
}
pub fn col(&self) -> usize {
self.col
}
pub fn byte_offset(&self) -> usize {
self.start_of_line + self.col
}
}
impl<I> Iterator for LineColIterator<I>
where
I: Iterator<Item = io::Result<u8>>,
{
type Item = io::Result<u8>;
fn next(&mut self) -> Option<io::Result<u8>> {
match self.iter.next() {
None => None,
Some(Ok(b'\n')) => {
self.start_of_line += self.col + 1;
self.line += 1;
self.col = 0;
Some(Ok(b'\n'))
}
Some(Ok(c)) => {
self.col += 1;
Some(Ok(c))
}
Some(Err(e)) => Some(Err(e)),
}
}
}

391
third_party/rust/serde_json/src/lib.rs vendored Normal file
View File

@ -0,0 +1,391 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! # Serde JSON
//!
//! JSON is a ubiquitous open-standard format that uses human-readable text to
//! transmit data objects consisting of key-value pairs.
//!
//! ```json,ignore
//! {
//! "name": "John Doe",
//! "age": 43,
//! "address": {
//! "street": "10 Downing Street",
//! "city": "London"
//! },
//! "phones": [
//! "+44 1234567",
//! "+44 2345678"
//! ]
//! }
//! ```
//!
//! There are three common ways that you might find yourself needing to work
//! with JSON data in Rust.
//!
//! - **As text data.** An unprocessed string of JSON data that you receive on
//! an HTTP endpoint, read from a file, or prepare to send to a remote
//! server.
//! - **As an untyped or loosely typed representation.** Maybe you want to
//! check that some JSON data is valid before passing it on, but without
//! knowing the structure of what it contains. Or you want to do very basic
//! manipulations like insert a key in a particular spot.
//! - **As a strongly typed Rust data structure.** When you expect all or most
//! of your data to conform to a particular structure and want to get real
//! work done without JSON's loosey-goosey nature tripping you up.
//!
//! Serde JSON provides efficient, flexible, safe ways of converting data
//! between each of these representations.
//!
//! # Operating on untyped JSON values
//!
//! Any valid JSON data can be manipulated in the following recursive enum
//! representation. This data structure is [`serde_json::Value`][value].
//!
//! ```rust
//! # use serde_json::{Number, Map};
//! #
//! # #[allow(dead_code)]
//! enum Value {
//! Null,
//! Bool(bool),
//! Number(Number),
//! String(String),
//! Array(Vec<Value>),
//! Object(Map<String, Value>),
//! }
//! ```
//!
//! A string of JSON data can be parsed into a `serde_json::Value` by the
//! [`serde_json::from_str`][from_str] function. There is also
//! [`from_slice`][from_slice] for parsing from a byte slice &[u8] and
//! [`from_reader`][from_reader] for parsing from any `io::Read` like a File or
//! a TCP stream.
//!
//! ```rust
//! extern crate serde_json;
//!
//! use serde_json::{Value, Error};
//!
//! fn untyped_example() -> Result<(), Error> {
//! // Some JSON input data as a &str. Maybe this comes from the user.
//! let data = r#"{
//! "name": "John Doe",
//! "age": 43,
//! "phones": [
//! "+44 1234567",
//! "+44 2345678"
//! ]
//! }"#;
//!
//! // Parse the string of data into serde_json::Value.
//! let v: Value = serde_json::from_str(data)?;
//!
//! // Access parts of the data by indexing with square brackets.
//! println!("Please call {} at the number {}", v["name"], v["phones"][0]);
//!
//! Ok(())
//! }
//! #
//! # fn main() {
//! # untyped_example().unwrap();
//! # }
//! ```
//!
//! The result of square bracket indexing like `v["name"]` is a borrow of the
//! data at that index, so the type is `&Value`. A JSON map can be indexed with
//! string keys, while a JSON array can be indexed with integer keys. If the
//! type of the data is not right for the type with which it is being indexed,
//! or if a map does not contain the key being indexed, or if the index into a
//! vector is out of bounds, the returned element is `Value::Null`.
//!
//! When a `Value` is printed, it is printed as a JSON string. So in the code
//! above, the output looks like `Please call "John Doe" at the number "+44
//! 1234567"`. The quotation marks appear because `v["name"]` is a `&Value`
//! containing a JSON string and its JSON representation is `"John Doe"`.
//! Printing as a plain string without quotation marks involves converting from
//! a JSON string to a Rust string with [`as_str()`] or avoiding the use of
//! `Value` as described in the following section.
//!
//! [`as_str()`]: https://docs.serde.rs/serde_json/enum.Value.html#method.as_str
//!
//! The `Value` representation is sufficient for very basic tasks but can be
//! tedious to work with for anything more significant. Error handling is
//! verbose to implement correctly, for example imagine trying to detect the
//! presence of unrecognized fields in the input data. The compiler is powerless
//! to help you when you make a mistake, for example imagine typoing `v["name"]`
//! as `v["nmae"]` in one of the dozens of places it is used in your code.
//!
//! # Parsing JSON as strongly typed data structures
//!
//! Serde provides a powerful way of mapping JSON data into Rust data structures
//! largely automatically.
//!
//! ```rust
//! extern crate serde;
//! extern crate serde_json;
//!
//! #[macro_use]
//! extern crate serde_derive;
//!
//! use serde_json::Error;
//!
//! #[derive(Serialize, Deserialize)]
//! struct Person {
//! name: String,
//! age: u8,
//! phones: Vec<String>,
//! }
//!
//! fn typed_example() -> Result<(), Error> {
//! // Some JSON input data as a &str. Maybe this comes from the user.
//! let data = r#"{
//! "name": "John Doe",
//! "age": 43,
//! "phones": [
//! "+44 1234567",
//! "+44 2345678"
//! ]
//! }"#;
//!
//! // Parse the string of data into a Person object. This is exactly the
//! // same function as the one that produced serde_json::Value above, but
//! // now we are asking it for a Person as output.
//! let p: Person = serde_json::from_str(data)?;
//!
//! // Do things just like with any other Rust data structure.
//! println!("Please call {} at the number {}", p.name, p.phones[0]);
//!
//! Ok(())
//! }
//! #
//! # fn main() {
//! # typed_example().unwrap();
//! # }
//! ```
//!
//! This is the same `serde_json::from_str` function as before, but this time we
//! assign the return value to a variable of type `Person` so Serde will
//! automatically interpret the input data as a `Person` and produce informative
//! error messages if the layout does not conform to what a `Person` is expected
//! to look like.
//!
//! Any type that implements Serde's `Deserialize` trait can be deserialized
//! this way. This includes built-in Rust standard library types like `Vec<T>`
//! and `HashMap<K, V>`, as well as any structs or enums annotated with
//! `#[derive(Deserialize)]`.
//!
//! Once we have `p` of type `Person`, our IDE and the Rust compiler can help us
//! use it correctly like they do for any other Rust code. The IDE can
//! autocomplete field names to prevent typos, which was impossible in the
//! `serde_json::Value` representation. And the Rust compiler can check that
//! when we write `p.phones[0]`, then `p.phones` is guaranteed to be a
//! `Vec<String>` so indexing into it makes sense and produces a `String`.
//!
//! # Constructing JSON values
//!
//! Serde JSON provides a [`json!` macro][macro] to build `serde_json::Value`
//! objects with very natural JSON syntax. In order to use this macro,
//! `serde_json` needs to be imported with the `#[macro_use]` attribute.
//!
//! ```rust
//! #[macro_use]
//! extern crate serde_json;
//!
//! fn main() {
//! // The type of `john` is `serde_json::Value`
//! let john = json!({
//! "name": "John Doe",
//! "age": 43,
//! "phones": [
//! "+44 1234567",
//! "+44 2345678"
//! ]
//! });
//!
//! println!("first phone number: {}", john["phones"][0]);
//!
//! // Convert to a string of JSON and print it out
//! println!("{}", john.to_string());
//! }
//! ```
//!
//! The `Value::to_string()` function converts a `serde_json::Value` into a
//! `String` of JSON text.
//!
//! One neat thing about the `json!` macro is that variables and expressions can
//! be interpolated directly into the JSON value as you are building it. Serde
//! will check at compile time that the value you are interpolating is able to
//! be represented as JSON.
//!
//! ```rust
//! # #[macro_use]
//! # extern crate serde_json;
//! #
//! # fn random_phone() -> u16 { 0 }
//! #
//! # fn main() {
//! let full_name = "John Doe";
//! let age_last_year = 42;
//!
//! // The type of `john` is `serde_json::Value`
//! let john = json!({
//! "name": full_name,
//! "age": age_last_year + 1,
//! "phones": [
//! format!("+44 {}", random_phone())
//! ]
//! });
//! # let _ = john;
//! # }
//! ```
//!
//! This is amazingly convenient but we have the problem we had before with
//! `Value` which is that the IDE and Rust compiler cannot help us if we get it
//! wrong. Serde JSON provides a better way of serializing strongly-typed data
//! structures into JSON text.
//!
//! # Creating JSON by serializing data structures
//!
//! A data structure can be converted to a JSON string by
//! [`serde_json::to_string`][to_string]. There is also
//! [`serde_json::to_vec`][to_vec] which serializes to a `Vec<u8>` and
//! [`serde_json::to_writer`][to_writer] which serializes to any `io::Write`
//! such as a File or a TCP stream.
//!
//! ```rust
//! extern crate serde;
//! extern crate serde_json;
//!
//! #[macro_use]
//! extern crate serde_derive;
//!
//! use serde_json::Error;
//!
//! #[derive(Serialize, Deserialize)]
//! struct Address {
//! street: String,
//! city: String,
//! }
//!
//! fn print_an_address() -> Result<(), Error> {
//! // Some data structure.
//! let address = Address {
//! street: "10 Downing Street".to_owned(),
//! city: "London".to_owned(),
//! };
//!
//! // Serialize it to a JSON string.
//! let j = serde_json::to_string(&address)?;
//!
//! // Print, write to a file, or send to an HTTP server.
//! println!("{}", j);
//!
//! Ok(())
//! }
//! #
//! # fn main() {
//! # print_an_address().unwrap();
//! # }
//! ```
//!
//! Any type that implements Serde's `Serialize` trait can be serialized this
//! way. This includes built-in Rust standard library types like `Vec<T>` and
//! `HashMap<K, V>`, as well as any structs or enums annotated with
//! `#[derive(Serialize)]`.
//!
//! # No-std support
//!
//! This crate currently requires the Rust standard library. For JSON support in
//! Serde without a standard library, please see the [`serde-json-core`] crate.
//!
//! [value]: https://docs.serde.rs/serde_json/value/enum.Value.html
//! [from_str]: https://docs.serde.rs/serde_json/de/fn.from_str.html
//! [from_slice]: https://docs.serde.rs/serde_json/de/fn.from_slice.html
//! [from_reader]: https://docs.serde.rs/serde_json/de/fn.from_reader.html
//! [to_string]: https://docs.serde.rs/serde_json/ser/fn.to_string.html
//! [to_vec]: https://docs.serde.rs/serde_json/ser/fn.to_vec.html
//! [to_writer]: https://docs.serde.rs/serde_json/ser/fn.to_writer.html
//! [macro]: https://docs.serde.rs/serde_json/macro.json.html
//! [`serde-json-core`]: https://japaric.github.io/serde-json-core/serde_json_core/
#![doc(html_root_url = "https://docs.rs/serde_json/1.0.26")]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(
feature = "cargo-clippy",
allow(doc_markdown, needless_pass_by_value)
)]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
// Deserializer::from_str, into_iter
should_implement_trait,
// integer and float ser/de requires these sorts of casts
cast_possible_truncation,
cast_possible_wrap,
cast_precision_loss,
cast_sign_loss,
// string ser/de uses indexing and slicing
indexing_slicing,
// things are often more readable this way
cast_lossless,
shadow_reuse,
shadow_unrelated,
single_match_else,
stutter,
use_self,
// not practical
missing_docs_in_private_items,
similar_names,
// we support older compilers
redundant_field_names,
))]
#![deny(missing_docs)]
#[macro_use]
extern crate serde;
extern crate ryu;
#[cfg(feature = "preserve_order")]
extern crate indexmap;
extern crate itoa;
#[doc(inline)]
pub use self::de::{from_reader, from_slice, from_str, Deserializer, StreamDeserializer};
#[doc(inline)]
pub use self::error::{Error, Result};
#[doc(inline)]
pub use self::ser::{
to_string, to_string_pretty, to_vec, to_vec_pretty, to_writer, to_writer_pretty, Serializer,
};
#[doc(inline)]
pub use self::value::{from_value, to_value, Map, Number, Value};
// We only use our own error type; no need for From conversions provided by the
// standard library's try! macro. This reduces lines of LLVM IR by 4%.
macro_rules! try {
($e:expr) => {
match $e {
::std::result::Result::Ok(val) => val,
::std::result::Result::Err(err) => return ::std::result::Result::Err(err),
}
};
}
#[macro_use]
mod macros;
pub mod de;
pub mod error;
pub mod map;
pub mod ser;
pub mod value;
mod iter;
mod number;
mod read;

View File

@ -0,0 +1,309 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/// Construct a `serde_json::Value` from a JSON literal.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// let value = json!({
/// "code": 200,
/// "success": true,
/// "payload": {
/// "features": [
/// "serde",
/// "json"
/// ]
/// }
/// });
/// # }
/// ```
///
/// Variables or expressions can be interpolated into the JSON literal. Any type
/// interpolated into an array element or object value must implement Serde's
/// `Serialize` trait, while any type interpolated into a object key must
/// implement `Into<String>`. If the `Serialize` implementation of the
/// interpolated type decides to fail, or if the interpolated type contains a
/// map with non-string keys, the `json!` macro will panic.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// let code = 200;
/// let features = vec!["serde", "json"];
///
/// let value = json!({
/// "code": code,
/// "success": code == 200,
/// "payload": {
/// features[0]: features[1]
/// }
/// });
/// # }
/// ```
///
/// Trailing commas are allowed inside both arrays and objects.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// let value = json!([
/// "notice",
/// "the",
/// "trailing",
/// "comma -->",
/// ]);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! json {
// Hide distracting implementation details from the generated rustdoc.
($($json:tt)+) => {
json_internal!($($json)+)
};
}
// Rocket relies on this because they export their own `json!` with a different
// doc comment than ours, and various Rust bugs prevent them from calling our
// `json!` from their `json!` so they call `json_internal!` directly. Check with
// @SergioBenitez before making breaking changes to this macro.
//
// Changes are fine as long as `json_internal!` does not call any new helper
// macros and can still be invoked as `json_internal!($($json)+)`.
#[macro_export(local_inner_macros)]
#[doc(hidden)]
macro_rules! json_internal {
//////////////////////////////////////////////////////////////////////////
// TT muncher for parsing the inside of an array [...]. Produces a vec![...]
// of the elements.
//
// Must be invoked as: json_internal!(@array [] $($tt)*)
//////////////////////////////////////////////////////////////////////////
// Done with trailing comma.
(@array [$($elems:expr,)*]) => {
json_internal_vec![$($elems,)*]
};
// Done without trailing comma.
(@array [$($elems:expr),*]) => {
json_internal_vec![$($elems),*]
};
// Next element is `null`.
(@array [$($elems:expr,)*] null $($rest:tt)*) => {
json_internal!(@array [$($elems,)* json_internal!(null)] $($rest)*)
};
// Next element is `true`.
(@array [$($elems:expr,)*] true $($rest:tt)*) => {
json_internal!(@array [$($elems,)* json_internal!(true)] $($rest)*)
};
// Next element is `false`.
(@array [$($elems:expr,)*] false $($rest:tt)*) => {
json_internal!(@array [$($elems,)* json_internal!(false)] $($rest)*)
};
// Next element is an array.
(@array [$($elems:expr,)*] [$($array:tt)*] $($rest:tt)*) => {
json_internal!(@array [$($elems,)* json_internal!([$($array)*])] $($rest)*)
};
// Next element is a map.
(@array [$($elems:expr,)*] {$($map:tt)*} $($rest:tt)*) => {
json_internal!(@array [$($elems,)* json_internal!({$($map)*})] $($rest)*)
};
// Next element is an expression followed by comma.
(@array [$($elems:expr,)*] $next:expr, $($rest:tt)*) => {
json_internal!(@array [$($elems,)* json_internal!($next),] $($rest)*)
};
// Last element is an expression with no trailing comma.
(@array [$($elems:expr,)*] $last:expr) => {
json_internal!(@array [$($elems,)* json_internal!($last)])
};
// Comma after the most recent element.
(@array [$($elems:expr),*] , $($rest:tt)*) => {
json_internal!(@array [$($elems,)*] $($rest)*)
};
// Unexpected token after most recent element.
(@array [$($elems:expr),*] $unexpected:tt $($rest:tt)*) => {
json_unexpected!($unexpected)
};
//////////////////////////////////////////////////////////////////////////
// TT muncher for parsing the inside of an object {...}. Each entry is
// inserted into the given map variable.
//
// Must be invoked as: json_internal!(@object $map () ($($tt)*) ($($tt)*))
//
// We require two copies of the input tokens so that we can match on one
// copy and trigger errors on the other copy.
//////////////////////////////////////////////////////////////////////////
// Done.
(@object $object:ident () () ()) => {};
// Insert the current entry followed by trailing comma.
(@object $object:ident [$($key:tt)+] ($value:expr) , $($rest:tt)*) => {
let _ = $object.insert(($($key)+).into(), $value);
json_internal!(@object $object () ($($rest)*) ($($rest)*));
};
// Current entry followed by unexpected token.
(@object $object:ident [$($key:tt)+] ($value:expr) $unexpected:tt $($rest:tt)*) => {
json_unexpected!($unexpected);
};
// Insert the last entry without trailing comma.
(@object $object:ident [$($key:tt)+] ($value:expr)) => {
let _ = $object.insert(($($key)+).into(), $value);
};
// Next value is `null`.
(@object $object:ident ($($key:tt)+) (: null $($rest:tt)*) $copy:tt) => {
json_internal!(@object $object [$($key)+] (json_internal!(null)) $($rest)*);
};
// Next value is `true`.
(@object $object:ident ($($key:tt)+) (: true $($rest:tt)*) $copy:tt) => {
json_internal!(@object $object [$($key)+] (json_internal!(true)) $($rest)*);
};
// Next value is `false`.
(@object $object:ident ($($key:tt)+) (: false $($rest:tt)*) $copy:tt) => {
json_internal!(@object $object [$($key)+] (json_internal!(false)) $($rest)*);
};
// Next value is an array.
(@object $object:ident ($($key:tt)+) (: [$($array:tt)*] $($rest:tt)*) $copy:tt) => {
json_internal!(@object $object [$($key)+] (json_internal!([$($array)*])) $($rest)*);
};
// Next value is a map.
(@object $object:ident ($($key:tt)+) (: {$($map:tt)*} $($rest:tt)*) $copy:tt) => {
json_internal!(@object $object [$($key)+] (json_internal!({$($map)*})) $($rest)*);
};
// Next value is an expression followed by comma.
(@object $object:ident ($($key:tt)+) (: $value:expr , $($rest:tt)*) $copy:tt) => {
json_internal!(@object $object [$($key)+] (json_internal!($value)) , $($rest)*);
};
// Last value is an expression with no trailing comma.
(@object $object:ident ($($key:tt)+) (: $value:expr) $copy:tt) => {
json_internal!(@object $object [$($key)+] (json_internal!($value)));
};
// Missing value for last entry. Trigger a reasonable error message.
(@object $object:ident ($($key:tt)+) (:) $copy:tt) => {
// "unexpected end of macro invocation"
json_internal!();
};
// Missing colon and value for last entry. Trigger a reasonable error
// message.
(@object $object:ident ($($key:tt)+) () $copy:tt) => {
// "unexpected end of macro invocation"
json_internal!();
};
// Misplaced colon. Trigger a reasonable error message.
(@object $object:ident () (: $($rest:tt)*) ($colon:tt $($copy:tt)*)) => {
// Takes no arguments so "no rules expected the token `:`".
json_unexpected!($colon);
};
// Found a comma inside a key. Trigger a reasonable error message.
(@object $object:ident ($($key:tt)*) (, $($rest:tt)*) ($comma:tt $($copy:tt)*)) => {
// Takes no arguments so "no rules expected the token `,`".
json_unexpected!($comma);
};
// Key is fully parenthesized. This avoids clippy double_parens false
// positives because the parenthesization may be necessary here.
(@object $object:ident () (($key:expr) : $($rest:tt)*) $copy:tt) => {
json_internal!(@object $object ($key) (: $($rest)*) (: $($rest)*));
};
// Munch a token into the current key.
(@object $object:ident ($($key:tt)*) ($tt:tt $($rest:tt)*) $copy:tt) => {
json_internal!(@object $object ($($key)* $tt) ($($rest)*) ($($rest)*));
};
//////////////////////////////////////////////////////////////////////////
// The main implementation.
//
// Must be invoked as: json_internal!($($json)+)
//////////////////////////////////////////////////////////////////////////
(null) => {
$crate::Value::Null
};
(true) => {
$crate::Value::Bool(true)
};
(false) => {
$crate::Value::Bool(false)
};
([]) => {
$crate::Value::Array(json_internal_vec![])
};
([ $($tt:tt)+ ]) => {
$crate::Value::Array(json_internal!(@array [] $($tt)+))
};
({}) => {
$crate::Value::Object($crate::Map::new())
};
({ $($tt:tt)+ }) => {
$crate::Value::Object({
let mut object = $crate::Map::new();
json_internal!(@object object () ($($tt)+) ($($tt)+));
object
})
};
// Any Serialize type: numbers, strings, struct literals, variables etc.
// Must be below every other rule.
($other:expr) => {
$crate::to_value(&$other).unwrap()
};
}
// The json_internal macro above cannot invoke vec directly because it uses
// local_inner_macros. A vec invocation there would resolve to $crate::vec.
// Instead invoke vec here outside of local_inner_macros.
#[macro_export]
#[doc(hidden)]
macro_rules! json_internal_vec {
($($content:tt)*) => {
vec![$($content)*]
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! json_unexpected {
() => {};
}

852
third_party/rust/serde_json/src/map.rs vendored Normal file
View File

@ -0,0 +1,852 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A map of String to serde_json::Value.
//!
//! By default the map is backed by a [`BTreeMap`]. Enable the `preserve_order`
//! feature of serde_json to use [`IndexMap`] instead.
//!
//! [`BTreeMap`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html
//! [`IndexMap`]: https://docs.rs/indexmap/*/indexmap/map/struct.IndexMap.html
use serde::{de, ser};
use std::borrow::Borrow;
use std::fmt::{self, Debug};
use std::hash::Hash;
use std::iter::FromIterator;
use std::ops;
use value::Value;
#[cfg(not(feature = "preserve_order"))]
use std::collections::{btree_map, BTreeMap};
#[cfg(feature = "preserve_order")]
use indexmap::{self, IndexMap};
/// Represents a JSON key/value type.
pub struct Map<K, V> {
map: MapImpl<K, V>,
}
#[cfg(not(feature = "preserve_order"))]
type MapImpl<K, V> = BTreeMap<K, V>;
#[cfg(feature = "preserve_order")]
type MapImpl<K, V> = IndexMap<K, V>;
impl Map<String, Value> {
/// Makes a new empty Map.
#[inline]
pub fn new() -> Self {
Map {
map: MapImpl::new(),
}
}
#[cfg(not(feature = "preserve_order"))]
/// Makes a new empty Map with the given initial capacity.
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
// does not support with_capacity
let _ = capacity;
Map {
map: BTreeMap::new(),
}
}
#[cfg(feature = "preserve_order")]
/// Makes a new empty Map with the given initial capacity.
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
Map {
map: IndexMap::with_capacity(capacity),
}
}
/// Clears the map, removing all values.
#[inline]
pub fn clear(&mut self) {
self.map.clear()
}
/// Returns a reference to the value corresponding to the key.
///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
#[inline]
pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&Value>
where
String: Borrow<Q>,
Q: Ord + Eq + Hash,
{
self.map.get(key)
}
/// Returns true if the map contains a value for the specified key.
///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
#[inline]
pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
where
String: Borrow<Q>,
Q: Ord + Eq + Hash,
{
self.map.contains_key(key)
}
/// Returns a mutable reference to the value corresponding to the key.
///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
#[inline]
pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut Value>
where
String: Borrow<Q>,
Q: Ord + Eq + Hash,
{
self.map.get_mut(key)
}
/// Inserts a key-value pair into the map.
///
/// If the map did not have this key present, `None` is returned.
///
/// If the map did have this key present, the value is updated, and the old
/// value is returned.
#[inline]
pub fn insert(&mut self, k: String, v: Value) -> Option<Value> {
self.map.insert(k, v)
}
/// Removes a key from the map, returning the value at the key if the key
/// was previously in the map.
///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
#[inline]
pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<Value>
where
String: Borrow<Q>,
Q: Ord + Eq + Hash,
{
self.map.remove(key)
}
/// Gets the given key's corresponding entry in the map for in-place
/// manipulation.
pub fn entry<S>(&mut self, key: S) -> Entry
where
S: Into<String>,
{
#[cfg(feature = "preserve_order")]
use indexmap::map::Entry as EntryImpl;
#[cfg(not(feature = "preserve_order"))]
use std::collections::btree_map::Entry as EntryImpl;
match self.map.entry(key.into()) {
EntryImpl::Vacant(vacant) => Entry::Vacant(VacantEntry { vacant: vacant }),
EntryImpl::Occupied(occupied) => Entry::Occupied(OccupiedEntry { occupied: occupied }),
}
}
/// Returns the number of elements in the map.
#[inline]
pub fn len(&self) -> usize {
self.map.len()
}
/// Returns true if the map contains no elements.
#[inline]
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
/// Gets an iterator over the entries of the map.
#[inline]
pub fn iter(&self) -> Iter {
Iter {
iter: self.map.iter(),
}
}
/// Gets a mutable iterator over the entries of the map.
#[inline]
pub fn iter_mut(&mut self) -> IterMut {
IterMut {
iter: self.map.iter_mut(),
}
}
/// Gets an iterator over the keys of the map.
#[inline]
pub fn keys(&self) -> Keys {
Keys {
iter: self.map.keys(),
}
}
/// Gets an iterator over the values of the map.
#[inline]
pub fn values(&self) -> Values {
Values {
iter: self.map.values(),
}
}
/// Gets an iterator over mutable values of the map.
#[inline]
pub fn values_mut(&mut self) -> ValuesMut {
ValuesMut {
iter: self.map.values_mut(),
}
}
}
impl Default for Map<String, Value> {
#[inline]
fn default() -> Self {
Map {
map: MapImpl::new(),
}
}
}
impl Clone for Map<String, Value> {
#[inline]
fn clone(&self) -> Self {
Map {
map: self.map.clone(),
}
}
}
impl PartialEq for Map<String, Value> {
#[inline]
fn eq(&self, other: &Self) -> bool {
if cfg!(feature = "preserve_order") {
if self.len() != other.len() {
return false;
}
self.iter()
.all(|(key, value)| other.get(key).map_or(false, |v| *value == *v))
} else {
self.map.eq(&other.map)
}
}
}
/// Access an element of this map. Panics if the given key is not present in the
/// map.
///
/// ```rust
/// # use serde_json::Value;
/// #
/// # let val = &Value::String("".to_owned());
/// # let _ =
/// match *val {
/// Value::String(ref s) => Some(s.as_str()),
/// Value::Array(ref arr) => arr[0].as_str(),
/// Value::Object(ref map) => map["type"].as_str(),
/// _ => None,
/// }
/// # ;
/// ```
impl<'a, Q: ?Sized> ops::Index<&'a Q> for Map<String, Value>
where
String: Borrow<Q>,
Q: Ord + Eq + Hash,
{
type Output = Value;
fn index(&self, index: &Q) -> &Value {
self.map.index(index)
}
}
/// Mutably access an element of this map. Panics if the given key is not
/// present in the map.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// # let mut map = serde_json::Map::new();
/// # map.insert("key".to_owned(), serde_json::Value::Null);
/// #
/// map["key"] = json!("value");
/// # }
/// ```
impl<'a, Q: ?Sized> ops::IndexMut<&'a Q> for Map<String, Value>
where
String: Borrow<Q>,
Q: Ord + Eq + Hash,
{
fn index_mut(&mut self, index: &Q) -> &mut Value {
self.map.get_mut(index).expect("no entry found for key")
}
}
impl Debug for Map<String, Value> {
#[inline]
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
self.map.fmt(formatter)
}
}
impl ser::Serialize for Map<String, Value> {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
use serde::ser::SerializeMap;
let mut map = try!(serializer.serialize_map(Some(self.len())));
for (k, v) in self {
try!(map.serialize_key(k));
try!(map.serialize_value(v));
}
map.end()
}
}
impl<'de> de::Deserialize<'de> for Map<String, Value> {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Map<String, Value>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a map")
}
#[inline]
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Map::new())
}
#[inline]
fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where
V: de::MapAccess<'de>,
{
let mut values = Map::new();
while let Some((key, value)) = try!(visitor.next_entry()) {
values.insert(key, value);
}
Ok(values)
}
}
deserializer.deserialize_map(Visitor)
}
}
impl FromIterator<(String, Value)> for Map<String, Value> {
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = (String, Value)>,
{
Map {
map: FromIterator::from_iter(iter),
}
}
}
impl Extend<(String, Value)> for Map<String, Value> {
fn extend<T>(&mut self, iter: T)
where
T: IntoIterator<Item = (String, Value)>,
{
self.map.extend(iter);
}
}
macro_rules! delegate_iterator {
(($name:ident $($generics:tt)*) => $item:ty) => {
impl $($generics)* Iterator for $name $($generics)* {
type Item = $item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl $($generics)* DoubleEndedIterator for $name $($generics)* {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back()
}
}
impl $($generics)* ExactSizeIterator for $name $($generics)* {
#[inline]
fn len(&self) -> usize {
self.iter.len()
}
}
}
}
//////////////////////////////////////////////////////////////////////////////
/// A view into a single entry in a map, which may either be vacant or occupied.
/// This enum is constructed from the [`entry`] method on [`Map`].
///
/// [`entry`]: struct.Map.html#method.entry
/// [`Map`]: struct.Map.html
pub enum Entry<'a> {
/// A vacant Entry.
Vacant(VacantEntry<'a>),
/// An occupied Entry.
Occupied(OccupiedEntry<'a>),
}
/// A vacant Entry. It is part of the [`Entry`] enum.
///
/// [`Entry`]: enum.Entry.html
pub struct VacantEntry<'a> {
vacant: VacantEntryImpl<'a>,
}
/// An occupied Entry. It is part of the [`Entry`] enum.
///
/// [`Entry`]: enum.Entry.html
pub struct OccupiedEntry<'a> {
occupied: OccupiedEntryImpl<'a>,
}
#[cfg(not(feature = "preserve_order"))]
type VacantEntryImpl<'a> = btree_map::VacantEntry<'a, String, Value>;
#[cfg(feature = "preserve_order")]
type VacantEntryImpl<'a> = indexmap::map::VacantEntry<'a, String, Value>;
#[cfg(not(feature = "preserve_order"))]
type OccupiedEntryImpl<'a> = btree_map::OccupiedEntry<'a, String, Value>;
#[cfg(feature = "preserve_order")]
type OccupiedEntryImpl<'a> = indexmap::map::OccupiedEntry<'a, String, Value>;
impl<'a> Entry<'a> {
/// Returns a reference to this entry's key.
///
/// # Examples
///
/// ```rust
/// let mut map = serde_json::Map::new();
/// assert_eq!(map.entry("serde").key(), &"serde");
/// ```
pub fn key(&self) -> &String {
match *self {
Entry::Vacant(ref e) => e.key(),
Entry::Occupied(ref e) => e.key(),
}
}
/// Ensures a value is in the entry by inserting the default if empty, and
/// returns a mutable reference to the value in the entry.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// let mut map = serde_json::Map::new();
/// map.entry("serde").or_insert(json!(12));
///
/// assert_eq!(map["serde"], 12);
/// # }
/// ```
pub fn or_insert(self, default: Value) -> &'a mut Value {
match self {
Entry::Vacant(entry) => entry.insert(default),
Entry::Occupied(entry) => entry.into_mut(),
}
}
/// Ensures a value is in the entry by inserting the result of the default
/// function if empty, and returns a mutable reference to the value in the
/// entry.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// let mut map = serde_json::Map::new();
/// map.entry("serde").or_insert_with(|| json!("hoho"));
///
/// assert_eq!(map["serde"], "hoho".to_owned());
/// # }
/// ```
pub fn or_insert_with<F>(self, default: F) -> &'a mut Value
where
F: FnOnce() -> Value,
{
match self {
Entry::Vacant(entry) => entry.insert(default()),
Entry::Occupied(entry) => entry.into_mut(),
}
}
}
impl<'a> VacantEntry<'a> {
/// Gets a reference to the key that would be used when inserting a value
/// through the VacantEntry.
///
/// # Examples
///
/// ```rust
/// use serde_json::map::Entry;
///
/// let mut map = serde_json::Map::new();
///
/// match map.entry("serde") {
/// Entry::Vacant(vacant) => {
/// assert_eq!(vacant.key(), &"serde");
/// }
/// Entry::Occupied(_) => unimplemented!(),
/// }
/// ```
#[inline]
pub fn key(&self) -> &String {
self.vacant.key()
}
/// Sets the value of the entry with the VacantEntry's key, and returns a
/// mutable reference to it.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::map::Entry;
///
/// let mut map = serde_json::Map::new();
///
/// match map.entry("serde") {
/// Entry::Vacant(vacant) => {
/// vacant.insert(json!("hoho"));
/// }
/// Entry::Occupied(_) => unimplemented!(),
/// }
/// # }
/// ```
#[inline]
pub fn insert(self, value: Value) -> &'a mut Value {
self.vacant.insert(value)
}
}
impl<'a> OccupiedEntry<'a> {
/// Gets a reference to the key in the entry.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::map::Entry;
///
/// let mut map = serde_json::Map::new();
/// map.insert("serde".to_owned(), json!(12));
///
/// match map.entry("serde") {
/// Entry::Occupied(occupied) => {
/// assert_eq!(occupied.key(), &"serde");
/// }
/// Entry::Vacant(_) => unimplemented!(),
/// }
/// # }
/// ```
#[inline]
pub fn key(&self) -> &String {
self.occupied.key()
}
/// Gets a reference to the value in the entry.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::map::Entry;
///
/// let mut map = serde_json::Map::new();
/// map.insert("serde".to_owned(), json!(12));
///
/// match map.entry("serde") {
/// Entry::Occupied(occupied) => {
/// assert_eq!(occupied.get(), 12);
/// }
/// Entry::Vacant(_) => unimplemented!(),
/// }
/// # }
/// ```
#[inline]
pub fn get(&self) -> &Value {
self.occupied.get()
}
/// Gets a mutable reference to the value in the entry.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::map::Entry;
///
/// let mut map = serde_json::Map::new();
/// map.insert("serde".to_owned(), json!([1, 2, 3]));
///
/// match map.entry("serde") {
/// Entry::Occupied(mut occupied) => {
/// occupied.get_mut().as_array_mut().unwrap().push(json!(4));
/// }
/// Entry::Vacant(_) => unimplemented!(),
/// }
///
/// assert_eq!(map["serde"].as_array().unwrap().len(), 4);
/// # }
/// ```
#[inline]
pub fn get_mut(&mut self) -> &mut Value {
self.occupied.get_mut()
}
/// Converts the entry into a mutable reference to its value.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::map::Entry;
///
/// let mut map = serde_json::Map::new();
/// map.insert("serde".to_owned(), json!([1, 2, 3]));
///
/// match map.entry("serde") {
/// Entry::Occupied(mut occupied) => {
/// occupied.into_mut().as_array_mut().unwrap().push(json!(4));
/// }
/// Entry::Vacant(_) => unimplemented!(),
/// }
///
/// assert_eq!(map["serde"].as_array().unwrap().len(), 4);
/// # }
/// ```
#[inline]
pub fn into_mut(self) -> &'a mut Value {
self.occupied.into_mut()
}
/// Sets the value of the entry with the `OccupiedEntry`'s key, and returns
/// the entry's old value.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::map::Entry;
///
/// let mut map = serde_json::Map::new();
/// map.insert("serde".to_owned(), json!(12));
///
/// match map.entry("serde") {
/// Entry::Occupied(mut occupied) => {
/// assert_eq!(occupied.insert(json!(13)), 12);
/// assert_eq!(occupied.get(), 13);
/// }
/// Entry::Vacant(_) => unimplemented!(),
/// }
/// # }
/// ```
#[inline]
pub fn insert(&mut self, value: Value) -> Value {
self.occupied.insert(value)
}
/// Takes the value of the entry out of the map, and returns it.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::map::Entry;
///
/// let mut map = serde_json::Map::new();
/// map.insert("serde".to_owned(), json!(12));
///
/// match map.entry("serde") {
/// Entry::Occupied(occupied) => {
/// assert_eq!(occupied.remove(), 12);
/// }
/// Entry::Vacant(_) => unimplemented!(),
/// }
/// # }
/// ```
#[inline]
pub fn remove(self) -> Value {
self.occupied.remove()
}
}
//////////////////////////////////////////////////////////////////////////////
impl<'a> IntoIterator for &'a Map<String, Value> {
type Item = (&'a String, &'a Value);
type IntoIter = Iter<'a>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
Iter {
iter: self.map.iter(),
}
}
}
/// An iterator over a serde_json::Map's entries.
pub struct Iter<'a> {
iter: IterImpl<'a>,
}
#[cfg(not(feature = "preserve_order"))]
type IterImpl<'a> = btree_map::Iter<'a, String, Value>;
#[cfg(feature = "preserve_order")]
type IterImpl<'a> = indexmap::map::Iter<'a, String, Value>;
delegate_iterator!((Iter<'a>) => (&'a String, &'a Value));
//////////////////////////////////////////////////////////////////////////////
impl<'a> IntoIterator for &'a mut Map<String, Value> {
type Item = (&'a String, &'a mut Value);
type IntoIter = IterMut<'a>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
IterMut {
iter: self.map.iter_mut(),
}
}
}
/// A mutable iterator over a serde_json::Map's entries.
pub struct IterMut<'a> {
iter: IterMutImpl<'a>,
}
#[cfg(not(feature = "preserve_order"))]
type IterMutImpl<'a> = btree_map::IterMut<'a, String, Value>;
#[cfg(feature = "preserve_order")]
type IterMutImpl<'a> = indexmap::map::IterMut<'a, String, Value>;
delegate_iterator!((IterMut<'a>) => (&'a String, &'a mut Value));
//////////////////////////////////////////////////////////////////////////////
impl IntoIterator for Map<String, Value> {
type Item = (String, Value);
type IntoIter = IntoIter;
#[inline]
fn into_iter(self) -> Self::IntoIter {
IntoIter {
iter: self.map.into_iter(),
}
}
}
/// An owning iterator over a serde_json::Map's entries.
pub struct IntoIter {
iter: IntoIterImpl,
}
#[cfg(not(feature = "preserve_order"))]
type IntoIterImpl = btree_map::IntoIter<String, Value>;
#[cfg(feature = "preserve_order")]
type IntoIterImpl = indexmap::map::IntoIter<String, Value>;
delegate_iterator!((IntoIter) => (String, Value));
//////////////////////////////////////////////////////////////////////////////
/// An iterator over a serde_json::Map's keys.
pub struct Keys<'a> {
iter: KeysImpl<'a>,
}
#[cfg(not(feature = "preserve_order"))]
type KeysImpl<'a> = btree_map::Keys<'a, String, Value>;
#[cfg(feature = "preserve_order")]
type KeysImpl<'a> = indexmap::map::Keys<'a, String, Value>;
delegate_iterator!((Keys<'a>) => &'a String);
//////////////////////////////////////////////////////////////////////////////
/// An iterator over a serde_json::Map's values.
pub struct Values<'a> {
iter: ValuesImpl<'a>,
}
#[cfg(not(feature = "preserve_order"))]
type ValuesImpl<'a> = btree_map::Values<'a, String, Value>;
#[cfg(feature = "preserve_order")]
type ValuesImpl<'a> = indexmap::map::Values<'a, String, Value>;
delegate_iterator!((Values<'a>) => &'a Value);
//////////////////////////////////////////////////////////////////////////////
/// A mutable iterator over a serde_json::Map's values.
pub struct ValuesMut<'a> {
iter: ValuesMutImpl<'a>,
}
#[cfg(not(feature = "preserve_order"))]
type ValuesMutImpl<'a> = btree_map::ValuesMut<'a, String, Value>;
#[cfg(feature = "preserve_order")]
type ValuesMutImpl<'a> = indexmap::map::ValuesMut<'a, String, Value>;
delegate_iterator!((ValuesMut<'a>) => &'a mut Value);

View File

@ -0,0 +1,770 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use error::Error;
use serde::de::{self, Unexpected, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt::{self, Debug, Display};
#[cfg(feature = "arbitrary_precision")]
use ryu;
#[cfg(feature = "arbitrary_precision")]
use itoa;
#[cfg(feature = "arbitrary_precision")]
use serde::de::{IntoDeserializer, MapAccess};
use de::ParserNumber;
#[cfg(feature = "arbitrary_precision")]
use error::ErrorCode;
#[cfg(feature = "arbitrary_precision")]
/// Not public API. Should be pub(crate).
#[doc(hidden)]
pub const SERDE_STRUCT_FIELD_NAME: &'static str = "$__serde_private_number";
#[cfg(feature = "arbitrary_precision")]
/// Not public API. Should be pub(crate).
#[doc(hidden)]
pub const SERDE_STRUCT_NAME: &'static str = "$__serde_private_Number";
/// Represents a JSON number, whether integer or floating point.
#[derive(Clone, PartialEq)]
pub struct Number {
n: N,
}
#[cfg(not(feature = "arbitrary_precision"))]
#[derive(Copy, Clone, PartialEq)]
enum N {
PosInt(u64),
/// Always less than zero.
NegInt(i64),
/// Always finite.
Float(f64),
}
#[cfg(feature = "arbitrary_precision")]
type N = String;
impl Number {
/// Returns true if the `Number` is an integer between `i64::MIN` and
/// `i64::MAX`.
///
/// For any Number on which `is_i64` returns true, `as_i64` is guaranteed to
/// return the integer value.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// let big = i64::max_value() as u64 + 10;
/// let v = json!({ "a": 64, "b": big, "c": 256.0 });
///
/// assert!(v["a"].is_i64());
///
/// // Greater than i64::MAX.
/// assert!(!v["b"].is_i64());
///
/// // Numbers with a decimal point are not considered integers.
/// assert!(!v["c"].is_i64());
/// # }
/// ```
#[inline]
pub fn is_i64(&self) -> bool {
#[cfg(not(feature = "arbitrary_precision"))]
match self.n {
N::PosInt(v) => v <= i64::max_value() as u64,
N::NegInt(_) => true,
N::Float(_) => false,
}
#[cfg(feature = "arbitrary_precision")]
self.as_i64().is_some()
}
/// Returns true if the `Number` is an integer between zero and `u64::MAX`.
///
/// For any Number on which `is_u64` returns true, `as_u64` is guaranteed to
/// return the integer value.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// let v = json!({ "a": 64, "b": -64, "c": 256.0 });
///
/// assert!(v["a"].is_u64());
///
/// // Negative integer.
/// assert!(!v["b"].is_u64());
///
/// // Numbers with a decimal point are not considered integers.
/// assert!(!v["c"].is_u64());
/// # }
/// ```
#[inline]
pub fn is_u64(&self) -> bool {
#[cfg(not(feature = "arbitrary_precision"))]
match self.n {
N::PosInt(_) => true,
N::NegInt(_) | N::Float(_) => false,
}
#[cfg(feature = "arbitrary_precision")]
self.as_u64().is_some()
}
/// Returns true if the `Number` can be represented by f64.
///
/// For any Number on which `is_f64` returns true, `as_f64` is guaranteed to
/// return the floating point value.
///
/// Currently this function returns true if and only if both `is_i64` and
/// `is_u64` return false but this is not a guarantee in the future.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// let v = json!({ "a": 256.0, "b": 64, "c": -64 });
///
/// assert!(v["a"].is_f64());
///
/// // Integers.
/// assert!(!v["b"].is_f64());
/// assert!(!v["c"].is_f64());
/// # }
/// ```
#[inline]
pub fn is_f64(&self) -> bool {
#[cfg(not(feature = "arbitrary_precision"))]
match self.n {
N::Float(_) => true,
N::PosInt(_) | N::NegInt(_) => false,
}
#[cfg(feature = "arbitrary_precision")]
{
for c in self.n.chars() {
if c == '.' || c == 'e' || c == 'E' {
return self.n.parse::<f64>().ok().map_or(false, |f| f.is_finite());
}
}
false
}
}
/// If the `Number` is an integer, represent it as i64 if possible. Returns
/// None otherwise.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// let big = i64::max_value() as u64 + 10;
/// let v = json!({ "a": 64, "b": big, "c": 256.0 });
///
/// assert_eq!(v["a"].as_i64(), Some(64));
/// assert_eq!(v["b"].as_i64(), None);
/// assert_eq!(v["c"].as_i64(), None);
/// # }
/// ```
#[inline]
pub fn as_i64(&self) -> Option<i64> {
#[cfg(not(feature = "arbitrary_precision"))]
match self.n {
N::PosInt(n) => if n <= i64::max_value() as u64 {
Some(n as i64)
} else {
None
},
N::NegInt(n) => Some(n),
N::Float(_) => None,
}
#[cfg(feature = "arbitrary_precision")]
self.n.parse().ok()
}
/// If the `Number` is an integer, represent it as u64 if possible. Returns
/// None otherwise.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// let v = json!({ "a": 64, "b": -64, "c": 256.0 });
///
/// assert_eq!(v["a"].as_u64(), Some(64));
/// assert_eq!(v["b"].as_u64(), None);
/// assert_eq!(v["c"].as_u64(), None);
/// # }
/// ```
#[inline]
pub fn as_u64(&self) -> Option<u64> {
#[cfg(not(feature = "arbitrary_precision"))]
match self.n {
N::PosInt(n) => Some(n),
N::NegInt(_) | N::Float(_) => None,
}
#[cfg(feature = "arbitrary_precision")]
self.n.parse().ok()
}
/// Represents the number as f64 if possible. Returns None otherwise.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// let v = json!({ "a": 256.0, "b": 64, "c": -64 });
///
/// assert_eq!(v["a"].as_f64(), Some(256.0));
/// assert_eq!(v["b"].as_f64(), Some(64.0));
/// assert_eq!(v["c"].as_f64(), Some(-64.0));
/// # }
/// ```
#[inline]
pub fn as_f64(&self) -> Option<f64> {
#[cfg(not(feature = "arbitrary_precision"))]
match self.n {
N::PosInt(n) => Some(n as f64),
N::NegInt(n) => Some(n as f64),
N::Float(n) => Some(n),
}
#[cfg(feature = "arbitrary_precision")]
self.n.parse().ok()
}
/// Converts a finite `f64` to a `Number`. Infinite or NaN values are not JSON
/// numbers.
///
/// ```rust
/// # use std::f64;
/// #
/// # use serde_json::Number;
/// #
/// assert!(Number::from_f64(256.0).is_some());
///
/// assert!(Number::from_f64(f64::NAN).is_none());
/// ```
#[inline]
pub fn from_f64(f: f64) -> Option<Number> {
if f.is_finite() {
let n = {
#[cfg(not(feature = "arbitrary_precision"))]
{
N::Float(f)
}
#[cfg(feature = "arbitrary_precision")]
{
ryu::Buffer::new().format(f).to_owned()
}
};
Some(Number { n: n })
} else {
None
}
}
#[cfg(feature = "arbitrary_precision")]
/// Not public API. Only tests use this.
#[doc(hidden)]
#[inline]
pub fn from_string_unchecked(n: String) -> Self {
Number { n: n }
}
}
impl fmt::Display for Number {
#[cfg(not(feature = "arbitrary_precision"))]
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self.n {
N::PosInt(u) => Display::fmt(&u, formatter),
N::NegInt(i) => Display::fmt(&i, formatter),
N::Float(f) => Display::fmt(&f, formatter),
}
}
#[cfg(feature = "arbitrary_precision")]
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.n, formatter)
}
}
impl Debug for Number {
#[cfg(not(feature = "arbitrary_precision"))]
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
let mut debug = formatter.debug_tuple("Number");
match self.n {
N::PosInt(i) => {
debug.field(&i);
}
N::NegInt(i) => {
debug.field(&i);
}
N::Float(f) => {
debug.field(&f);
}
}
debug.finish()
}
#[cfg(feature = "arbitrary_precision")]
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "Number({})", &self.n)
}
}
impl Serialize for Number {
#[cfg(not(feature = "arbitrary_precision"))]
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self.n {
N::PosInt(u) => serializer.serialize_u64(u),
N::NegInt(i) => serializer.serialize_i64(i),
N::Float(f) => serializer.serialize_f64(f),
}
}
#[cfg(feature = "arbitrary_precision")]
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use serde::ser::SerializeStruct;
let mut s = serializer.serialize_struct(SERDE_STRUCT_NAME, 1)?;
s.serialize_field(SERDE_STRUCT_FIELD_NAME, &self.n)?;
s.end()
}
}
impl<'de> Deserialize<'de> for Number {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Number, D::Error>
where
D: Deserializer<'de>,
{
struct NumberVisitor;
impl<'de> Visitor<'de> for NumberVisitor {
type Value = Number;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a JSON number")
}
#[inline]
fn visit_i64<E>(self, value: i64) -> Result<Number, E> {
Ok(value.into())
}
#[inline]
fn visit_u64<E>(self, value: u64) -> Result<Number, E> {
Ok(value.into())
}
#[inline]
fn visit_f64<E>(self, value: f64) -> Result<Number, E>
where
E: de::Error,
{
Number::from_f64(value).ok_or_else(|| de::Error::custom("not a JSON number"))
}
#[cfg(feature = "arbitrary_precision")]
#[inline]
fn visit_map<V>(self, mut visitor: V) -> Result<Number, V::Error>
where
V: de::MapAccess<'de>,
{
let value = visitor.next_key::<NumberKey>()?;
if value.is_none() {
return Err(de::Error::invalid_type(Unexpected::Map, &self));
}
let v: NumberFromString = visitor.next_value()?;
Ok(v.value)
}
}
deserializer.deserialize_any(NumberVisitor)
}
}
#[cfg(feature = "arbitrary_precision")]
struct NumberKey;
#[cfg(feature = "arbitrary_precision")]
impl<'de> de::Deserialize<'de> for NumberKey {
fn deserialize<D>(deserializer: D) -> Result<NumberKey, D::Error>
where
D: de::Deserializer<'de>,
{
struct FieldVisitor;
impl<'de> de::Visitor<'de> for FieldVisitor {
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a valid number field")
}
fn visit_str<E>(self, s: &str) -> Result<(), E>
where
E: de::Error,
{
if s == SERDE_STRUCT_FIELD_NAME {
Ok(())
} else {
Err(de::Error::custom("expected field with custom name"))
}
}
}
deserializer.deserialize_identifier(FieldVisitor)?;
Ok(NumberKey)
}
}
#[cfg(feature = "arbitrary_precision")]
pub struct NumberFromString {
pub value: Number,
}
#[cfg(feature = "arbitrary_precision")]
impl<'de> de::Deserialize<'de> for NumberFromString {
fn deserialize<D>(deserializer: D) -> Result<NumberFromString, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = NumberFromString;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("string containing a number")
}
fn visit_str<E>(self, s: &str) -> Result<NumberFromString, E>
where
E: de::Error,
{
let n = try!(s.parse().map_err(de::Error::custom));
Ok(NumberFromString { value: n })
}
}
deserializer.deserialize_str(Visitor)
}
}
#[cfg(feature = "arbitrary_precision")]
fn invalid_number() -> Error {
Error::syntax(ErrorCode::InvalidNumber, 0, 0)
}
macro_rules! deserialize_any {
(@expand [$($num_string:tt)*]) => {
#[cfg(not(feature = "arbitrary_precision"))]
#[inline]
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
match self.n {
N::PosInt(u) => visitor.visit_u64(u),
N::NegInt(i) => visitor.visit_i64(i),
N::Float(f) => visitor.visit_f64(f),
}
}
#[cfg(feature = "arbitrary_precision")]
#[inline]
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
where V: Visitor<'de>
{
if let Some(u) = self.as_u64() {
return visitor.visit_u64(u);
} else if let Some(i) = self.as_i64() {
return visitor.visit_i64(i);
} else if let Some(f) = self.as_f64() {
if f.to_string() == self.n {
return visitor.visit_f64(f);
}
}
visitor.visit_map(NumberDeserializer {
number: Some(self.$($num_string)*),
})
}
};
(owned) => {
deserialize_any!(@expand [n]);
};
(ref) => {
deserialize_any!(@expand [n.clone()]);
};
}
macro_rules! deserialize_number {
($deserialize:ident => $visit:ident) => {
#[cfg(not(feature = "arbitrary_precision"))]
fn $deserialize<V>(self, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
self.deserialize_any(visitor)
}
#[cfg(feature = "arbitrary_precision")]
fn $deserialize<V>(self, visitor: V) -> Result<V::Value, Error>
where
V: de::Visitor<'de>,
{
visitor.$visit(self.n.parse().map_err(|_| invalid_number())?)
}
}
}
impl<'de> Deserializer<'de> for Number {
type Error = Error;
deserialize_any!(owned);
deserialize_number!(deserialize_i8 => visit_i8);
deserialize_number!(deserialize_i16 => visit_i16);
deserialize_number!(deserialize_i32 => visit_i32);
deserialize_number!(deserialize_i64 => visit_i64);
deserialize_number!(deserialize_u8 => visit_u8);
deserialize_number!(deserialize_u16 => visit_u16);
deserialize_number!(deserialize_u32 => visit_u32);
deserialize_number!(deserialize_u64 => visit_u64);
deserialize_number!(deserialize_f32 => visit_f32);
deserialize_number!(deserialize_f64 => visit_f64);
serde_if_integer128! {
deserialize_number!(deserialize_i128 => visit_i128);
deserialize_number!(deserialize_u128 => visit_u128);
}
forward_to_deserialize_any! {
bool char str string bytes byte_buf option unit unit_struct
newtype_struct seq tuple tuple_struct map struct enum identifier
ignored_any
}
}
impl<'de, 'a> Deserializer<'de> for &'a Number {
type Error = Error;
deserialize_any!(ref);
deserialize_number!(deserialize_i8 => visit_i8);
deserialize_number!(deserialize_i16 => visit_i16);
deserialize_number!(deserialize_i32 => visit_i32);
deserialize_number!(deserialize_i64 => visit_i64);
deserialize_number!(deserialize_u8 => visit_u8);
deserialize_number!(deserialize_u16 => visit_u16);
deserialize_number!(deserialize_u32 => visit_u32);
deserialize_number!(deserialize_u64 => visit_u64);
deserialize_number!(deserialize_f32 => visit_f32);
deserialize_number!(deserialize_f64 => visit_f64);
serde_if_integer128! {
deserialize_number!(deserialize_i128 => visit_i128);
deserialize_number!(deserialize_u128 => visit_u128);
}
forward_to_deserialize_any! {
bool char str string bytes byte_buf option unit unit_struct
newtype_struct seq tuple tuple_struct map struct enum identifier
ignored_any
}
}
#[cfg(feature = "arbitrary_precision")]
// Not public API. Should be pub(crate).
#[doc(hidden)]
pub struct NumberDeserializer {
pub number: Option<String>,
}
#[cfg(feature = "arbitrary_precision")]
impl<'de> MapAccess<'de> for NumberDeserializer {
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where
K: de::DeserializeSeed<'de>,
{
if self.number.is_none() {
return Ok(None);
}
seed.deserialize(NumberFieldDeserializer).map(Some)
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
where
V: de::DeserializeSeed<'de>,
{
seed.deserialize(self.number.take().unwrap().into_deserializer())
}
}
#[cfg(feature = "arbitrary_precision")]
struct NumberFieldDeserializer;
#[cfg(feature = "arbitrary_precision")]
impl<'de> Deserializer<'de> for NumberFieldDeserializer {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
where
V: de::Visitor<'de>,
{
visitor.visit_borrowed_str(SERDE_STRUCT_FIELD_NAME)
}
forward_to_deserialize_any! {
bool u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 char str string seq
bytes byte_buf map struct option unit newtype_struct ignored_any
unit_struct tuple_struct tuple enum identifier
}
}
impl From<ParserNumber> for Number {
fn from(value: ParserNumber) -> Self {
let n = match value {
ParserNumber::F64(f) => {
#[cfg(not(feature = "arbitrary_precision"))]
{
N::Float(f)
}
#[cfg(feature = "arbitrary_precision")]
{
f.to_string()
}
}
ParserNumber::U64(u) => {
#[cfg(not(feature = "arbitrary_precision"))]
{
N::PosInt(u)
}
#[cfg(feature = "arbitrary_precision")]
{
u.to_string()
}
}
ParserNumber::I64(i) => {
#[cfg(not(feature = "arbitrary_precision"))]
{
N::NegInt(i)
}
#[cfg(feature = "arbitrary_precision")]
{
i.to_string()
}
}
#[cfg(feature = "arbitrary_precision")]
ParserNumber::String(s) => s,
};
Number { n: n }
}
}
macro_rules! impl_from_unsigned {
(
$($ty:ty),*
) => {
$(
impl From<$ty> for Number {
#[inline]
fn from(u: $ty) -> Self {
let n = {
#[cfg(not(feature = "arbitrary_precision"))]
{ N::PosInt(u as u64) }
#[cfg(feature = "arbitrary_precision")]
{
let mut buf = Vec::new();
itoa::write(&mut buf, u).unwrap();
String::from_utf8(buf).unwrap()
}
};
Number { n: n }
}
}
)*
};
}
macro_rules! impl_from_signed {
(
$($ty:ty),*
) => {
$(
impl From<$ty> for Number {
#[inline]
fn from(i: $ty) -> Self {
let n = {
#[cfg(not(feature = "arbitrary_precision"))]
{
if i < 0 {
N::NegInt(i as i64)
} else {
N::PosInt(i as u64)
}
}
#[cfg(feature = "arbitrary_precision")]
{
let mut buf = Vec::new();
itoa::write(&mut buf, i).unwrap();
String::from_utf8(buf).unwrap()
}
};
Number { n: n }
}
}
)*
};
}
impl_from_unsigned!(u8, u16, u32, u64, usize);
impl_from_signed!(i8, i16, i32, i64, isize);
impl Number {
#[cfg(not(feature = "arbitrary_precision"))]
// Not public API. Should be pub(crate).
#[doc(hidden)]
#[cold]
pub fn unexpected(&self) -> Unexpected {
match self.n {
N::PosInt(u) => Unexpected::Unsigned(u),
N::NegInt(i) => Unexpected::Signed(i),
N::Float(f) => Unexpected::Float(f),
}
}
#[cfg(feature = "arbitrary_precision")]
// Not public API. Should be pub(crate).
#[doc(hidden)]
#[cold]
pub fn unexpected(&self) -> Unexpected {
Unexpected::Other("number")
}
}

677
third_party/rust/serde_json/src/read.rs vendored Normal file
View File

@ -0,0 +1,677 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::ops::Deref;
use std::{char, cmp, io, str};
use iter::LineColIterator;
use super::error::{Error, ErrorCode, Result};
/// Trait used by the deserializer for iterating over input. This is manually
/// "specialized" for iterating over &[u8]. Once feature(specialization) is
/// stable we can use actual specialization.
///
/// This trait is sealed and cannot be implemented for types outside of
/// `serde_json`.
pub trait Read<'de>: private::Sealed {
#[doc(hidden)]
fn next(&mut self) -> io::Result<Option<u8>>;
#[doc(hidden)]
fn peek(&mut self) -> io::Result<Option<u8>>;
/// Only valid after a call to peek(). Discards the peeked byte.
#[doc(hidden)]
fn discard(&mut self);
/// Position of the most recent call to next().
///
/// The most recent call was probably next() and not peek(), but this method
/// should try to return a sensible result if the most recent call was
/// actually peek() because we don't always know.
///
/// Only called in case of an error, so performance is not important.
#[doc(hidden)]
fn position(&self) -> Position;
/// Position of the most recent call to peek().
///
/// The most recent call was probably peek() and not next(), but this method
/// should try to return a sensible result if the most recent call was
/// actually next() because we don't always know.
///
/// Only called in case of an error, so performance is not important.
#[doc(hidden)]
fn peek_position(&self) -> Position;
/// Offset from the beginning of the input to the next byte that would be
/// returned by next() or peek().
#[doc(hidden)]
fn byte_offset(&self) -> usize;
/// Assumes the previous byte was a quotation mark. Parses a JSON-escaped
/// string until the next quotation mark using the given scratch space if
/// necessary. The scratch space is initially empty.
#[doc(hidden)]
fn parse_str<'s>(&'s mut self, scratch: &'s mut Vec<u8>) -> Result<Reference<'de, 's, str>>;
/// Assumes the previous byte was a quotation mark. Parses a JSON-escaped
/// string until the next quotation mark using the given scratch space if
/// necessary. The scratch space is initially empty.
///
/// This function returns the raw bytes in the string with escape sequences
/// expanded but without performing unicode validation.
#[doc(hidden)]
fn parse_str_raw<'s>(
&'s mut self,
scratch: &'s mut Vec<u8>,
) -> Result<Reference<'de, 's, [u8]>>;
/// Assumes the previous byte was a quotation mark. Parses a JSON-escaped
/// string until the next quotation mark but discards the data.
#[doc(hidden)]
fn ignore_str(&mut self) -> Result<()>;
}
pub struct Position {
pub line: usize,
pub column: usize,
}
pub enum Reference<'b, 'c, T: ?Sized + 'static> {
Borrowed(&'b T),
Copied(&'c T),
}
impl<'b, 'c, T: ?Sized + 'static> Deref for Reference<'b, 'c, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
match *self {
Reference::Borrowed(b) => b,
Reference::Copied(c) => c,
}
}
}
/// JSON input source that reads from a std::io input stream.
pub struct IoRead<R>
where
R: io::Read,
{
iter: LineColIterator<io::Bytes<R>>,
/// Temporary storage of peeked byte.
ch: Option<u8>,
}
/// JSON input source that reads from a slice of bytes.
//
// This is more efficient than other iterators because peek() can be read-only
// and we can compute line/col position only if an error happens.
pub struct SliceRead<'a> {
slice: &'a [u8],
/// Index of the *next* byte that will be returned by next() or peek().
index: usize,
}
/// JSON input source that reads from a UTF-8 string.
//
// Able to elide UTF-8 checks by assuming that the input is valid UTF-8.
pub struct StrRead<'a> {
delegate: SliceRead<'a>,
}
// Prevent users from implementing the Read trait.
mod private {
pub trait Sealed {}
}
//////////////////////////////////////////////////////////////////////////////
impl<R> IoRead<R>
where
R: io::Read,
{
/// Create a JSON input source to read from a std::io input stream.
pub fn new(reader: R) -> Self {
IoRead {
iter: LineColIterator::new(reader.bytes()),
ch: None,
}
}
}
impl<R> private::Sealed for IoRead<R> where R: io::Read {}
impl<R> IoRead<R>
where
R: io::Read,
{
fn parse_str_bytes<'s, T, F>(
&'s mut self,
scratch: &'s mut Vec<u8>,
validate: bool,
result: F,
) -> Result<T>
where
T: 's,
F: FnOnce(&'s Self, &'s [u8]) -> Result<T>,
{
loop {
let ch = try!(next_or_eof(self));
if !ESCAPE[ch as usize] {
scratch.push(ch);
continue;
}
match ch {
b'"' => {
return result(self, scratch);
}
b'\\' => {
try!(parse_escape(self, scratch));
}
_ => {
if validate {
return error(self, ErrorCode::ControlCharacterWhileParsingString);
}
scratch.push(ch);
}
}
}
}
}
impl<'de, R> Read<'de> for IoRead<R>
where
R: io::Read,
{
#[inline]
fn next(&mut self) -> io::Result<Option<u8>> {
match self.ch.take() {
Some(ch) => Ok(Some(ch)),
None => match self.iter.next() {
Some(Err(err)) => Err(err),
Some(Ok(ch)) => Ok(Some(ch)),
None => Ok(None),
},
}
}
#[inline]
fn peek(&mut self) -> io::Result<Option<u8>> {
match self.ch {
Some(ch) => Ok(Some(ch)),
None => match self.iter.next() {
Some(Err(err)) => Err(err),
Some(Ok(ch)) => {
self.ch = Some(ch);
Ok(self.ch)
}
None => Ok(None),
},
}
}
#[inline]
fn discard(&mut self) {
self.ch = None;
}
fn position(&self) -> Position {
Position {
line: self.iter.line(),
column: self.iter.col(),
}
}
fn peek_position(&self) -> Position {
// The LineColIterator updates its position during peek() so it has the
// right one here.
self.position()
}
fn byte_offset(&self) -> usize {
match self.ch {
Some(_) => self.iter.byte_offset() - 1,
None => self.iter.byte_offset(),
}
}
fn parse_str<'s>(&'s mut self, scratch: &'s mut Vec<u8>) -> Result<Reference<'de, 's, str>> {
self.parse_str_bytes(scratch, true, as_str)
.map(Reference::Copied)
}
fn parse_str_raw<'s>(
&'s mut self,
scratch: &'s mut Vec<u8>,
) -> Result<Reference<'de, 's, [u8]>> {
self.parse_str_bytes(scratch, false, |_, bytes| Ok(bytes))
.map(Reference::Copied)
}
fn ignore_str(&mut self) -> Result<()> {
loop {
let ch = try!(next_or_eof(self));
if !ESCAPE[ch as usize] {
continue;
}
match ch {
b'"' => {
return Ok(());
}
b'\\' => {
try!(ignore_escape(self));
}
_ => {
return error(self, ErrorCode::ControlCharacterWhileParsingString);
}
}
}
}
}
//////////////////////////////////////////////////////////////////////////////
impl<'a> SliceRead<'a> {
/// Create a JSON input source to read from a slice of bytes.
pub fn new(slice: &'a [u8]) -> Self {
SliceRead {
slice: slice,
index: 0,
}
}
fn position_of_index(&self, i: usize) -> Position {
let mut position = Position { line: 1, column: 0 };
for ch in &self.slice[..i] {
match *ch {
b'\n' => {
position.line += 1;
position.column = 0;
}
_ => {
position.column += 1;
}
}
}
position
}
/// The big optimization here over IoRead is that if the string contains no
/// backslash escape sequences, the returned &str is a slice of the raw JSON
/// data so we avoid copying into the scratch space.
fn parse_str_bytes<'s, T: ?Sized, F>(
&'s mut self,
scratch: &'s mut Vec<u8>,
validate: bool,
result: F,
) -> Result<Reference<'a, 's, T>>
where
T: 's,
F: for<'f> FnOnce(&'s Self, &'f [u8]) -> Result<&'f T>,
{
// Index of the first byte not yet copied into the scratch space.
let mut start = self.index;
loop {
while self.index < self.slice.len() && !ESCAPE[self.slice[self.index] as usize] {
self.index += 1;
}
if self.index == self.slice.len() {
return error(self, ErrorCode::EofWhileParsingString);
}
match self.slice[self.index] {
b'"' => {
if scratch.is_empty() {
// Fast path: return a slice of the raw JSON without any
// copying.
let borrowed = &self.slice[start..self.index];
self.index += 1;
return result(self, borrowed).map(Reference::Borrowed);
} else {
scratch.extend_from_slice(&self.slice[start..self.index]);
self.index += 1;
return result(self, scratch).map(Reference::Copied);
}
}
b'\\' => {
scratch.extend_from_slice(&self.slice[start..self.index]);
self.index += 1;
try!(parse_escape(self, scratch));
start = self.index;
}
_ => {
if validate {
return error(self, ErrorCode::ControlCharacterWhileParsingString);
}
self.index += 1;
}
}
}
}
}
impl<'a> private::Sealed for SliceRead<'a> {}
impl<'a> Read<'a> for SliceRead<'a> {
#[inline]
fn next(&mut self) -> io::Result<Option<u8>> {
// `Ok(self.slice.get(self.index).map(|ch| { self.index += 1; *ch }))`
// is about 10% slower.
Ok(if self.index < self.slice.len() {
let ch = self.slice[self.index];
self.index += 1;
Some(ch)
} else {
None
})
}
#[inline]
fn peek(&mut self) -> io::Result<Option<u8>> {
// `Ok(self.slice.get(self.index).map(|ch| *ch))` is about 10% slower
// for some reason.
Ok(if self.index < self.slice.len() {
Some(self.slice[self.index])
} else {
None
})
}
#[inline]
fn discard(&mut self) {
self.index += 1;
}
fn position(&self) -> Position {
self.position_of_index(self.index)
}
fn peek_position(&self) -> Position {
// Cap it at slice.len() just in case the most recent call was next()
// and it returned the last byte.
self.position_of_index(cmp::min(self.slice.len(), self.index + 1))
}
fn byte_offset(&self) -> usize {
self.index
}
fn parse_str<'s>(&'s mut self, scratch: &'s mut Vec<u8>) -> Result<Reference<'a, 's, str>> {
self.parse_str_bytes(scratch, true, as_str)
}
fn parse_str_raw<'s>(
&'s mut self,
scratch: &'s mut Vec<u8>,
) -> Result<Reference<'a, 's, [u8]>> {
self.parse_str_bytes(scratch, false, |_, bytes| Ok(bytes))
}
fn ignore_str(&mut self) -> Result<()> {
loop {
while self.index < self.slice.len() && !ESCAPE[self.slice[self.index] as usize] {
self.index += 1;
}
if self.index == self.slice.len() {
return error(self, ErrorCode::EofWhileParsingString);
}
match self.slice[self.index] {
b'"' => {
self.index += 1;
return Ok(());
}
b'\\' => {
self.index += 1;
try!(ignore_escape(self));
}
_ => {
return error(self, ErrorCode::ControlCharacterWhileParsingString);
}
}
}
}
}
//////////////////////////////////////////////////////////////////////////////
impl<'a> StrRead<'a> {
/// Create a JSON input source to read from a UTF-8 string.
pub fn new(s: &'a str) -> Self {
StrRead {
delegate: SliceRead::new(s.as_bytes()),
}
}
}
impl<'a> private::Sealed for StrRead<'a> {}
impl<'a> Read<'a> for StrRead<'a> {
#[inline]
fn next(&mut self) -> io::Result<Option<u8>> {
self.delegate.next()
}
#[inline]
fn peek(&mut self) -> io::Result<Option<u8>> {
self.delegate.peek()
}
#[inline]
fn discard(&mut self) {
self.delegate.discard();
}
fn position(&self) -> Position {
self.delegate.position()
}
fn peek_position(&self) -> Position {
self.delegate.peek_position()
}
fn byte_offset(&self) -> usize {
self.delegate.byte_offset()
}
fn parse_str<'s>(&'s mut self, scratch: &'s mut Vec<u8>) -> Result<Reference<'a, 's, str>> {
self.delegate.parse_str_bytes(scratch, true, |_, bytes| {
// The input is assumed to be valid UTF-8 and the \u-escapes are
// checked along the way, so don't need to check here.
Ok(unsafe { str::from_utf8_unchecked(bytes) })
})
}
fn parse_str_raw<'s>(
&'s mut self,
scratch: &'s mut Vec<u8>,
) -> Result<Reference<'a, 's, [u8]>> {
self.delegate.parse_str_raw(scratch)
}
fn ignore_str(&mut self) -> Result<()> {
self.delegate.ignore_str()
}
}
//////////////////////////////////////////////////////////////////////////////
const CT: bool = true; // control character \x00...\x1F
const QU: bool = true; // quote \x22
const BS: bool = true; // backslash \x5C
const O: bool = false; // allow unescaped
// Lookup table of bytes that must be escaped. A value of true at index i means
// that byte i requires an escape sequence in the input.
#[cfg_attr(rustfmt, rustfmt_skip)]
static ESCAPE: [bool; 256] = [
// 1 2 3 4 5 6 7 8 9 A B C D E F
CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, // 0
CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, // 1
O, O, QU, O, O, O, O, O, O, O, O, O, O, O, O, O, // 2
O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, // 3
O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, // 4
O, O, O, O, O, O, O, O, O, O, O, O, BS, O, O, O, // 5
O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, // 6
O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, // 7
O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, // 8
O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, // 9
O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, // A
O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, // B
O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, // C
O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, // D
O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, // E
O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, // F
];
fn next_or_eof<'de, R: ?Sized + Read<'de>>(read: &mut R) -> Result<u8> {
match try!(read.next().map_err(Error::io)) {
Some(b) => Ok(b),
None => error(read, ErrorCode::EofWhileParsingString),
}
}
fn error<'de, R: ?Sized + Read<'de>, T>(read: &R, reason: ErrorCode) -> Result<T> {
let position = read.position();
Err(Error::syntax(reason, position.line, position.column))
}
fn as_str<'de, 's, R: Read<'de>>(read: &R, slice: &'s [u8]) -> Result<&'s str> {
str::from_utf8(slice).or_else(|_| error(read, ErrorCode::InvalidUnicodeCodePoint))
}
/// Parses a JSON escape sequence and appends it into the scratch space. Assumes
/// the previous byte read was a backslash.
fn parse_escape<'de, R: Read<'de>>(read: &mut R, scratch: &mut Vec<u8>) -> Result<()> {
let ch = try!(next_or_eof(read));
match ch {
b'"' => scratch.push(b'"'),
b'\\' => scratch.push(b'\\'),
b'/' => scratch.push(b'/'),
b'b' => scratch.push(b'\x08'),
b'f' => scratch.push(b'\x0c'),
b'n' => scratch.push(b'\n'),
b'r' => scratch.push(b'\r'),
b't' => scratch.push(b'\t'),
b'u' => {
let c = match try!(decode_hex_escape(read)) {
0xDC00...0xDFFF => {
return error(read, ErrorCode::LoneLeadingSurrogateInHexEscape);
}
// Non-BMP characters are encoded as a sequence of
// two hex escapes, representing UTF-16 surrogates.
n1 @ 0xD800...0xDBFF => {
if try!(next_or_eof(read)) != b'\\' {
return error(read, ErrorCode::UnexpectedEndOfHexEscape);
}
if try!(next_or_eof(read)) != b'u' {
return error(read, ErrorCode::UnexpectedEndOfHexEscape);
}
let n2 = try!(decode_hex_escape(read));
if n2 < 0xDC00 || n2 > 0xDFFF {
return error(read, ErrorCode::LoneLeadingSurrogateInHexEscape);
}
let n = (((n1 - 0xD800) as u32) << 10 | (n2 - 0xDC00) as u32) + 0x1_0000;
match char::from_u32(n) {
Some(c) => c,
None => {
return error(read, ErrorCode::InvalidUnicodeCodePoint);
}
}
}
n => match char::from_u32(n as u32) {
Some(c) => c,
None => {
return error(read, ErrorCode::InvalidUnicodeCodePoint);
}
},
};
scratch.extend_from_slice(c.encode_utf8(&mut [0_u8; 4]).as_bytes());
}
_ => {
return error(read, ErrorCode::InvalidEscape);
}
}
Ok(())
}
/// Parses a JSON escape sequence and discards the value. Assumes the previous
/// byte read was a backslash.
fn ignore_escape<'de, R: ?Sized + Read<'de>>(read: &mut R) -> Result<()> {
let ch = try!(next_or_eof(read));
match ch {
b'"' | b'\\' | b'/' | b'b' | b'f' | b'n' | b'r' | b't' => {}
b'u' => {
let n = match try!(decode_hex_escape(read)) {
0xDC00...0xDFFF => {
return error(read, ErrorCode::LoneLeadingSurrogateInHexEscape);
}
// Non-BMP characters are encoded as a sequence of
// two hex escapes, representing UTF-16 surrogates.
n1 @ 0xD800...0xDBFF => {
if try!(next_or_eof(read)) != b'\\' {
return error(read, ErrorCode::UnexpectedEndOfHexEscape);
}
if try!(next_or_eof(read)) != b'u' {
return error(read, ErrorCode::UnexpectedEndOfHexEscape);
}
let n2 = try!(decode_hex_escape(read));
if n2 < 0xDC00 || n2 > 0xDFFF {
return error(read, ErrorCode::LoneLeadingSurrogateInHexEscape);
}
(((n1 - 0xD800) as u32) << 10 | (n2 - 0xDC00) as u32) + 0x1_0000
}
n => n as u32,
};
if char::from_u32(n).is_none() {
return error(read, ErrorCode::InvalidUnicodeCodePoint);
}
}
_ => {
return error(read, ErrorCode::InvalidEscape);
}
}
Ok(())
}
fn decode_hex_escape<'de, R: ?Sized + Read<'de>>(read: &mut R) -> Result<u16> {
let mut n = 0;
for _ in 0..4 {
n = match try!(next_or_eof(read)) {
c @ b'0'...b'9' => n * 16_u16 + ((c as u16) - (b'0' as u16)),
b'a' | b'A' => n * 16_u16 + 10_u16,
b'b' | b'B' => n * 16_u16 + 11_u16,
b'c' | b'C' => n * 16_u16 + 12_u16,
b'd' | b'D' => n * 16_u16 + 13_u16,
b'e' | b'E' => n * 16_u16 + 14_u16,
b'f' | b'F' => n * 16_u16 + 15_u16,
_ => {
return error(read, ErrorCode::InvalidEscape);
}
};
}
Ok(n)
}

2096
third_party/rust/serde_json/src/ser.rs vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,266 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::borrow::Cow;
use super::Value;
use map::Map;
use number::Number;
macro_rules! from_integer {
($($ty:ident)*) => {
$(
impl From<$ty> for Value {
fn from(n: $ty) -> Self {
Value::Number(n.into())
}
}
)*
};
}
from_integer! {
i8 i16 i32 i64 isize
u8 u16 u32 u64 usize
}
impl From<f32> for Value {
/// Convert 32-bit floating point number to `Value`
///
/// # Examples
///
/// ```rust
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::Value;
///
/// let f: f32 = 13.37;
/// let x: Value = f.into();
/// # }
/// ```
fn from(f: f32) -> Self {
From::from(f as f64)
}
}
impl From<f64> for Value {
/// Convert 64-bit floating point number to `Value`
///
/// # Examples
///
/// ```rust
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::Value;
///
/// let f: f64 = 13.37;
/// let x: Value = f.into();
/// # }
/// ```
fn from(f: f64) -> Self {
Number::from_f64(f).map_or(Value::Null, Value::Number)
}
}
impl From<bool> for Value {
/// Convert boolean to `Value`
///
/// # Examples
///
/// ```rust
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::Value;
///
/// let b = false;
/// let x: Value = b.into();
/// # }
/// ```
fn from(f: bool) -> Self {
Value::Bool(f)
}
}
impl From<String> for Value {
/// Convert `String` to `Value`
///
/// # Examples
///
/// ```rust
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::Value;
///
/// let s: String = "lorem".to_string();
/// let x: Value = s.into();
/// # }
/// ```
fn from(f: String) -> Self {
Value::String(f)
}
}
impl<'a> From<&'a str> for Value {
/// Convert string slice to `Value`
///
/// # Examples
///
/// ```rust
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::Value;
///
/// let s: &str = "lorem";
/// let x: Value = s.into();
/// # }
/// ```
fn from(f: &str) -> Self {
Value::String(f.to_string())
}
}
impl<'a> From<Cow<'a, str>> for Value {
/// Convert copy-on-write string to `Value`
///
/// # Examples
///
/// ```rust
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::Value;
/// use std::borrow::Cow;
///
/// let s: Cow<str> = Cow::Borrowed("lorem");
/// let x: Value = s.into();
/// # }
/// ```
///
/// ```rust
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::Value;
/// use std::borrow::Cow;
///
/// let s: Cow<str> = Cow::Owned("lorem".to_string());
/// let x: Value = s.into();
/// # }
/// ```
fn from(f: Cow<'a, str>) -> Self {
Value::String(f.into_owned())
}
}
impl From<Map<String, Value>> for Value {
/// Convert map (with string keys) to `Value`
///
/// # Examples
///
/// ```rust
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::{Map, Value};
///
/// let mut m = Map::new();
/// m.insert("Lorem".to_string(), "ipsum".into());
/// let x: Value = m.into();
/// # }
/// ```
fn from(f: Map<String, Value>) -> Self {
Value::Object(f)
}
}
impl<T: Into<Value>> From<Vec<T>> for Value {
/// Convert a `Vec` to `Value`
///
/// # Examples
///
/// ```rust
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::Value;
///
/// let v = vec!["lorem", "ipsum", "dolor"];
/// let x: Value = v.into();
/// # }
/// ```
fn from(f: Vec<T>) -> Self {
Value::Array(f.into_iter().map(Into::into).collect())
}
}
impl<'a, T: Clone + Into<Value>> From<&'a [T]> for Value {
/// Convert a slice to `Value`
///
/// # Examples
///
/// ```rust
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::Value;
///
/// let v: &[&str] = &["lorem", "ipsum", "dolor"];
/// let x: Value = v.into();
/// # }
/// ```
fn from(f: &'a [T]) -> Self {
Value::Array(f.into_iter().cloned().map(Into::into).collect())
}
}
impl<T: Into<Value>> ::std::iter::FromIterator<T> for Value {
/// Convert an iteratable type to a `Value`
///
/// # Examples
///
/// ```rust
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::Value;
///
/// let v = std::iter::repeat(42).take(5);
/// let x: Value = v.collect();
/// # }
/// ```
///
/// ```rust
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use serde_json::Value;
///
/// let v: Vec<_> = vec!["lorem", "ipsum", "dolor"];
/// let x: Value = v.into_iter().collect();
/// # }
/// ```
///
/// ```rust
/// # extern crate serde_json;
/// #
/// # fn main() {
/// use std::iter::FromIterator;
/// use serde_json::Value;
///
/// let x: Value = Value::from_iter(vec!["lorem", "ipsum", "dolor"]);
/// # }
/// ```
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
Value::Array(iter.into_iter().map(Into::into).collect())
}
}

View File

@ -0,0 +1,274 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt;
use std::ops;
use super::Value;
use map::Map;
/// A type that can be used to index into a `serde_json::Value`.
///
/// The [`get`] and [`get_mut`] methods of `Value` accept any type that
/// implements `Index`, as does the [square-bracket indexing operator]. This
/// trait is implemented for strings which are used as the index into a JSON
/// map, and for `usize` which is used as the index into a JSON array.
///
/// [`get`]: ../enum.Value.html#method.get
/// [`get_mut`]: ../enum.Value.html#method.get_mut
/// [square-bracket indexing operator]: ../enum.Value.html#impl-Index%3CI%3E
///
/// This trait is sealed and cannot be implemented for types outside of
/// `serde_json`.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// let data = json!({ "inner": [1, 2, 3] });
///
/// // Data is a JSON map so it can be indexed with a string.
/// let inner = &data["inner"];
///
/// // Inner is a JSON array so it can be indexed with an integer.
/// let first = &inner[0];
///
/// assert_eq!(first, 1);
/// # }
/// ```
pub trait Index: private::Sealed {
/// Return None if the key is not already in the array or object.
#[doc(hidden)]
fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>;
/// Return None if the key is not already in the array or object.
#[doc(hidden)]
fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>;
/// Panic if array index out of bounds. If key is not already in the object,
/// insert it with a value of null. Panic if Value is a type that cannot be
/// indexed into, except if Value is null then it can be treated as an empty
/// object.
#[doc(hidden)]
fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value;
}
impl Index for usize {
fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
match *v {
Value::Array(ref vec) => vec.get(*self),
_ => None,
}
}
fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
match *v {
Value::Array(ref mut vec) => vec.get_mut(*self),
_ => None,
}
}
fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
match *v {
Value::Array(ref mut vec) => {
let len = vec.len();
vec.get_mut(*self).unwrap_or_else(|| {
panic!(
"cannot access index {} of JSON array of length {}",
self, len
)
})
}
_ => panic!("cannot access index {} of JSON {}", self, Type(v)),
}
}
}
impl Index for str {
fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
match *v {
Value::Object(ref map) => map.get(self),
_ => None,
}
}
fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
match *v {
Value::Object(ref mut map) => map.get_mut(self),
_ => None,
}
}
fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
if let Value::Null = *v {
*v = Value::Object(Map::new());
}
match *v {
Value::Object(ref mut map) => map.entry(self.to_owned()).or_insert(Value::Null),
_ => panic!("cannot access key {:?} in JSON {}", self, Type(v)),
}
}
}
impl Index for String {
fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
self[..].index_into(v)
}
fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
self[..].index_into_mut(v)
}
fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
self[..].index_or_insert(v)
}
}
impl<'a, T: ?Sized> Index for &'a T
where
T: Index,
{
fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
(**self).index_into(v)
}
fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
(**self).index_into_mut(v)
}
fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
(**self).index_or_insert(v)
}
}
// Prevent users from implementing the Index trait.
mod private {
pub trait Sealed {}
impl Sealed for usize {}
impl Sealed for str {}
impl Sealed for String {}
impl<'a, T: ?Sized> Sealed for &'a T where T: Sealed {}
}
/// Used in panic messages.
struct Type<'a>(&'a Value);
impl<'a> fmt::Display for Type<'a> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match *self.0 {
Value::Null => formatter.write_str("null"),
Value::Bool(_) => formatter.write_str("boolean"),
Value::Number(_) => formatter.write_str("number"),
Value::String(_) => formatter.write_str("string"),
Value::Array(_) => formatter.write_str("array"),
Value::Object(_) => formatter.write_str("object"),
}
}
}
// The usual semantics of Index is to panic on invalid indexing.
//
// That said, the usual semantics are for things like Vec and BTreeMap which
// have different use cases than Value. If you are working with a Vec, you know
// that you are working with a Vec and you can get the len of the Vec and make
// sure your indices are within bounds. The Value use cases are more
// loosey-goosey. You got some JSON from an endpoint and you want to pull values
// out of it. Outside of this Index impl, you already have the option of using
// value.as_array() and working with the Vec directly, or matching on
// Value::Array and getting the Vec directly. The Index impl means you can skip
// that and index directly into the thing using a concise syntax. You don't have
// to check the type, you don't have to check the len, it is all about what you
// expect the Value to look like.
//
// Basically the use cases that would be well served by panicking here are
// better served by using one of the other approaches: get and get_mut,
// as_array, or match. The value of this impl is that it adds a way of working
// with Value that is not well served by the existing approaches: concise and
// careless and sometimes that is exactly what you want.
impl<I> ops::Index<I> for Value
where
I: Index,
{
type Output = Value;
/// Index into a `serde_json::Value` using the syntax `value[0]` or
/// `value["k"]`.
///
/// Returns `Value::Null` if the type of `self` does not match the type of
/// the index, for example if the index is a string and `self` is an array
/// or a number. Also returns `Value::Null` if the given key does not exist
/// in the map or the given index is not within the bounds of the array.
///
/// For retrieving deeply nested values, you should have a look at the
/// `Value::pointer` method.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// let data = json!({
/// "x": {
/// "y": ["z", "zz"]
/// }
/// });
///
/// assert_eq!(data["x"]["y"], json!(["z", "zz"]));
/// assert_eq!(data["x"]["y"][0], json!("z"));
///
/// assert_eq!(data["a"], json!(null)); // returns null for undefined values
/// assert_eq!(data["a"]["b"], json!(null)); // does not panic
/// # }
/// ```
fn index(&self, index: I) -> &Value {
static NULL: Value = Value::Null;
index.index_into(self).unwrap_or(&NULL)
}
}
impl<I> ops::IndexMut<I> for Value
where
I: Index,
{
/// Write into a `serde_json::Value` using the syntax `value[0] = ...` or
/// `value["k"] = ...`.
///
/// If the index is a number, the value must be an array of length bigger
/// than the index. Indexing into a value that is not an array or an array
/// that is too small will panic.
///
/// If the index is a string, the value must be an object or null which is
/// treated like an empty object. If the key is not already present in the
/// object, it will be inserted with a value of null. Indexing into a value
/// that is neither an object nor null will panic.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde_json;
/// #
/// # fn main() {
/// let mut data = json!({ "x": 0 });
///
/// // replace an existing key
/// data["x"] = json!(1);
///
/// // insert a new key
/// data["y"] = json!([false, false, false]);
///
/// // replace an array value
/// data["y"][0] = json!(true);
///
/// // inserted a deeply nested key
/// data["a"]["b"]["c"]["d"] = json!(true);
///
/// println!("{}", data);
/// # }
/// ```
fn index_mut(&mut self, index: I) -> &mut Value {
index.index_or_insert(self)
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,102 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use super::Value;
fn eq_i64(value: &Value, other: i64) -> bool {
value.as_i64().map_or(false, |i| i == other)
}
fn eq_u64(value: &Value, other: u64) -> bool {
value.as_u64().map_or(false, |i| i == other)
}
fn eq_f64(value: &Value, other: f64) -> bool {
value.as_f64().map_or(false, |i| i == other)
}
fn eq_bool(value: &Value, other: bool) -> bool {
value.as_bool().map_or(false, |i| i == other)
}
fn eq_str(value: &Value, other: &str) -> bool {
value.as_str().map_or(false, |i| i == other)
}
impl PartialEq<str> for Value {
fn eq(&self, other: &str) -> bool {
eq_str(self, other)
}
}
impl<'a> PartialEq<&'a str> for Value {
fn eq(&self, other: &&str) -> bool {
eq_str(self, *other)
}
}
impl PartialEq<Value> for str {
fn eq(&self, other: &Value) -> bool {
eq_str(other, self)
}
}
impl<'a> PartialEq<Value> for &'a str {
fn eq(&self, other: &Value) -> bool {
eq_str(other, *self)
}
}
impl PartialEq<String> for Value {
fn eq(&self, other: &String) -> bool {
eq_str(self, other.as_str())
}
}
impl PartialEq<Value> for String {
fn eq(&self, other: &Value) -> bool {
eq_str(other, self.as_str())
}
}
macro_rules! partialeq_numeric {
($($eq:ident [$($ty:ty)*])*) => {
$($(
impl PartialEq<$ty> for Value {
fn eq(&self, other: &$ty) -> bool {
$eq(self, *other as _)
}
}
impl PartialEq<Value> for $ty {
fn eq(&self, other: &Value) -> bool {
$eq(other, *self as _)
}
}
impl<'a> PartialEq<$ty> for &'a Value {
fn eq(&self, other: &$ty) -> bool {
$eq(*self, *other as _)
}
}
impl<'a> PartialEq<$ty> for &'a mut Value {
fn eq(&self, other: &$ty) -> bool {
$eq(*self, *other as _)
}
}
)*)*
}
}
partialeq_numeric! {
eq_i64[i8 i16 i32 i64 isize]
eq_u64[u8 u16 u32 u64 usize]
eq_f64[f32 f64]
eq_bool[bool]
}

View File

@ -0,0 +1,827 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use serde::ser::Impossible;
use serde::{self, Serialize};
use error::{Error, ErrorCode};
use map::Map;
use number::Number;
use value::{to_value, Value};
#[cfg(feature = "arbitrary_precision")]
use serde::ser;
#[cfg(feature = "arbitrary_precision")]
use number::{SERDE_STRUCT_FIELD_NAME, SERDE_STRUCT_NAME};
impl Serialize for Value {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ::serde::Serializer,
{
match *self {
Value::Null => serializer.serialize_unit(),
Value::Bool(b) => serializer.serialize_bool(b),
Value::Number(ref n) => n.serialize(serializer),
Value::String(ref s) => serializer.serialize_str(s),
Value::Array(ref v) => v.serialize(serializer),
Value::Object(ref m) => {
use serde::ser::SerializeMap;
let mut map = try!(serializer.serialize_map(Some(m.len())));
for (k, v) in m {
try!(map.serialize_key(k));
try!(map.serialize_value(v));
}
map.end()
}
}
}
}
pub struct Serializer;
impl serde::Serializer for Serializer {
type Ok = Value;
type Error = Error;
type SerializeSeq = SerializeVec;
type SerializeTuple = SerializeVec;
type SerializeTupleStruct = SerializeVec;
type SerializeTupleVariant = SerializeTupleVariant;
type SerializeMap = SerializeMap;
type SerializeStruct = SerializeMap;
type SerializeStructVariant = SerializeStructVariant;
#[inline]
fn serialize_bool(self, value: bool) -> Result<Value, Error> {
Ok(Value::Bool(value))
}
#[inline]
fn serialize_i8(self, value: i8) -> Result<Value, Error> {
self.serialize_i64(value as i64)
}
#[inline]
fn serialize_i16(self, value: i16) -> Result<Value, Error> {
self.serialize_i64(value as i64)
}
#[inline]
fn serialize_i32(self, value: i32) -> Result<Value, Error> {
self.serialize_i64(value as i64)
}
fn serialize_i64(self, value: i64) -> Result<Value, Error> {
Ok(Value::Number(value.into()))
}
#[inline]
fn serialize_u8(self, value: u8) -> Result<Value, Error> {
self.serialize_u64(value as u64)
}
#[inline]
fn serialize_u16(self, value: u16) -> Result<Value, Error> {
self.serialize_u64(value as u64)
}
#[inline]
fn serialize_u32(self, value: u32) -> Result<Value, Error> {
self.serialize_u64(value as u64)
}
#[inline]
fn serialize_u64(self, value: u64) -> Result<Value, Error> {
Ok(Value::Number(value.into()))
}
#[inline]
fn serialize_f32(self, value: f32) -> Result<Value, Error> {
self.serialize_f64(value as f64)
}
#[inline]
fn serialize_f64(self, value: f64) -> Result<Value, Error> {
Ok(Number::from_f64(value).map_or(Value::Null, Value::Number))
}
#[inline]
fn serialize_char(self, value: char) -> Result<Value, Error> {
let mut s = String::new();
s.push(value);
self.serialize_str(&s)
}
#[inline]
fn serialize_str(self, value: &str) -> Result<Value, Error> {
Ok(Value::String(value.to_owned()))
}
fn serialize_bytes(self, value: &[u8]) -> Result<Value, Error> {
let vec = value.iter().map(|&b| Value::Number(b.into())).collect();
Ok(Value::Array(vec))
}
#[inline]
fn serialize_unit(self) -> Result<Value, Error> {
Ok(Value::Null)
}
#[inline]
fn serialize_unit_struct(self, _name: &'static str) -> Result<Value, Error> {
self.serialize_unit()
}
#[inline]
fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
) -> Result<Value, Error> {
self.serialize_str(variant)
}
#[inline]
fn serialize_newtype_struct<T: ?Sized>(
self,
_name: &'static str,
value: &T,
) -> Result<Value, Error>
where
T: Serialize,
{
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
value: &T,
) -> Result<Value, Error>
where
T: Serialize,
{
let mut values = Map::new();
values.insert(String::from(variant), try!(to_value(&value)));
Ok(Value::Object(values))
}
#[inline]
fn serialize_none(self) -> Result<Value, Error> {
self.serialize_unit()
}
#[inline]
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Value, Error>
where
T: Serialize,
{
value.serialize(self)
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Error> {
Ok(SerializeVec {
vec: Vec::with_capacity(len.unwrap_or(0)),
})
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Error> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_struct(
self,
_name: &'static str,
len: usize,
) -> Result<Self::SerializeTupleStruct, Error> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeTupleVariant, Error> {
Ok(SerializeTupleVariant {
name: String::from(variant),
vec: Vec::with_capacity(len),
})
}
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Error> {
Ok(SerializeMap::Map {
map: Map::new(),
next_key: None,
})
}
#[cfg(not(feature = "arbitrary_precision"))]
fn serialize_struct(
self,
_name: &'static str,
len: usize,
) -> Result<Self::SerializeStruct, Error> {
self.serialize_map(Some(len))
}
#[cfg(feature = "arbitrary_precision")]
fn serialize_struct(
self,
name: &'static str,
len: usize,
) -> Result<Self::SerializeStruct, Error> {
if name == SERDE_STRUCT_NAME {
Ok(SerializeMap::Number { out_value: None })
} else {
self.serialize_map(Some(len))
}
}
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant, Error> {
Ok(SerializeStructVariant {
name: String::from(variant),
map: Map::new(),
})
}
}
pub struct SerializeVec {
vec: Vec<Value>,
}
pub struct SerializeTupleVariant {
name: String,
vec: Vec<Value>,
}
pub enum SerializeMap {
Map {
map: Map<String, Value>,
next_key: Option<String>,
},
#[cfg(feature = "arbitrary_precision")]
Number { out_value: Option<Value> },
}
pub struct SerializeStructVariant {
name: String,
map: Map<String, Value>,
}
impl serde::ser::SerializeSeq for SerializeVec {
type Ok = Value;
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
self.vec.push(try!(to_value(&value)));
Ok(())
}
fn end(self) -> Result<Value, Error> {
Ok(Value::Array(self.vec))
}
}
impl serde::ser::SerializeTuple for SerializeVec {
type Ok = Value;
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
serde::ser::SerializeSeq::serialize_element(self, value)
}
fn end(self) -> Result<Value, Error> {
serde::ser::SerializeSeq::end(self)
}
}
impl serde::ser::SerializeTupleStruct for SerializeVec {
type Ok = Value;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
serde::ser::SerializeSeq::serialize_element(self, value)
}
fn end(self) -> Result<Value, Error> {
serde::ser::SerializeSeq::end(self)
}
}
impl serde::ser::SerializeTupleVariant for SerializeTupleVariant {
type Ok = Value;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
self.vec.push(try!(to_value(&value)));
Ok(())
}
fn end(self) -> Result<Value, Error> {
let mut object = Map::new();
object.insert(self.name, Value::Array(self.vec));
Ok(Value::Object(object))
}
}
impl serde::ser::SerializeMap for SerializeMap {
type Ok = Value;
type Error = Error;
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Error>
where
T: Serialize,
{
match *self {
SerializeMap::Map {
ref mut next_key, ..
} => {
*next_key = Some(try!(key.serialize(MapKeySerializer)));
Ok(())
}
#[cfg(feature = "arbitrary_precision")]
SerializeMap::Number { .. } => unreachable!(),
}
}
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
match *self {
SerializeMap::Map {
ref mut map,
ref mut next_key,
} => {
let key = next_key.take();
// Panic because this indicates a bug in the program rather than an
// expected failure.
let key = key.expect("serialize_value called before serialize_key");
map.insert(key, try!(to_value(&value)));
Ok(())
}
#[cfg(feature = "arbitrary_precision")]
SerializeMap::Number { .. } => unreachable!(),
}
}
fn end(self) -> Result<Value, Error> {
match self {
SerializeMap::Map { map, .. } => Ok(Value::Object(map)),
#[cfg(feature = "arbitrary_precision")]
SerializeMap::Number { .. } => unreachable!(),
}
}
}
struct MapKeySerializer;
fn key_must_be_a_string() -> Error {
Error::syntax(ErrorCode::KeyMustBeAString, 0, 0)
}
impl serde::Serializer for MapKeySerializer {
type Ok = String;
type Error = Error;
type SerializeSeq = Impossible<String, Error>;
type SerializeTuple = Impossible<String, Error>;
type SerializeTupleStruct = Impossible<String, Error>;
type SerializeTupleVariant = Impossible<String, Error>;
type SerializeMap = Impossible<String, Error>;
type SerializeStruct = Impossible<String, Error>;
type SerializeStructVariant = Impossible<String, Error>;
#[inline]
fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
) -> Result<Self::Ok, Self::Error> {
Ok(variant.to_owned())
}
#[inline]
fn serialize_newtype_struct<T: ?Sized>(
self,
_name: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
{
value.serialize(self)
}
fn serialize_bool(self, _value: bool) -> Result<Self::Ok, Self::Error> {
Err(key_must_be_a_string())
}
fn serialize_i8(self, value: i8) -> Result<Self::Ok, Self::Error> {
Ok(value.to_string())
}
fn serialize_i16(self, value: i16) -> Result<Self::Ok, Self::Error> {
Ok(value.to_string())
}
fn serialize_i32(self, value: i32) -> Result<Self::Ok, Self::Error> {
Ok(value.to_string())
}
fn serialize_i64(self, value: i64) -> Result<Self::Ok, Self::Error> {
Ok(value.to_string())
}
fn serialize_u8(self, value: u8) -> Result<Self::Ok, Self::Error> {
Ok(value.to_string())
}
fn serialize_u16(self, value: u16) -> Result<Self::Ok, Self::Error> {
Ok(value.to_string())
}
fn serialize_u32(self, value: u32) -> Result<Self::Ok, Self::Error> {
Ok(value.to_string())
}
fn serialize_u64(self, value: u64) -> Result<Self::Ok, Self::Error> {
Ok(value.to_string())
}
fn serialize_f32(self, _value: f32) -> Result<Self::Ok, Self::Error> {
Err(key_must_be_a_string())
}
fn serialize_f64(self, _value: f64) -> Result<Self::Ok, Self::Error> {
Err(key_must_be_a_string())
}
#[inline]
fn serialize_char(self, value: char) -> Result<Self::Ok, Self::Error> {
Ok({
let mut s = String::new();
s.push(value);
s
})
}
#[inline]
fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error> {
Ok(value.to_owned())
}
fn serialize_bytes(self, _value: &[u8]) -> Result<Self::Ok, Self::Error> {
Err(key_must_be_a_string())
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Err(key_must_be_a_string())
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
Err(key_must_be_a_string())
}
fn serialize_newtype_variant<T: ?Sized>(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
{
Err(key_must_be_a_string())
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Err(key_must_be_a_string())
}
fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
{
Err(key_must_be_a_string())
}
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Err(key_must_be_a_string())
}
fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
Err(key_must_be_a_string())
}
fn serialize_tuple_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
Err(key_must_be_a_string())
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
Err(key_must_be_a_string())
}
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
Err(key_must_be_a_string())
}
fn serialize_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
Err(key_must_be_a_string())
}
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
Err(key_must_be_a_string())
}
}
impl serde::ser::SerializeStruct for SerializeMap {
type Ok = Value;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
where
T: Serialize,
{
match *self {
SerializeMap::Map { .. } => {
try!(serde::ser::SerializeMap::serialize_key(self, key));
serde::ser::SerializeMap::serialize_value(self, value)
}
#[cfg(feature = "arbitrary_precision")]
SerializeMap::Number { ref mut out_value } => {
if key == SERDE_STRUCT_FIELD_NAME {
*out_value = Some(value.serialize(NumberValueEmitter)?);
Ok(())
} else {
Err(invalid_number())
}
}
}
}
fn end(self) -> Result<Value, Error> {
match self {
SerializeMap::Map { .. } => serde::ser::SerializeMap::end(self),
#[cfg(feature = "arbitrary_precision")]
SerializeMap::Number { out_value, .. } => {
Ok(out_value.expect("number value was not emitted"))
}
}
}
}
impl serde::ser::SerializeStructVariant for SerializeStructVariant {
type Ok = Value;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
where
T: Serialize,
{
self.map.insert(String::from(key), try!(to_value(&value)));
Ok(())
}
fn end(self) -> Result<Value, Error> {
let mut object = Map::new();
object.insert(self.name, Value::Object(self.map));
Ok(Value::Object(object))
}
}
#[cfg(feature = "arbitrary_precision")]
struct NumberValueEmitter;
#[cfg(feature = "arbitrary_precision")]
fn invalid_number() -> Error {
Error::syntax(ErrorCode::InvalidNumber, 0, 0)
}
#[cfg(feature = "arbitrary_precision")]
impl ser::Serializer for NumberValueEmitter {
type Ok = Value;
type Error = Error;
type SerializeSeq = Impossible<Value, Error>;
type SerializeTuple = Impossible<Value, Error>;
type SerializeTupleStruct = Impossible<Value, Error>;
type SerializeTupleVariant = Impossible<Value, Error>;
type SerializeMap = Impossible<Value, Error>;
type SerializeStruct = Impossible<Value, Error>;
type SerializeStructVariant = Impossible<Value, Error>;
fn serialize_bool(self, _v: bool) -> Result<Self::Ok, Self::Error> {
Err(invalid_number())
}
fn serialize_i8(self, _v: i8) -> Result<Self::Ok, Self::Error> {
Err(invalid_number())
}
fn serialize_i16(self, _v: i16) -> Result<Self::Ok, Self::Error> {
Err(invalid_number())
}
fn serialize_i32(self, _v: i32) -> Result<Self::Ok, Self::Error> {
Err(invalid_number())
}
fn serialize_i64(self, _v: i64) -> Result<Self::Ok, Self::Error> {
Err(invalid_number())
}
fn serialize_u8(self, _v: u8) -> Result<Self::Ok, Self::Error> {
Err(invalid_number())
}
fn serialize_u16(self, _v: u16) -> Result<Self::Ok, Self::Error> {
Err(invalid_number())
}
fn serialize_u32(self, _v: u32) -> Result<Self::Ok, Self::Error> {
Err(invalid_number())
}
fn serialize_u64(self, _v: u64) -> Result<Self::Ok, Self::Error> {
Err(invalid_number())
}
fn serialize_f32(self, _v: f32) -> Result<Self::Ok, Self::Error> {
Err(invalid_number())
}
fn serialize_f64(self, _v: f64) -> Result<Self::Ok, Self::Error> {
Err(invalid_number())
}
fn serialize_char(self, _v: char) -> Result<Self::Ok, Self::Error> {
Err(invalid_number())
}
fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error> {
let n = try!(value.to_owned().parse());
Ok(Value::Number(n))
}
fn serialize_bytes(self, _value: &[u8]) -> Result<Self::Ok, Self::Error> {
Err(invalid_number())
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Err(invalid_number())
}
fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
{
Err(invalid_number())
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Err(invalid_number())
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
Err(invalid_number())
}
fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
) -> Result<Self::Ok, Self::Error> {
Err(invalid_number())
}
fn serialize_newtype_struct<T: ?Sized>(
self,
_name: &'static str,
_value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
{
Err(invalid_number())
}
fn serialize_newtype_variant<T: ?Sized>(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: Serialize,
{
Err(invalid_number())
}
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Err(invalid_number())
}
fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
Err(invalid_number())
}
fn serialize_tuple_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
Err(invalid_number())
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
Err(invalid_number())
}
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
Err(invalid_number())
}
fn serialize_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
Err(invalid_number())
}
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
Err(invalid_number())
}
}