Bug 1669055: Vendor Cranelift e22e2c3722f2fbccd3c8d3230119fa04c332c69c. r=jseward

This patch pulls in an updated Cranelift with a new validation strategy,
introduced by bytecodealliance/wasmtime#2059. This new design validates
the Wasm module as it parses the function bodies. A subsequent patch
will adapt Baldrdash to work with this.

Differential Revision: https://phabricator.services.mozilla.com/D92503
This commit is contained in:
Chris Fallin 2020-10-07 06:25:50 +00:00
Родитель a82c2aca89
Коммит 7a5957abe6
141 изменённых файлов: 18512 добавлений и 4387 удалений

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

@ -60,7 +60,7 @@ rev = "3224e2dee65c0726c448484d4c3c43956b9330ec"
[source."https://github.com/bytecodealliance/wasmtime"]
git = "https://github.com/bytecodealliance/wasmtime"
replace-with = "vendored-sources"
rev = "57fed697920cb888c6cb7e406d13518f7edd12ea"
rev = "e22e2c3722f2fbccd3c8d3230119fa04c332c69c"
[source."https://github.com/badboy/failure"]
git = "https://github.com/badboy/failure"

34
Cargo.lock сгенерированный
Просмотреть файл

@ -762,7 +762,7 @@ dependencies = [
[[package]]
name = "cranelift-bforest"
version = "0.67.0"
source = "git+https://github.com/bytecodealliance/wasmtime?rev=57fed697920cb888c6cb7e406d13518f7edd12ea#57fed697920cb888c6cb7e406d13518f7edd12ea"
source = "git+https://github.com/bytecodealliance/wasmtime?rev=e22e2c3722f2fbccd3c8d3230119fa04c332c69c#e22e2c3722f2fbccd3c8d3230119fa04c332c69c"
dependencies = [
"cranelift-entity 0.67.0",
]
@ -770,7 +770,7 @@ dependencies = [
[[package]]
name = "cranelift-codegen"
version = "0.67.0"
source = "git+https://github.com/bytecodealliance/wasmtime?rev=57fed697920cb888c6cb7e406d13518f7edd12ea#57fed697920cb888c6cb7e406d13518f7edd12ea"
source = "git+https://github.com/bytecodealliance/wasmtime?rev=e22e2c3722f2fbccd3c8d3230119fa04c332c69c#e22e2c3722f2fbccd3c8d3230119fa04c332c69c"
dependencies = [
"byteorder",
"cranelift-bforest",
@ -787,7 +787,7 @@ dependencies = [
[[package]]
name = "cranelift-codegen-meta"
version = "0.67.0"
source = "git+https://github.com/bytecodealliance/wasmtime?rev=57fed697920cb888c6cb7e406d13518f7edd12ea#57fed697920cb888c6cb7e406d13518f7edd12ea"
source = "git+https://github.com/bytecodealliance/wasmtime?rev=e22e2c3722f2fbccd3c8d3230119fa04c332c69c#e22e2c3722f2fbccd3c8d3230119fa04c332c69c"
dependencies = [
"cranelift-codegen-shared",
"cranelift-entity 0.67.0",
@ -796,7 +796,7 @@ dependencies = [
[[package]]
name = "cranelift-codegen-shared"
version = "0.67.0"
source = "git+https://github.com/bytecodealliance/wasmtime?rev=57fed697920cb888c6cb7e406d13518f7edd12ea#57fed697920cb888c6cb7e406d13518f7edd12ea"
source = "git+https://github.com/bytecodealliance/wasmtime?rev=e22e2c3722f2fbccd3c8d3230119fa04c332c69c#e22e2c3722f2fbccd3c8d3230119fa04c332c69c"
[[package]]
name = "cranelift-entity"
@ -806,12 +806,12 @@ source = "git+https://github.com/PLSysSec/lucet_sandbox_compiler?rev=477d8fc53a6
[[package]]
name = "cranelift-entity"
version = "0.67.0"
source = "git+https://github.com/bytecodealliance/wasmtime?rev=57fed697920cb888c6cb7e406d13518f7edd12ea#57fed697920cb888c6cb7e406d13518f7edd12ea"
source = "git+https://github.com/bytecodealliance/wasmtime?rev=e22e2c3722f2fbccd3c8d3230119fa04c332c69c#e22e2c3722f2fbccd3c8d3230119fa04c332c69c"
[[package]]
name = "cranelift-frontend"
version = "0.67.0"
source = "git+https://github.com/bytecodealliance/wasmtime?rev=57fed697920cb888c6cb7e406d13518f7edd12ea#57fed697920cb888c6cb7e406d13518f7edd12ea"
source = "git+https://github.com/bytecodealliance/wasmtime?rev=e22e2c3722f2fbccd3c8d3230119fa04c332c69c#e22e2c3722f2fbccd3c8d3230119fa04c332c69c"
dependencies = [
"cranelift-codegen",
"log",
@ -822,14 +822,15 @@ dependencies = [
[[package]]
name = "cranelift-wasm"
version = "0.67.0"
source = "git+https://github.com/bytecodealliance/wasmtime?rev=57fed697920cb888c6cb7e406d13518f7edd12ea#57fed697920cb888c6cb7e406d13518f7edd12ea"
source = "git+https://github.com/bytecodealliance/wasmtime?rev=e22e2c3722f2fbccd3c8d3230119fa04c332c69c#e22e2c3722f2fbccd3c8d3230119fa04c332c69c"
dependencies = [
"cranelift-codegen",
"cranelift-entity 0.67.0",
"cranelift-frontend",
"itertools 0.9.0",
"log",
"thiserror",
"wasmparser 0.59.0",
"wasmparser 0.63.0",
]
[[package]]
@ -2422,6 +2423,15 @@ dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "0.4.4"
@ -3884,7 +3894,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "537aa19b95acde10a12fec4301466386f757403de4cd4e5b4fa78fb5ecb18f72"
dependencies = [
"anyhow",
"itertools",
"itertools 0.8.0",
"proc-macro2",
"quote",
"syn",
@ -4738,7 +4748,7 @@ dependencies = [
"hashbrown",
"hashglobe",
"indexmap",
"itertools",
"itertools 0.8.0",
"itoa",
"lazy_static",
"log",
@ -5551,9 +5561,9 @@ checksum = "073da89bf1c84db000dd68ce660c1b4a08e3a2d28fd1e3394ab9e7abdde4a0f8"
[[package]]
name = "wasmparser"
version = "0.59.0"
version = "0.63.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a950e6a618f62147fd514ff445b2a0b53120d382751960797f85f058c7eda9b9"
checksum = "57da5d7300428d75d8b3cdfb736e41ee6af8926d69c1de2f201a1a22f234b7b5"
[[package]]
name = "wast"

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

@ -75,8 +75,8 @@ failure_derive = { git = "https://github.com/badboy/failure", rev = "64af847bc5f
[patch.crates-io.cranelift-codegen]
git = "https://github.com/bytecodealliance/wasmtime"
rev = "57fed697920cb888c6cb7e406d13518f7edd12ea"
rev = "e22e2c3722f2fbccd3c8d3230119fa04c332c69c"
[patch.crates-io.cranelift-wasm]
git = "https://github.com/bytecodealliance/wasmtime"
rev = "57fed697920cb888c6cb7e406d13518f7edd12ea"
rev = "e22e2c3722f2fbccd3c8d3230119fa04c332c69c"

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

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

@ -30,7 +30,7 @@ peepmatic-traits = { path = "../peepmatic/crates/traits", optional = true, versi
peepmatic-runtime = { path = "../peepmatic/crates/runtime", optional = true, version = "0.67.0" }
regalloc = "0.0.30"
souper-ir = { version = "1", optional = true }
wast = { version = "22.0.0", optional = true }
wast = { version = "25.0.0", optional = true }
# It is a goal of the cranelift-codegen crate to have minimal external dependencies.
# Please don't add any unless they are essential to the task of creating binary
# machine code. Integration tests that need external dependencies can be

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

@ -476,7 +476,7 @@ pub(crate) fn emit(
state: &mut EmitState,
) {
match inst {
Inst::Alu_RMI_R {
Inst::AluRmiR {
is_64,
op,
src,
@ -517,8 +517,8 @@ pub(crate) fn emit(
}
RegMemImm::Imm { simm32 } => {
let useImm8 = low8_will_sign_extend_to_32(*simm32);
let opcode = if useImm8 { 0x6B } else { 0x69 };
let use_imm8 = low8_will_sign_extend_to_32(*simm32);
let opcode = if use_imm8 { 0x6B } else { 0x69 };
// Yes, really, reg_g twice.
emit_std_reg_reg(
sink,
@ -529,7 +529,7 @@ pub(crate) fn emit(
reg_g.to_reg(),
rex,
);
emit_simm(sink, if useImm8 { 1 } else { 4 }, *simm32);
emit_simm(sink, if use_imm8 { 1 } else { 4 }, *simm32);
}
}
} else {
@ -891,7 +891,7 @@ pub(crate) fn emit(
}
}
Inst::Mov_R_R { is_64, src, dst } => {
Inst::MovRR { is_64, src, dst } => {
let rex = if *is_64 {
RexFlags::set_w()
} else {
@ -900,7 +900,7 @@ pub(crate) fn emit(
emit_std_reg_reg(sink, LegacyPrefixes::None, 0x89, 1, *src, dst.to_reg(), rex);
}
Inst::MovZX_RM_R {
Inst::MovzxRmR {
ext_mode,
src,
dst,
@ -981,7 +981,7 @@ pub(crate) fn emit(
}
}
Inst::Mov64_M_R { src, dst, srcloc } => {
Inst::Mov64MR { src, dst, srcloc } => {
let src = &src.finalize(state);
if let Some(srcloc) = *srcloc {
@ -1010,7 +1010,7 @@ pub(crate) fn emit(
RexFlags::set_w(),
),
Inst::MovSX_RM_R {
Inst::MovsxRmR {
ext_mode,
src,
dst,
@ -1083,7 +1083,7 @@ pub(crate) fn emit(
}
}
Inst::Mov_R_M {
Inst::MovRM {
size,
src,
dst,
@ -1155,7 +1155,7 @@ pub(crate) fn emit(
}
}
Inst::Shift_R {
Inst::ShiftR {
size,
kind,
num_bits,
@ -1255,7 +1255,7 @@ pub(crate) fn emit(
};
}
Inst::Cmp_RMI_R {
Inst::CmpRmiR {
size,
src: src_e,
dst: reg_g,
@ -1424,13 +1424,12 @@ pub(crate) fn emit(
}
Inst::Pop64 { dst } => {
let encDst = int_reg_enc(dst.to_reg());
if encDst >= 8 {
// 0x41 == REX.{W=0, B=1}. It seems that REX.W is irrelevant
// here.
let enc_dst = int_reg_enc(dst.to_reg());
if enc_dst >= 8 {
// 0x41 == REX.{W=0, B=1}. It seems that REX.W is irrelevant here.
sink.put1(0x41);
}
sink.put1(0x58 + (encDst & 7));
sink.put1(0x58 + (enc_dst & 7));
}
Inst::CallKnown {
@ -1741,7 +1740,7 @@ pub(crate) fn emit(
};
}
Inst::XMM_RM_R {
Inst::XmmRmR {
op,
src: src_e,
dst: reg_g,
@ -2008,7 +2007,7 @@ pub(crate) fn emit(
// emitted.
}
Inst::Xmm_Mov_R_M {
Inst::XmmMovRM {
op,
src,
dst,
@ -2090,7 +2089,7 @@ pub(crate) fn emit(
}
}
Inst::XMM_Cmp_RM_R { op, src, dst } => {
Inst::XmmCmpRmR { op, src, dst } => {
let rex = RexFlags::clear_w();
let (prefix, opcode, len) = match op {
SseOpcode::Ptest => (LegacyPrefixes::_66, 0x0F3817, 3),

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

@ -1,7 +1,5 @@
//! This module defines x86_64-specific machine instruction types.
#![allow(dead_code)]
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
use crate::binemit::{CodeOffset, StackMap};
use crate::ir::{types, ExternalName, Opcode, SourceLoc, TrapCode, Type};
@ -34,13 +32,13 @@ use regs::{create_reg_universe_systemv, show_ireg_sized};
/// Instructions. Destinations are on the RIGHT (a la AT&T syntax).
#[derive(Clone)]
pub enum Inst {
/// nops of various sizes, including zero
/// Nops of various sizes, including zero.
Nop { len: u8 },
// =====================================
// Integer instructions.
/// Integer arithmetic/bit-twiddling: (add sub and or xor mul adc? sbb?) (32 64) (reg addr imm) reg
Alu_RMI_R {
AluRmiR {
is_64: bool,
op: AluRmiROpcode,
src: RegMemImm,
@ -114,7 +112,7 @@ pub enum Inst {
},
/// GPR to GPR move: mov (64 32) reg reg.
Mov_R_R {
MovRR {
is_64: bool,
src: Reg,
dst: Writable<Reg>,
@ -123,7 +121,7 @@ pub enum Inst {
/// Zero-extended loads, except for 64 bits: movz (bl bq wl wq lq) addr reg.
/// Note that the lq variant doesn't really exist since the default zero-extend rule makes it
/// unnecessary. For that case we emit the equivalent "movl AM, reg32".
MovZX_RM_R {
MovzxRmR {
ext_mode: ExtMode,
src: RegMem,
dst: Writable<Reg>,
@ -132,7 +130,7 @@ pub enum Inst {
},
/// A plain 64-bit integer load, since MovZX_RM_R can't represent that.
Mov64_M_R {
Mov64MR {
src: SyntheticAmode,
dst: Writable<Reg>,
/// Source location, if the memory access can be out-of-bounds.
@ -146,7 +144,7 @@ pub enum Inst {
},
/// Sign-extended loads and moves: movs (bl bq wl wq lq) addr reg.
MovSX_RM_R {
MovsxRmR {
ext_mode: ExtMode,
src: RegMem,
dst: Writable<Reg>,
@ -155,7 +153,7 @@ pub enum Inst {
},
/// Integer stores: mov (b w l q) reg addr.
Mov_R_M {
MovRM {
size: u8, // 1, 2, 4 or 8.
src: Reg,
dst: SyntheticAmode,
@ -164,7 +162,7 @@ pub enum Inst {
},
/// Arithmetic shifts: (shl shr sar) (b w l q) imm reg.
Shift_R {
ShiftR {
size: u8, // 1, 2, 4 or 8
kind: ShiftKind,
/// shift count: Some(0 .. #bits-in-type - 1), or None to mean "%cl".
@ -180,7 +178,7 @@ pub enum Inst {
},
/// Integer comparisons/tests: cmp (b w l q) (reg addr imm) reg.
Cmp_RMI_R {
CmpRmiR {
size: u8, // 1, 2, 4 or 8
src: RegMemImm,
dst: Reg,
@ -210,7 +208,7 @@ pub enum Inst {
// =====================================
// Floating-point operations.
/// XMM (scalar or vector) binary op: (add sub and or xor mul adc? sbb?) (32 64) (reg addr) reg
XMM_RM_R {
XmmRmR {
op: SseOpcode,
src: RegMem,
dst: Writable<Reg>,
@ -231,7 +229,7 @@ pub enum Inst {
},
/// XMM (scalar or vector) unary op (from xmm to reg/mem): stores, movd, movq
Xmm_Mov_R_M {
XmmMovRM {
op: SseOpcode,
src: Reg,
dst: SyntheticAmode,
@ -327,7 +325,7 @@ pub enum Inst {
},
/// Float comparisons/tests: cmp (b w l q) (reg addr imm) reg.
XMM_Cmp_RM_R {
XmmCmpRmR {
op: SseOpcode,
src: RegMem,
dst: Reg,
@ -519,7 +517,7 @@ impl Inst {
) -> Self {
src.assert_regclass_is(RegClass::I64);
debug_assert!(dst.to_reg().get_class() == RegClass::I64);
Self::Alu_RMI_R {
Self::AluRmiR {
is_64,
op,
src,
@ -609,7 +607,7 @@ impl Inst {
pub(crate) fn mov_r_r(is_64: bool, src: Reg, dst: Writable<Reg>) -> Inst {
debug_assert!(src.get_class() == RegClass::I64);
debug_assert!(dst.to_reg().get_class() == RegClass::I64);
Inst::Mov_R_R { is_64, src, dst }
Inst::MovRR { is_64, src, dst }
}
// TODO Can be replaced by `Inst::move` (high-level) and `Inst::unary_rm_r` (low-level)
@ -651,7 +649,7 @@ impl Inst {
pub(crate) fn xmm_rm_r(op: SseOpcode, src: RegMem, dst: Writable<Reg>) -> Self {
src.assert_regclass_is(RegClass::V128);
debug_assert!(dst.to_reg().get_class() == RegClass::V128);
Inst::XMM_RM_R { op, src, dst }
Inst::XmmRmR { op, src, dst }
}
pub(crate) fn xmm_uninit_value(dst: Writable<Reg>) -> Self {
@ -666,7 +664,7 @@ impl Inst {
srcloc: Option<SourceLoc>,
) -> Inst {
debug_assert!(src.get_class() == RegClass::V128);
Inst::Xmm_Mov_R_M {
Inst::XmmMovRM {
op,
src,
dst: dst.into(),
@ -709,7 +707,7 @@ impl Inst {
pub(crate) fn xmm_cmp_rm_r(op: SseOpcode, src: RegMem, dst: Reg) -> Inst {
src.assert_regclass_is(RegClass::V128);
debug_assert!(dst.get_class() == RegClass::V128);
Inst::XMM_Cmp_RM_R { op, src, dst }
Inst::XmmCmpRmR { op, src, dst }
}
pub(crate) fn cvt_u64_to_float_seq(
@ -824,7 +822,7 @@ impl Inst {
) -> Inst {
src.assert_regclass_is(RegClass::I64);
debug_assert!(dst.to_reg().get_class() == RegClass::I64);
Inst::MovZX_RM_R {
Inst::MovzxRmR {
ext_mode,
src,
dst,
@ -846,7 +844,7 @@ impl Inst {
) -> Inst {
src.assert_regclass_is(RegClass::I64);
debug_assert!(dst.to_reg().get_class() == RegClass::I64);
Inst::MovSX_RM_R {
Inst::MovsxRmR {
ext_mode,
src,
dst,
@ -860,7 +858,7 @@ impl Inst {
srcloc: Option<SourceLoc>,
) -> Inst {
debug_assert!(dst.to_reg().get_class() == RegClass::I64);
Inst::Mov64_M_R {
Inst::Mov64MR {
src: src.into(),
dst,
srcloc,
@ -884,7 +882,7 @@ impl Inst {
) -> Inst {
debug_assert!(size == 8 || size == 4 || size == 2 || size == 1);
debug_assert!(src.get_class() == RegClass::I64);
Inst::Mov_R_M {
Inst::MovRM {
size,
src,
dst: dst.into(),
@ -913,7 +911,7 @@ impl Inst {
true
});
debug_assert!(dst.to_reg().get_class() == RegClass::I64);
Inst::Shift_R {
Inst::ShiftR {
size,
kind,
num_bits,
@ -931,7 +929,7 @@ impl Inst {
src.assert_regclass_is(RegClass::I64);
debug_assert!(size == 8 || size == 4 || size == 2 || size == 1);
debug_assert!(dst.get_class() == RegClass::I64);
Inst::Cmp_RMI_R { size, src, dst }
Inst::CmpRmiR { size, src, dst }
}
pub(crate) fn trap(srcloc: SourceLoc, trap_code: TrapCode) -> Inst {
@ -1135,12 +1133,12 @@ impl Inst {
/// same as the first register (already handled).
fn produces_const(&self) -> bool {
match self {
Self::Alu_RMI_R { op, src, dst, .. } => {
Self::AluRmiR { op, src, dst, .. } => {
src.to_reg() == Some(dst.to_reg())
&& (*op == AluRmiROpcode::Xor || *op == AluRmiROpcode::Sub)
}
Self::XMM_RM_R { op, src, dst, .. } => {
Self::XmmRmR { op, src, dst, .. } => {
src.to_reg() == Some(dst.to_reg())
&& (*op == SseOpcode::Xorps
|| *op == SseOpcode::Xorpd
@ -1183,11 +1181,11 @@ impl ShowWithRRU for Inst {
ljustify(s1 + &s2)
}
fn suffixLQ(is_64: bool) -> String {
fn suffix_lq(is_64: bool) -> String {
(if is_64 { "q" } else { "l" }).to_string()
}
fn sizeLQ(is_64: bool) -> u8 {
fn size_lq(is_64: bool) -> u8 {
if is_64 {
8
} else {
@ -1195,7 +1193,7 @@ impl ShowWithRRU for Inst {
}
}
fn suffixBWLQ(size: u8) -> String {
fn suffix_bwlq(size: u8) -> String {
match size {
1 => "b".to_string(),
2 => "w".to_string(),
@ -1208,34 +1206,34 @@ impl ShowWithRRU for Inst {
match self {
Inst::Nop { len } => format!("{} len={}", ljustify("nop".to_string()), len),
Inst::Alu_RMI_R {
Inst::AluRmiR {
is_64,
op,
src,
dst,
} => format!(
"{} {}, {}",
ljustify2(op.to_string(), suffixLQ(*is_64)),
src.show_rru_sized(mb_rru, sizeLQ(*is_64)),
show_ireg_sized(dst.to_reg(), mb_rru, sizeLQ(*is_64)),
ljustify2(op.to_string(), suffix_lq(*is_64)),
src.show_rru_sized(mb_rru, size_lq(*is_64)),
show_ireg_sized(dst.to_reg(), mb_rru, size_lq(*is_64)),
),
Inst::UnaryRmR { src, dst, op, size } => format!(
"{} {}, {}",
ljustify2(op.to_string(), suffixBWLQ(*size)),
ljustify2(op.to_string(), suffix_bwlq(*size)),
src.show_rru_sized(mb_rru, *size),
show_ireg_sized(dst.to_reg(), mb_rru, *size),
),
Inst::Not { size, src } => format!(
"{} {}",
ljustify2("not".to_string(), suffixBWLQ(*size)),
ljustify2("not".to_string(), suffix_bwlq(*size)),
show_ireg_sized(src.to_reg(), mb_rru, *size)
),
Inst::Neg { size, src } => format!(
"{} {}",
ljustify2("neg".to_string(), suffixBWLQ(*size)),
ljustify2("neg".to_string(), suffix_bwlq(*size)),
show_ireg_sized(src.to_reg(), mb_rru, *size)
),
@ -1298,14 +1296,14 @@ impl ShowWithRRU for Inst {
show_ireg_sized(dst.to_reg(), mb_rru, 8),
),
Inst::Xmm_Mov_R_M { op, src, dst, .. } => format!(
Inst::XmmMovRM { op, src, dst, .. } => format!(
"{} {}, {}",
ljustify(op.to_string()),
show_ireg_sized(*src, mb_rru, 8),
dst.show_rru(mb_rru),
),
Inst::XMM_RM_R { op, src, dst } => format!(
Inst::XmmRmR { op, src, dst } => format!(
"{} {}, {}",
ljustify(op.to_string()),
src.show_rru_sized(mb_rru, 8),
@ -1383,7 +1381,7 @@ impl ShowWithRRU for Inst {
dst.show_rru(mb_rru)
),
Inst::XMM_Cmp_RM_R { op, src, dst } => format!(
Inst::XmmCmpRmR { op, src, dst } => format!(
"{} {}, {}",
ljustify(op.to_string()),
src.show_rru_sized(mb_rru, 8),
@ -1474,14 +1472,14 @@ impl ShowWithRRU for Inst {
}
}
Inst::Mov_R_R { is_64, src, dst } => format!(
Inst::MovRR { is_64, src, dst } => format!(
"{} {}, {}",
ljustify2("mov".to_string(), suffixLQ(*is_64)),
show_ireg_sized(*src, mb_rru, sizeLQ(*is_64)),
show_ireg_sized(dst.to_reg(), mb_rru, sizeLQ(*is_64))
ljustify2("mov".to_string(), suffix_lq(*is_64)),
show_ireg_sized(*src, mb_rru, size_lq(*is_64)),
show_ireg_sized(dst.to_reg(), mb_rru, size_lq(*is_64))
),
Inst::MovZX_RM_R {
Inst::MovzxRmR {
ext_mode, src, dst, ..
} => {
if *ext_mode == ExtMode::LQ {
@ -1501,7 +1499,7 @@ impl ShowWithRRU for Inst {
}
}
Inst::Mov64_M_R { src, dst, .. } => format!(
Inst::Mov64MR { src, dst, .. } => format!(
"{} {}, {}",
ljustify("movq".to_string()),
src.show_rru(mb_rru),
@ -1515,7 +1513,7 @@ impl ShowWithRRU for Inst {
dst.show_rru(mb_rru)
),
Inst::MovSX_RM_R {
Inst::MovsxRmR {
ext_mode, src, dst, ..
} => format!(
"{} {}, {}",
@ -1524,14 +1522,14 @@ impl ShowWithRRU for Inst {
show_ireg_sized(dst.to_reg(), mb_rru, ext_mode.dst_size())
),
Inst::Mov_R_M { size, src, dst, .. } => format!(
Inst::MovRM { size, src, dst, .. } => format!(
"{} {}, {}",
ljustify2("mov".to_string(), suffixBWLQ(*size)),
ljustify2("mov".to_string(), suffix_bwlq(*size)),
show_ireg_sized(*src, mb_rru, *size),
dst.show_rru(mb_rru)
),
Inst::Shift_R {
Inst::ShiftR {
size,
kind,
num_bits,
@ -1539,13 +1537,13 @@ impl ShowWithRRU for Inst {
} => match num_bits {
None => format!(
"{} %cl, {}",
ljustify2(kind.to_string(), suffixBWLQ(*size)),
ljustify2(kind.to_string(), suffix_bwlq(*size)),
show_ireg_sized(dst.to_reg(), mb_rru, *size)
),
Some(num_bits) => format!(
"{} ${}, {}",
ljustify2(kind.to_string(), suffixBWLQ(*size)),
ljustify2(kind.to_string(), suffix_bwlq(*size)),
num_bits,
show_ireg_sized(dst.to_reg(), mb_rru, *size)
),
@ -1558,9 +1556,9 @@ impl ShowWithRRU for Inst {
dst.to_reg().show_rru(mb_rru)
),
Inst::Cmp_RMI_R { size, src, dst } => format!(
Inst::CmpRmiR { size, src, dst } => format!(
"{} {}, {}",
ljustify2("cmp".to_string(), suffixBWLQ(*size)),
ljustify2("cmp".to_string(), suffix_bwlq(*size)),
src.show_rru_sized(mb_rru, *size),
show_ireg_sized(*dst, mb_rru, *size)
),
@ -1573,7 +1571,7 @@ impl ShowWithRRU for Inst {
Inst::Cmove { size, cc, src, dst } => format!(
"{} {}, {}",
ljustify(format!("cmov{}{}", cc.to_string(), suffixBWLQ(*size))),
ljustify(format!("cmov{}{}", cc.to_string(), suffix_bwlq(*size))),
src.show_rru_sized(mb_rru, *size),
show_ireg_sized(dst.to_reg(), mb_rru, *size)
),
@ -1662,7 +1660,7 @@ impl ShowWithRRU for Inst {
Inst::LockCmpxchg { ty, src, dst, .. } => {
let size = ty.bytes() as u8;
format!("lock cmpxchg{} {}, {}",
suffixBWLQ(size), show_ireg_sized(*src, mb_rru, size), dst.show_rru(mb_rru))
suffix_bwlq(size), show_ireg_sized(*src, mb_rru, size), dst.show_rru(mb_rru))
}
Inst::AtomicRmwSeq { ty, op, .. } => {
@ -1702,7 +1700,7 @@ fn x64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
// regalloc.rs will "fix" this for us by removing the the modified set from the use and def
// sets.
match inst {
Inst::Alu_RMI_R { src, dst, .. } => {
Inst::AluRmiR { src, dst, .. } => {
if inst.produces_const() {
// No need to account for src, since src == dst.
collector.add_def(*dst);
@ -1754,7 +1752,7 @@ fn x64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
src.get_regs_as_uses(collector);
collector.add_def(*dst);
}
Inst::XMM_RM_R { src, dst, .. } => {
Inst::XmmRmR { src, dst, .. } => {
if inst.produces_const() {
// No need to account for src, since src == dst.
collector.add_def(*dst);
@ -1789,18 +1787,18 @@ fn x64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
src.get_regs_as_uses(collector);
collector.add_mod(*dst);
}
Inst::Xmm_Mov_R_M { src, dst, .. } => {
Inst::XmmMovRM { src, dst, .. } => {
collector.add_use(*src);
dst.get_regs_as_uses(collector);
}
Inst::XMM_Cmp_RM_R { src, dst, .. } => {
Inst::XmmCmpRmR { src, dst, .. } => {
src.get_regs_as_uses(collector);
collector.add_use(*dst);
}
Inst::Imm { dst, .. } => {
collector.add_def(*dst);
}
Inst::Mov_R_R { src, dst, .. } | Inst::XmmToGpr { src, dst, .. } => {
Inst::MovRR { src, dst, .. } | Inst::XmmToGpr { src, dst, .. } => {
collector.add_use(*src);
collector.add_def(*dst);
}
@ -1839,29 +1837,29 @@ fn x64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
collector.add_def(*tmp_gpr);
collector.add_def(*tmp_xmm);
}
Inst::MovZX_RM_R { src, dst, .. } => {
Inst::MovzxRmR { src, dst, .. } => {
src.get_regs_as_uses(collector);
collector.add_def(*dst);
}
Inst::Mov64_M_R { src, dst, .. } | Inst::LoadEffectiveAddress { addr: src, dst } => {
Inst::Mov64MR { src, dst, .. } | Inst::LoadEffectiveAddress { addr: src, dst } => {
src.get_regs_as_uses(collector);
collector.add_def(*dst)
}
Inst::MovSX_RM_R { src, dst, .. } => {
Inst::MovsxRmR { src, dst, .. } => {
src.get_regs_as_uses(collector);
collector.add_def(*dst);
}
Inst::Mov_R_M { src, dst, .. } => {
Inst::MovRM { src, dst, .. } => {
collector.add_use(*src);
dst.get_regs_as_uses(collector);
}
Inst::Shift_R { num_bits, dst, .. } => {
Inst::ShiftR { num_bits, dst, .. } => {
if num_bits.is_none() {
collector.add_use(regs::rcx());
}
collector.add_mod(*dst);
}
Inst::Cmp_RMI_R { src, dst, .. } => {
Inst::CmpRmiR { src, dst, .. } => {
src.get_regs_as_uses(collector);
collector.add_use(*dst); // yes, really `add_use`
}
@ -2036,7 +2034,7 @@ fn x64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
match inst {
// ** Nop
Inst::Alu_RMI_R {
Inst::AluRmiR {
ref mut src,
ref mut dst,
..
@ -2093,7 +2091,7 @@ fn x64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
map_mod(mapper, dst);
}
}
Inst::XMM_RM_R {
Inst::XmmRmR {
ref mut src,
ref mut dst,
..
@ -2128,7 +2126,7 @@ fn x64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
map_use(mapper, lhs);
map_mod(mapper, rhs_dst);
}
Inst::Xmm_Mov_R_M {
Inst::XmmMovRM {
ref mut src,
ref mut dst,
..
@ -2136,7 +2134,7 @@ fn x64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
map_use(mapper, src);
dst.map_uses(mapper);
}
Inst::XMM_Cmp_RM_R {
Inst::XmmCmpRmR {
ref mut src,
ref mut dst,
..
@ -2145,7 +2143,7 @@ fn x64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
map_use(mapper, dst);
}
Inst::Imm { ref mut dst, .. } => map_def(mapper, dst),
Inst::Mov_R_R {
Inst::MovRR {
ref mut src,
ref mut dst,
..
@ -2197,7 +2195,7 @@ fn x64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
map_def(mapper, tmp_gpr);
map_def(mapper, tmp_xmm);
}
Inst::MovZX_RM_R {
Inst::MovzxRmR {
ref mut src,
ref mut dst,
..
@ -2205,11 +2203,11 @@ fn x64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
src.map_uses(mapper);
map_def(mapper, dst);
}
Inst::Mov64_M_R { src, dst, .. } | Inst::LoadEffectiveAddress { addr: src, dst } => {
Inst::Mov64MR { src, dst, .. } | Inst::LoadEffectiveAddress { addr: src, dst } => {
src.map_uses(mapper);
map_def(mapper, dst);
}
Inst::MovSX_RM_R {
Inst::MovsxRmR {
ref mut src,
ref mut dst,
..
@ -2217,7 +2215,7 @@ fn x64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
src.map_uses(mapper);
map_def(mapper, dst);
}
Inst::Mov_R_M {
Inst::MovRM {
ref mut src,
ref mut dst,
..
@ -2225,10 +2223,10 @@ fn x64_map_regs<RUM: RegUsageMapper>(inst: &mut Inst, mapper: &RUM) {
map_use(mapper, src);
dst.map_uses(mapper);
}
Inst::Shift_R { ref mut dst, .. } => {
Inst::ShiftR { ref mut dst, .. } => {
map_mod(mapper, dst);
}
Inst::Cmp_RMI_R {
Inst::CmpRmiR {
ref mut src,
ref mut dst,
..
@ -2343,7 +2341,7 @@ impl MachInst for Inst {
// out the upper 32 bits of the destination. For example, we could
// conceivably use `movl %reg, %reg` to zero out the top 32 bits of
// %reg.
Self::Mov_R_R {
Self::MovRR {
is_64, src, dst, ..
} if *is_64 => Some((*dst, *src)),
// Note as well that MOVS[S|D] when used in the `XmmUnaryRmR` context are pure moves of

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

@ -1,7 +1,5 @@
//! Lowering rules for X64.
#![allow(non_snake_case)]
use crate::ir::{
condcodes::FloatCC, condcodes::IntCC, types, AbiParam, ArgumentPurpose, ExternalName,
Inst as IRInst, InstructionData, LibCall, Opcode, Signature, Type,
@ -1763,12 +1761,204 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
let is_min = op == Opcode::Fmin;
let output_ty = ty.unwrap();
ctx.emit(Inst::gen_move(dst, rhs, output_ty));
let op_size = match output_ty {
types::F32 => OperandSize::Size32,
types::F64 => OperandSize::Size64,
_ => panic!("unexpected type {:?} for fmin/fmax", output_ty),
};
ctx.emit(Inst::xmm_min_max_seq(op_size, is_min, lhs, dst));
if !output_ty.is_vector() {
let op_size = match output_ty {
types::F32 => OperandSize::Size32,
types::F64 => OperandSize::Size64,
_ => panic!("unexpected type {:?} for fmin/fmax", output_ty),
};
ctx.emit(Inst::xmm_min_max_seq(op_size, is_min, lhs, dst));
} else {
// X64's implementation of floating point min and floating point max does not
// propagate NaNs and +0's in a way that is friendly to the SIMD spec. For the
// scalar approach we use jumps to handle cases where NaN and +0 propagation is
// not consistent with what is needed. However for packed floating point min and
// floating point max we implement a different approach to avoid the sequence
// of jumps that would be required on a per lane basis. Because we do not need to
// lower labels and jumps but do need ctx for creating temporaries we implement
// the lowering here in lower.rs instead of emit.rs as is done in the case for scalars.
// The outline of approach is as follows:
//
// First we preform the Min/Max in both directions. This is because in the
// case of an operand's lane containing a NaN or in the case of the lanes of the
// two operands containing 0 but with mismatched signs, x64 will return the second
// operand regardless of its contents. So in order to make sure we capture NaNs and
// normalize NaNs and 0 values we capture the operation in both directions and merge the
// results. Then we normalize the results through operations that create a mask for the
// lanes containing NaNs, we use that mask to adjust NaNs to quite NaNs and normalize
// 0s.
//
// The following sequence is generated for min:
//
// movap{s,d} %lhs, %tmp
// minp{s,d} %dst, %tmp
// minp,{s,d} %lhs, %dst
// orp{s,d} %dst, %tmp
// cmpp{s,d} %tmp, %dst, $3
// orps{s,d} %dst, %tmp
// psrl{s,d} {$10, $13}, %dst
// andnp{s,d} %tmp, %dst
//
// and for max the sequence is:
//
// movap{s,d} %lhs, %tmp
// minp{s,d} %dst, %tmp
// minp,{s,d} %lhs, %dst
// xorp{s,d} %tmp, %dst
// orp{s,d} %dst, %tmp
// subp{s,d} %dst, %tmp
// cmpp{s,d} %tmp, %dst, $3
// psrl{s,d} {$10, $13}, %dst
// andnp{s,d} %tmp, %dst
if is_min {
let (mov_op, min_op, or_op, cmp_op, shift_op, shift_by, andn_op) =
match output_ty {
types::F32X4 => (
SseOpcode::Movaps,
SseOpcode::Minps,
SseOpcode::Orps,
SseOpcode::Cmpps,
SseOpcode::Psrld,
10,
SseOpcode::Andnps,
),
types::F64X2 => (
SseOpcode::Movapd,
SseOpcode::Minpd,
SseOpcode::Orpd,
SseOpcode::Cmppd,
SseOpcode::Psrlq,
13,
SseOpcode::Andnpd,
),
_ => unimplemented!("unsupported op type {:?}", output_ty),
};
// Copy lhs into tmp
let tmp_xmm1 = ctx.alloc_tmp(RegClass::V128, output_ty);
ctx.emit(Inst::xmm_mov(mov_op, RegMem::reg(lhs), tmp_xmm1, None));
// Perform min in reverse direction
ctx.emit(Inst::xmm_rm_r(min_op, RegMem::from(dst), tmp_xmm1));
// Perform min in original direction
ctx.emit(Inst::xmm_rm_r(min_op, RegMem::reg(lhs), dst));
// X64 handles propagation of -0's and Nans differently between left and right
// operands. After doing the min in both directions, this OR will
// guarrentee capture of -0's and Nan in our tmp register
ctx.emit(Inst::xmm_rm_r(or_op, RegMem::from(dst), tmp_xmm1));
// Compare unordered to create mask for lanes containing NaNs and then use
// that mask to saturate the NaN containing lanes in the tmp register with 1s.
// TODO: Would a check for NaN and then a jump be better here in the
// common case than continuing on to normalize NaNs that might not exist?
let cond = FcmpImm::from(FloatCC::Unordered);
ctx.emit(Inst::xmm_rm_r_imm(
cmp_op,
RegMem::reg(tmp_xmm1.to_reg()),
dst,
cond.encode(),
false,
));
ctx.emit(Inst::xmm_rm_r(or_op, RegMem::reg(dst.to_reg()), tmp_xmm1));
// The dst register holds a mask for lanes containing NaNs.
// We take that mask and shift in preparation for creating a different mask
// to normalize NaNs (create a quite NaN) by zeroing out the appropriate
// number of least signficant bits. We shift right each lane by 10 bits
// (1 sign + 8 exp. + 1 MSB sig.) for F32X4 and by 13 bits (1 sign +
// 11 exp. + 1 MSB sig.) for F64X2.
ctx.emit(Inst::xmm_rmi_reg(shift_op, RegMemImm::imm(shift_by), dst));
// Finally we do a nand with the tmp register to produce the final results
// in the dst.
ctx.emit(Inst::xmm_rm_r(andn_op, RegMem::reg(tmp_xmm1.to_reg()), dst));
} else {
let (
mov_op,
max_op,
xor_op,
or_op,
sub_op,
cmp_op,
shift_op,
shift_by,
andn_op,
) = match output_ty {
types::F32X4 => (
SseOpcode::Movaps,
SseOpcode::Maxps,
SseOpcode::Xorps,
SseOpcode::Orps,
SseOpcode::Subps,
SseOpcode::Cmpps,
SseOpcode::Psrld,
10,
SseOpcode::Andnps,
),
types::F64X2 => (
SseOpcode::Movapd,
SseOpcode::Maxpd,
SseOpcode::Xorpd,
SseOpcode::Orpd,
SseOpcode::Subpd,
SseOpcode::Cmppd,
SseOpcode::Psrlq,
13,
SseOpcode::Andnpd,
),
_ => unimplemented!("unsupported op type {:?}", output_ty),
};
// Copy lhs into tmp.
let tmp_xmm1 = ctx.alloc_tmp(RegClass::V128, types::F32);
ctx.emit(Inst::xmm_mov(mov_op, RegMem::reg(lhs), tmp_xmm1, None));
// Perform max in reverse direction.
ctx.emit(Inst::xmm_rm_r(max_op, RegMem::reg(dst.to_reg()), tmp_xmm1));
// Perform max in original direction.
ctx.emit(Inst::xmm_rm_r(max_op, RegMem::reg(lhs), dst));
// Get the difference between the two results and store in tmp.
// Max uses a different approach than min to account for potential
// discrepancies with plus/minus 0.
ctx.emit(Inst::xmm_rm_r(xor_op, RegMem::reg(tmp_xmm1.to_reg()), dst));
// X64 handles propagation of -0's and Nans differently between left and right
// operands. After doing the max in both directions, this OR will
// guarentee capture of 0's and Nan in our tmp register.
ctx.emit(Inst::xmm_rm_r(or_op, RegMem::reg(dst.to_reg()), tmp_xmm1));
// Capture NaNs and sign discrepancies.
ctx.emit(Inst::xmm_rm_r(sub_op, RegMem::reg(dst.to_reg()), tmp_xmm1));
// Compare unordered to create mask for lanes containing NaNs and then use
// that mask to saturate the NaN containing lanes in the tmp register with 1s.
let cond = FcmpImm::from(FloatCC::Unordered);
ctx.emit(Inst::xmm_rm_r_imm(
cmp_op,
RegMem::reg(tmp_xmm1.to_reg()),
dst,
cond.encode(),
false,
));
// The dst register holds a mask for lanes containing NaNs.
// We take that mask and shift in preparation for creating a different mask
// to normalize NaNs (create a quite NaN) by zeroing out the appropriate
// number of least signficant bits. We shift right each lane by 10 bits
// (1 sign + 8 exp. + 1 MSB sig.) for F32X4 and by 13 bits (1 sign +
// 11 exp. + 1 MSB sig.) for F64X2.
ctx.emit(Inst::xmm_rmi_reg(shift_op, RegMemImm::imm(shift_by), dst));
// Finally we do a nand with the tmp register to produce the final results
// in the dst.
ctx.emit(Inst::xmm_rm_r(andn_op, RegMem::reg(tmp_xmm1.to_reg()), dst));
}
}
}
Opcode::Sqrt => {

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

@ -1 +1 @@
{"files":{"Cargo.toml":"7a4570632d7829d4596daeae9c0d17cb5a7120e34e4234022b2cd3b9700e8c93","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"c82c252fbeeaa101a0eef042b9a925eb1fa3d2b51d19481b9c22e593e6a8d772","src/code_translator.rs":"d85885a51f19f25a1c60c94f6f35815273547a18b04d73584d7a8d283c099651","src/environ/dummy.rs":"0c05a77ab37a305c799f1b0e99c9debe1b8f59a3e3aa764e2fe39a923716b2ee","src/environ/mod.rs":"692f35d75f125f9c071f7166252f427e4bac29401356f73307c6c36e23c667fb","src/environ/spec.rs":"0f97fff3cc545772a1959f7d0439713fd7dc8d8adf43a2636f8174126dc1393c","src/func_translator.rs":"6af2fe6d71ab05aac84aaa7149bfb7be18f1ab056895bf9208a5fe0d502118c9","src/lib.rs":"7bdbcf638fa30fb05e8320439881f7536824f7f60a7db4f0c1b51ab369edf895","src/module_translator.rs":"1374fa56ca18a782083fa0f25f2ad675044a92bbf1a0a1cc44fcaf695807e044","src/sections_translator.rs":"11d65fd2e595e41f976e5c7d0df823f70449f79a9d2facbed61263616f8cfec1","src/state/func_state.rs":"581a5648b11fa07aef3cff0752597864c7cd44a4d44e27c50fc7349955b3fda3","src/state/mod.rs":"20014cb93615467b4d20321b52f67f66040417efcaa739a4804093bb559eed19","src/state/module_state.rs":"7ca3cb06b4481bc3ae74697fbcd437aea1d851eaa3cfe18cc013a4af43728957","src/translation_utils.rs":"69f20c47ea22f0badd21a6187b5f9764252a00d19643a7e3e691797a9fe34f1b","tests/wasm_testsuite.rs":"da8dedfd11918946e9cf6af68fd4826f020ef90a4e22742b1a30e61a3fb4aedd"},"package":null}
{"files":{"Cargo.toml":"53367fadfe62cdc349a55a3460992677690300d6e568e38b8d73e2b5c7376c7d","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"c82c252fbeeaa101a0eef042b9a925eb1fa3d2b51d19481b9c22e593e6a8d772","src/code_translator.rs":"b25c4a4b002f2fab0364fd890539de76bc163e6f8a817d1a53bec271970ea903","src/environ/dummy.rs":"f780d523b7024d4fed923992bbe95ca4816e3a8770a83ea01de94d4cd1625b6e","src/environ/mod.rs":"692f35d75f125f9c071f7166252f427e4bac29401356f73307c6c36e23c667fb","src/environ/spec.rs":"ed806f95bd13e26ae14684287f547e77bdcc31c10a6a23ee45764f573ff4793f","src/func_translator.rs":"ebc7e7f872d03fc05e9c013e0eb575b0ae2828322b7194c60b8e764f2816d12e","src/lib.rs":"83fbcf3561b7255d346b6b33114f4a051f3a7133f11f1a238c0fe12ddbdd1ba7","src/module_translator.rs":"dc63d45d1917034f9d06008899143e32041e6d3475629d3c6eee3bb0195a0b3e","src/sections_translator.rs":"00012d18f1467f71959c4b68dcb2c059523011cac50f7ac869d3206ce9021475","src/state/func_state.rs":"581a5648b11fa07aef3cff0752597864c7cd44a4d44e27c50fc7349955b3fda3","src/state/mod.rs":"20014cb93615467b4d20321b52f67f66040417efcaa739a4804093bb559eed19","src/state/module_state.rs":"7ca3cb06b4481bc3ae74697fbcd437aea1d851eaa3cfe18cc013a4af43728957","src/translation_utils.rs":"1b9d3d63fc259c9c657747da750d0434f0acbc53381ca32860b04d017754eb55","tests/wasm_testsuite.rs":"5e9f8441acdafe1552b4ae79c8c27603dad2b047791b035d28354d9f29b4d4e7"},"package":null}

3
third_party/rust/cranelift-wasm/Cargo.toml поставляемый
Просмотреть файл

@ -12,11 +12,12 @@ keywords = ["webassembly", "wasm"]
edition = "2018"
[dependencies]
wasmparser = { version = "0.59.0", default-features = false }
wasmparser = { version = "0.63.0", default-features = false }
cranelift-codegen = { path = "../codegen", version = "0.67.0", default-features = false }
cranelift-entity = { path = "../entity", version = "0.67.0" }
cranelift-frontend = { path = "../frontend", version = "0.67.0", default-features = false }
hashbrown = { version = "0.7", optional = true }
itertools = "0.9.0"
log = { version = "0.4.6", default-features = false }
serde = { version = "1.0.94", features = ["derive"], optional = true }
thiserror = "1.0.4"

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

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

@ -10,7 +10,6 @@ use crate::environ::{
WasmFuncType, WasmResult,
};
use crate::func_translator::FuncTranslator;
use crate::state::ModuleTranslationState;
use crate::translation_utils::{
DataIndex, DefinedFuncIndex, ElemIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex,
SignatureIndex, Table, TableIndex,
@ -26,6 +25,7 @@ use cranelift_frontend::FunctionBuilder;
use std::boxed::Box;
use std::string::String;
use std::vec::Vec;
use wasmparser::{FuncValidator, FunctionBody, ValidatorResources, WasmFeatures};
/// Compute a `ir::ExternalName` for a given wasm function index.
fn get_func_name(func_index: FuncIndex) -> ir::ExternalName {
@ -738,10 +738,11 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
fn define_function_body(
&mut self,
module_translation_state: &ModuleTranslationState,
body_bytes: &'data [u8],
body_offset: usize,
mut validator: FuncValidator<ValidatorResources>,
body: FunctionBody<'data>,
) -> WasmResult<()> {
self.func_bytecode_sizes
.push(body.get_binary_reader().bytes_remaining());
let func = {
let mut func_environ = DummyFuncEnvironment::new(&self.info, self.return_mode);
let func_index =
@ -752,16 +753,10 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
if self.debug_info {
func.collect_debug_info();
}
self.trans.translate(
module_translation_state,
body_bytes,
body_offset,
&mut func,
&mut func_environ,
)?;
self.trans
.translate_body(&mut validator, body, &mut func, &mut func_environ)?;
func
};
self.func_bytecode_sizes.push(body_bytes.len());
self.info.function_bodies.push(func);
Ok(())
}
@ -773,4 +768,14 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
fn declare_func_name(&mut self, func_index: FuncIndex, name: &'data str) {
self.function_names[func_index] = String::from(name);
}
fn wasm_features(&self) -> WasmFeatures {
WasmFeatures {
multi_value: true,
simd: true,
reference_types: true,
bulk_memory: true,
..WasmFeatures::default()
}
}
}

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

@ -6,7 +6,7 @@
//!
//! [Wasmtime]: https://github.com/bytecodealliance/wasmtime
use crate::state::{FuncTranslationState, ModuleTranslationState};
use crate::state::FuncTranslationState;
use crate::translation_utils::{
DataIndex, ElemIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex,
Table, TableIndex,
@ -23,8 +23,8 @@ use serde::{Deserialize, Serialize};
use std::boxed::Box;
use std::string::ToString;
use thiserror::Error;
use wasmparser::BinaryReaderError;
use wasmparser::Operator;
use wasmparser::ValidatorResources;
use wasmparser::{BinaryReaderError, FuncValidator, FunctionBody, Operator, WasmFeatures};
/// WebAssembly value type -- equivalent of `wasmparser`'s Type.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@ -798,9 +798,8 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
/// Provides the contents of a function body.
fn define_function_body(
&mut self,
module_translation_state: &ModuleTranslationState,
body_bytes: &'data [u8],
body_offset: usize,
validator: FuncValidator<ValidatorResources>,
body: FunctionBody<'data>,
) -> WasmResult<()>;
/// Provides the number of data initializers up front. By default this does nothing, but
@ -841,4 +840,9 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
fn custom_section(&mut self, _name: &'data str, _data: &'data [u8]) -> WasmResult<()> {
Ok(())
}
/// Returns the list of enabled wasm features this translation will be using.
fn wasm_features(&self) -> WasmFeatures {
WasmFeatures::default()
}
}

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

@ -6,7 +6,7 @@
use crate::code_translator::{bitcast_arguments, translate_operator, wasm_param_types};
use crate::environ::{FuncEnvironment, ReturnMode, WasmResult};
use crate::state::{FuncTranslationState, ModuleTranslationState};
use crate::state::FuncTranslationState;
use crate::translation_utils::get_vmctx_value_label;
use crate::wasm_unsupported;
use core::convert::TryInto;
@ -14,7 +14,7 @@ use cranelift_codegen::entity::EntityRef;
use cranelift_codegen::ir::{self, Block, InstBuilder, ValueLabel};
use cranelift_codegen::timing;
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
use wasmparser::{self, BinaryReader};
use wasmparser::{self, BinaryReader, FuncValidator, FunctionBody, WasmModuleResources};
/// WebAssembly to Cranelift IR function translator.
///
@ -55,29 +55,30 @@ impl FuncTranslator {
///
pub fn translate<FE: FuncEnvironment + ?Sized>(
&mut self,
module_translation_state: &ModuleTranslationState,
validator: &mut FuncValidator<impl WasmModuleResources>,
code: &[u8],
code_offset: usize,
func: &mut ir::Function,
environ: &mut FE,
) -> WasmResult<()> {
self.translate_from_reader(
module_translation_state,
BinaryReader::new_with_offset(code, code_offset),
self.translate_body(
validator,
FunctionBody::new(code_offset, code),
func,
environ,
)
}
/// Translate a binary WebAssembly function from a `BinaryReader`.
pub fn translate_from_reader<FE: FuncEnvironment + ?Sized>(
/// Translate a binary WebAssembly function from a `FunctionBody`.
pub fn translate_body<FE: FuncEnvironment + ?Sized>(
&mut self,
module_translation_state: &ModuleTranslationState,
mut reader: BinaryReader,
validator: &mut FuncValidator<impl WasmModuleResources>,
body: FunctionBody<'_>,
func: &mut ir::Function,
environ: &mut FE,
) -> WasmResult<()> {
let _tt = timing::wasm_translate_function();
let mut reader = body.get_binary_reader();
log::debug!(
"translate({} bytes, {}{})",
reader.bytes_remaining(),
@ -107,14 +108,8 @@ impl FuncTranslator {
builder.append_block_params_for_function_returns(exit_block);
self.state.initialize(&builder.func.signature, exit_block);
parse_local_decls(&mut reader, &mut builder, num_params, environ)?;
parse_function_body(
module_translation_state,
reader,
&mut builder,
&mut self.state,
environ,
)?;
parse_local_decls(&mut reader, &mut builder, num_params, environ, validator)?;
parse_function_body(validator, reader, &mut builder, &mut self.state, environ)?;
builder.finalize();
Ok(())
@ -161,14 +156,17 @@ fn parse_local_decls<FE: FuncEnvironment + ?Sized>(
builder: &mut FunctionBuilder,
num_params: usize,
environ: &mut FE,
validator: &mut FuncValidator<impl WasmModuleResources>,
) -> WasmResult<()> {
let mut next_local = num_params;
let local_count = reader.read_local_count()?;
let local_count = reader.read_var_u32()?;
let mut locals_total = 0;
for _ in 0..local_count {
builder.set_srcloc(cur_srcloc(reader));
let (count, ty) = reader.read_local_decl(&mut locals_total)?;
let pos = reader.original_position();
let count = reader.read_var_u32()?;
let ty = reader.read_type()?;
validator.define_locals(pos, count, ty)?;
declare_locals(builder, count, ty, &mut next_local, environ)?;
}
@ -218,7 +216,7 @@ fn declare_locals<FE: FuncEnvironment + ?Sized>(
/// This assumes that the local variable declarations have already been parsed and function
/// arguments and locals are declared in the builder.
fn parse_function_body<FE: FuncEnvironment + ?Sized>(
module_translation_state: &ModuleTranslationState,
validator: &mut FuncValidator<impl WasmModuleResources>,
mut reader: BinaryReader,
builder: &mut FunctionBuilder,
state: &mut FuncTranslationState,
@ -227,14 +225,17 @@ fn parse_function_body<FE: FuncEnvironment + ?Sized>(
// The control stack is initialized with a single block representing the whole function.
debug_assert_eq!(state.control_stack.len(), 1, "State not initialized");
// Keep going until the final `End` operator which pops the outermost block.
while !state.control_stack.is_empty() {
while !reader.eof() {
let pos = reader.original_position();
builder.set_srcloc(cur_srcloc(&reader));
let op = reader.read_operator()?;
validator.op(pos, &op)?;
environ.before_translate_operator(&op, builder, state)?;
translate_operator(module_translation_state, &op, builder, state, environ)?;
translate_operator(validator, &op, builder, state, environ)?;
environ.after_translate_operator(&op, builder, state)?;
}
let pos = reader.original_position();
validator.finish(pos)?;
// The final `End` operator left us in the exit block where we need to manually add a return
// instruction.
@ -261,8 +262,6 @@ fn parse_function_body<FE: FuncEnvironment + ?Sized>(
// or the end of the function is unreachable.
state.stack.clear();
debug_assert!(reader.eof());
Ok(())
}
@ -277,26 +276,27 @@ fn cur_srcloc(reader: &BinaryReader) -> ir::SourceLoc {
mod tests {
use super::{FuncTranslator, ReturnMode};
use crate::environ::DummyEnvironment;
use crate::ModuleTranslationState;
use cranelift_codegen::ir::types::I32;
use cranelift_codegen::{ir, isa, settings, Context};
use log::debug;
use target_lexicon::PointerWidth;
use wasmparser::{
FuncValidator, FunctionBody, Parser, ValidPayload, Validator, ValidatorResources,
};
#[test]
fn small1() {
// Implicit return.
//
// (func $small1 (param i32) (result i32)
// (i32.add (get_local 0) (i32.const 1))
// )
const BODY: [u8; 7] = [
0x00, // local decl count
0x20, 0x00, // get_local 0
0x41, 0x01, // i32.const 1
0x6a, // i32.add
0x0b, // end
];
let wasm = wat::parse_str(
"
(module
(func $small2 (param i32) (result i32)
(i32.add (get_local 0) (i32.const 1))
)
)
",
)
.unwrap();
let mut trans = FuncTranslator::new();
let flags = settings::Flags::new(settings::builder());
@ -309,21 +309,15 @@ mod tests {
false,
);
let module_translation_state = ModuleTranslationState::new();
let mut ctx = Context::new();
ctx.func.name = ir::ExternalName::testcase("small1");
ctx.func.signature.params.push(ir::AbiParam::new(I32));
ctx.func.signature.returns.push(ir::AbiParam::new(I32));
let (body, mut validator) = extract_func(&wasm);
trans
.translate(
&module_translation_state,
&BODY,
0,
&mut ctx.func,
&mut runtime.func_env(),
)
.translate_body(&mut validator, body, &mut ctx.func, &mut runtime.func_env())
.unwrap();
debug!("{}", ctx.func.display(None));
ctx.verify(&flags).unwrap();
@ -332,18 +326,16 @@ mod tests {
#[test]
fn small2() {
// Same as above, but with an explicit return instruction.
//
// (func $small2 (param i32) (result i32)
// (return (i32.add (get_local 0) (i32.const 1)))
// )
const BODY: [u8; 8] = [
0x00, // local decl count
0x20, 0x00, // get_local 0
0x41, 0x01, // i32.const 1
0x6a, // i32.add
0x0f, // return
0x0b, // end
];
let wasm = wat::parse_str(
"
(module
(func $small2 (param i32) (result i32)
(return (i32.add (get_local 0) (i32.const 1)))
)
)
",
)
.unwrap();
let mut trans = FuncTranslator::new();
let flags = settings::Flags::new(settings::builder());
@ -356,21 +348,15 @@ mod tests {
false,
);
let module_translation_state = ModuleTranslationState::new();
let mut ctx = Context::new();
ctx.func.name = ir::ExternalName::testcase("small2");
ctx.func.signature.params.push(ir::AbiParam::new(I32));
ctx.func.signature.returns.push(ir::AbiParam::new(I32));
let (body, mut validator) = extract_func(&wasm);
trans
.translate(
&module_translation_state,
&BODY,
0,
&mut ctx.func,
&mut runtime.func_env(),
)
.translate_body(&mut validator, body, &mut ctx.func, &mut runtime.func_env())
.unwrap();
debug!("{}", ctx.func.display(None));
ctx.verify(&flags).unwrap();
@ -379,27 +365,21 @@ mod tests {
#[test]
fn infloop() {
// An infinite loop, no return instructions.
//
// (func $infloop (result i32)
// (local i32)
// (loop (result i32)
// (i32.add (get_local 0) (i32.const 1))
// (set_local 0)
// (br 0)
// )
// )
const BODY: [u8; 16] = [
0x01, // 1 local decl.
0x01, 0x7f, // 1 i32 local.
0x03, 0x7f, // loop i32
0x20, 0x00, // get_local 0
0x41, 0x01, // i32.const 0
0x6a, // i32.add
0x21, 0x00, // set_local 0
0x0c, 0x00, // br 0
0x0b, // end
0x0b, // end
];
let wasm = wat::parse_str(
"
(module
(func $infloop (result i32)
(local i32)
(loop (result i32)
(i32.add (get_local 0) (i32.const 1))
(set_local 0)
(br 0)
)
)
)
",
)
.unwrap();
let mut trans = FuncTranslator::new();
let flags = settings::Flags::new(settings::builder());
@ -412,22 +392,27 @@ mod tests {
false,
);
let module_translation_state = ModuleTranslationState::new();
let mut ctx = Context::new();
ctx.func.name = ir::ExternalName::testcase("infloop");
ctx.func.signature.returns.push(ir::AbiParam::new(I32));
let (body, mut validator) = extract_func(&wasm);
trans
.translate(
&module_translation_state,
&BODY,
0,
&mut ctx.func,
&mut runtime.func_env(),
)
.translate_body(&mut validator, body, &mut ctx.func, &mut runtime.func_env())
.unwrap();
debug!("{}", ctx.func.display(None));
ctx.verify(&flags).unwrap();
}
fn extract_func(wat: &[u8]) -> (FunctionBody<'_>, FuncValidator<ValidatorResources>) {
let mut validator = Validator::new();
for payload in Parser::new(0).parse_all(wat) {
match validator.payload(&payload.unwrap()).unwrap() {
ValidPayload::Func(validator, body) => return (body, validator),
_ => {}
}
}
panic!("failed to find function");
}
}

5
third_party/rust/cranelift-wasm/src/lib.rs поставляемый
Просмотреть файл

@ -72,5 +72,10 @@ pub use crate::translation_utils::{
};
pub use cranelift_frontend::FunctionBuilder;
// Convenience reexport of the wasmparser crate that we're linking against,
// since a number of types in `wasmparser` show up in the public API of
// `cranelift-wasm`.
pub use wasmparser;
/// Version number of this crate.
pub const VERSION: &str = env!("CARGO_PKG_VERSION");

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

@ -8,7 +8,7 @@ use crate::sections_translator::{
};
use crate::state::ModuleTranslationState;
use cranelift_codegen::timing;
use wasmparser::{NameSectionReader, Parser, Payload};
use wasmparser::{NameSectionReader, Parser, Payload, Validator};
/// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cranelift IR
/// [`Function`](cranelift_codegen::ir::Function).
@ -18,75 +18,105 @@ pub fn translate_module<'data>(
) -> WasmResult<ModuleTranslationState> {
let _tt = timing::wasm_translate_module();
let mut module_translation_state = ModuleTranslationState::new();
let mut validator = Validator::new();
validator.wasm_features(environ.wasm_features());
for payload in Parser::new(0).parse_all(data) {
match payload? {
Payload::Version { .. } | Payload::End => {}
Payload::Version { num, range } => {
validator.version(num, &range)?;
}
Payload::End => {
validator.end()?;
}
Payload::TypeSection(types) => {
validator.type_section(&types)?;
parse_type_section(types, &mut module_translation_state, environ)?;
}
Payload::ImportSection(imports) => {
validator.import_section(&imports)?;
parse_import_section(imports, environ)?;
}
Payload::FunctionSection(functions) => {
validator.function_section(&functions)?;
parse_function_section(functions, environ)?;
}
Payload::TableSection(tables) => {
validator.table_section(&tables)?;
parse_table_section(tables, environ)?;
}
Payload::MemorySection(memories) => {
validator.memory_section(&memories)?;
parse_memory_section(memories, environ)?;
}
Payload::GlobalSection(globals) => {
validator.global_section(&globals)?;
parse_global_section(globals, environ)?;
}
Payload::ExportSection(exports) => {
validator.export_section(&exports)?;
parse_export_section(exports, environ)?;
}
Payload::StartSection { func, .. } => {
Payload::StartSection { func, range } => {
validator.start_section(func, &range)?;
parse_start_section(func, environ)?;
}
Payload::ElementSection(elements) => {
validator.element_section(&elements)?;
parse_element_section(elements, environ)?;
}
Payload::CodeSectionStart { count, range, .. } => {
validator.code_section_start(count, &range)?;
environ.reserve_function_bodies(count, range.start as u64);
}
Payload::CodeSectionEntry(code) => {
let mut code = code.get_binary_reader();
let size = code.bytes_remaining();
let offset = code.original_position();
environ.define_function_body(
&module_translation_state,
code.read_bytes(size)?,
offset,
)?;
Payload::CodeSectionEntry(body) => {
let func_validator = validator.code_section_entry()?;
environ.define_function_body(func_validator, body)?;
}
Payload::DataSection(data) => {
validator.data_section(&data)?;
parse_data_section(data, environ)?;
}
Payload::DataCountSection { count, .. } => {
Payload::DataCountSection { count, range } => {
validator.data_count_section(count, &range)?;
environ.reserve_passive_data(count)?;
}
Payload::ModuleSection(_)
| Payload::InstanceSection(_)
| Payload::AliasSection(_)
| Payload::ModuleCodeSectionStart { .. }
| Payload::ModuleCodeSectionEntry { .. } => {
Payload::ModuleSection(s) => {
validator.module_section(&s)?;
unimplemented!("module linking not implemented yet")
}
Payload::InstanceSection(s) => {
validator.instance_section(&s)?;
unimplemented!("module linking not implemented yet")
}
Payload::AliasSection(s) => {
validator.alias_section(&s)?;
unimplemented!("module linking not implemented yet")
}
Payload::ModuleCodeSectionStart {
count,
range,
size: _,
} => {
validator.module_code_section_start(count, &range)?;
unimplemented!("module linking not implemented yet")
}
Payload::ModuleCodeSectionEntry { .. } => {
unimplemented!("module linking not implemented yet")
}
@ -105,7 +135,10 @@ pub fn translate_module<'data>(
Payload::CustomSection { name, data, .. } => environ.custom_section(name, data)?,
Payload::UnknownSection { .. } => unreachable!(),
Payload::UnknownSection { id, range, .. } => {
validator.unknown_section(id, &range)?;
unreachable!();
}
}
}

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

@ -26,7 +26,7 @@ use wasmparser::{
self, Data, DataKind, DataSectionReader, Element, ElementItem, ElementItems, ElementKind,
ElementSectionReader, Export, ExportSectionReader, ExternalKind, FunctionSectionReader,
GlobalSectionReader, GlobalType, ImportSectionEntryType, ImportSectionReader,
MemorySectionReader, MemoryType, NameSectionReader, Naming, Operator, TableSectionReader, Type,
MemorySectionReader, MemoryType, NameSectionReader, Naming, Operator, TableSectionReader,
TypeDef, TypeSectionReader,
};
@ -88,7 +88,7 @@ pub fn parse_import_section<'data>(
ImportSectionEntryType::Module(_sig) | ImportSectionEntryType::Instance(_sig) => {
unimplemented!("module linking not implemented yet")
}
ImportSectionEntryType::Memory(MemoryType {
ImportSectionEntryType::Memory(MemoryType::M32 {
limits: ref memlimits,
shared,
}) => {
@ -102,6 +102,9 @@ pub fn parse_import_section<'data>(
field_name,
)?;
}
ImportSectionEntryType::Memory(MemoryType::M64 { .. }) => {
unimplemented!();
}
ImportSectionEntryType::Global(ref ty) => {
environ.declare_global_import(
Global {
@ -189,11 +192,16 @@ pub fn parse_memory_section(
for entry in memories {
let memory = entry?;
environ.declare_memory(Memory {
minimum: memory.limits.initial,
maximum: memory.limits.maximum,
shared: memory.shared,
})?;
match memory {
MemoryType::M32 { limits, shared } => {
environ.declare_memory(Memory {
minimum: limits.initial,
maximum: limits.maximum,
shared: shared,
})?;
}
MemoryType::M64 { .. } => unimplemented!(),
}
}
Ok(())
@ -313,13 +321,7 @@ pub fn parse_element_section<'data>(
environ.reserve_table_elements(elements.get_count())?;
for (index, entry) in elements.into_iter().enumerate() {
let Element { kind, items, ty } = entry?;
if ty != Type::FuncRef {
return Err(wasm_unsupported!(
"unsupported table element type: {:?}",
ty
));
}
let Element { kind, items, ty: _ } = entry?;
let segments = read_elems(&items)?;
match kind {
ElementKind::Active {

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

@ -1,6 +1,5 @@
//! Helper functions and structures for the translation.
use crate::environ::{TargetEnvironment, WasmResult, WasmType};
use crate::state::ModuleTranslationState;
use crate::wasm_unsupported;
use core::convert::TryInto;
use core::u32;
@ -10,7 +9,7 @@ use cranelift_codegen::ir::immediates::V128Imm;
use cranelift_frontend::FunctionBuilder;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
use wasmparser;
use wasmparser::{FuncValidator, WasmFuncType, WasmModuleResources};
/// Index type of a function (imported or defined) inside the WebAssembly module.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
@ -194,38 +193,56 @@ pub fn tabletype_to_type<PE: TargetEnvironment + ?Sized>(
}
/// Get the parameter and result types for the given Wasm blocktype.
pub fn blocktype_params_results(
module_translation_state: &ModuleTranslationState,
pub fn blocktype_params_results<'a, T>(
validator: &'a FuncValidator<T>,
ty_or_ft: wasmparser::TypeOrFuncType,
) -> WasmResult<(&[wasmparser::Type], &[wasmparser::Type])> {
Ok(match ty_or_ft {
wasmparser::TypeOrFuncType::Type(ty) => match ty {
wasmparser::Type::I32 => (&[], &[wasmparser::Type::I32]),
wasmparser::Type::I64 => (&[], &[wasmparser::Type::I64]),
wasmparser::Type::F32 => (&[], &[wasmparser::Type::F32]),
wasmparser::Type::F64 => (&[], &[wasmparser::Type::F64]),
wasmparser::Type::V128 => (&[], &[wasmparser::Type::V128]),
wasmparser::Type::ExternRef => (&[], &[wasmparser::Type::ExternRef]),
wasmparser::Type::FuncRef => (&[], &[wasmparser::Type::FuncRef]),
wasmparser::Type::EmptyBlockType => (&[], &[]),
ty => return Err(wasm_unsupported!("blocktype_params_results: type {:?}", ty)),
},
wasmparser::TypeOrFuncType::FuncType(ty_index) => {
let sig_idx = SignatureIndex::from_u32(ty_index);
let (ref params, ref returns) = module_translation_state.wasm_types[sig_idx];
(&*params, &*returns)
) -> WasmResult<(
impl ExactSizeIterator<Item = wasmparser::Type> + Clone + 'a,
impl ExactSizeIterator<Item = wasmparser::Type> + Clone + 'a,
)>
where
T: WasmModuleResources,
{
return Ok(match ty_or_ft {
wasmparser::TypeOrFuncType::Type(ty) => {
let (params, results): (&'static [wasmparser::Type], &'static [wasmparser::Type]) =
match ty {
wasmparser::Type::I32 => (&[], &[wasmparser::Type::I32]),
wasmparser::Type::I64 => (&[], &[wasmparser::Type::I64]),
wasmparser::Type::F32 => (&[], &[wasmparser::Type::F32]),
wasmparser::Type::F64 => (&[], &[wasmparser::Type::F64]),
wasmparser::Type::V128 => (&[], &[wasmparser::Type::V128]),
wasmparser::Type::ExternRef => (&[], &[wasmparser::Type::ExternRef]),
wasmparser::Type::FuncRef => (&[], &[wasmparser::Type::FuncRef]),
wasmparser::Type::EmptyBlockType => (&[], &[]),
ty => return Err(wasm_unsupported!("blocktype_params_results: type {:?}", ty)),
};
(
itertools::Either::Left(params.iter().copied()),
itertools::Either::Left(results.iter().copied()),
)
}
})
wasmparser::TypeOrFuncType::FuncType(ty_index) => {
let ty = validator
.resources()
.func_type_at(ty_index)
.expect("should be valid");
(
itertools::Either::Right(ty.inputs()),
itertools::Either::Right(ty.outputs()),
)
}
});
}
/// Create a `Block` with the given Wasm parameters.
pub fn block_with_params<PE: TargetEnvironment + ?Sized>(
builder: &mut FunctionBuilder,
params: &[wasmparser::Type],
params: impl IntoIterator<Item = wasmparser::Type>,
environ: &PE,
) -> WasmResult<ir::Block> {
let block = builder.create_block();
for ty in params.iter() {
for ty in params {
match ty {
wasmparser::Type::I32 => {
builder.append_block_param(block, ir::types::I32);
@ -240,7 +257,7 @@ pub fn block_with_params<PE: TargetEnvironment + ?Sized>(
builder.append_block_param(block, ir::types::F64);
}
wasmparser::Type::ExternRef | wasmparser::Type::FuncRef => {
builder.append_block_param(block, environ.reference_type((*ty).try_into()?));
builder.append_block_param(block, environ.reference_type(ty.try_into()?));
}
wasmparser::Type::V128 => {
builder.append_block_param(block, ir::types::I8X16);

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

@ -4,9 +4,6 @@ use cranelift_codegen::settings::{self, Flags};
use cranelift_codegen::verifier;
use cranelift_wasm::{translate_module, DummyEnvironment, FuncIndex, ReturnMode};
use std::fs;
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::path::Path;
use std::str::FromStr;
use target_lexicon::triple;
@ -69,20 +66,13 @@ fn use_name_section() {
);
}
fn read_file(path: &Path) -> io::Result<Vec<u8>> {
let mut buf: Vec<u8> = Vec::new();
let mut file = File::open(path)?;
file.read_to_end(&mut buf)?;
Ok(buf)
}
fn read_module(path: &Path) -> Vec<u8> {
match path.extension() {
None => {
panic!("the file extension is not wasm or wat");
}
Some(ext) => match ext.to_str() {
Some("wasm") => read_file(path).expect("error reading wasm file"),
Some("wasm") => std::fs::read(path).expect("error reading wasm file"),
Some("wat") => wat::parse_file(path)
.map_err(|e| e.to_string())
.expect("failed to parse wat"),

1
third_party/rust/itertools-0.8.0/.cargo-checksum.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
{"files":{"Cargo.toml":"a4dc734c8e5ac0e5b57ded98adeb9340621d5c586d196d423781d7ceab06538b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7576269ea71f767b99297934c0b2367532690f8c4badc695edf8e04ab6a1e545","README.rst":"9db27658be49c4d5501c6bb6fbed1dcc1e796c7d934757cf3e94eab14d241d1d","benches/bench1.rs":"9794e5377019e4cf8caee3e7bb30034cf8ac291a485e64407df321f3f33affa0","benches/extra/mod.rs":"4c5b03e74fc5b02383500c9da9fd6550262706ee569d70d085700f6d0b5749ba","benches/extra/zipslices.rs":"108dd488de366b2d83fb6bcc603ecbf9a017e165ac19d03440074fa244af3fb2","benches/tree_fold1.rs":"84cddbabb1a681f3196430a8e27b060103366143a3ee4c42c3b0628fc00a7543","benches/tuple_combinations.rs":"6a4b89eb2e45fa0c99e5e5942b3196b76998213c66c44b3765b869be42016a82","benches/tuples.rs":"412a952f08bb03695952d5cfd57949dcf28be8b99e3c6653994bdb8af9654653","examples/iris.data":"596ffd580471ca4d4880f8e439c7281f3b50d8249a5960353cb200b1490f63a0","examples/iris.rs":"3996ca0a62762aec2b102f0f4244fe90d4b4354286d68d80cdc40e35f4352ba3","src/adaptors/mod.rs":"11ef622421a5980a722a8cd2a732e9379470c1817d8b9c4bcde654c3e417b794","src/adaptors/multi_product.rs":"bb239555be38cde1f419bacfd09728f6ccaf51b6b4811c266b5677705175e685","src/combinations.rs":"a9a3fc78eb5c9f3933ff60275a635d0c81f4864a73515dc052aeb2add4ad4909","src/concat_impl.rs":"276339b00588f54c25f8ffbe0ae3c0031f7e52fb53c6578554a0bde1681b58a5","src/cons_tuples_impl.rs":"87c620d2ffdd3475218f5f493dbef601491be9f6cdfe57c44929449b32e6709f","src/diff.rs":"921e2b867d7b32ffedc72a5eb780811322d14d1e0883a608b9028a2afcad0df2","src/either_or_both.rs":"8ea6db74fa21535de45cb48ee7134495e8822a0fa181fdb646e081251ac9459f","src/format.rs":"412fbe02f12311c6fbcec1044f57ad6991783f5a3f323b9c391accfe4915106f","src/free.rs":"473d19906720eb2a1309c0505497658b1426f3ea0c845b40f41f3154194fff18","src/group_map.rs":"872d6e243e649ad30c94973c034596cc3377b10018e361bca07e11c612006de6","src/groupbylazy.rs":"a067a12671be9ae05a9152518103f39f7286fde09f758de8af75a1064a3b5567","src/impl_macros.rs":"eb0bb3f70ec1bcaffa6110ae4134c777951ed1e5f48d8c811dbf0a597dc48faa","src/intersperse.rs":"9c18f239654ebfcce1d68a0256d2df6d79a2b8c4fb5df87d67e2ebe04a07e1a9","src/kmerge_impl.rs":"51e71d3e76670a8efb16597a9224d2c9b40cee6bc6270d06b66aadafea6dc26b","src/lib.rs":"edac21e8bff7bc7695480022a33ded58916eb1c5ed43f5aa68a7c965b452af0b","src/merge_join.rs":"98e6fcc761a558ad21789efe041c3f90e62f6c75e05840670df45ad4f9b07e1f","src/minmax.rs":"4668a7f824fbc133599f43ffb6f7283e5bd603e07df2d8176abc6f25d6af9db0","src/multipeek_impl.rs":"ebe9544d94d0bf7200f7625241a3b5a291b7b564091a08cad40ff08b51f1b1bf","src/pad_tail.rs":"078615a2892f8c6db665074cf6f1be1bef4cf5ee418bc174edcfd4dc703e163f","src/peeking_take_while.rs":"6aea3bb40fb480e9f3695ce2a7a3a2e2346d437ca846d20e6bb3c09beb0934f4","src/process_results_impl.rs":"5f454cf62ceb82cab7c08c0c190de3ae083e219a8acc7a1a22f17eec9cfcd65c","src/put_back_n_impl.rs":"d35858184c525372b22d14d42cdf63726cf0fd50f5bd42ec7a82d55a8e180e9f","src/rciter_impl.rs":"8f51abc7e1ae3320cc5d56fadd66f880a7a06773be656bd8c4712357f01ae1d9","src/repeatn.rs":"4bd1782364b16105fbef3f3de7bf62780710e5c996db44a00e4b5f16c2625d86","src/size_hint.rs":"c1d35b422a696cf3d63e7c90d8f9fdf01a304cf8156e914287c4ef48fea62dd3","src/sources.rs":"cb6ebe06b05f7da0ac1073ba486c45afaeebf8b558c0f5499f0eacd2cd1785da","src/tee.rs":"59cf9ef0b41882307ea1e3503a2ff351f401f4c43d95acf423a990b0bf0e29ae","src/tuple_impl.rs":"0c7f907e85d2ef0661583b36c7b8a7341b8feadafe28d10539a211dff5c028ea","src/unique_impl.rs":"63db2d720ff5e3d9c0d6c2b245ffff25d4040e4fcbcb2a6524b0f912826f86af","src/with_position.rs":"d922f045f6fa090a431be928f3221c6dc37ac6f9bb54461b3b84f99a7e91244a","src/zip_eq_impl.rs":"f857c69120255db16ad6ddec628c79cb573b1d5179fcebab1906bf5b762c02e3","src/zip_longest.rs":"375325ef069970e6fb83c6097c2824877bb0f06e4f1e664e4fe681804abe003c","src/ziptuple.rs":"d7ae7d3c33185ad74ab2bba750ac337b5c236750cc8341dd9883faf6465712a1","tests/merge_join.rs":"546eaffae40010f15a7bcf95bc53f5e9b67424c5b93df6ffb0aaa1e48e8b90c0","tests/peeking_take_while.rs":"a2ae6474e09620a47bb8a6e3c62929261e72c52881370adb2d22e89aa9e9aec8","tests/quick.rs":"290d52047c66b5c493ff425cc527a476c55a150bc859709a8a8559f3f0a74274","tests/test_core.rs":"1a1c4c2dbb657e9ce5cd2bb0d6475cf965878e2a259b730ada9238c71c2a8d4f","tests/test_std.rs":"90d2794cbee64b3a5a1cb53193387e2d83d2b9bdf588edb506a7bf3c5191d2ec","tests/tuples.rs":"5323d15a7abf6545b2655167d3206b6cf6a947e9409a244ea6a8cf4ad8ceac64","tests/zip.rs":"fe213d70c4fa114cb4d1930a6b971f4af617a239041ddb87e6b5a9bbe62261b8"},"package":"5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"}

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

@ -0,0 +1,47 @@
# 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 = "itertools"
version = "0.8.0"
authors = ["bluss"]
exclude = ["/bors.toml"]
description = "Extra iterator adaptors, iterator methods, free functions, and macros."
documentation = "https://docs.rs/itertools/"
keywords = ["iterator", "data-structure", "zip", "product", "group-by"]
categories = ["algorithms", "rust-patterns"]
license = "MIT/Apache-2.0"
repository = "https://github.com/bluss/rust-itertools"
[package.metadata.release]
no-dev-version = true
[profile.bench]
debug = true
[lib]
test = false
bench = false
[dependencies.either]
version = "1.0"
default-features = false
[dev-dependencies.permutohedron]
version = "0.2"
[dev-dependencies.quickcheck]
version = "0.7"
default-features = false
[dev-dependencies.rand]
version = "0.6"
[features]
default = ["use_std"]
use_std = []

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

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

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

@ -0,0 +1,25 @@
Copyright (c) 2015
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

526
third_party/rust/itertools-0.8.0/README.rst поставляемый Normal file
Просмотреть файл

@ -0,0 +1,526 @@
Itertools
=========
Extra iterator adaptors, functions and macros.
Please read the `API documentation here`__
__ https://docs.rs/itertools/
|build_status|_ |crates|_
.. |build_status| image:: https://travis-ci.org/bluss/rust-itertools.svg?branch=master
.. _build_status: https://travis-ci.org/bluss/rust-itertools
.. |crates| image:: http://meritbadge.herokuapp.com/itertools
.. _crates: https://crates.io/crates/itertools
How to use with cargo:
.. code:: toml
[dependencies]
itertools = "0.8"
How to use in your crate:
.. code:: rust
#[macro_use] extern crate itertools;
use itertools::Itertools;
How to contribute
-----------------
- Fix a bug or implement a new thing
- Include tests for your new feature, preferably a quickcheck test
- Make a Pull Request
For new features, please first consider filing a PR to `rust-lang/rust <https://github.com/rust-lang/rust/>`_,
adding your new feature to the `Iterator` trait of the standard library, if you believe it is reasonable.
If it isn't accepted there, proposing it for inclusion in ``itertools`` is a good idea.
The reason for doing is this is so that we avoid future breakage as with ``.flatten()``.
However, if your feature involves heap allocation, such as storing elements in a ``Vec<T>``,
then it can't be accepted into ``libcore``, and you should propose it for ``itertools`` directly instead.
Recent Changes
--------------
- 0.8.0
- Added new adaptor ``.map_into()`` for conversions using ``Into`` by @vorner
- Improved ``Itertools`` docs by @JohnHeitmann
- The return type of ``.sorted/_by/_by_key()`` is now an iterator, not a Vec.
- The return type of the ``izip!(x, y)`` macro with exactly two arguments
is now the usual ``Iterator::zip``.
- Remove ``.flatten()`` in favour of std's ``.flatten()``
- Deprecate ``.foreach()`` in favour of std's ``.for_each()``
- Deprecate ``.step()`` in favour of std's ``.step_by()``
- Deprecate ``repeat_call`` in favour of std's ``repeat_with``
- Deprecate ``.fold_while()`` in favour of std's ``.try_fold()``
- Require Rust 1.24 as minimal version.
- 0.7.11
- Add convenience methods to ``EitherOrBoth``, making it more similar to ``Option``
and ``Either`` by @jethrogb
- 0.7.10
- No changes.
- 0.7.9
- New inclusion policy: See the readme about suggesting features for std before
accepting them in itertools.
- The ``FoldWhile`` type now implements ``Eq`` and ``PartialEq`` by @jturner314
- 0.7.8
- Add new iterator method ``.tree_fold1()`` which is like ``.fold1()``
except items are combined in a tree structure (see its docs).
By @scottmcm
- Add more ``Debug`` impls by @phimuemue: KMerge, KMergeBy, MergeJoinBy,
ConsTuples, Intersperse, ProcessResults, RcIter, Tee, TupleWindows, Tee,
ZipLongest, ZipEq, Zip.
- 0.7.7
- Add new iterator method ``.into_group_map() -> HashMap<K, Vec<V>>``
which turns an iterator of ``(K, V)`` elements into such a hash table,
where values are grouped by key. By @tobz1000
- Add new free function ``flatten`` for the ``.flatten()`` adaptor.
**NOTE:** recent Rust nightlies have ``Iterator::flatten`` and thus a clash
with our flatten adaptor. One workaround is to use the itertools ``flatten``
free function.
- 0.7.6
- Add new adaptor ``.multi_cartesian_product()`` which is an n-ary product
iterator by @tobz1000
- Add new method ``.sorted_by_key()`` by @Xion
- Provide simpler and faster ``.count()`` for ``.unique()`` and ``.unique_by()``
- 0.7.5
- ``.multipeek()`` now implements ``PeekingNext``, by @nicopap.
- 0.7.4
- Add new adaptor ``.update()`` by @lucasem; this adaptor is used
to modify an element before passing it on in an iterator chain.
- 0.7.3
- Add new method ``.collect_tuple()`` by @matklad; it makes a tuple out of
the iterator's elements if the number of them matches **exactly**.
- Implement ``fold`` and ``collect`` for ``.map_results()`` which means
it reuses the code of the standard ``.map()`` for these methods.
- 0.7.2
- Add new adaptor ``.merge_join_by`` by @srijs; a heterogeneous merge join
for two ordered sequences.
- 0.7.1
- Iterator adaptors and iterators in itertools now use the same ``must_use``
reminder that the standard library adaptors do, by @matematikaedit and @bluss
*“iterator adaptors are lazy and do nothing unless consumed”*.
- 0.7.0
- Faster ``izip!()`` by @krdln
- ``izip!()`` is now a wrapper for repeated regular ``.zip()`` and
a single ``.map()``. This means it optimizes as well as the standard
library ``.zip()`` it uses.
**Note:** ``multizip`` and ``izip!()`` are now different! The former
has a named type but the latter optimizes better.
- Faster ``.unique()``
- ``no_std`` support, which is opt-in!
- Many lovable features are still there without std, like ``izip!()``
or ``.format()`` or ``.merge()``, but not those that use collections.
- Trait bounds were required up front instead of just on the type:
``group_by``'s ``PartialEq`` by @Phlosioneer and ``repeat_call``'s
``FnMut``.
- Removed deprecated constructor ``Zip::new`` — use ``izip!()`` or ``multizip()``
- 0.6.5
- Fix bug in ``.cartesian_product()``'s fold (which only was visible for
unfused iterators).
- 0.6.4
- Add specific ``fold`` implementations for ``.cartesian_product()`` and
``cons_tuples()``, which improves their performance in fold, foreach, and
iterator consumers derived from them.
- 0.6.3
- Add iterator adaptor ``.positions(predicate)`` by @tmccombs
- 0.6.2
- Add function ``process_results`` which can “lift” a function of the regular
values of an iterator so that it can process the ``Ok`` values from an
iterator of ``Results`` instead, by @shepmaster
- Add iterator method ``.concat()`` which combines all iterator elements
into a single collection using the ``Extend`` trait, by @srijs
- 0.6.1
- Better size hint testing and subsequent size hint bugfixes by @rkarp.
Fixes bugs in product, interleave_shortest size hints.
- New iterator method ``.all_equal()`` by @phimuemue
- 0.6.0
- Deprecated names were removed in favour of their replacements
- ``.flatten()`` does not implement double ended iteration anymore
- ``.fold_while()`` uses ``&mut self`` and returns ``FoldWhile<T>``, for
composability (#168)
- ``.foreach()`` and ``.fold1()`` use ``self``, like ``.fold()`` does.
- ``.combinations(0)`` now produces a single empty vector. (#174)
- 0.5.10
- Add itertools method ``.kmerge_by()`` (and corresponding free function)
- Relaxed trait requirement of ``.kmerge()`` and ``.minmax()`` to PartialOrd.
- 0.5.9
- Add multipeek method ``.reset_peek()``
- Add categories
- 0.5.8
- Add iterator adaptor ``.peeking_take_while()`` and its trait ``PeekingNext``.
- 0.5.7
- Add iterator adaptor ``.with_position()``
- Fix multipeek's performance for long peeks by using ``VecDeque``.
- 0.5.6
- Add ``.map_results()``
- 0.5.5
- Many more adaptors now implement ``Debug``
- Add free function constructor ``repeat_n``. ``RepeatN::new`` is now
deprecated.
- 0.5.4
- Add infinite generator function ``iterate``, that takes a seed and a
closure.
- 0.5.3
- Special-cased ``.fold()`` for flatten and put back. ``.foreach()``
now uses fold on the iterator, to pick up any iterator specific loop
implementation.
- ``.combinations(n)`` asserts up front that ``n != 0``, instead of
running into an error on the second iterator element.
- 0.5.2
- Add ``.tuples::<T>()`` that iterates by two, three or four elements at
a time (where ``T`` is a tuple type).
- Add ``.tuple_windows::<T>()`` that iterates using a window of the
two, three or four most recent elements.
- Add ``.next_tuple::<T>()`` method, that picks the next two, three or four
elements in one go.
- ``.interleave()`` now has an accurate size hint.
- 0.5.1
- Workaround module/function name clash that made racer crash on completing
itertools. Only internal changes needed.
- 0.5.0
- `Release announcement <http://bluss.github.io/rust/2016/09/26/itertools-0.5.0/>`_
- Renamed:
- combinations is now tuple_combinations
- combinations_n to combinations
- group_by_lazy, chunks_lazy to group_by, chunks
- Unfold::new to unfold()
- RepeatCall::new to repeat_call()
- Zip::new to multizip
- PutBack::new, PutBackN::new to put_back, put_back_n
- PutBack::with_value is now a builder setter, not a constructor
- MultiPeek::new, .multipeek() to multipeek()
- format to format_with and format_default to format
- .into_rc() to rciter
- ``Partition`` enum is now ``Either``
- Module reorganization:
- All iterator structs are under ``itertools::structs`` but also
reexported to the top level, for backwards compatibility
- All free functions are reexported at the root, ``itertools::free`` will
be removed in the next version
- Removed:
- ZipSlices, use .zip() instead
- .enumerate_from(), ZipTrusted, due to being unstable
- .mend_slices(), moved to crate odds
- Stride, StrideMut, moved to crate odds
- linspace(), moved to crate itertools-num
- .sort_by(), use .sorted_by()
- .is_empty_hint(), use .size_hint()
- .dropn(), use .dropping()
- .map_fn(), use .map()
- .slice(), use .take() / .skip()
- helper traits in misc
- ``new`` constructors on iterator structs, use Itertools trait or free
functions instead
- ``itertools::size_hint`` is now private
- Behaviour changes:
- format and format_with helpers now panic if you try to format them more
than once.
- ``repeat_call`` is not double ended anymore
- New features:
- tuple flattening iterator is constructible with ``cons_tuples``
- itertools reexports ``Either`` from the ``either`` crate. ``Either<L, R>``
is an iterator when ``L, R`` are.
- ``MinMaxResult`` now implements Copy and Clone
- tuple_combinations supports 1-4 tuples of combinations (previously just 2)
- 0.4.19
- Add ``.minmax_by()``
- Add ``itertools::free::cloned``
- Add ``itertools::free::rciter``
- Improve ``.step(n)`` slightly to take advantage of specialized Fuse better.
- 0.4.18
- Only changes related to the "unstable" crate feature. This feature is more
or less deprecated.
- Use deprecated warnings when unstable is enabled. .enumerate_from() will
be removed imminently since it's using a deprecated libstd trait.
- 0.4.17
- Fix bug in .kmerge() that caused it to often produce the wrong order (#134)
- 0.4.16
- Improve precision of the interleave_shortest adaptor's size hint (it is
now computed exactly when possible).
- 0.4.15
- Fixup on top of the workaround in 0.4.14. A function in itertools::free was
removed by mistake and now it is added back again.
- 0.4.14
- Workaround an upstream regression in a rust nightly build that broke
compilation of of itertools::free::{interleave, merge}
- 0.4.13
- Add .minmax() and .minmax_by_key(), iterator methods for finding both minimum
and maximum in one scan.
- Add .format_default(), a simpler version of .format() (lazy formatting
for iterators).
- 0.4.12
- Add .zip_eq(), an adaptor like .zip() except it ensures iterators
of inequal length don't pass silently (instead it panics).
- Add .fold_while(), an iterator method that is a fold that
can short-circuit.
- Add .partition_map(), an iterator method that can separate elements
into two collections.
- 0.4.11
- Add .get() for Stride{,Mut} and .get_mut() for StrideMut
- 0.4.10
- Improve performance of .kmerge()
- 0.4.9
- Add k-ary merge adaptor .kmerge()
- Fix a bug in .islice() with ranges a..b where a > b.
- 0.4.8
- Implement Clone, Debug for Linspace
- 0.4.7
- Add function diff_with() that compares two iterators
- Add .combinations_n(), an n-ary combinations iterator
- Add methods PutBack::with_value and PutBack::into_parts.
- 0.4.6
- Add method .sorted()
- Add module ``itertools::free`` with free function variants of common
iterator adaptors and methods.
For example ``enumerate(iterable)``, ``rev(iterable)``, and so on.
- 0.4.5
- Add .flatten()
- 0.4.4
- Allow composing ZipSlices with itself
- 0.4.3
- Write iproduct!() as a single expression; this allows temporary values
in its arguments.
- 0.4.2
- Add .fold_options()
- Require Rust 1.1 or later
- 0.4.1
- Update .dropping() to take advantage of .nth()
- 0.4.0
- .merge(), .unique() and .dedup() now perform better due to not using
function pointers
- Add free functions enumerate() and rev()
- Breaking changes:
- Return types of .merge() and .merge_by() renamed and changed
- Method Merge::new removed
- .merge_by() now takes a closure that returns bool.
- Return type of .dedup() changed
- Return type of .mend_slices() changed
- Return type of .unique() changed
- Removed function times(), struct Times: use a range instead
- Removed deprecated macro icompr!()
- Removed deprecated FnMap and method .fn_map(): use .map_fn()
- .interleave_shortest() is no longer guaranteed to act like fused
- 0.3.25
- Rename .sort_by() to .sorted_by(). Old name is deprecated.
- Fix well-formedness warnings from RFC 1214, no user visible impact
- 0.3.24
- Improve performance of .merge()'s ordering function slightly
- 0.3.23
- Added .chunks(), similar to (and based on) .group_by_lazy().
- Tweak linspace to match numpy.linspace and make it double ended.
- 0.3.22
- Added ZipSlices, a fast zip for slices
- 0.3.21
- Remove `Debug` impl for `Format`, it will have different use later
- 0.3.20
- Optimize .group_by_lazy()
- 0.3.19
- Added .group_by_lazy(), a possibly nonallocating group by
- Added .format(), a nonallocating formatting helper for iterators
- Remove uses of RandomAccessIterator since it has been deprecated in rust.
- 0.3.17
- Added (adopted) Unfold from rust
- 0.3.16
- Added adaptors .unique(), .unique_by()
- 0.3.15
- Added method .sort_by()
- 0.3.14
- Added adaptor .while_some()
- 0.3.13
- Added adaptor .interleave_shortest()
- Added adaptor .pad_using()
- 0.3.11
- Added assert_equal function
- 0.3.10
- Bugfix .combinations() size_hint.
- 0.3.8
- Added source RepeatCall
- 0.3.7
- Added adaptor PutBackN
- Added adaptor .combinations()
- 0.3.6
- Added itertools::partition, partition a sequence in place based on a predicate.
- Deprecate icompr!() with no replacement.
- 0.3.5
- .map_fn() replaces deprecated .fn_map().
- 0.3.4
- .take_while_ref() *by-ref adaptor*
- .coalesce() *adaptor*
- .mend_slices() *adaptor*
- 0.3.3
- .dropping_back() *method*
- .fold1() *method*
- .is_empty_hint() *method*
License
-------
Dual-licensed to be compatible with the Rust project.
Licensed under the Apache License, Version 2.0
http://www.apache.org/licenses/LICENSE-2.0 or the MIT license
http://opensource.org/licenses/MIT, at your
option. This file may not be copied, modified, or distributed
except according to those terms.

733
third_party/rust/itertools-0.8.0/benches/bench1.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,733 @@
#![feature(test)]
extern crate test;
#[macro_use] extern crate itertools;
use test::{black_box};
use itertools::Itertools;
use itertools::free::cloned;
use std::iter::repeat;
use std::cmp;
use std::ops::Add;
mod extra;
use extra::ZipSlices;
#[bench]
fn slice_iter(b: &mut test::Bencher)
{
let xs: Vec<_> = repeat(1i32).take(20).collect();
b.iter(|| for elt in xs.iter() {
test::black_box(elt);
})
}
#[bench]
fn slice_iter_rev(b: &mut test::Bencher)
{
let xs: Vec<_> = repeat(1i32).take(20).collect();
b.iter(|| for elt in xs.iter().rev() {
test::black_box(elt);
})
}
#[bench]
fn zip_default_zip(b: &mut test::Bencher)
{
let xs = vec![0; 1024];
let ys = vec![0; 768];
let xs = black_box(xs);
let ys = black_box(ys);
b.iter(|| {
for (&x, &y) in xs.iter().zip(&ys) {
test::black_box(x);
test::black_box(y);
}
})
}
#[bench]
fn zipdot_i32_default_zip(b: &mut test::Bencher)
{
let xs = vec![2; 1024];
let ys = vec![2; 768];
let xs = black_box(xs);
let ys = black_box(ys);
b.iter(|| {
let mut s = 0;
for (&x, &y) in xs.iter().zip(&ys) {
s += x * y;
}
s
})
}
#[bench]
fn zipdot_f32_default_zip(b: &mut test::Bencher)
{
let xs = vec![2f32; 1024];
let ys = vec![2f32; 768];
let xs = black_box(xs);
let ys = black_box(ys);
b.iter(|| {
let mut s = 0.;
for (&x, &y) in xs.iter().zip(&ys) {
s += x * y;
}
s
})
}
#[bench]
fn zip_default_zip3(b: &mut test::Bencher)
{
let xs = vec![0; 1024];
let ys = vec![0; 768];
let zs = vec![0; 766];
let xs = black_box(xs);
let ys = black_box(ys);
let zs = black_box(zs);
b.iter(|| {
for ((&x, &y), &z) in xs.iter().zip(&ys).zip(&zs) {
test::black_box(x);
test::black_box(y);
test::black_box(z);
}
})
}
#[bench]
fn zip_slices_ziptuple(b: &mut test::Bencher)
{
let xs = vec![0; 1024];
let ys = vec![0; 768];
b.iter(|| {
let xs = black_box(&xs);
let ys = black_box(&ys);
for (&x, &y) in itertools::multizip((xs, ys)) {
test::black_box(x);
test::black_box(y);
}
})
}
#[bench]
fn zipslices(b: &mut test::Bencher)
{
let xs = vec![0; 1024];
let ys = vec![0; 768];
let xs = black_box(xs);
let ys = black_box(ys);
b.iter(|| {
for (&x, &y) in ZipSlices::new(&xs, &ys) {
test::black_box(x);
test::black_box(y);
}
})
}
#[bench]
fn zipslices_mut(b: &mut test::Bencher)
{
let xs = vec![0; 1024];
let ys = vec![0; 768];
let xs = black_box(xs);
let mut ys = black_box(ys);
b.iter(|| {
for (&x, &mut y) in ZipSlices::from_slices(&xs[..], &mut ys[..]) {
test::black_box(x);
test::black_box(y);
}
})
}
#[bench]
fn zipdot_i32_zipslices(b: &mut test::Bencher)
{
let xs = vec![2; 1024];
let ys = vec![2; 768];
let xs = black_box(xs);
let ys = black_box(ys);
b.iter(|| {
let mut s = 0i32;
for (&x, &y) in ZipSlices::new(&xs, &ys) {
s += x * y;
}
s
})
}
#[bench]
fn zipdot_f32_zipslices(b: &mut test::Bencher)
{
let xs = vec![2f32; 1024];
let ys = vec![2f32; 768];
let xs = black_box(xs);
let ys = black_box(ys);
b.iter(|| {
let mut s = 0.;
for (&x, &y) in ZipSlices::new(&xs, &ys) {
s += x * y;
}
s
})
}
#[bench]
fn zip_checked_counted_loop(b: &mut test::Bencher)
{
let xs = vec![0; 1024];
let ys = vec![0; 768];
let xs = black_box(xs);
let ys = black_box(ys);
b.iter(|| {
// Must slice to equal lengths, and then bounds checks are eliminated!
let len = cmp::min(xs.len(), ys.len());
let xs = &xs[..len];
let ys = &ys[..len];
for i in 0..len {
let x = xs[i];
let y = ys[i];
test::black_box(x);
test::black_box(y);
}
})
}
#[bench]
fn zipdot_i32_checked_counted_loop(b: &mut test::Bencher)
{
let xs = vec![2; 1024];
let ys = vec![2; 768];
let xs = black_box(xs);
let ys = black_box(ys);
b.iter(|| {
// Must slice to equal lengths, and then bounds checks are eliminated!
let len = cmp::min(xs.len(), ys.len());
let xs = &xs[..len];
let ys = &ys[..len];
let mut s = 0i32;
for i in 0..len {
s += xs[i] * ys[i];
}
s
})
}
#[bench]
fn zipdot_f32_checked_counted_loop(b: &mut test::Bencher)
{
let xs = vec![2f32; 1024];
let ys = vec![2f32; 768];
let xs = black_box(xs);
let ys = black_box(ys);
b.iter(|| {
// Must slice to equal lengths, and then bounds checks are eliminated!
let len = cmp::min(xs.len(), ys.len());
let xs = &xs[..len];
let ys = &ys[..len];
let mut s = 0.;
for i in 0..len {
s += xs[i] * ys[i];
}
s
})
}
#[bench]
fn zipdot_f32_checked_counted_unrolled_loop(b: &mut test::Bencher)
{
let xs = vec![2f32; 1024];
let ys = vec![2f32; 768];
let xs = black_box(xs);
let ys = black_box(ys);
b.iter(|| {
// Must slice to equal lengths, and then bounds checks are eliminated!
let len = cmp::min(xs.len(), ys.len());
let mut xs = &xs[..len];
let mut ys = &ys[..len];
let mut s = 0.;
let (mut p0, mut p1, mut p2, mut p3, mut p4, mut p5, mut p6, mut p7) =
(0., 0., 0., 0., 0., 0., 0., 0.);
// how to unroll and have bounds checks eliminated (by cristicbz)
// split sum into eight parts to enable vectorization (by bluss)
while xs.len() >= 8 {
p0 += xs[0] * ys[0];
p1 += xs[1] * ys[1];
p2 += xs[2] * ys[2];
p3 += xs[3] * ys[3];
p4 += xs[4] * ys[4];
p5 += xs[5] * ys[5];
p6 += xs[6] * ys[6];
p7 += xs[7] * ys[7];
xs = &xs[8..];
ys = &ys[8..];
}
s += p0 + p4;
s += p1 + p5;
s += p2 + p6;
s += p3 + p7;
for i in 0..xs.len() {
s += xs[i] * ys[i];
}
s
})
}
#[bench]
fn zip_unchecked_counted_loop(b: &mut test::Bencher)
{
let xs = vec![0; 1024];
let ys = vec![0; 768];
let xs = black_box(xs);
let ys = black_box(ys);
b.iter(|| {
let len = cmp::min(xs.len(), ys.len());
for i in 0..len {
unsafe {
let x = *xs.get_unchecked(i);
let y = *ys.get_unchecked(i);
test::black_box(x);
test::black_box(y);
}
}
})
}
#[bench]
fn zipdot_i32_unchecked_counted_loop(b: &mut test::Bencher)
{
let xs = vec![2; 1024];
let ys = vec![2; 768];
let xs = black_box(xs);
let ys = black_box(ys);
b.iter(|| {
let len = cmp::min(xs.len(), ys.len());
let mut s = 0i32;
for i in 0..len {
unsafe {
let x = *xs.get_unchecked(i);
let y = *ys.get_unchecked(i);
s += x * y;
}
}
s
})
}
#[bench]
fn zipdot_f32_unchecked_counted_loop(b: &mut test::Bencher)
{
let xs = vec![2.; 1024];
let ys = vec![2.; 768];
let xs = black_box(xs);
let ys = black_box(ys);
b.iter(|| {
let len = cmp::min(xs.len(), ys.len());
let mut s = 0f32;
for i in 0..len {
unsafe {
let x = *xs.get_unchecked(i);
let y = *ys.get_unchecked(i);
s += x * y;
}
}
s
})
}
#[bench]
fn zip_unchecked_counted_loop3(b: &mut test::Bencher)
{
let xs = vec![0; 1024];
let ys = vec![0; 768];
let zs = vec![0; 766];
let xs = black_box(xs);
let ys = black_box(ys);
let zs = black_box(zs);
b.iter(|| {
let len = cmp::min(xs.len(), cmp::min(ys.len(), zs.len()));
for i in 0..len {
unsafe {
let x = *xs.get_unchecked(i);
let y = *ys.get_unchecked(i);
let z = *zs.get_unchecked(i);
test::black_box(x);
test::black_box(y);
test::black_box(z);
}
}
})
}
#[bench]
fn group_by_lazy_1(b: &mut test::Bencher) {
let mut data = vec![0; 1024];
for (index, elt) in data.iter_mut().enumerate() {
*elt = index / 10;
}
let data = test::black_box(data);
b.iter(|| {
for (_key, group) in &data.iter().group_by(|elt| **elt) {
for elt in group {
test::black_box(elt);
}
}
})
}
#[bench]
fn group_by_lazy_2(b: &mut test::Bencher) {
let mut data = vec![0; 1024];
for (index, elt) in data.iter_mut().enumerate() {
*elt = index / 2;
}
let data = test::black_box(data);
b.iter(|| {
for (_key, group) in &data.iter().group_by(|elt| **elt) {
for elt in group {
test::black_box(elt);
}
}
})
}
#[bench]
fn slice_chunks(b: &mut test::Bencher) {
let data = vec![0; 1024];
let data = test::black_box(data);
let sz = test::black_box(10);
b.iter(|| {
for group in data.chunks(sz) {
for elt in group {
test::black_box(elt);
}
}
})
}
#[bench]
fn chunks_lazy_1(b: &mut test::Bencher) {
let data = vec![0; 1024];
let data = test::black_box(data);
let sz = test::black_box(10);
b.iter(|| {
for group in &data.iter().chunks(sz) {
for elt in group {
test::black_box(elt);
}
}
})
}
#[bench]
fn equal(b: &mut test::Bencher) {
let data = vec![7; 1024];
let l = data.len();
let alpha = test::black_box(&data[1..]);
let beta = test::black_box(&data[..l - 1]);
b.iter(|| {
itertools::equal(alpha, beta)
})
}
#[bench]
fn merge_default(b: &mut test::Bencher) {
let mut data1 = vec![0; 1024];
let mut data2 = vec![0; 800];
let mut x = 0;
for (_, elt) in data1.iter_mut().enumerate() {
*elt = x;
x += 1;
}
let mut y = 0;
for (i, elt) in data2.iter_mut().enumerate() {
*elt += y;
if i % 3 == 0 {
y += 3;
} else {
y += 0;
}
}
let data1 = test::black_box(data1);
let data2 = test::black_box(data2);
b.iter(|| {
data1.iter().merge(&data2).count()
})
}
#[bench]
fn merge_by_cmp(b: &mut test::Bencher) {
let mut data1 = vec![0; 1024];
let mut data2 = vec![0; 800];
let mut x = 0;
for (_, elt) in data1.iter_mut().enumerate() {
*elt = x;
x += 1;
}
let mut y = 0;
for (i, elt) in data2.iter_mut().enumerate() {
*elt += y;
if i % 3 == 0 {
y += 3;
} else {
y += 0;
}
}
let data1 = test::black_box(data1);
let data2 = test::black_box(data2);
b.iter(|| {
data1.iter().merge_by(&data2, PartialOrd::le).count()
})
}
#[bench]
fn merge_by_lt(b: &mut test::Bencher) {
let mut data1 = vec![0; 1024];
let mut data2 = vec![0; 800];
let mut x = 0;
for (_, elt) in data1.iter_mut().enumerate() {
*elt = x;
x += 1;
}
let mut y = 0;
for (i, elt) in data2.iter_mut().enumerate() {
*elt += y;
if i % 3 == 0 {
y += 3;
} else {
y += 0;
}
}
let data1 = test::black_box(data1);
let data2 = test::black_box(data2);
b.iter(|| {
data1.iter().merge_by(&data2, |a, b| a <= b).count()
})
}
#[bench]
fn kmerge_default(b: &mut test::Bencher) {
let mut data1 = vec![0; 1024];
let mut data2 = vec![0; 800];
let mut x = 0;
for (_, elt) in data1.iter_mut().enumerate() {
*elt = x;
x += 1;
}
let mut y = 0;
for (i, elt) in data2.iter_mut().enumerate() {
*elt += y;
if i % 3 == 0 {
y += 3;
} else {
y += 0;
}
}
let data1 = test::black_box(data1);
let data2 = test::black_box(data2);
let its = &[data1.iter(), data2.iter()];
b.iter(|| {
its.iter().cloned().kmerge().count()
})
}
#[bench]
fn kmerge_tenway(b: &mut test::Bencher) {
let mut data = vec![0; 10240];
let mut state = 1729u16;
fn rng(state: &mut u16) -> u16 {
let new = state.wrapping_mul(31421) + 6927;
*state = new;
new
}
for elt in &mut data {
*elt = rng(&mut state);
}
let mut chunks = Vec::new();
let mut rest = &mut data[..];
while rest.len() > 0 {
let chunk_len = 1 + rng(&mut state) % 512;
let chunk_len = cmp::min(rest.len(), chunk_len as usize);
let (fst, tail) = {rest}.split_at_mut(chunk_len);
fst.sort();
chunks.push(fst.iter().cloned());
rest = tail;
}
// println!("Chunk lengths: {}", chunks.iter().format_with(", ", |elt, f| f(&elt.len())));
b.iter(|| {
chunks.iter().cloned().kmerge().count()
})
}
fn fast_integer_sum<I>(iter: I) -> I::Item
where I: IntoIterator,
I::Item: Default + Add<Output=I::Item>
{
iter.into_iter().fold(<_>::default(), |x, y| x + y)
}
#[bench]
fn step_vec_2(b: &mut test::Bencher) {
let v = vec![0; 1024];
b.iter(|| {
fast_integer_sum(cloned(v.iter().step(2)))
});
}
#[bench]
fn step_vec_10(b: &mut test::Bencher) {
let v = vec![0; 1024];
b.iter(|| {
fast_integer_sum(cloned(v.iter().step(10)))
});
}
#[bench]
fn step_range_2(b: &mut test::Bencher) {
let v = black_box(0..1024);
b.iter(|| {
fast_integer_sum(v.clone().step(2))
});
}
#[bench]
fn step_range_10(b: &mut test::Bencher) {
let v = black_box(0..1024);
b.iter(|| {
fast_integer_sum(v.clone().step(10))
});
}
#[bench]
fn cartesian_product_iterator(b: &mut test::Bencher)
{
let xs = vec![0; 16];
b.iter(|| {
let mut sum = 0;
for (&x, &y, &z) in iproduct!(&xs, &xs, &xs) {
sum += x;
sum += y;
sum += z;
}
sum
})
}
#[bench]
fn cartesian_product_fold(b: &mut test::Bencher)
{
let xs = vec![0; 16];
b.iter(|| {
let mut sum = 0;
iproduct!(&xs, &xs, &xs).fold((), |(), (&x, &y, &z)| {
sum += x;
sum += y;
sum += z;
});
sum
})
}
#[bench]
fn multi_cartesian_product_iterator(b: &mut test::Bencher)
{
let xs = [vec![0; 16], vec![0; 16], vec![0; 16]];
b.iter(|| {
let mut sum = 0;
for x in xs.into_iter().multi_cartesian_product() {
sum += x[0];
sum += x[1];
sum += x[2];
}
sum
})
}
#[bench]
fn multi_cartesian_product_fold(b: &mut test::Bencher)
{
let xs = [vec![0; 16], vec![0; 16], vec![0; 16]];
b.iter(|| {
let mut sum = 0;
xs.into_iter().multi_cartesian_product().fold((), |(), x| {
sum += x[0];
sum += x[1];
sum += x[2];
});
sum
})
}
#[bench]
fn cartesian_product_nested_for(b: &mut test::Bencher)
{
let xs = vec![0; 16];
b.iter(|| {
let mut sum = 0;
for &x in &xs {
for &y in &xs {
for &z in &xs {
sum += x;
sum += y;
sum += z;
}
}
}
sum
})
}

4
third_party/rust/itertools-0.8.0/benches/extra/mod.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,4 @@
pub use self::zipslices::ZipSlices;
mod zipslices;

189
third_party/rust/itertools-0.8.0/benches/extra/zipslices.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,189 @@
use std::cmp;
// Note: There are different ways to implement ZipSlices.
// This version performed the best in benchmarks.
//
// I also implemented a version with three pointes (tptr, tend, uptr),
// that mimiced slice::Iter and only checked bounds by using tptr == tend,
// but that was inferior to this solution.
/// An iterator which iterates two slices simultaneously.
///
/// `ZipSlices` acts like a double-ended `.zip()` iterator.
///
/// It was intended to be more efficient than `.zip()`, and it was, then
/// rustc changed how it optimizes so it can not promise improved performance
/// at this time.
///
/// Note that elements past the end of the shortest of the two slices are ignored.
///
/// Iterator element type for `ZipSlices<T, U>` is `(T::Item, U::Item)`. For example,
/// for a `ZipSlices<&'a [A], &'b mut [B]>`, the element type is `(&'a A, &'b mut B)`.
#[derive(Clone)]
pub struct ZipSlices<T, U> {
t: T,
u: U,
len: usize,
index: usize,
}
impl<'a, 'b, A, B> ZipSlices<&'a [A], &'b [B]> {
/// Create a new `ZipSlices` from slices `a` and `b`.
///
/// Act like a double-ended `.zip()` iterator, but more efficiently.
///
/// Note that elements past the end of the shortest of the two slices are ignored.
#[inline(always)]
pub fn new(a: &'a [A], b: &'b [B]) -> Self {
let minl = cmp::min(a.len(), b.len());
ZipSlices {
t: a,
u: b,
len: minl,
index: 0,
}
}
}
impl<T, U> ZipSlices<T, U>
where T: Slice,
U: Slice
{
/// Create a new `ZipSlices` from slices `a` and `b`.
///
/// Act like a double-ended `.zip()` iterator, but more efficiently.
///
/// Note that elements past the end of the shortest of the two slices are ignored.
#[inline(always)]
pub fn from_slices(a: T, b: U) -> Self {
let minl = cmp::min(a.len(), b.len());
ZipSlices {
t: a,
u: b,
len: minl,
index: 0,
}
}
}
impl<T, U> Iterator for ZipSlices<T, U>
where T: Slice,
U: Slice
{
type Item = (T::Item, U::Item);
#[inline(always)]
fn next(&mut self) -> Option<Self::Item> {
unsafe {
if self.index >= self.len {
None
} else {
let i = self.index;
self.index += 1;
Some((
self.t.get_unchecked(i),
self.u.get_unchecked(i)))
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len - self.index;
(len, Some(len))
}
}
impl<T, U> DoubleEndedIterator for ZipSlices<T, U>
where T: Slice,
U: Slice
{
#[inline(always)]
fn next_back(&mut self) -> Option<Self::Item> {
unsafe {
if self.index >= self.len {
None
} else {
self.len -= 1;
let i = self.len;
Some((
self.t.get_unchecked(i),
self.u.get_unchecked(i)))
}
}
}
}
impl<T, U> ExactSizeIterator for ZipSlices<T, U>
where T: Slice,
U: Slice
{}
unsafe impl<T, U> Slice for ZipSlices<T, U>
where T: Slice,
U: Slice
{
type Item = (T::Item, U::Item);
fn len(&self) -> usize {
self.len - self.index
}
unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item {
(self.t.get_unchecked(i),
self.u.get_unchecked(i))
}
}
/// A helper trait to let `ZipSlices` accept both `&[T]` and `&mut [T]`.
///
/// Unsafe trait because:
///
/// - Implementors must guarantee that `get_unchecked` is valid for all indices `0..len()`.
pub unsafe trait Slice {
/// The type of a reference to the slice's elements
type Item;
#[doc(hidden)]
fn len(&self) -> usize;
#[doc(hidden)]
unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item;
}
unsafe impl<'a, T> Slice for &'a [T] {
type Item = &'a T;
#[inline(always)]
fn len(&self) -> usize { (**self).len() }
#[inline(always)]
unsafe fn get_unchecked(&mut self, i: usize) -> &'a T {
debug_assert!(i < self.len());
(**self).get_unchecked(i)
}
}
unsafe impl<'a, T> Slice for &'a mut [T] {
type Item = &'a mut T;
#[inline(always)]
fn len(&self) -> usize { (**self).len() }
#[inline(always)]
unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T {
debug_assert!(i < self.len());
// override the lifetime constraints of &mut &'a mut [T]
(*(*self as *mut [T])).get_unchecked_mut(i)
}
}
#[test]
fn zipslices() {
let xs = [1, 2, 3, 4, 5, 6];
let ys = [1, 2, 3, 7];
::itertools::assert_equal(ZipSlices::new(&xs, &ys), xs.iter().zip(&ys));
let xs = [1, 2, 3, 4, 5, 6];
let mut ys = [0; 6];
for (x, y) in ZipSlices::from_slices(&xs[..], &mut ys[..]) {
*y = *x;
}
::itertools::assert_equal(&xs, &ys);
}

126
third_party/rust/itertools-0.8.0/benches/tree_fold1.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,126 @@
#![feature(test)]
extern crate test;
extern crate itertools;
use itertools::Itertools;
use itertools::cloned;
use test::Bencher;
trait IterEx : Iterator {
// Another efficient implementation against which to compare,
// but needs `std` so is less desirable.
fn tree_fold1_vec<F>(self, mut f: F) -> Option<Self::Item>
where F: FnMut(Self::Item, Self::Item) -> Self::Item,
Self: Sized,
{
let hint = self.size_hint().0;
let cap = std::mem::size_of::<usize>() * 8 - hint.leading_zeros() as usize;
let mut stack = Vec::with_capacity(cap);
self.enumerate().foreach(|(mut i, mut x)| {
while (i & 1) != 0 {
x = f(stack.pop().unwrap(), x);
i >>= 1;
}
stack.push(x);
});
stack.into_iter().fold1(f)
}
}
impl<T:Iterator> IterEx for T {}
macro_rules! def_benchs {
($N:expr,
$FUN:ident,
$BENCH_NAME:ident,
) => (
mod $BENCH_NAME {
use super::*;
#[bench]
fn sum(b: &mut Bencher) {
let v: Vec<u32> = (0.. $N).collect();
b.iter(|| {
cloned(&v).$FUN(|x, y| x + y)
});
}
#[bench]
fn complex_iter(b: &mut Bencher) {
let u = (3..).take($N / 2);
let v = (5..).take($N / 2);
let it = u.chain(v);
b.iter(|| {
it.clone().map(|x| x as f32).$FUN(f32::atan2)
});
}
#[bench]
fn string_format(b: &mut Bencher) {
// This goes quadratic with linear `fold1`, so use a smaller
// size to not waste too much time in travis. The allocations
// in here are so expensive anyway that it'll still take
// way longer per iteration than the other two benchmarks.
let v: Vec<u32> = (0.. ($N/4)).collect();
b.iter(|| {
cloned(&v).map(|x| x.to_string()).$FUN(|x, y| format!("{} + {}", x, y))
});
}
}
)
}
def_benchs!{
10_000,
fold1,
fold1_10k,
}
def_benchs!{
10_000,
tree_fold1,
tree_fold1_stack_10k,
}
def_benchs!{
10_000,
tree_fold1_vec,
tree_fold1_vec_10k,
}
def_benchs!{
100,
fold1,
fold1_100,
}
def_benchs!{
100,
tree_fold1,
tree_fold1_stack_100,
}
def_benchs!{
100,
tree_fold1_vec,
tree_fold1_vec_100,
}
def_benchs!{
8,
fold1,
fold1_08,
}
def_benchs!{
8,
tree_fold1,
tree_fold1_stack_08,
}
def_benchs!{
8,
tree_fold1_vec,
tree_fold1_vec_08,
}

97
third_party/rust/itertools-0.8.0/benches/tuple_combinations.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,97 @@
#![feature(test)]
extern crate test;
extern crate itertools;
use test::{black_box, Bencher};
use itertools::Itertools;
// approximate 100_000 iterations for each combination
const N1: usize = 100_000;
const N2: usize = 448;
const N3: usize = 86;
const N4: usize = 41;
#[bench]
fn comb_for1(b: &mut Bencher) {
b.iter(|| {
for i in 0..N1 {
black_box(i);
}
});
}
#[bench]
fn comb_for2(b: &mut Bencher) {
b.iter(|| {
for i in 0..N2 {
for j in (i + 1)..N2 {
black_box(i + j);
}
}
});
}
#[bench]
fn comb_for3(b: &mut Bencher) {
b.iter(|| {
for i in 0..N3 {
for j in (i + 1)..N3 {
for k in (j + 1)..N3 {
black_box(i + j + k);
}
}
}
});
}
#[bench]
fn comb_for4(b: &mut Bencher) {
b.iter(|| {
for i in 0..N4 {
for j in (i + 1)..N4 {
for k in (j + 1)..N4 {
for l in (k + 1)..N4 {
black_box(i + j + k + l);
}
}
}
}
});
}
#[bench]
fn comb_c1(b: &mut Bencher) {
b.iter(|| {
for (i,) in (0..N1).tuple_combinations() {
black_box(i);
}
});
}
#[bench]
fn comb_c2(b: &mut Bencher) {
b.iter(|| {
for (i, j) in (0..N2).tuple_combinations() {
black_box(i + j);
}
});
}
#[bench]
fn comb_c3(b: &mut Bencher) {
b.iter(|| {
for (i, j, k) in (0..N3).tuple_combinations() {
black_box(i + j + k);
}
});
}
#[bench]
fn comb_c4(b: &mut Bencher) {
b.iter(|| {
for (i, j, k, l) in (0..N4).tuple_combinations() {
black_box(i + j + k + l);
}
});
}

190
third_party/rust/itertools-0.8.0/benches/tuples.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,190 @@
#![feature(test)]
extern crate test;
extern crate itertools;
use test::Bencher;
use itertools::Itertools;
fn s1(a: u32) -> u32 {
a
}
fn s2(a: u32, b: u32) -> u32 {
a + b
}
fn s3(a: u32, b: u32, c: u32) -> u32 {
a + b + c
}
fn s4(a: u32, b: u32, c: u32, d: u32) -> u32 {
a + b + c + d
}
fn sum_s1(s: &[u32]) -> u32 {
s1(s[0])
}
fn sum_s2(s: &[u32]) -> u32 {
s2(s[0], s[1])
}
fn sum_s3(s: &[u32]) -> u32 {
s3(s[0], s[1], s[2])
}
fn sum_s4(s: &[u32]) -> u32 {
s4(s[0], s[1], s[2], s[3])
}
fn sum_t1(s: &(&u32, )) -> u32 {
s1(*s.0)
}
fn sum_t2(s: &(&u32, &u32)) -> u32 {
s2(*s.0, *s.1)
}
fn sum_t3(s: &(&u32, &u32, &u32)) -> u32 {
s3(*s.0, *s.1, *s.2)
}
fn sum_t4(s: &(&u32, &u32, &u32, &u32)) -> u32 {
s4(*s.0, *s.1, *s.2, *s.3)
}
macro_rules! def_benchs {
($N:expr;
$TUPLE_FUN:ident,
$TUPLES:ident,
$TUPLE_WINDOWS:ident;
$SLICE_FUN:ident,
$CHUNKS:ident,
$WINDOWS:ident;
$FOR_CHUNKS:ident,
$FOR_WINDOWS:ident
) => (
#[bench]
fn $FOR_CHUNKS(b: &mut Bencher) {
let v: Vec<u32> = (0.. $N * 1_000).collect();
let mut s = 0;
b.iter(|| {
let mut j = 0;
for _ in 0..1_000 {
s += $SLICE_FUN(&v[j..(j + $N)]);
j += $N;
}
s
});
}
#[bench]
fn $FOR_WINDOWS(b: &mut Bencher) {
let v: Vec<u32> = (0..1_000).collect();
let mut s = 0;
b.iter(|| {
for i in 0..(1_000 - $N) {
s += $SLICE_FUN(&v[i..(i + $N)]);
}
s
});
}
#[bench]
fn $TUPLES(b: &mut Bencher) {
let v: Vec<u32> = (0.. $N * 1_000).collect();
let mut s = 0;
b.iter(|| {
for x in v.iter().tuples() {
s += $TUPLE_FUN(&x);
}
s
});
}
#[bench]
fn $CHUNKS(b: &mut Bencher) {
let v: Vec<u32> = (0.. $N * 1_000).collect();
let mut s = 0;
b.iter(|| {
for x in v.chunks($N) {
s += $SLICE_FUN(x);
}
s
});
}
#[bench]
fn $TUPLE_WINDOWS(b: &mut Bencher) {
let v: Vec<u32> = (0..1_000).collect();
let mut s = 0;
b.iter(|| {
for x in v.iter().tuple_windows() {
s += $TUPLE_FUN(&x);
}
s
});
}
#[bench]
fn $WINDOWS(b: &mut Bencher) {
let v: Vec<u32> = (0..1_000).collect();
let mut s = 0;
b.iter(|| {
for x in v.windows($N) {
s += $SLICE_FUN(x);
}
s
});
}
)
}
def_benchs!{
1;
sum_t1,
tuple_chunks_1,
tuple_windows_1;
sum_s1,
slice_chunks_1,
slice_windows_1;
for_chunks_1,
for_windows_1
}
def_benchs!{
2;
sum_t2,
tuple_chunks_2,
tuple_windows_2;
sum_s2,
slice_chunks_2,
slice_windows_2;
for_chunks_2,
for_windows_2
}
def_benchs!{
3;
sum_t3,
tuple_chunks_3,
tuple_windows_3;
sum_s3,
slice_chunks_3,
slice_windows_3;
for_chunks_3,
for_windows_3
}
def_benchs!{
4;
sum_t4,
tuple_chunks_4,
tuple_windows_4;
sum_s4,
slice_chunks_4,
slice_windows_4;
for_chunks_4,
for_windows_4
}

150
third_party/rust/itertools-0.8.0/examples/iris.data поставляемый Normal file
Просмотреть файл

@ -0,0 +1,150 @@
5.1,3.5,1.4,0.2,Iris-setosa
4.9,3.0,1.4,0.2,Iris-setosa
4.7,3.2,1.3,0.2,Iris-setosa
4.6,3.1,1.5,0.2,Iris-setosa
5.0,3.6,1.4,0.2,Iris-setosa
5.4,3.9,1.7,0.4,Iris-setosa
4.6,3.4,1.4,0.3,Iris-setosa
5.0,3.4,1.5,0.2,Iris-setosa
4.4,2.9,1.4,0.2,Iris-setosa
4.9,3.1,1.5,0.1,Iris-setosa
5.4,3.7,1.5,0.2,Iris-setosa
4.8,3.4,1.6,0.2,Iris-setosa
4.8,3.0,1.4,0.1,Iris-setosa
4.3,3.0,1.1,0.1,Iris-setosa
5.8,4.0,1.2,0.2,Iris-setosa
5.7,4.4,1.5,0.4,Iris-setosa
5.4,3.9,1.3,0.4,Iris-setosa
5.1,3.5,1.4,0.3,Iris-setosa
5.7,3.8,1.7,0.3,Iris-setosa
5.1,3.8,1.5,0.3,Iris-setosa
5.4,3.4,1.7,0.2,Iris-setosa
5.1,3.7,1.5,0.4,Iris-setosa
4.6,3.6,1.0,0.2,Iris-setosa
5.1,3.3,1.7,0.5,Iris-setosa
4.8,3.4,1.9,0.2,Iris-setosa
5.0,3.0,1.6,0.2,Iris-setosa
5.0,3.4,1.6,0.4,Iris-setosa
5.2,3.5,1.5,0.2,Iris-setosa
5.2,3.4,1.4,0.2,Iris-setosa
4.7,3.2,1.6,0.2,Iris-setosa
4.8,3.1,1.6,0.2,Iris-setosa
5.4,3.4,1.5,0.4,Iris-setosa
5.2,4.1,1.5,0.1,Iris-setosa
5.5,4.2,1.4,0.2,Iris-setosa
4.9,3.1,1.5,0.1,Iris-setosa
5.0,3.2,1.2,0.2,Iris-setosa
5.5,3.5,1.3,0.2,Iris-setosa
4.9,3.1,1.5,0.1,Iris-setosa
4.4,3.0,1.3,0.2,Iris-setosa
5.1,3.4,1.5,0.2,Iris-setosa
5.0,3.5,1.3,0.3,Iris-setosa
4.5,2.3,1.3,0.3,Iris-setosa
4.4,3.2,1.3,0.2,Iris-setosa
5.0,3.5,1.6,0.6,Iris-setosa
5.1,3.8,1.9,0.4,Iris-setosa
4.8,3.0,1.4,0.3,Iris-setosa
5.1,3.8,1.6,0.2,Iris-setosa
4.6,3.2,1.4,0.2,Iris-setosa
5.3,3.7,1.5,0.2,Iris-setosa
5.0,3.3,1.4,0.2,Iris-setosa
7.0,3.2,4.7,1.4,Iris-versicolor
6.4,3.2,4.5,1.5,Iris-versicolor
6.9,3.1,4.9,1.5,Iris-versicolor
5.5,2.3,4.0,1.3,Iris-versicolor
6.5,2.8,4.6,1.5,Iris-versicolor
5.7,2.8,4.5,1.3,Iris-versicolor
6.3,3.3,4.7,1.6,Iris-versicolor
4.9,2.4,3.3,1.0,Iris-versicolor
6.6,2.9,4.6,1.3,Iris-versicolor
5.2,2.7,3.9,1.4,Iris-versicolor
5.0,2.0,3.5,1.0,Iris-versicolor
5.9,3.0,4.2,1.5,Iris-versicolor
6.0,2.2,4.0,1.0,Iris-versicolor
6.1,2.9,4.7,1.4,Iris-versicolor
5.6,2.9,3.6,1.3,Iris-versicolor
6.7,3.1,4.4,1.4,Iris-versicolor
5.6,3.0,4.5,1.5,Iris-versicolor
5.8,2.7,4.1,1.0,Iris-versicolor
6.2,2.2,4.5,1.5,Iris-versicolor
5.6,2.5,3.9,1.1,Iris-versicolor
5.9,3.2,4.8,1.8,Iris-versicolor
6.1,2.8,4.0,1.3,Iris-versicolor
6.3,2.5,4.9,1.5,Iris-versicolor
6.1,2.8,4.7,1.2,Iris-versicolor
6.4,2.9,4.3,1.3,Iris-versicolor
6.6,3.0,4.4,1.4,Iris-versicolor
6.8,2.8,4.8,1.4,Iris-versicolor
6.7,3.0,5.0,1.7,Iris-versicolor
6.0,2.9,4.5,1.5,Iris-versicolor
5.7,2.6,3.5,1.0,Iris-versicolor
5.5,2.4,3.8,1.1,Iris-versicolor
5.5,2.4,3.7,1.0,Iris-versicolor
5.8,2.7,3.9,1.2,Iris-versicolor
6.0,2.7,5.1,1.6,Iris-versicolor
5.4,3.0,4.5,1.5,Iris-versicolor
6.0,3.4,4.5,1.6,Iris-versicolor
6.7,3.1,4.7,1.5,Iris-versicolor
6.3,2.3,4.4,1.3,Iris-versicolor
5.6,3.0,4.1,1.3,Iris-versicolor
5.5,2.5,4.0,1.3,Iris-versicolor
5.5,2.6,4.4,1.2,Iris-versicolor
6.1,3.0,4.6,1.4,Iris-versicolor
5.8,2.6,4.0,1.2,Iris-versicolor
5.0,2.3,3.3,1.0,Iris-versicolor
5.6,2.7,4.2,1.3,Iris-versicolor
5.7,3.0,4.2,1.2,Iris-versicolor
5.7,2.9,4.2,1.3,Iris-versicolor
6.2,2.9,4.3,1.3,Iris-versicolor
5.1,2.5,3.0,1.1,Iris-versicolor
5.7,2.8,4.1,1.3,Iris-versicolor
6.3,3.3,6.0,2.5,Iris-virginica
5.8,2.7,5.1,1.9,Iris-virginica
7.1,3.0,5.9,2.1,Iris-virginica
6.3,2.9,5.6,1.8,Iris-virginica
6.5,3.0,5.8,2.2,Iris-virginica
7.6,3.0,6.6,2.1,Iris-virginica
4.9,2.5,4.5,1.7,Iris-virginica
7.3,2.9,6.3,1.8,Iris-virginica
6.7,2.5,5.8,1.8,Iris-virginica
7.2,3.6,6.1,2.5,Iris-virginica
6.5,3.2,5.1,2.0,Iris-virginica
6.4,2.7,5.3,1.9,Iris-virginica
6.8,3.0,5.5,2.1,Iris-virginica
5.7,2.5,5.0,2.0,Iris-virginica
5.8,2.8,5.1,2.4,Iris-virginica
6.4,3.2,5.3,2.3,Iris-virginica
6.5,3.0,5.5,1.8,Iris-virginica
7.7,3.8,6.7,2.2,Iris-virginica
7.7,2.6,6.9,2.3,Iris-virginica
6.0,2.2,5.0,1.5,Iris-virginica
6.9,3.2,5.7,2.3,Iris-virginica
5.6,2.8,4.9,2.0,Iris-virginica
7.7,2.8,6.7,2.0,Iris-virginica
6.3,2.7,4.9,1.8,Iris-virginica
6.7,3.3,5.7,2.1,Iris-virginica
7.2,3.2,6.0,1.8,Iris-virginica
6.2,2.8,4.8,1.8,Iris-virginica
6.1,3.0,4.9,1.8,Iris-virginica
6.4,2.8,5.6,2.1,Iris-virginica
7.2,3.0,5.8,1.6,Iris-virginica
7.4,2.8,6.1,1.9,Iris-virginica
7.9,3.8,6.4,2.0,Iris-virginica
6.4,2.8,5.6,2.2,Iris-virginica
6.3,2.8,5.1,1.5,Iris-virginica
6.1,2.6,5.6,1.4,Iris-virginica
7.7,3.0,6.1,2.3,Iris-virginica
6.3,3.4,5.6,2.4,Iris-virginica
6.4,3.1,5.5,1.8,Iris-virginica
6.0,3.0,4.8,1.8,Iris-virginica
6.9,3.1,5.4,2.1,Iris-virginica
6.7,3.1,5.6,2.4,Iris-virginica
6.9,3.1,5.1,2.3,Iris-virginica
5.8,2.7,5.1,1.9,Iris-virginica
6.8,3.2,5.9,2.3,Iris-virginica
6.7,3.3,5.7,2.5,Iris-virginica
6.7,3.0,5.2,2.3,Iris-virginica
6.3,2.5,5.0,1.9,Iris-virginica
6.5,3.0,5.2,2.0,Iris-virginica
6.2,3.4,5.4,2.3,Iris-virginica
5.9,3.0,5.1,1.8,Iris-virginica

141
third_party/rust/itertools-0.8.0/examples/iris.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,141 @@
///
/// This example parses, sorts and groups the iris dataset
/// and does some simple manipulations.
///
/// Iterators and itertools functionality are used throughout.
///
///
extern crate itertools;
use itertools::Itertools;
use std::collections::HashMap;
use std::iter::repeat;
use std::num::ParseFloatError;
use std::str::FromStr;
static DATA: &'static str = include_str!("iris.data");
#[derive(Clone, Debug)]
struct Iris {
name: String,
data: [f32; 4],
}
#[derive(Clone, Debug)]
enum ParseError {
Numeric(ParseFloatError),
Other(&'static str),
}
impl From<ParseFloatError> for ParseError {
fn from(err: ParseFloatError) -> Self {
ParseError::Numeric(err)
}
}
/// Parse an Iris from a comma-separated line
impl FromStr for Iris {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut iris = Iris { name: "".into(), data: [0.; 4] };
let mut parts = s.split(",").map(str::trim);
// using Iterator::by_ref()
for (index, part) in parts.by_ref().take(4).enumerate() {
iris.data[index] = try!(part.parse::<f32>());
}
if let Some(name) = parts.next() {
iris.name = name.into();
} else {
return Err(ParseError::Other("Missing name"))
}
Ok(iris)
}
}
fn main() {
// using Itertools::fold_results to create the result of parsing
let irises = DATA.lines()
.map(str::parse)
.fold_results(Vec::new(), |mut v, iris: Iris| {
v.push(iris);
v
});
let mut irises = match irises {
Err(e) => {
println!("Error parsing: {:?}", e);
std::process::exit(1);
}
Ok(data) => data,
};
// Sort them and group them
irises.sort_by(|a, b| Ord::cmp(&a.name, &b.name));
// using Iterator::cycle()
let mut plot_symbols = "+ox".chars().cycle();
let mut symbolmap = HashMap::new();
// using Itertools::group_by
for (species, species_group) in &irises.iter().group_by(|iris| &iris.name) {
// assign a plot symbol
symbolmap.entry(species).or_insert_with(|| {
plot_symbols.next().unwrap()
});
println!("{} (symbol={})", species, symbolmap[species]);
for iris in species_group {
// using Itertools::format for lazy formatting
println!("{:>3.1}", iris.data.iter().format(", "));
}
}
// Look at all combinations of the four columns
//
// See https://en.wikipedia.org/wiki/Iris_flower_data_set
//
let n = 30; // plot size
let mut plot = vec![' '; n * n];
// using Itertools::tuple_combinations
for (a, b) in (0..4).tuple_combinations() {
println!("Column {} vs {}:", a, b);
// Clear plot
//
// using std::iter::repeat;
// using Itertools::set_from
plot.iter_mut().set_from(repeat(' '));
// using Itertools::minmax
let min_max = |data: &[Iris], col| {
data.iter()
.map(|iris| iris.data[col])
.minmax()
.into_option()
.expect("Can't find min/max of empty iterator")
};
let (min_x, max_x) = min_max(&irises, a);
let (min_y, max_y) = min_max(&irises, b);
// Plot the data points
let round_to_grid = |x, min, max| ((x - min) / (max - min) * ((n - 1) as f32)) as usize;
let flip = |ix| n - 1 - ix; // reverse axis direction
for iris in &irises {
let ix = round_to_grid(iris.data[a], min_x, max_x);
let iy = flip(round_to_grid(iris.data[b], min_y, max_y));
plot[n * iy + ix] = symbolmap[&iris.name];
}
// render plot
//
// using Itertools::join
for line in plot.chunks(n) {
println!("{}", line.iter().join(" "))
}
}
}

1278
third_party/rust/itertools-0.8.0/src/adaptors/mod.rs поставляемый Normal file

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

220
third_party/rust/itertools-0.8.0/src/adaptors/multi_product.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,220 @@
#![cfg(feature = "use_std")]
use size_hint;
use Itertools;
#[derive(Clone)]
/// An iterator adaptor that iterates over the cartesian product of
/// multiple iterators of type `I`.
///
/// An iterator element type is `Vec<I>`.
///
/// See [`.multi_cartesian_product()`](../trait.Itertools.html#method.multi_cartesian_product)
/// for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct MultiProduct<I>(Vec<MultiProductIter<I>>)
where I: Iterator + Clone,
I::Item: Clone;
/// Create a new cartesian product iterator over an arbitrary number
/// of iterators of the same type.
///
/// Iterator element is of type `Vec<H::Item::Item>`.
pub fn multi_cartesian_product<H>(iters: H) -> MultiProduct<<H::Item as IntoIterator>::IntoIter>
where H: Iterator,
H::Item: IntoIterator,
<H::Item as IntoIterator>::IntoIter: Clone,
<H::Item as IntoIterator>::Item: Clone
{
MultiProduct(iters.map(|i| MultiProductIter::new(i.into_iter())).collect())
}
#[derive(Clone, Debug)]
/// Holds the state of a single iterator within a MultiProduct.
struct MultiProductIter<I>
where I: Iterator + Clone,
I::Item: Clone
{
cur: Option<I::Item>,
iter: I,
iter_orig: I,
}
/// Holds the current state during an iteration of a MultiProduct.
#[derive(Debug)]
enum MultiProductIterState {
StartOfIter,
MidIter { on_first_iter: bool },
}
impl<I> MultiProduct<I>
where I: Iterator + Clone,
I::Item: Clone
{
/// Iterates the rightmost iterator, then recursively iterates iterators
/// to the left if necessary.
///
/// Returns true if the iteration succeeded, else false.
fn iterate_last(
multi_iters: &mut [MultiProductIter<I>],
mut state: MultiProductIterState
) -> bool {
use self::MultiProductIterState::*;
if let Some((last, rest)) = multi_iters.split_last_mut() {
let on_first_iter = match state {
StartOfIter => {
let on_first_iter = !last.in_progress();
state = MidIter { on_first_iter: on_first_iter };
on_first_iter
},
MidIter { on_first_iter } => on_first_iter
};
if !on_first_iter {
last.iterate();
}
if last.in_progress() {
true
} else if MultiProduct::iterate_last(rest, state) {
last.reset();
last.iterate();
// If iterator is None twice consecutively, then iterator is
// empty; whole product is empty.
last.in_progress()
} else {
false
}
} else {
// Reached end of iterator list. On initialisation, return true.
// At end of iteration (final iterator finishes), finish.
match state {
StartOfIter => false,
MidIter { on_first_iter } => on_first_iter
}
}
}
/// Returns the unwrapped value of the next iteration.
fn curr_iterator(&self) -> Vec<I::Item> {
self.0.iter().map(|multi_iter| {
multi_iter.cur.clone().unwrap()
}).collect()
}
/// Returns true if iteration has started and has not yet finished; false
/// otherwise.
fn in_progress(&self) -> bool {
if let Some(last) = self.0.last() {
last.in_progress()
} else {
false
}
}
}
impl<I> MultiProductIter<I>
where I: Iterator + Clone,
I::Item: Clone
{
fn new(iter: I) -> Self {
MultiProductIter {
cur: None,
iter: iter.clone(),
iter_orig: iter
}
}
/// Iterate the managed iterator.
fn iterate(&mut self) {
self.cur = self.iter.next();
}
/// Reset the managed iterator.
fn reset(&mut self) {
self.iter = self.iter_orig.clone();
}
/// Returns true if the current iterator has been started and has not yet
/// finished; false otherwise.
fn in_progress(&self) -> bool {
self.cur.is_some()
}
}
impl<I> Iterator for MultiProduct<I>
where I: Iterator + Clone,
I::Item: Clone
{
type Item = Vec<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
if MultiProduct::iterate_last(
&mut self.0,
MultiProductIterState::StartOfIter
) {
Some(self.curr_iterator())
} else {
None
}
}
fn count(self) -> usize {
if self.0.len() == 0 {
return 0;
}
if !self.in_progress() {
return self.0.into_iter().fold(1, |acc, multi_iter| {
acc * multi_iter.iter.count()
});
}
self.0.into_iter().fold(
0,
|acc, MultiProductIter { iter, iter_orig, cur: _ }| {
let total_count = iter_orig.count();
let cur_count = iter.count();
acc * total_count + cur_count
}
)
}
fn size_hint(&self) -> (usize, Option<usize>) {
// Not ExactSizeIterator because size may be larger than usize
if self.0.len() == 0 {
return (0, Some(0));
}
if !self.in_progress() {
return self.0.iter().fold((1, Some(1)), |acc, multi_iter| {
size_hint::mul(acc, multi_iter.iter.size_hint())
});
}
self.0.iter().fold(
(0, Some(0)),
|acc, &MultiProductIter { ref iter, ref iter_orig, cur: _ }| {
let cur_size = iter.size_hint();
let total_size = iter_orig.size_hint();
size_hint::add(size_hint::mul(acc, total_size), cur_size)
}
)
}
fn last(self) -> Option<Self::Item> {
let iter_count = self.0.len();
let lasts: Self::Item = self.0.into_iter()
.map(|multi_iter| multi_iter.iter.last())
.while_some()
.collect();
if lasts.len() == iter_count {
Some(lasts)
} else {
None
}
}
}

165
third_party/rust/itertools-0.8.0/src/combinations.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,165 @@
use std::ops::Index;
use std::fmt;
/// An iterator to iterate through all the `n`-length combinations in an iterator.
///
/// See [`.combinations()`](../trait.Itertools.html#method.combinations) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Combinations<I: Iterator> {
n: usize,
indices: Vec<usize>,
pool: LazyBuffer<I>,
first: bool,
}
impl<I> fmt::Debug for Combinations<I>
where I: Iterator + fmt::Debug,
I::Item: fmt::Debug,
{
debug_fmt_fields!(Combinations, n, indices, pool, first);
}
/// Create a new `Combinations` from a clonable iterator.
pub fn combinations<I>(iter: I, n: usize) -> Combinations<I>
where I: Iterator
{
let mut indices: Vec<usize> = Vec::with_capacity(n);
for i in 0..n {
indices.push(i);
}
let mut pool: LazyBuffer<I> = LazyBuffer::new(iter);
for _ in 0..n {
if !pool.get_next() {
break;
}
}
Combinations {
n: n,
indices: indices,
pool: pool,
first: true,
}
}
impl<I> Iterator for Combinations<I>
where I: Iterator,
I::Item: Clone
{
type Item = Vec<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
let mut pool_len = self.pool.len();
if self.pool.is_done() {
if pool_len == 0 || self.n > pool_len {
return None;
}
}
if self.first {
self.first = false;
} else if self.n == 0 {
return None;
} else {
// Scan from the end, looking for an index to increment
let mut i: usize = self.n - 1;
// Check if we need to consume more from the iterator
if self.indices[i] == pool_len - 1 && !self.pool.is_done() {
if self.pool.get_next() {
pool_len += 1;
}
}
while self.indices[i] == i + pool_len - self.n {
if i > 0 {
i -= 1;
} else {
// Reached the last combination
return None;
}
}
// Increment index, and reset the ones to its right
self.indices[i] += 1;
let mut j = i + 1;
while j < self.n {
self.indices[j] = self.indices[j - 1] + 1;
j += 1;
}
}
// Create result vector based on the indices
let mut result = Vec::with_capacity(self.n);
for i in self.indices.iter() {
result.push(self.pool[*i].clone());
}
Some(result)
}
}
#[derive(Debug)]
struct LazyBuffer<I: Iterator> {
it: I,
done: bool,
buffer: Vec<I::Item>,
}
impl<I> LazyBuffer<I>
where I: Iterator
{
pub fn new(it: I) -> LazyBuffer<I> {
let mut it = it;
let mut buffer = Vec::new();
let done;
if let Some(first) = it.next() {
buffer.push(first);
done = false;
} else {
done = true;
}
LazyBuffer {
it: it,
done: done,
buffer: buffer,
}
}
pub fn len(&self) -> usize {
self.buffer.len()
}
pub fn is_done(&self) -> bool {
self.done
}
pub fn get_next(&mut self) -> bool {
if self.done {
return false;
}
let next_item = self.it.next();
match next_item {
Some(x) => {
self.buffer.push(x);
true
}
None => {
self.done = true;
false
}
}
}
}
impl<I> Index<usize> for LazyBuffer<I>
where I: Iterator,
I::Item: Sized
{
type Output = I::Item;
fn index<'b>(&'b self, _index: usize) -> &'b I::Item {
self.buffer.index(_index)
}
}

22
third_party/rust/itertools-0.8.0/src/concat_impl.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,22 @@
use Itertools;
/// Combine all an iterator's elements into one element by using `Extend`.
///
/// `IntoIterator`-enabled version of `.concat()`
///
/// This combinator will extend the first item with each of the rest of the
/// items of the iterator. If the iterator is empty, the default value of
/// `I::Item` is returned.
///
/// ```rust
/// use itertools::concat;
///
/// let input = vec![vec![1], vec![2, 3], vec![4, 5, 6]];
/// assert_eq!(concat(input), vec![1, 2, 3, 4, 5, 6]);
/// ```
pub fn concat<I>(iterable: I) -> I::Item
where I: IntoIterator,
I::Item: Extend<<<I as IntoIterator>::Item as IntoIterator>::Item> + IntoIterator + Default
{
iterable.into_iter().fold1(|mut a, b| { a.extend(b); a }).unwrap_or_else(|| <_>::default())
}

68
third_party/rust/itertools-0.8.0/src/cons_tuples_impl.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,68 @@
macro_rules! impl_cons_iter(
($_A:ident, $_B:ident, ) => (); // stop
($A:ident, $($B:ident,)*) => (
impl_cons_iter!($($B,)*);
#[allow(non_snake_case)]
impl<X, Iter, $($B),*> Iterator for ConsTuples<Iter, (($($B,)*), X)>
where Iter: Iterator<Item = (($($B,)*), X)>,
{
type Item = ($($B,)* X, );
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|(($($B,)*), x)| ($($B,)* x, ))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
fn fold<Acc, Fold>(self, accum: Acc, mut f: Fold) -> Acc
where Fold: FnMut(Acc, Self::Item) -> Acc,
{
self.iter.fold(accum, move |acc, (($($B,)*), x)| f(acc, ($($B,)* x, )))
}
}
#[allow(non_snake_case)]
impl<X, Iter, $($B),*> DoubleEndedIterator for ConsTuples<Iter, (($($B,)*), X)>
where Iter: DoubleEndedIterator<Item = (($($B,)*), X)>,
{
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next().map(|(($($B,)*), x)| ($($B,)* x, ))
}
}
);
);
impl_cons_iter!(A, B, C, D, E, F, G, H,);
/// An iterator that maps an iterator of tuples like
/// `((A, B), C)` to an iterator of `(A, B, C)`.
///
/// Used by the `iproduct!()` macro.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Debug)]
pub struct ConsTuples<I, J>
where I: Iterator<Item=J>,
{
iter: I,
}
impl<I, J> Clone for ConsTuples<I, J>
where I: Clone + Iterator<Item=J>,
{
fn clone(&self) -> Self {
ConsTuples {
iter: self.iter.clone(),
}
}
}
/// Create an iterator that maps for example iterators of
/// `((A, B), C)` to `(A, B, C)`.
pub fn cons_tuples<I, J>(iterable: I) -> ConsTuples<I, J>
where I: Iterator<Item=J>
{
ConsTuples { iter: iterable.into_iter() }
}

61
third_party/rust/itertools-0.8.0/src/diff.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,61 @@
//! "Diff"ing iterators for caching elements to sequential collections without requiring the new
//! elements' iterator to be `Clone`.
//!
//! - [**Diff**](./enum.Diff.html) (produced by the [**diff_with**](./fn.diff_with.html) function)
//! describes the difference between two non-`Clone` iterators `I` and `J` after breaking ASAP from
//! a lock-step comparison.
use free::put_back;
use structs::PutBack;
/// A type returned by the [`diff_with`](./fn.diff_with.html) function.
///
/// `Diff` represents the way in which the elements yielded by the iterator `I` differ to some
/// iterator `J`.
pub enum Diff<I, J>
where I: Iterator,
J: Iterator
{
/// The index of the first non-matching element along with both iterator's remaining elements
/// starting with the first mis-match.
FirstMismatch(usize, PutBack<I>, PutBack<J>),
/// The total number of elements that were in `J` along with the remaining elements of `I`.
Shorter(usize, PutBack<I>),
/// The total number of elements that were in `I` along with the remaining elements of `J`.
Longer(usize, PutBack<J>),
}
/// Compares every element yielded by both `i` and `j` with the given function in lock-step and
/// returns a `Diff` which describes how `j` differs from `i`.
///
/// If the number of elements yielded by `j` is less than the number of elements yielded by `i`,
/// the number of `j` elements yielded will be returned along with `i`'s remaining elements as
/// `Diff::Shorter`.
///
/// If the two elements of a step differ, the index of those elements along with the remaining
/// elements of both `i` and `j` are returned as `Diff::FirstMismatch`.
///
/// If `i` becomes exhausted before `j` becomes exhausted, the number of elements in `i` along with
/// the remaining `j` elements will be returned as `Diff::Longer`.
pub fn diff_with<I, J, F>(i: I, j: J, is_equal: F)
-> Option<Diff<I::IntoIter, J::IntoIter>>
where I: IntoIterator,
J: IntoIterator,
F: Fn(&I::Item, &J::Item) -> bool
{
let mut i = i.into_iter();
let mut j = j.into_iter();
let mut idx = 0;
while let Some(i_elem) = i.next() {
match j.next() {
None => return Some(Diff::Shorter(idx, put_back(i).with_value(i_elem))),
Some(j_elem) => if !is_equal(&i_elem, &j_elem) {
let remaining_i = put_back(i).with_value(i_elem);
let remaining_j = put_back(j).with_value(j_elem);
return Some(Diff::FirstMismatch(idx, remaining_i, remaining_j));
},
}
idx += 1;
}
j.next().map(|j_elem| Diff::Longer(idx, put_back(j).with_value(j_elem)))
}

58
third_party/rust/itertools-0.8.0/src/either_or_both.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,58 @@
use EitherOrBoth::*;
/// Value that either holds a single A or B, or both.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum EitherOrBoth<A, B> {
/// Both values are present.
Both(A, B),
/// Only the left value of type `A` is present.
Left(A),
/// Only the right value of type `B` is present.
Right(B),
}
impl<A, B> EitherOrBoth<A, B> {
/// If `Left`, or `Both`, return true, otherwise, return false.
pub fn has_left(&self) -> bool {
self.as_ref().left().is_some()
}
/// If `Right`, or `Both`, return true, otherwise, return false.
pub fn has_right(&self) -> bool {
self.as_ref().right().is_some()
}
/// If `Left`, or `Both`, return `Some` with the left value, otherwise, return `None`.
pub fn left(self) -> Option<A> {
match self {
Left(left) | Both(left, _) => Some(left),
_ => None
}
}
/// If `Right`, or `Both`, return `Some` with the right value, otherwise, return `None`.
pub fn right(self) -> Option<B> {
match self {
Right(right) | Both(_, right) => Some(right),
_ => None
}
}
/// Converts from `&EitherOrBoth<A, B>` to `EitherOrBoth<&A, &B>`.
pub fn as_ref(&self) -> EitherOrBoth<&A, &B> {
match *self {
Left(ref left) => Left(left),
Right(ref right) => Right(right),
Both(ref left, ref right) => Both(left, right),
}
}
/// Converts from `&mut EitherOrBoth<A, B>` to `EitherOrBoth<&mut A, &mut B>`.
pub fn as_mut(&mut self) -> EitherOrBoth<&mut A, &mut B> {
match *self {
Left(ref mut left) => Left(left),
Right(ref mut right) => Right(right),
Both(ref mut left, ref mut right) => Both(left, right),
}
}
}

113
third_party/rust/itertools-0.8.0/src/format.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,113 @@
use std::fmt;
use std::cell::RefCell;
/// Format all iterator elements lazily, separated by `sep`.
///
/// The format value can only be formatted once, after that the iterator is
/// exhausted.
///
/// See [`.format_with()`](../trait.Itertools.html#method.format_with) for more information.
pub struct FormatWith<'a, I, F> {
sep: &'a str,
/// FormatWith uses interior mutability because Display::fmt takes &self.
inner: RefCell<Option<(I, F)>>,
}
/// Format all iterator elements lazily, separated by `sep`.
///
/// The format value can only be formatted once, after that the iterator is
/// exhausted.
///
/// See [`.format()`](../trait.Itertools.html#method.format)
/// for more information.
#[derive(Clone)]
pub struct Format<'a, I> {
sep: &'a str,
/// Format uses interior mutability because Display::fmt takes &self.
inner: RefCell<Option<I>>,
}
pub fn new_format<'a, I, F>(iter: I, separator: &'a str, f: F) -> FormatWith<'a, I, F>
where I: Iterator,
F: FnMut(I::Item, &mut FnMut(&fmt::Display) -> fmt::Result) -> fmt::Result
{
FormatWith {
sep: separator,
inner: RefCell::new(Some((iter, f))),
}
}
pub fn new_format_default<'a, I>(iter: I, separator: &'a str) -> Format<'a, I>
where I: Iterator,
{
Format {
sep: separator,
inner: RefCell::new(Some(iter)),
}
}
impl<'a, I, F> fmt::Display for FormatWith<'a, I, F>
where I: Iterator,
F: FnMut(I::Item, &mut FnMut(&fmt::Display) -> fmt::Result) -> fmt::Result
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (mut iter, mut format) = match self.inner.borrow_mut().take() {
Some(t) => t,
None => panic!("FormatWith: was already formatted once"),
};
if let Some(fst) = iter.next() {
try!(format(fst, &mut |disp: &fmt::Display| disp.fmt(f)));
for elt in iter {
if self.sep.len() > 0 {
try!(f.write_str(self.sep));
}
try!(format(elt, &mut |disp: &fmt::Display| disp.fmt(f)));
}
}
Ok(())
}
}
impl<'a, I> Format<'a, I>
where I: Iterator,
{
fn format<F>(&self, f: &mut fmt::Formatter, mut cb: F) -> fmt::Result
where F: FnMut(&I::Item, &mut fmt::Formatter) -> fmt::Result,
{
let mut iter = match self.inner.borrow_mut().take() {
Some(t) => t,
None => panic!("Format: was already formatted once"),
};
if let Some(fst) = iter.next() {
try!(cb(&fst, f));
for elt in iter {
if self.sep.len() > 0 {
try!(f.write_str(self.sep));
}
try!(cb(&elt, f));
}
}
Ok(())
}
}
macro_rules! impl_format {
($($fmt_trait:ident)*) => {
$(
impl<'a, I> fmt::$fmt_trait for Format<'a, I>
where I: Iterator,
I::Item: fmt::$fmt_trait,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f, fmt::$fmt_trait::fmt)
}
}
)*
}
}
impl_format!{Display Debug
UpperExp LowerExp UpperHex LowerHex Octal Binary Pointer}

236
third_party/rust/itertools-0.8.0/src/free.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,236 @@
//! Free functions that create iterator adaptors or call iterator methods.
//!
//! The benefit of free functions is that they accept any `IntoIterator` as
//! argument, so the resulting code may be easier to read.
#[cfg(feature = "use_std")]
use std::fmt::Display;
use std::iter::{self, Zip};
#[cfg(feature = "use_std")]
type VecIntoIter<T> = ::std::vec::IntoIter<T>;
#[cfg(feature = "use_std")]
use Itertools;
pub use adaptors::{
interleave,
merge,
put_back,
};
#[cfg(feature = "use_std")]
pub use put_back_n_impl::put_back_n;
#[cfg(feature = "use_std")]
pub use multipeek_impl::multipeek;
#[cfg(feature = "use_std")]
pub use kmerge_impl::kmerge;
pub use zip_eq_impl::zip_eq;
pub use merge_join::merge_join_by;
#[cfg(feature = "use_std")]
pub use rciter_impl::rciter;
/// Iterate `iterable` with a running index.
///
/// `IntoIterator` enabled version of `.enumerate()`.
///
/// ```
/// use itertools::enumerate;
///
/// for (i, elt) in enumerate(&[1, 2, 3]) {
/// /* loop body */
/// }
/// ```
pub fn enumerate<I>(iterable: I) -> iter::Enumerate<I::IntoIter>
where I: IntoIterator
{
iterable.into_iter().enumerate()
}
/// Iterate `iterable` in reverse.
///
/// `IntoIterator` enabled version of `.rev()`.
///
/// ```
/// use itertools::rev;
///
/// for elt in rev(&[1, 2, 3]) {
/// /* loop body */
/// }
/// ```
pub fn rev<I>(iterable: I) -> iter::Rev<I::IntoIter>
where I: IntoIterator,
I::IntoIter: DoubleEndedIterator
{
iterable.into_iter().rev()
}
/// Iterate `i` and `j` in lock step.
///
/// `IntoIterator` enabled version of `i.zip(j)`.
///
/// ```
/// use itertools::zip;
///
/// let data = [1, 2, 3, 4, 5];
/// for (a, b) in zip(&data, &data[1..]) {
/// /* loop body */
/// }
/// ```
pub fn zip<I, J>(i: I, j: J) -> Zip<I::IntoIter, J::IntoIter>
where I: IntoIterator,
J: IntoIterator
{
i.into_iter().zip(j)
}
/// Create an iterator that first iterates `i` and then `j`.
///
/// `IntoIterator` enabled version of `i.chain(j)`.
///
/// ```
/// use itertools::chain;
///
/// for elt in chain(&[1, 2, 3], &[4]) {
/// /* loop body */
/// }
/// ```
pub fn chain<I, J>(i: I, j: J) -> iter::Chain<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter>
where I: IntoIterator,
J: IntoIterator<Item = I::Item>
{
i.into_iter().chain(j)
}
/// Create an iterator that clones each element from &T to T
///
/// `IntoIterator` enabled version of `i.cloned()`.
///
/// ```
/// use itertools::cloned;
///
/// assert_eq!(cloned(b"abc").next(), Some(b'a'));
/// ```
pub fn cloned<'a, I, T: 'a>(iterable: I) -> iter::Cloned<I::IntoIter>
where I: IntoIterator<Item=&'a T>,
T: Clone,
{
iterable.into_iter().cloned()
}
/// Perform a fold operation over the iterable.
///
/// `IntoIterator` enabled version of `i.fold(init, f)`
///
/// ```
/// use itertools::fold;
///
/// assert_eq!(fold(&[1., 2., 3.], 0., |a, &b| f32::max(a, b)), 3.);
/// ```
pub fn fold<I, B, F>(iterable: I, init: B, f: F) -> B
where I: IntoIterator,
F: FnMut(B, I::Item) -> B
{
iterable.into_iter().fold(init, f)
}
/// Test whether the predicate holds for all elements in the iterable.
///
/// `IntoIterator` enabled version of `i.all(f)`
///
/// ```
/// use itertools::all;
///
/// assert!(all(&[1, 2, 3], |elt| *elt > 0));
/// ```
pub fn all<I, F>(iterable: I, f: F) -> bool
where I: IntoIterator,
F: FnMut(I::Item) -> bool
{
iterable.into_iter().all(f)
}
/// Test whether the predicate holds for any elements in the iterable.
///
/// `IntoIterator` enabled version of `i.any(f)`
///
/// ```
/// use itertools::any;
///
/// assert!(any(&[0, -1, 2], |elt| *elt > 0));
/// ```
pub fn any<I, F>(iterable: I, f: F) -> bool
where I: IntoIterator,
F: FnMut(I::Item) -> bool
{
iterable.into_iter().any(f)
}
/// Return the maximum value of the iterable.
///
/// `IntoIterator` enabled version of `i.max()`.
///
/// ```
/// use itertools::max;
///
/// assert_eq!(max(0..10), Some(9));
/// ```
pub fn max<I>(iterable: I) -> Option<I::Item>
where I: IntoIterator,
I::Item: Ord
{
iterable.into_iter().max()
}
/// Return the minimum value of the iterable.
///
/// `IntoIterator` enabled version of `i.min()`.
///
/// ```
/// use itertools::min;
///
/// assert_eq!(min(0..10), Some(0));
/// ```
pub fn min<I>(iterable: I) -> Option<I::Item>
where I: IntoIterator,
I::Item: Ord
{
iterable.into_iter().min()
}
/// Combine all iterator elements into one String, seperated by `sep`.
///
/// `IntoIterator` enabled version of `iterable.join(sep)`.
///
/// ```
/// use itertools::join;
///
/// assert_eq!(join(&[1, 2, 3], ", "), "1, 2, 3");
/// ```
#[cfg(feature = "use_std")]
pub fn join<I>(iterable: I, sep: &str) -> String
where I: IntoIterator,
I::Item: Display
{
iterable.into_iter().join(sep)
}
/// Sort all iterator elements into a new iterator in ascending order.
///
/// `IntoIterator` enabled version of [`iterable.sorted()`][1].
///
/// [1]: trait.Itertools.html#method.sorted
///
/// ```
/// use itertools::sorted;
/// use itertools::assert_equal;
///
/// assert_equal(sorted("rust".chars()), "rstu".chars());
/// ```
#[cfg(feature = "use_std")]
pub fn sorted<I>(iterable: I) -> VecIntoIter<I::Item>
where I: IntoIterator,
I::Item: Ord
{
iterable.into_iter().sorted()
}

22
third_party/rust/itertools-0.8.0/src/group_map.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,22 @@
#![cfg(feature = "use_std")]
use std::collections::HashMap;
use std::hash::Hash;
use std::iter::Iterator;
/// Return a `HashMap` of keys mapped to a list of their corresponding values.
///
/// See [`.into_group_map()`](../trait.Itertools.html#method.into_group_map)
/// for more information.
pub fn into_group_map<I, K, V>(iter: I) -> HashMap<K, Vec<V>>
where I: Iterator<Item=(K, V)>,
K: Hash + Eq,
{
let mut lookup = HashMap::new();
for (key, val) in iter {
lookup.entry(key).or_insert(Vec::new()).push(val);
}
lookup
}

571
third_party/rust/itertools-0.8.0/src/groupbylazy.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,571 @@
use std::cell::{Cell, RefCell};
use std::vec;
/// A trait to unify FnMut for GroupBy with the chunk key in IntoChunks
trait KeyFunction<A> {
type Key;
fn call_mut(&mut self, arg: A) -> Self::Key;
}
impl<'a, A, K, F: ?Sized> KeyFunction<A> for F
where F: FnMut(A) -> K
{
type Key = K;
#[inline]
fn call_mut(&mut self, arg: A) -> Self::Key {
(*self)(arg)
}
}
/// ChunkIndex acts like the grouping key function for IntoChunks
#[derive(Debug)]
struct ChunkIndex {
size: usize,
index: usize,
key: usize,
}
impl ChunkIndex {
#[inline(always)]
fn new(size: usize) -> Self {
ChunkIndex {
size: size,
index: 0,
key: 0,
}
}
}
impl<'a, A> KeyFunction<A> for ChunkIndex {
type Key = usize;
#[inline(always)]
fn call_mut(&mut self, _arg: A) -> Self::Key {
if self.index == self.size {
self.key += 1;
self.index = 0;
}
self.index += 1;
self.key
}
}
struct GroupInner<K, I, F>
where I: Iterator
{
key: F,
iter: I,
current_key: Option<K>,
current_elt: Option<I::Item>,
/// flag set if iterator is exhausted
done: bool,
/// Index of group we are currently buffering or visiting
top_group: usize,
/// Least index for which we still have elements buffered
oldest_buffered_group: usize,
/// Group index for `buffer[0]` -- the slots
/// bottom_group..oldest_buffered_group are unused and will be erased when
/// that range is large enough.
bottom_group: usize,
/// Buffered groups, from `bottom_group` (index 0) to `top_group`.
buffer: Vec<vec::IntoIter<I::Item>>,
/// index of last group iter that was dropped, usize::MAX == none
dropped_group: usize,
}
impl<K, I, F> GroupInner<K, I, F>
where I: Iterator,
F: for<'a> KeyFunction<&'a I::Item, Key=K>,
K: PartialEq,
{
/// `client`: Index of group that requests next element
#[inline(always)]
fn step(&mut self, client: usize) -> Option<I::Item> {
/*
println!("client={}, bottom_group={}, oldest_buffered_group={}, top_group={}, buffers=[{}]",
client, self.bottom_group, self.oldest_buffered_group,
self.top_group,
self.buffer.iter().map(|elt| elt.len()).format(", "));
*/
if client < self.oldest_buffered_group {
None
} else if client < self.top_group ||
(client == self.top_group &&
self.buffer.len() > self.top_group - self.bottom_group)
{
self.lookup_buffer(client)
} else if self.done {
None
} else if self.top_group == client {
self.step_current()
} else {
self.step_buffering(client)
}
}
#[inline(never)]
fn lookup_buffer(&mut self, client: usize) -> Option<I::Item> {
// if `bufidx` doesn't exist in self.buffer, it might be empty
let bufidx = client - self.bottom_group;
if client < self.oldest_buffered_group {
return None;
}
let elt = self.buffer.get_mut(bufidx).and_then(|queue| queue.next());
if elt.is_none() && client == self.oldest_buffered_group {
// FIXME: VecDeque is unfortunately not zero allocation when empty,
// so we do this job manually.
// `bottom_group..oldest_buffered_group` is unused, and if it's large enough, erase it.
self.oldest_buffered_group += 1;
// skip forward further empty queues too
while self.buffer.get(self.oldest_buffered_group - self.bottom_group)
.map_or(false, |buf| buf.len() == 0)
{
self.oldest_buffered_group += 1;
}
let nclear = self.oldest_buffered_group - self.bottom_group;
if nclear > 0 && nclear >= self.buffer.len() / 2 {
let mut i = 0;
self.buffer.retain(|buf| {
i += 1;
debug_assert!(buf.len() == 0 || i > nclear);
i > nclear
});
self.bottom_group = self.oldest_buffered_group;
}
}
elt
}
/// Take the next element from the iterator, and set the done
/// flag if exhausted. Must not be called after done.
#[inline(always)]
fn next_element(&mut self) -> Option<I::Item> {
debug_assert!(!self.done);
match self.iter.next() {
None => { self.done = true; None }
otherwise => otherwise,
}
}
#[inline(never)]
fn step_buffering(&mut self, client: usize) -> Option<I::Item> {
// requested a later group -- walk through the current group up to
// the requested group index, and buffer the elements (unless
// the group is marked as dropped).
// Because the `Groups` iterator is always the first to request
// each group index, client is the next index efter top_group.
debug_assert!(self.top_group + 1 == client);
let mut group = Vec::new();
if let Some(elt) = self.current_elt.take() {
if self.top_group != self.dropped_group {
group.push(elt);
}
}
let mut first_elt = None; // first element of the next group
while let Some(elt) = self.next_element() {
let key = self.key.call_mut(&elt);
match self.current_key.take() {
None => {}
Some(old_key) => if old_key != key {
self.current_key = Some(key);
first_elt = Some(elt);
break;
},
}
self.current_key = Some(key);
if self.top_group != self.dropped_group {
group.push(elt);
}
}
if self.top_group != self.dropped_group {
self.push_next_group(group);
}
if first_elt.is_some() {
self.top_group += 1;
debug_assert!(self.top_group == client);
}
first_elt
}
fn push_next_group(&mut self, group: Vec<I::Item>) {
// When we add a new buffered group, fill up slots between oldest_buffered_group and top_group
while self.top_group - self.bottom_group > self.buffer.len() {
if self.buffer.is_empty() {
self.bottom_group += 1;
self.oldest_buffered_group += 1;
} else {
self.buffer.push(Vec::new().into_iter());
}
}
self.buffer.push(group.into_iter());
debug_assert!(self.top_group + 1 - self.bottom_group == self.buffer.len());
}
/// This is the immediate case, where we use no buffering
#[inline]
fn step_current(&mut self) -> Option<I::Item> {
debug_assert!(!self.done);
if let elt @ Some(..) = self.current_elt.take() {
return elt;
}
match self.next_element() {
None => None,
Some(elt) => {
let key = self.key.call_mut(&elt);
match self.current_key.take() {
None => {}
Some(old_key) => if old_key != key {
self.current_key = Some(key);
self.current_elt = Some(elt);
self.top_group += 1;
return None;
},
}
self.current_key = Some(key);
Some(elt)
}
}
}
/// Request the just started groups' key.
///
/// `client`: Index of group
///
/// **Panics** if no group key is available.
fn group_key(&mut self, client: usize) -> K {
// This can only be called after we have just returned the first
// element of a group.
// Perform this by simply buffering one more element, grabbing the
// next key.
debug_assert!(!self.done);
debug_assert!(client == self.top_group);
debug_assert!(self.current_key.is_some());
debug_assert!(self.current_elt.is_none());
let old_key = self.current_key.take().unwrap();
if let Some(elt) = self.next_element() {
let key = self.key.call_mut(&elt);
if old_key != key {
self.top_group += 1;
}
self.current_key = Some(key);
self.current_elt = Some(elt);
}
old_key
}
}
impl<K, I, F> GroupInner<K, I, F>
where I: Iterator,
{
/// Called when a group is dropped
fn drop_group(&mut self, client: usize) {
// It's only useful to track the maximal index
if self.dropped_group == !0 || client > self.dropped_group {
self.dropped_group = client;
}
}
}
/// `GroupBy` is the storage for the lazy grouping operation.
///
/// If the groups are consumed in their original order, or if each
/// group is dropped without keeping it around, then `GroupBy` uses
/// no allocations. It needs allocations only if several group iterators
/// are alive at the same time.
///
/// This type implements `IntoIterator` (it is **not** an iterator
/// itself), because the group iterators need to borrow from this
/// value. It should be stored in a local variable or temporary and
/// iterated.
///
/// See [`.group_by()`](../trait.Itertools.html#method.group_by) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct GroupBy<K, I, F>
where I: Iterator,
{
inner: RefCell<GroupInner<K, I, F>>,
// the group iterator's current index. Keep this in the main value
// so that simultaneous iterators all use the same state.
index: Cell<usize>,
}
/// Create a new
pub fn new<K, J, F>(iter: J, f: F) -> GroupBy<K, J::IntoIter, F>
where J: IntoIterator,
F: FnMut(&J::Item) -> K,
{
GroupBy {
inner: RefCell::new(GroupInner {
key: f,
iter: iter.into_iter(),
current_key: None,
current_elt: None,
done: false,
top_group: 0,
oldest_buffered_group: 0,
bottom_group: 0,
buffer: Vec::new(),
dropped_group: !0,
}),
index: Cell::new(0),
}
}
impl<K, I, F> GroupBy<K, I, F>
where I: Iterator,
{
/// `client`: Index of group that requests next element
fn step(&self, client: usize) -> Option<I::Item>
where F: FnMut(&I::Item) -> K,
K: PartialEq,
{
self.inner.borrow_mut().step(client)
}
/// `client`: Index of group
fn drop_group(&self, client: usize) {
self.inner.borrow_mut().drop_group(client)
}
}
impl<'a, K, I, F> IntoIterator for &'a GroupBy<K, I, F>
where I: Iterator,
I::Item: 'a,
F: FnMut(&I::Item) -> K,
K: PartialEq
{
type Item = (K, Group<'a, K, I, F>);
type IntoIter = Groups<'a, K, I, F>;
fn into_iter(self) -> Self::IntoIter {
Groups { parent: self }
}
}
/// An iterator that yields the Group iterators.
///
/// Iterator element type is `(K, Group)`:
/// the group's key `K` and the group's iterator.
///
/// See [`.group_by()`](../trait.Itertools.html#method.group_by) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Groups<'a, K: 'a, I: 'a, F: 'a>
where I: Iterator,
I::Item: 'a
{
parent: &'a GroupBy<K, I, F>,
}
impl<'a, K, I, F> Iterator for Groups<'a, K, I, F>
where I: Iterator,
I::Item: 'a,
F: FnMut(&I::Item) -> K,
K: PartialEq
{
type Item = (K, Group<'a, K, I, F>);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let index = self.parent.index.get();
self.parent.index.set(index + 1);
let inner = &mut *self.parent.inner.borrow_mut();
inner.step(index).map(|elt| {
let key = inner.group_key(index);
(key, Group {
parent: self.parent,
index: index,
first: Some(elt),
})
})
}
}
/// An iterator for the elements in a single group.
///
/// Iterator element type is `I::Item`.
pub struct Group<'a, K: 'a, I: 'a, F: 'a>
where I: Iterator,
I::Item: 'a,
{
parent: &'a GroupBy<K, I, F>,
index: usize,
first: Option<I::Item>,
}
impl<'a, K, I, F> Drop for Group<'a, K, I, F>
where I: Iterator,
I::Item: 'a,
{
fn drop(&mut self) {
self.parent.drop_group(self.index);
}
}
impl<'a, K, I, F> Iterator for Group<'a, K, I, F>
where I: Iterator,
I::Item: 'a,
F: FnMut(&I::Item) -> K,
K: PartialEq,
{
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if let elt @ Some(..) = self.first.take() {
return elt;
}
self.parent.step(self.index)
}
}
///// IntoChunks /////
/// Create a new
pub fn new_chunks<J>(iter: J, size: usize) -> IntoChunks<J::IntoIter>
where J: IntoIterator,
{
IntoChunks {
inner: RefCell::new(GroupInner {
key: ChunkIndex::new(size),
iter: iter.into_iter(),
current_key: None,
current_elt: None,
done: false,
top_group: 0,
oldest_buffered_group: 0,
bottom_group: 0,
buffer: Vec::new(),
dropped_group: !0,
}),
index: Cell::new(0),
}
}
/// `ChunkLazy` is the storage for a lazy chunking operation.
///
/// `IntoChunks` behaves just like `GroupBy`: it is iterable, and
/// it only buffers if several chunk iterators are alive at the same time.
///
/// This type implements `IntoIterator` (it is **not** an iterator
/// itself), because the chunk iterators need to borrow from this
/// value. It should be stored in a local variable or temporary and
/// iterated.
///
/// Iterator element type is `Chunk`, each chunk's iterator.
///
/// See [`.chunks()`](../trait.Itertools.html#method.chunks) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct IntoChunks<I>
where I: Iterator,
{
inner: RefCell<GroupInner<usize, I, ChunkIndex>>,
// the chunk iterator's current index. Keep this in the main value
// so that simultaneous iterators all use the same state.
index: Cell<usize>,
}
impl<I> IntoChunks<I>
where I: Iterator,
{
/// `client`: Index of chunk that requests next element
fn step(&self, client: usize) -> Option<I::Item> {
self.inner.borrow_mut().step(client)
}
/// `client`: Index of chunk
fn drop_group(&self, client: usize) {
self.inner.borrow_mut().drop_group(client)
}
}
impl<'a, I> IntoIterator for &'a IntoChunks<I>
where I: Iterator,
I::Item: 'a,
{
type Item = Chunk<'a, I>;
type IntoIter = Chunks<'a, I>;
fn into_iter(self) -> Self::IntoIter {
Chunks {
parent: self,
}
}
}
/// An iterator that yields the Chunk iterators.
///
/// Iterator element type is `Chunk`.
///
/// See [`.chunks()`](../trait.Itertools.html#method.chunks) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Chunks<'a, I: 'a>
where I: Iterator,
I::Item: 'a,
{
parent: &'a IntoChunks<I>,
}
impl<'a, I> Iterator for Chunks<'a, I>
where I: Iterator,
I::Item: 'a,
{
type Item = Chunk<'a, I>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let index = self.parent.index.get();
self.parent.index.set(index + 1);
let inner = &mut *self.parent.inner.borrow_mut();
inner.step(index).map(|elt| {
Chunk {
parent: self.parent,
index: index,
first: Some(elt),
}
})
}
}
/// An iterator for the elements in a single chunk.
///
/// Iterator element type is `I::Item`.
pub struct Chunk<'a, I: 'a>
where I: Iterator,
I::Item: 'a,
{
parent: &'a IntoChunks<I>,
index: usize,
first: Option<I::Item>,
}
impl<'a, I> Drop for Chunk<'a, I>
where I: Iterator,
I::Item: 'a,
{
fn drop(&mut self) {
self.parent.drop_group(self.index);
}
}
impl<'a, I> Iterator for Chunk<'a, I>
where I: Iterator,
I::Item: 'a,
{
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if let elt @ Some(..) = self.first.take() {
return elt;
}
self.parent.step(self.index)
}
}

14
third_party/rust/itertools-0.8.0/src/impl_macros.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,14 @@
//!
//! Implementation's internal macros
macro_rules! debug_fmt_fields {
($tyname:ident, $($($field:ident).+),*) => {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
f.debug_struct(stringify!($tyname))
$(
.field(stringify!($($field).+), &self.$($field).+)
)*
.finish()
}
}
}

60
third_party/rust/itertools-0.8.0/src/intersperse.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,60 @@
use std::iter::Fuse;
use super::size_hint;
#[derive(Clone)]
/// An iterator adaptor to insert a particular value
/// between each element of the adapted iterator.
///
/// Iterator element type is `I::Item`
///
/// This iterator is *fused*.
///
/// See [`.intersperse()`](../trait.Itertools.html#method.intersperse) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Debug)]
pub struct Intersperse<I>
where I: Iterator
{
element: I::Item,
iter: Fuse<I>,
peek: Option<I::Item>,
}
/// Create a new Intersperse iterator
pub fn intersperse<I>(iter: I, elt: I::Item) -> Intersperse<I>
where I: Iterator
{
let mut iter = iter.fuse();
Intersperse {
peek: iter.next(),
iter: iter,
element: elt,
}
}
impl<I> Iterator for Intersperse<I>
where I: Iterator,
I::Item: Clone
{
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<I::Item> {
if self.peek.is_some() {
self.peek.take()
} else {
self.peek = self.iter.next();
if self.peek.is_some() {
Some(self.element.clone())
} else {
None
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
// 2 * SH + { 1 or 0 }
let has_peek = self.peek.is_some() as usize;
let sh = self.iter.size_hint();
size_hint::add_scalar(size_hint::add(sh, sh), has_peek)
}
}

256
third_party/rust/itertools-0.8.0/src/kmerge_impl.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,256 @@
use size_hint;
use Itertools;
use std::mem::replace;
use std::fmt;
macro_rules! clone_fields {
($name:ident, $base:expr, $($field:ident),+) => (
$name {
$(
$field : $base . $field .clone()
),*
}
);
}
/// Head element and Tail iterator pair
///
/// `PartialEq`, `Eq`, `PartialOrd` and `Ord` are implemented by comparing sequences based on
/// first items (which are guaranteed to exist).
///
/// The meanings of `PartialOrd` and `Ord` are reversed so as to turn the heap used in
/// `KMerge` into a min-heap.
#[derive(Debug)]
struct HeadTail<I>
where I: Iterator
{
head: I::Item,
tail: I,
}
impl<I> HeadTail<I>
where I: Iterator
{
/// Constructs a `HeadTail` from an `Iterator`. Returns `None` if the `Iterator` is empty.
fn new(mut it: I) -> Option<HeadTail<I>> {
let head = it.next();
head.map(|h| {
HeadTail {
head: h,
tail: it,
}
})
}
/// Get the next element and update `head`, returning the old head in `Some`.
///
/// Returns `None` when the tail is exhausted (only `head` then remains).
fn next(&mut self) -> Option<I::Item> {
if let Some(next) = self.tail.next() {
Some(replace(&mut self.head, next))
} else {
None
}
}
/// Hints at the size of the sequence, same as the `Iterator` method.
fn size_hint(&self) -> (usize, Option<usize>) {
size_hint::add_scalar(self.tail.size_hint(), 1)
}
}
impl<I> Clone for HeadTail<I>
where I: Iterator + Clone,
I::Item: Clone
{
fn clone(&self) -> Self {
clone_fields!(HeadTail, self, head, tail)
}
}
/// Make `data` a heap (min-heap w.r.t the sorting).
fn heapify<T, S>(data: &mut [T], mut less_than: S)
where S: FnMut(&T, &T) -> bool
{
for i in (0..data.len() / 2).rev() {
sift_down(data, i, &mut less_than);
}
}
/// Sift down element at `index` (`heap` is a min-heap wrt the ordering)
fn sift_down<T, S>(heap: &mut [T], index: usize, mut less_than: S)
where S: FnMut(&T, &T) -> bool
{
debug_assert!(index <= heap.len());
let mut pos = index;
let mut child = 2 * pos + 1;
// the `pos` conditional is to avoid a bounds check
while pos < heap.len() && child < heap.len() {
let right = child + 1;
// pick the smaller of the two children
if right < heap.len() && less_than(&heap[right], &heap[child]) {
child = right;
}
// sift down is done if we are already in order
if !less_than(&heap[child], &heap[pos]) {
return;
}
heap.swap(pos, child);
pos = child;
child = 2 * pos + 1;
}
}
/// An iterator adaptor that merges an abitrary number of base iterators in ascending order.
/// If all base iterators are sorted (ascending), the result is sorted.
///
/// Iterator element type is `I::Item`.
///
/// See [`.kmerge()`](../trait.Itertools.html#method.kmerge) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct KMerge<I>
where I: Iterator
{
heap: Vec<HeadTail<I>>,
}
impl<I> fmt::Debug for KMerge<I>
where I: Iterator + fmt::Debug,
I::Item: fmt::Debug,
{
debug_fmt_fields!(KMerge, heap);
}
/// Create an iterator that merges elements of the contained iterators using
/// the ordering function.
///
/// Equivalent to `iterable.into_iter().kmerge()`.
///
/// ```
/// use itertools::kmerge;
///
/// for elt in kmerge(vec![vec![0, 2, 4], vec![1, 3, 5], vec![6, 7]]) {
/// /* loop body */
/// }
/// ```
pub fn kmerge<I>(iterable: I) -> KMerge<<I::Item as IntoIterator>::IntoIter>
where I: IntoIterator,
I::Item: IntoIterator,
<<I as IntoIterator>::Item as IntoIterator>::Item: PartialOrd
{
let iter = iterable.into_iter();
let (lower, _) = iter.size_hint();
let mut heap = Vec::with_capacity(lower);
heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter())));
heapify(&mut heap, |a, b| a.head < b.head);
KMerge { heap: heap }
}
impl<I> Clone for KMerge<I>
where I: Iterator + Clone,
I::Item: Clone
{
fn clone(&self) -> KMerge<I> {
clone_fields!(KMerge, self, heap)
}
}
impl<I> Iterator for KMerge<I>
where I: Iterator,
I::Item: PartialOrd
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
if self.heap.is_empty() {
return None;
}
let result = if let Some(next) = self.heap[0].next() {
next
} else {
self.heap.swap_remove(0).head
};
sift_down(&mut self.heap, 0, |a, b| a.head < b.head);
Some(result)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.heap.iter()
.map(|i| i.size_hint())
.fold1(size_hint::add)
.unwrap_or((0, Some(0)))
}
}
/// An iterator adaptor that merges an abitrary number of base iterators
/// according to an ordering function.
///
/// Iterator element type is `I::Item`.
///
/// See [`.kmerge_by()`](../trait.Itertools.html#method.kmerge_by) for more
/// information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct KMergeBy<I, F>
where I: Iterator,
{
heap: Vec<HeadTail<I>>,
less_than: F,
}
impl<I, F> fmt::Debug for KMergeBy<I, F>
where I: Iterator + fmt::Debug,
I::Item: fmt::Debug,
{
debug_fmt_fields!(KMergeBy, heap);
}
/// Create an iterator that merges elements of the contained iterators.
///
/// Equivalent to `iterable.into_iter().kmerge_by(less_than)`.
pub fn kmerge_by<I, F>(iterable: I, mut less_than: F)
-> KMergeBy<<I::Item as IntoIterator>::IntoIter, F>
where I: IntoIterator,
I::Item: IntoIterator,
F: FnMut(&<<I as IntoIterator>::Item as IntoIterator>::Item,
&<<I as IntoIterator>::Item as IntoIterator>::Item) -> bool
{
let iter = iterable.into_iter();
let (lower, _) = iter.size_hint();
let mut heap: Vec<_> = Vec::with_capacity(lower);
heap.extend(iter.filter_map(|it| HeadTail::new(it.into_iter())));
heapify(&mut heap, |a, b| less_than(&a.head, &b.head));
KMergeBy { heap: heap, less_than: less_than }
}
impl<I, F> Iterator for KMergeBy<I, F>
where I: Iterator,
F: FnMut(&I::Item, &I::Item) -> bool
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
if self.heap.is_empty() {
return None;
}
let result = if let Some(next) = self.heap[0].next() {
next
} else {
self.heap.swap_remove(0).head
};
let less_than = &mut self.less_than;
sift_down(&mut self.heap, 0, |a, b| less_than(&a.head, &b.head));
Some(result)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.heap.iter()
.map(|i| i.size_hint())
.fold1(size_hint::add)
.unwrap_or((0, Some(0)))
}
}

2176
third_party/rust/itertools-0.8.0/src/lib.rs поставляемый Normal file

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

87
third_party/rust/itertools-0.8.0/src/merge_join.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,87 @@
use std::cmp::Ordering;
use std::iter::Fuse;
use std::fmt;
use super::adaptors::{PutBack, put_back};
use either_or_both::EitherOrBoth;
/// Return an iterator adaptor that merge-joins items from the two base iterators in ascending order.
///
/// See [`.merge_join_by()`](trait.Itertools.html#method.merge_join_by) for more information.
pub fn merge_join_by<I, J, F>(left: I, right: J, cmp_fn: F)
-> MergeJoinBy<I::IntoIter, J::IntoIter, F>
where I: IntoIterator,
J: IntoIterator,
F: FnMut(&I::Item, &J::Item) -> Ordering
{
MergeJoinBy {
left: put_back(left.into_iter().fuse()),
right: put_back(right.into_iter().fuse()),
cmp_fn: cmp_fn
}
}
/// An iterator adaptor that merge-joins items from the two base iterators in ascending order.
///
/// See [`.merge_join_by()`](../trait.Itertools.html#method.merge_join_by) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct MergeJoinBy<I: Iterator, J: Iterator, F> {
left: PutBack<Fuse<I>>,
right: PutBack<Fuse<J>>,
cmp_fn: F
}
impl<I, J, F> fmt::Debug for MergeJoinBy<I, J, F>
where I: Iterator + fmt::Debug,
I::Item: fmt::Debug,
J: Iterator + fmt::Debug,
J::Item: fmt::Debug,
{
debug_fmt_fields!(MergeJoinBy, left, right);
}
impl<I, J, F> Iterator for MergeJoinBy<I, J, F>
where I: Iterator,
J: Iterator,
F: FnMut(&I::Item, &J::Item) -> Ordering
{
type Item = EitherOrBoth<I::Item, J::Item>;
fn next(&mut self) -> Option<Self::Item> {
match (self.left.next(), self.right.next()) {
(None, None) => None,
(Some(left), None) =>
Some(EitherOrBoth::Left(left)),
(None, Some(right)) =>
Some(EitherOrBoth::Right(right)),
(Some(left), Some(right)) => {
match (self.cmp_fn)(&left, &right) {
Ordering::Equal =>
Some(EitherOrBoth::Both(left, right)),
Ordering::Less => {
self.right.put_back(right);
Some(EitherOrBoth::Left(left))
},
Ordering::Greater => {
self.left.put_back(left);
Some(EitherOrBoth::Right(right))
}
}
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (a_lower, a_upper) = self.left.size_hint();
let (b_lower, b_upper) = self.right.size_hint();
let lower = ::std::cmp::max(a_lower, b_lower);
let upper = match (a_upper, b_upper) {
(Some(x), Some(y)) => Some(x + y),
_ => None,
};
(lower, upper)
}
}

114
third_party/rust/itertools-0.8.0/src/minmax.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,114 @@
/// `MinMaxResult` is an enum returned by `minmax`. See `Itertools::minmax()` for
/// more detail.
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum MinMaxResult<T> {
/// Empty iterator
NoElements,
/// Iterator with one element, so the minimum and maximum are the same
OneElement(T),
/// More than one element in the iterator, the first element is not larger
/// than the second
MinMax(T, T)
}
impl<T: Clone> MinMaxResult<T> {
/// `into_option` creates an `Option` of type `(T, T)`. The returned `Option`
/// has variant `None` if and only if the `MinMaxResult` has variant
/// `NoElements`. Otherwise `Some((x, y))` is returned where `x <= y`.
/// If the `MinMaxResult` has variant `OneElement(x)`, performing this
/// operation will make one clone of `x`.
///
/// # Examples
///
/// ```
/// use itertools::MinMaxResult::{self, NoElements, OneElement, MinMax};
///
/// let r: MinMaxResult<i32> = NoElements;
/// assert_eq!(r.into_option(), None);
///
/// let r = OneElement(1);
/// assert_eq!(r.into_option(), Some((1, 1)));
///
/// let r = MinMax(1, 2);
/// assert_eq!(r.into_option(), Some((1, 2)));
/// ```
pub fn into_option(self) -> Option<(T,T)> {
match self {
MinMaxResult::NoElements => None,
MinMaxResult::OneElement(x) => Some((x.clone(), x)),
MinMaxResult::MinMax(x, y) => Some((x, y))
}
}
}
/// Implementation guts for `minmax` and `minmax_by_key`.
pub fn minmax_impl<I, K, F, L>(mut it: I, mut key_for: F,
mut lt: L) -> MinMaxResult<I::Item>
where I: Iterator,
F: FnMut(&I::Item) -> K,
L: FnMut(&I::Item, &I::Item, &K, &K) -> bool,
{
let (mut min, mut max, mut min_key, mut max_key) = match it.next() {
None => return MinMaxResult::NoElements,
Some(x) => {
match it.next() {
None => return MinMaxResult::OneElement(x),
Some(y) => {
let xk = key_for(&x);
let yk = key_for(&y);
if !lt(&y, &x, &yk, &xk) {(x, y, xk, yk)} else {(y, x, yk, xk)}
}
}
}
};
loop {
// `first` and `second` are the two next elements we want to look
// at. We first compare `first` and `second` (#1). The smaller one
// is then compared to current minimum (#2). The larger one is
// compared to current maximum (#3). This way we do 3 comparisons
// for 2 elements.
let first = match it.next() {
None => break,
Some(x) => x
};
let second = match it.next() {
None => {
let first_key = key_for(&first);
if lt(&first, &min, &first_key, &min_key) {
min = first;
} else if !lt(&first, &max, &first_key, &max_key) {
max = first;
}
break;
}
Some(x) => x
};
let first_key = key_for(&first);
let second_key = key_for(&second);
if !lt(&second, &first, &second_key, &first_key) {
if lt(&first, &min, &first_key, &min_key) {
min = first;
min_key = first_key;
}
if !lt(&second, &max, &second_key, &max_key) {
max = second;
max_key = second_key;
}
} else {
if lt(&second, &min, &second_key, &min_key) {
min = second;
min_key = second_key;
}
if !lt(&first, &max, &first_key, &max_key) {
max = first;
max_key = first_key;
}
}
}
MinMaxResult::MinMax(min, max)
}

104
third_party/rust/itertools-0.8.0/src/multipeek_impl.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,104 @@
use std::iter::Fuse;
use std::collections::VecDeque;
use size_hint;
use PeekingNext;
/// See [`multipeek()`](../fn.multipeek.html) for more information.
#[derive(Clone, Debug)]
pub struct MultiPeek<I>
where I: Iterator
{
iter: Fuse<I>,
buf: VecDeque<I::Item>,
index: usize,
}
/// An iterator adaptor that allows the user to peek at multiple `.next()`
/// values without advancing the base iterator.
pub fn multipeek<I>(iterable: I) -> MultiPeek<I::IntoIter>
where I: IntoIterator
{
MultiPeek {
iter: iterable.into_iter().fuse(),
buf: VecDeque::new(),
index: 0,
}
}
impl<I> MultiPeek<I>
where I: Iterator
{
/// Reset the peeking “cursor”
pub fn reset_peek(&mut self) {
self.index = 0;
}
}
impl<I: Iterator> MultiPeek<I> {
/// Works exactly like `.next()` with the only difference that it doesn't
/// advance itself. `.peek()` can be called multiple times, to peek
/// further ahead.
pub fn peek(&mut self) -> Option<&I::Item> {
let ret = if self.index < self.buf.len() {
Some(&self.buf[self.index])
} else {
match self.iter.next() {
Some(x) => {
self.buf.push_back(x);
Some(&self.buf[self.index])
}
None => return None,
}
};
self.index += 1;
ret
}
}
impl<I> PeekingNext for MultiPeek<I>
where I: Iterator,
{
fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
where F: FnOnce(&Self::Item) -> bool
{
if self.buf.is_empty() {
if let Some(r) = self.peek() {
if !accept(r) { return None }
}
} else {
if let Some(r) = self.buf.get(0) {
if !accept(r) { return None }
}
}
self.next()
}
}
impl<I> Iterator for MultiPeek<I>
where I: Iterator
{
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
self.index = 0;
if self.buf.is_empty() {
self.iter.next()
} else {
self.buf.pop_front()
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
size_hint::add_scalar(self.iter.size_hint(), self.buf.len())
}
}
// Same size
impl<I> ExactSizeIterator for MultiPeek<I>
where I: ExactSizeIterator
{}

83
third_party/rust/itertools-0.8.0/src/pad_tail.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,83 @@
use std::iter::Fuse;
use size_hint;
/// An iterator adaptor that pads a sequence to a minimum length by filling
/// missing elements using a closure.
///
/// Iterator element type is `I::Item`.
///
/// See [`.pad_using()`](../trait.Itertools.html#method.pad_using) for more information.
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct PadUsing<I, F> {
iter: Fuse<I>,
min: usize,
pos: usize,
filler: F,
}
/// Create a new **PadUsing** iterator.
pub fn pad_using<I, F>(iter: I, min: usize, filler: F) -> PadUsing<I, F>
where I: Iterator,
F: FnMut(usize) -> I::Item
{
PadUsing {
iter: iter.fuse(),
min: min,
pos: 0,
filler: filler,
}
}
impl<I, F> Iterator for PadUsing<I, F>
where I: Iterator,
F: FnMut(usize) -> I::Item
{
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<I::Item> {
match self.iter.next() {
None => {
if self.pos < self.min {
let e = Some((self.filler)(self.pos));
self.pos += 1;
e
} else {
None
}
},
e => {
self.pos += 1;
e
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let tail = self.min.saturating_sub(self.pos);
size_hint::max(self.iter.size_hint(), (tail, Some(tail)))
}
}
impl<I, F> DoubleEndedIterator for PadUsing<I, F>
where I: DoubleEndedIterator + ExactSizeIterator,
F: FnMut(usize) -> I::Item
{
fn next_back(&mut self) -> Option<I::Item> {
if self.min == 0 {
self.iter.next_back()
} else if self.iter.len() >= self.min {
self.min -= 1;
self.iter.next_back()
} else {
self.min -= 1;
Some((self.filler)(self.min))
}
}
}
impl<I, F> ExactSizeIterator for PadUsing<I, F>
where I: ExactSizeIterator,
F: FnMut(usize) -> I::Item
{}

149
third_party/rust/itertools-0.8.0/src/peeking_take_while.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,149 @@
use std::iter::Peekable;
use PutBack;
#[cfg(feature = "use_std")]
use PutBackN;
/// An iterator that allows peeking at an element before deciding to accept it.
///
/// See [`.peeking_take_while()`](trait.Itertools.html#method.peeking_take_while)
/// for more information.
///
/// This is implemented by peeking adaptors like peekable and put back,
/// but also by a few iterators that can be peeked natively, like the slices
/// by reference iterator (`std::slice::Iter`).
pub trait PeekingNext : Iterator {
/// Pass a reference to the next iterator element to the closure `accept`;
/// if `accept` returns true, return it as the next element,
/// else None.
fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
where F: FnOnce(&Self::Item) -> bool;
}
impl<I> PeekingNext for Peekable<I>
where I: Iterator,
{
fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
where F: FnOnce(&Self::Item) -> bool
{
if let Some(r) = self.peek() {
if !accept(r) {
return None;
}
}
self.next()
}
}
impl<I> PeekingNext for PutBack<I>
where I: Iterator,
{
fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
where F: FnOnce(&Self::Item) -> bool
{
if let Some(r) = self.next() {
if !accept(&r) {
self.put_back(r);
return None;
}
Some(r)
} else {
None
}
}
}
#[cfg(feature = "use_std")]
impl<I> PeekingNext for PutBackN<I>
where I: Iterator,
{
fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
where F: FnOnce(&Self::Item) -> bool
{
if let Some(r) = self.next() {
if !accept(&r) {
self.put_back(r);
return None;
}
Some(r)
} else {
None
}
}
}
/// An iterator adaptor that takes items while a closure returns `true`.
///
/// See [`.peeking_take_while()`](../trait.Itertools.html#method.peeking_take_while)
/// for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct PeekingTakeWhile<'a, I: 'a, F>
where I: Iterator,
{
iter: &'a mut I,
f: F,
}
/// Create a PeekingTakeWhile
pub fn peeking_take_while<I, F>(iter: &mut I, f: F) -> PeekingTakeWhile<I, F>
where I: Iterator,
{
PeekingTakeWhile {
iter: iter,
f: f,
}
}
impl<'a, I, F> Iterator for PeekingTakeWhile<'a, I, F>
where I: PeekingNext,
F: FnMut(&I::Item) -> bool,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
self.iter.peeking_next(&mut self.f)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, hi) = self.iter.size_hint();
(0, hi)
}
}
// Some iterators are so lightweight we can simply clone them to save their
// state and use that for peeking.
macro_rules! peeking_next_by_clone {
([$($typarm:tt)*] $type_:ty) => {
impl<$($typarm)*> PeekingNext for $type_ {
fn peeking_next<F>(&mut self, accept: F) -> Option<Self::Item>
where F: FnOnce(&Self::Item) -> bool
{
let saved_state = self.clone();
if let Some(r) = self.next() {
if !accept(&r) {
*self = saved_state;
} else {
return Some(r)
}
}
None
}
}
}
}
peeking_next_by_clone! { ['a, T] ::std::slice::Iter<'a, T> }
peeking_next_by_clone! { ['a] ::std::str::Chars<'a> }
peeking_next_by_clone! { ['a] ::std::str::CharIndices<'a> }
peeking_next_by_clone! { ['a] ::std::str::Bytes<'a> }
peeking_next_by_clone! { ['a, T] ::std::option::Iter<'a, T> }
peeking_next_by_clone! { ['a, T] ::std::result::Iter<'a, T> }
peeking_next_by_clone! { [T] ::std::iter::Empty<T> }
#[cfg(feature = "use_std")]
peeking_next_by_clone! { ['a, T] ::std::collections::linked_list::Iter<'a, T> }
#[cfg(feature = "use_std")]
peeking_next_by_clone! { ['a, T] ::std::collections::vec_deque::Iter<'a, T> }
// cloning a Rev has no extra overhead; peekable and put backs are never DEI.
peeking_next_by_clone! { [I: Clone + PeekingNext + DoubleEndedIterator]
::std::iter::Rev<I> }

81
third_party/rust/itertools-0.8.0/src/process_results_impl.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,81 @@
/// An iterator that produces only the `T` values as long as the
/// inner iterator produces `Ok(T)`.
///
/// Used by [`process_results`](../fn.process_results.html), see its docs
/// for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Debug)]
pub struct ProcessResults<'a, I, E: 'a> {
error: &'a mut Result<(), E>,
iter: I,
}
impl<'a, I, T, E> Iterator for ProcessResults<'a, I, E>
where I: Iterator<Item = Result<T, E>>
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
match self.iter.next() {
Some(Ok(x)) => Some(x),
Some(Err(e)) => {
*self.error = Err(e);
None
}
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, hi) = self.iter.size_hint();
(0, hi)
}
}
/// “Lift” a function of the values of an iterator so that it can process
/// an iterator of `Result` values instead.
///
/// `iterable` is an iterator or iterable with `Result<T, E>` elements, where
/// `T` is the value type and `E` the error type.
///
/// `processor` is a closure that receives an adapted version of the iterable
/// as the only argument — the adapted iterator produces elements of type `T`,
/// as long as the original iterator produces `Ok` values.
///
/// If the original iterable produces an error at any point, the adapted
/// iterator ends and the `process_results` function will return the
/// error iself.
///
/// Otherwise, the return value from the closure is returned wrapped
/// inside `Ok`.
///
/// # Example
///
/// ```
/// use itertools::process_results;
///
/// type R = Result<i32, &'static str>;
///
/// let first_values: Vec<R> = vec![Ok(1), Ok(0), Ok(3)];
/// let second_values: Vec<R> = vec![Ok(2), Ok(1), Err("overflow")];
///
/// // “Lift” the iterator .max() method to work on the values in Results using process_results
///
/// let first_max = process_results(first_values, |iter| iter.max().unwrap_or(0));
/// let second_max = process_results(second_values, |iter| iter.max().unwrap_or(0));
///
/// assert_eq!(first_max, Ok(3));
/// assert!(second_max.is_err());
/// ```
pub fn process_results<I, F, T, E, R>(iterable: I, processor: F) -> Result<R, E>
where I: IntoIterator<Item = Result<T, E>>,
F: FnOnce(ProcessResults<I::IntoIter, E>) -> R
{
let iter = iterable.into_iter();
let mut error = Ok(());
let result = processor(ProcessResults { error: &mut error, iter: iter });
error.map(|_| result)
}

63
third_party/rust/itertools-0.8.0/src/put_back_n_impl.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,63 @@
use size_hint;
/// An iterator adaptor that allows putting multiple
/// items in front of the iterator.
///
/// Iterator element type is `I::Item`.
#[derive(Debug, Clone)]
pub struct PutBackN<I: Iterator> {
top: Vec<I::Item>,
iter: I,
}
/// Create an iterator where you can put back multiple values to the front
/// of the iteration.
///
/// Iterator element type is `I::Item`.
pub fn put_back_n<I>(iterable: I) -> PutBackN<I::IntoIter>
where I: IntoIterator
{
PutBackN {
top: Vec::new(),
iter: iterable.into_iter(),
}
}
impl<I: Iterator> PutBackN<I> {
/// Puts x in front of the iterator.
/// The values are yielded in order of the most recently put back
/// values first.
///
/// ```rust
/// use itertools::put_back_n;
///
/// let mut it = put_back_n(1..5);
/// it.next();
/// it.put_back(1);
/// it.put_back(0);
///
/// assert!(itertools::equal(it, 0..5));
/// ```
#[inline]
pub fn put_back(&mut self, x: I::Item) {
self.top.push(x);
}
}
impl<I: Iterator> Iterator for PutBackN<I> {
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<I::Item> {
if self.top.is_empty() {
self.iter.next()
} else {
self.top.pop()
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
size_hint::add_scalar(self.iter.size_hint(), self.top.len())
}
}

98
third_party/rust/itertools-0.8.0/src/rciter_impl.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,98 @@
use std::iter::IntoIterator;
use std::rc::Rc;
use std::cell::RefCell;
/// A wrapper for `Rc<RefCell<I>>`, that implements the `Iterator` trait.
#[derive(Debug)]
pub struct RcIter<I> {
/// The boxed iterator.
pub rciter: Rc<RefCell<I>>,
}
/// Return an iterator inside a `Rc<RefCell<_>>` wrapper.
///
/// The returned `RcIter` can be cloned, and each clone will refer back to the
/// same original iterator.
///
/// `RcIter` allows doing interesting things like using `.zip()` on an iterator with
/// itself, at the cost of runtime borrow checking which may have a performance
/// penalty.
///
/// Iterator element type is `Self::Item`.
///
/// ```
/// use itertools::rciter;
/// use itertools::zip;
///
/// // In this example a range iterator is created and we iterate it using
/// // three separate handles (two of them given to zip).
/// // We also use the IntoIterator implementation for `&RcIter`.
///
/// let mut iter = rciter(0..9);
/// let mut z = zip(&iter, &iter);
///
/// assert_eq!(z.next(), Some((0, 1)));
/// assert_eq!(z.next(), Some((2, 3)));
/// assert_eq!(z.next(), Some((4, 5)));
/// assert_eq!(iter.next(), Some(6));
/// assert_eq!(z.next(), Some((7, 8)));
/// assert_eq!(z.next(), None);
/// ```
///
/// **Panics** in iterator methods if a borrow error is encountered in the
/// iterator methods. It can only happen if the `RcIter` is reentered in
/// `.next()`, i.e. if it somehow participates in an “iterator knot”
/// where it is an adaptor of itself.
pub fn rciter<I>(iterable: I) -> RcIter<I::IntoIter>
where I: IntoIterator
{
RcIter { rciter: Rc::new(RefCell::new(iterable.into_iter())) }
}
impl<I> Clone for RcIter<I> {
#[inline]
fn clone(&self) -> RcIter<I> {
RcIter { rciter: self.rciter.clone() }
}
}
impl<A, I> Iterator for RcIter<I>
where I: Iterator<Item = A>
{
type Item = A;
#[inline]
fn next(&mut self) -> Option<A> {
self.rciter.borrow_mut().next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
// To work sanely with other API that assume they own an iterator,
// so it can't change in other places, we can't guarantee as much
// in our size_hint. Other clones may drain values under our feet.
let (_, hi) = self.rciter.borrow().size_hint();
(0, hi)
}
}
impl<I> DoubleEndedIterator for RcIter<I>
where I: DoubleEndedIterator
{
#[inline]
fn next_back(&mut self) -> Option<I::Item> {
self.rciter.borrow_mut().next_back()
}
}
/// Return an iterator from `&RcIter<I>` (by simply cloning it).
impl<'a, I> IntoIterator for &'a RcIter<I>
where I: Iterator
{
type Item = I::Item;
type IntoIter = RcIter<I>;
fn into_iter(self) -> RcIter<I> {
self.clone()
}
}

54
third_party/rust/itertools-0.8.0/src/repeatn.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,54 @@
/// An iterator that produces *n* repetitions of an element.
///
/// See [`repeat_n()`](../fn.repeat_n.html) for more information.
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[derive(Debug)]
pub struct RepeatN<A> {
elt: Option<A>,
n: usize,
}
/// Create an iterator that produces `n` repetitions of `element`.
pub fn repeat_n<A>(element: A, n: usize) -> RepeatN<A>
where A: Clone,
{
if n == 0 {
RepeatN { elt: None, n: n, }
} else {
RepeatN { elt: Some(element), n: n, }
}
}
impl<A> Iterator for RepeatN<A>
where A: Clone
{
type Item = A;
fn next(&mut self) -> Option<Self::Item> {
if self.n > 1 {
self.n -= 1;
self.elt.as_ref().cloned()
} else {
self.n = 0;
self.elt.take()
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.n, Some(self.n))
}
}
impl<A> DoubleEndedIterator for RepeatN<A>
where A: Clone
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.next()
}
}
impl<A> ExactSizeIterator for RepeatN<A>
where A: Clone
{}

104
third_party/rust/itertools-0.8.0/src/size_hint.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,104 @@
//! Arithmetic on **Iterator** *.size_hint()* values.
//!
use std::usize;
use std::cmp;
/// **SizeHint** is the return type of **Iterator::size_hint()**.
pub type SizeHint = (usize, Option<usize>);
/// Add **SizeHint** correctly.
#[inline]
pub fn add(a: SizeHint, b: SizeHint) -> SizeHint {
let min = a.0.checked_add(b.0).unwrap_or(usize::MAX);
let max = match (a.1, b.1) {
(Some(x), Some(y)) => x.checked_add(y),
_ => None,
};
(min, max)
}
/// Add **x** correctly to a **SizeHint**.
#[inline]
pub fn add_scalar(sh: SizeHint, x: usize) -> SizeHint {
let (mut low, mut hi) = sh;
low = low.saturating_add(x);
hi = hi.and_then(|elt| elt.checked_add(x));
(low, hi)
}
/// Sbb **x** correctly to a **SizeHint**.
#[inline]
#[allow(dead_code)]
pub fn sub_scalar(sh: SizeHint, x: usize) -> SizeHint {
let (mut low, mut hi) = sh;
low = low.saturating_sub(x);
hi = hi.map(|elt| elt.saturating_sub(x));
(low, hi)
}
/// Multiply **SizeHint** correctly
///
/// ```ignore
/// use std::usize;
/// use itertools::size_hint;
///
/// assert_eq!(size_hint::mul((3, Some(4)), (3, Some(4))),
/// (9, Some(16)));
///
/// assert_eq!(size_hint::mul((3, Some(4)), (usize::MAX, None)),
/// (usize::MAX, None));
///
/// assert_eq!(size_hint::mul((3, None), (0, Some(0))),
/// (0, Some(0)));
/// ```
#[inline]
pub fn mul(a: SizeHint, b: SizeHint) -> SizeHint {
let low = a.0.checked_mul(b.0).unwrap_or(usize::MAX);
let hi = match (a.1, b.1) {
(Some(x), Some(y)) => x.checked_mul(y),
(Some(0), None) | (None, Some(0)) => Some(0),
_ => None,
};
(low, hi)
}
/// Multiply **x** correctly with a **SizeHint**.
#[inline]
pub fn mul_scalar(sh: SizeHint, x: usize) -> SizeHint {
let (mut low, mut hi) = sh;
low = low.saturating_mul(x);
hi = hi.and_then(|elt| elt.checked_mul(x));
(low, hi)
}
/// Return the maximum
#[inline]
pub fn max(a: SizeHint, b: SizeHint) -> SizeHint {
let (a_lower, a_upper) = a;
let (b_lower, b_upper) = b;
let lower = cmp::max(a_lower, b_lower);
let upper = match (a_upper, b_upper) {
(Some(x), Some(y)) => Some(cmp::max(x, y)),
_ => None,
};
(lower, upper)
}
/// Return the minimum
#[inline]
pub fn min(a: SizeHint, b: SizeHint) -> SizeHint {
let (a_lower, a_upper) = a;
let (b_lower, b_upper) = b;
let lower = cmp::min(a_lower, b_lower);
let upper = match (a_upper, b_upper) {
(Some(u1), Some(u2)) => Some(cmp::min(u1, u2)),
_ => a_upper.or(b_upper),
};
(lower, upper)
}

190
third_party/rust/itertools-0.8.0/src/sources.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,190 @@
//! Iterators that are sources (produce elements from parameters,
//! not from another iterator).
#![allow(deprecated)]
use std::fmt;
use std::mem;
/// See [`repeat_call`](../fn.repeat_call.html) for more information.
#[deprecated(note="Use std repeat_with() instead", since="0.8")]
pub struct RepeatCall<F> {
f: F,
}
impl<F> fmt::Debug for RepeatCall<F>
{
debug_fmt_fields!(RepeatCall, );
}
/// An iterator source that produces elements indefinitely by calling
/// a given closure.
///
/// Iterator element type is the return type of the closure.
///
/// ```
/// use itertools::repeat_call;
/// use itertools::Itertools;
/// use std::collections::BinaryHeap;
///
/// let mut heap = BinaryHeap::from(vec![2, 5, 3, 7, 8]);
///
/// // extract each element in sorted order
/// for element in repeat_call(|| heap.pop()).while_some() {
/// print!("{}", element);
/// }
///
/// itertools::assert_equal(
/// repeat_call(|| 1).take(5),
/// vec![1, 1, 1, 1, 1]
/// );
/// ```
#[deprecated(note="Use std repeat_with() instead", since="0.8")]
pub fn repeat_call<F, A>(function: F) -> RepeatCall<F>
where F: FnMut() -> A
{
RepeatCall { f: function }
}
impl<A, F> Iterator for RepeatCall<F>
where F: FnMut() -> A
{
type Item = A;
#[inline]
fn next(&mut self) -> Option<A> {
Some((self.f)())
}
fn size_hint(&self) -> (usize, Option<usize>) {
(usize::max_value(), None)
}
}
/// Creates a new unfold source with the specified closure as the "iterator
/// function" and an initial state to eventually pass to the closure
///
/// `unfold` is a general iterator builder: it has a mutable state value,
/// and a closure with access to the state that produces the next value.
///
/// This more or less equivalent to a regular struct with an `Iterator`
/// implementation, and is useful for one-off iterators.
///
/// ```
/// // an iterator that yields sequential Fibonacci numbers,
/// // and stops at the maximum representable value.
///
/// use itertools::unfold;
///
/// let (mut x1, mut x2) = (1u32, 1u32);
/// let mut fibonacci = unfold((), move |_| {
/// // Attempt to get the next Fibonacci number
/// let next = x1.saturating_add(x2);
///
/// // Shift left: ret <- x1 <- x2 <- next
/// let ret = x1;
/// x1 = x2;
/// x2 = next;
///
/// // If addition has saturated at the maximum, we are finished
/// if ret == x1 && ret > 1 {
/// return None;
/// }
///
/// Some(ret)
/// });
///
/// itertools::assert_equal(fibonacci.by_ref().take(8),
/// vec![1, 1, 2, 3, 5, 8, 13, 21]);
/// assert_eq!(fibonacci.last(), Some(2_971_215_073))
/// ```
pub fn unfold<A, St, F>(initial_state: St, f: F) -> Unfold<St, F>
where F: FnMut(&mut St) -> Option<A>
{
Unfold {
f: f,
state: initial_state,
}
}
impl<St, F> fmt::Debug for Unfold<St, F>
where St: fmt::Debug,
{
debug_fmt_fields!(Unfold, state);
}
/// See [`unfold`](../fn.unfold.html) for more information.
#[derive(Clone)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct Unfold<St, F> {
f: F,
/// Internal state that will be passed to the closure on the next iteration
pub state: St,
}
impl<A, St, F> Iterator for Unfold<St, F>
where F: FnMut(&mut St) -> Option<A>
{
type Item = A;
#[inline]
fn next(&mut self) -> Option<A> {
(self.f)(&mut self.state)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
// no possible known bounds at this point
(0, None)
}
}
/// An iterator that infinitely applies function to value and yields results.
///
/// This `struct` is created by the [`iterate()`] function. See its documentation for more.
///
/// [`iterate()`]: ../fn.iterate.html
#[derive(Clone)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct Iterate<St, F> {
state: St,
f: F,
}
impl<St, F> fmt::Debug for Iterate<St, F>
where St: fmt::Debug,
{
debug_fmt_fields!(Iterate, state);
}
impl<St, F> Iterator for Iterate<St, F>
where F: FnMut(&St) -> St
{
type Item = St;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let next_state = (self.f)(&self.state);
Some(mem::replace(&mut self.state, next_state))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(usize::max_value(), None)
}
}
/// Creates a new iterator that infinitely applies function to value and yields results.
///
/// ```
/// use itertools::iterate;
///
/// itertools::assert_equal(iterate(1, |&i| i * 3).take(5), vec![1, 3, 9, 27, 81]);
/// ```
pub fn iterate<St, F>(initial_value: St, f: F) -> Iterate<St, F>
where F: FnMut(&St) -> St
{
Iterate {
state: initial_value,
f: f,
}
}

78
third_party/rust/itertools-0.8.0/src/tee.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,78 @@
use super::size_hint;
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;
/// Common buffer object for the two tee halves
#[derive(Debug)]
struct TeeBuffer<A, I> {
backlog: VecDeque<A>,
iter: I,
/// The owner field indicates which id should read from the backlog
owner: bool,
}
/// One half of an iterator pair where both return the same elements.
///
/// See [`.tee()`](../trait.Itertools.html#method.tee) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Debug)]
pub struct Tee<I>
where I: Iterator
{
rcbuffer: Rc<RefCell<TeeBuffer<I::Item, I>>>,
id: bool,
}
pub fn new<I>(iter: I) -> (Tee<I>, Tee<I>)
where I: Iterator
{
let buffer = TeeBuffer{backlog: VecDeque::new(), iter: iter, owner: false};
let t1 = Tee{rcbuffer: Rc::new(RefCell::new(buffer)), id: true};
let t2 = Tee{rcbuffer: t1.rcbuffer.clone(), id: false};
(t1, t2)
}
impl<I> Iterator for Tee<I>
where I: Iterator,
I::Item: Clone
{
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
// .borrow_mut may fail here -- but only if the user has tied some kind of weird
// knot where the iterator refers back to itself.
let mut buffer = self.rcbuffer.borrow_mut();
if buffer.owner == self.id {
match buffer.backlog.pop_front() {
None => {}
some_elt => return some_elt,
}
}
match buffer.iter.next() {
None => None,
Some(elt) => {
buffer.backlog.push_back(elt.clone());
buffer.owner = !self.id;
Some(elt)
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let buffer = self.rcbuffer.borrow();
let sh = buffer.iter.size_hint();
if buffer.owner == self.id {
let log_len = buffer.backlog.len();
size_hint::add_scalar(sh, log_len)
} else {
sh
}
}
}
impl<I> ExactSizeIterator for Tee<I>
where I: ExactSizeIterator,
I::Item: Clone
{}

266
third_party/rust/itertools-0.8.0/src/tuple_impl.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,266 @@
//! Some iterator that produces tuples
use std::iter::Fuse;
/// An iterator over a incomplete tuple.
///
/// See [`.tuples()`](../trait.Itertools.html#method.tuples) and
/// [`Tuples::into_buffer()`](struct.Tuples.html#method.into_buffer).
#[derive(Debug)]
pub struct TupleBuffer<T>
where T: TupleCollect
{
cur: usize,
buf: T::Buffer,
}
impl<T> TupleBuffer<T>
where T: TupleCollect
{
fn new(buf: T::Buffer) -> Self {
TupleBuffer {
cur: 0,
buf: buf,
}
}
}
impl<T> Iterator for TupleBuffer<T>
where T: TupleCollect
{
type Item = T::Item;
fn next(&mut self) -> Option<Self::Item> {
let s = self.buf.as_mut();
if let Some(ref mut item) = s.get_mut(self.cur) {
self.cur += 1;
item.take()
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let buffer = &self.buf.as_ref()[self.cur..];
let len = if buffer.len() == 0 {
0
} else {
buffer.iter()
.position(|x| x.is_none())
.unwrap_or(buffer.len())
};
(len, Some(len))
}
}
impl<T> ExactSizeIterator for TupleBuffer<T>
where T: TupleCollect
{
}
/// An iterator that groups the items in tuples of a specific size.
///
/// See [`.tuples()`](../trait.Itertools.html#method.tuples) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Tuples<I, T>
where I: Iterator<Item = T::Item>,
T: TupleCollect
{
iter: Fuse<I>,
buf: T::Buffer,
}
/// Create a new tuples iterator.
pub fn tuples<I, T>(iter: I) -> Tuples<I, T>
where I: Iterator<Item = T::Item>,
T: TupleCollect
{
Tuples {
iter: iter.fuse(),
buf: Default::default(),
}
}
impl<I, T> Iterator for Tuples<I, T>
where I: Iterator<Item = T::Item>,
T: TupleCollect
{
type Item = T;
fn next(&mut self) -> Option<T> {
T::collect_from_iter(&mut self.iter, &mut self.buf)
}
}
impl<I, T> Tuples<I, T>
where I: Iterator<Item = T::Item>,
T: TupleCollect
{
/// Return a buffer with the produced items that was not enough to be grouped in a tuple.
///
/// ```
/// use itertools::Itertools;
///
/// let mut iter = (0..5).tuples();
/// assert_eq!(Some((0, 1, 2)), iter.next());
/// assert_eq!(None, iter.next());
/// itertools::assert_equal(vec![3, 4], iter.into_buffer());
/// ```
pub fn into_buffer(self) -> TupleBuffer<T> {
TupleBuffer::new(self.buf)
}
}
/// An iterator over all contiguous windows that produces tuples of a specific size.
///
/// See [`.tuple_windows()`](../trait.Itertools.html#method.tuple_windows) for more
/// information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Debug)]
pub struct TupleWindows<I, T>
where I: Iterator<Item = T::Item>,
T: TupleCollect
{
iter: I,
last: Option<T>,
}
/// Create a new tuple windows iterator.
pub fn tuple_windows<I, T>(mut iter: I) -> TupleWindows<I, T>
where I: Iterator<Item = T::Item>,
T: TupleCollect,
T::Item: Clone
{
use std::iter::once;
let mut last = None;
if T::num_items() != 1 {
// put in a duplicate item in front of the tuple; this simplifies
// .next() function.
if let Some(item) = iter.next() {
let iter = once(item.clone()).chain(once(item)).chain(&mut iter);
last = T::collect_from_iter_no_buf(iter);
}
}
TupleWindows {
last: last,
iter: iter,
}
}
impl<I, T> Iterator for TupleWindows<I, T>
where I: Iterator<Item = T::Item>,
T: TupleCollect + Clone,
T::Item: Clone
{
type Item = T;
fn next(&mut self) -> Option<T> {
if T::num_items() == 1 {
return T::collect_from_iter_no_buf(&mut self.iter)
}
if let Some(ref mut last) = self.last {
if let Some(new) = self.iter.next() {
last.left_shift_push(new);
return Some(last.clone());
}
}
None
}
}
pub trait TupleCollect: Sized {
type Item;
type Buffer: Default + AsRef<[Option<Self::Item>]> + AsMut<[Option<Self::Item>]>;
fn collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self>
where I: IntoIterator<Item = Self::Item>;
fn collect_from_iter_no_buf<I>(iter: I) -> Option<Self>
where I: IntoIterator<Item = Self::Item>;
fn num_items() -> usize;
fn left_shift_push(&mut self, item: Self::Item);
}
macro_rules! impl_tuple_collect {
() => ();
($N:expr; $A:ident ; $($X:ident),* ; $($Y:ident),* ; $($Y_rev:ident),*) => (
impl<$A> TupleCollect for ($($X),*,) {
type Item = $A;
type Buffer = [Option<$A>; $N - 1];
#[allow(unused_assignments, unused_mut)]
fn collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self>
where I: IntoIterator<Item = $A>
{
let mut iter = iter.into_iter();
$(
let mut $Y = None;
)*
loop {
$(
$Y = iter.next();
if $Y.is_none() {
break
}
)*
return Some(($($Y.unwrap()),*,))
}
let mut i = 0;
let mut s = buf.as_mut();
$(
if i < s.len() {
s[i] = $Y;
i += 1;
}
)*
return None;
}
#[allow(unused_assignments)]
fn collect_from_iter_no_buf<I>(iter: I) -> Option<Self>
where I: IntoIterator<Item = $A>
{
let mut iter = iter.into_iter();
loop {
$(
let $Y = if let Some($Y) = iter.next() {
$Y
} else {
break;
};
)*
return Some(($($Y),*,))
}
return None;
}
fn num_items() -> usize {
$N
}
fn left_shift_push(&mut self, item: $A) {
use std::mem::replace;
let &mut ($(ref mut $Y),*,) = self;
let tmp = item;
$(
let tmp = replace($Y_rev, tmp);
)*
drop(tmp);
}
}
)
}
impl_tuple_collect!(1; A; A; a; a);
impl_tuple_collect!(2; A; A, A; a, b; b, a);
impl_tuple_collect!(3; A; A, A, A; a, b, c; c, b, a);
impl_tuple_collect!(4; A; A, A, A, A; a, b, c, d; d, c, b, a);

134
third_party/rust/itertools-0.8.0/src/unique_impl.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,134 @@
use std::collections::HashMap;
use std::collections::hash_map::{Entry};
use std::hash::Hash;
use std::fmt;
/// An iterator adapter to filter out duplicate elements.
///
/// See [`.unique_by()`](../trait.Itertools.html#method.unique) for more information.
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct UniqueBy<I: Iterator, V, F> {
iter: I,
// Use a hashmap for the entry API
used: HashMap<V, ()>,
f: F,
}
impl<I, V, F> fmt::Debug for UniqueBy<I, V, F>
where I: Iterator + fmt::Debug,
V: fmt::Debug + Hash + Eq,
{
debug_fmt_fields!(UniqueBy, iter, used);
}
/// Create a new `UniqueBy` iterator.
pub fn unique_by<I, V, F>(iter: I, f: F) -> UniqueBy<I, V, F>
where V: Eq + Hash,
F: FnMut(&I::Item) -> V,
I: Iterator,
{
UniqueBy {
iter: iter,
used: HashMap::new(),
f: f,
}
}
// count the number of new unique keys in iterable (`used` is the set already seen)
fn count_new_keys<I, K>(mut used: HashMap<K, ()>, iterable: I) -> usize
where I: IntoIterator<Item=K>,
K: Hash + Eq,
{
let iter = iterable.into_iter();
let current_used = used.len();
used.extend(iter.map(|key| (key, ())));
used.len() - current_used
}
impl<I, V, F> Iterator for UniqueBy<I, V, F>
where I: Iterator,
V: Eq + Hash,
F: FnMut(&I::Item) -> V
{
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
while let Some(v) = self.iter.next() {
let key = (self.f)(&v);
if self.used.insert(key, ()).is_none() {
return Some(v);
}
}
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (low, hi) = self.iter.size_hint();
((low > 0 && self.used.is_empty()) as usize, hi)
}
fn count(self) -> usize {
let mut key_f = self.f;
count_new_keys(self.used, self.iter.map(move |elt| key_f(&elt)))
}
}
impl<I> Iterator for Unique<I>
where I: Iterator,
I::Item: Eq + Hash + Clone
{
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
while let Some(v) = self.iter.iter.next() {
if let Entry::Vacant(entry) = self.iter.used.entry(v) {
let elt = entry.key().clone();
entry.insert(());
return Some(elt);
}
}
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (low, hi) = self.iter.iter.size_hint();
((low > 0 && self.iter.used.is_empty()) as usize, hi)
}
fn count(self) -> usize {
count_new_keys(self.iter.used, self.iter.iter)
}
}
/// An iterator adapter to filter out duplicate elements.
///
/// See [`.unique()`](../trait.Itertools.html#method.unique) for more information.
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Unique<I: Iterator> {
iter: UniqueBy<I, I::Item, ()>,
}
impl<I> fmt::Debug for Unique<I>
where I: Iterator + fmt::Debug,
I::Item: Hash + Eq + fmt::Debug,
{
debug_fmt_fields!(Unique, iter);
}
pub fn unique<I>(iter: I) -> Unique<I>
where I: Iterator,
I::Item: Eq + Hash,
{
Unique {
iter: UniqueBy {
iter: iter,
used: HashMap::new(),
f: (),
}
}
}

90
third_party/rust/itertools-0.8.0/src/with_position.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,90 @@
use std::iter::{Fuse,Peekable};
/// An iterator adaptor that wraps each element in an [`Position`](../enum.Position.html).
///
/// Iterator element type is `Position<I::Item>`.
///
/// See [`.with_position()`](../trait.Itertools.html#method.with_position) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct WithPosition<I>
where I: Iterator,
{
handled_first: bool,
peekable: Peekable<Fuse<I>>,
}
/// Create a new `WithPosition` iterator.
pub fn with_position<I>(iter: I) -> WithPosition<I>
where I: Iterator,
{
WithPosition {
handled_first: false,
peekable: iter.fuse().peekable(),
}
}
/// A value yielded by `WithPosition`.
/// Indicates the position of this element in the iterator results.
///
/// See [`.with_position()`](trait.Itertools.html#method.with_position) for more information.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Position<T> {
/// This is the first element.
First(T),
/// This is neither the first nor the last element.
Middle(T),
/// This is the last element.
Last(T),
/// This is the only element.
Only(T),
}
impl<T> Position<T> {
/// Return the inner value.
pub fn into_inner(self) -> T {
match self {
Position::First(x) |
Position::Middle(x) |
Position::Last(x) |
Position::Only(x) => x,
}
}
}
impl<I: Iterator> Iterator for WithPosition<I> {
type Item = Position<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
match self.peekable.next() {
Some(item) => {
if !self.handled_first {
// Haven't seen the first item yet, and there is one to give.
self.handled_first = true;
// Peek to see if this is also the last item,
// in which case tag it as `Only`.
match self.peekable.peek() {
Some(_) => Some(Position::First(item)),
None => Some(Position::Only(item)),
}
} else {
// Have seen the first item, and there's something left.
// Peek to see if this is the last item.
match self.peekable.peek() {
Some(_) => Some(Position::Middle(item)),
None => Some(Position::Last(item)),
}
}
}
// Iterator is finished.
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.peekable.size_hint()
}
}
impl<I> ExactSizeIterator for WithPosition<I>
where I: ExactSizeIterator,
{ }

60
third_party/rust/itertools-0.8.0/src/zip_eq_impl.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,60 @@
use super::size_hint;
/// An iterator which iterates two other iterators simultaneously
///
/// See [`.zip_eq()`](../trait.Itertools.html#method.zip_eq) for more information.
#[derive(Clone, Debug)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct ZipEq<I, J> {
a: I,
b: J,
}
/// Iterate `i` and `j` in lock step.
///
/// **Panics** if the iterators are not of the same length.
///
/// `IntoIterator` enabled version of `i.zip_eq(j)`.
///
/// ```
/// use itertools::zip_eq;
///
/// let data = [1, 2, 3, 4, 5];
/// for (a, b) in zip_eq(&data[..data.len() - 1], &data[1..]) {
/// /* loop body */
/// }
/// ```
pub fn zip_eq<I, J>(i: I, j: J) -> ZipEq<I::IntoIter, J::IntoIter>
where I: IntoIterator,
J: IntoIterator
{
ZipEq {
a: i.into_iter(),
b: j.into_iter(),
}
}
impl<I, J> Iterator for ZipEq<I, J>
where I: Iterator,
J: Iterator
{
type Item = (I::Item, J::Item);
fn next(&mut self) -> Option<Self::Item> {
match (self.a.next(), self.b.next()) {
(None, None) => None,
(Some(a), Some(b)) => Some((a, b)),
(None, Some(_)) | (Some(_), None) =>
panic!("itertools: .zip_eq() reached end of one iterator before the other")
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
size_hint::min(self.a.size_hint(), self.b.size_hint())
}
}
impl<I, J> ExactSizeIterator for ZipEq<I, J>
where I: ExactSizeIterator,
J: ExactSizeIterator
{}

78
third_party/rust/itertools-0.8.0/src/zip_longest.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,78 @@
use std::cmp::Ordering::{Equal, Greater, Less};
use super::size_hint;
use std::iter::Fuse;
use either_or_both::EitherOrBoth;
// ZipLongest originally written by SimonSapin,
// and dedicated to itertools https://github.com/rust-lang/rust/pull/19283
/// An iterator which iterates two other iterators simultaneously
///
/// This iterator is *fused*.
///
/// See [`.zip_longest()`](../trait.Itertools.html#method.zip_longest) for more information.
#[derive(Clone, Debug)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct ZipLongest<T, U> {
a: Fuse<T>,
b: Fuse<U>,
}
/// Create a new `ZipLongest` iterator.
pub fn zip_longest<T, U>(a: T, b: U) -> ZipLongest<T, U>
where T: Iterator,
U: Iterator
{
ZipLongest {
a: a.fuse(),
b: b.fuse(),
}
}
impl<T, U> Iterator for ZipLongest<T, U>
where T: Iterator,
U: Iterator
{
type Item = EitherOrBoth<T::Item, U::Item>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match (self.a.next(), self.b.next()) {
(None, None) => None,
(Some(a), None) => Some(EitherOrBoth::Left(a)),
(None, Some(b)) => Some(EitherOrBoth::Right(b)),
(Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)),
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
size_hint::max(self.a.size_hint(), self.b.size_hint())
}
}
impl<T, U> DoubleEndedIterator for ZipLongest<T, U>
where T: DoubleEndedIterator + ExactSizeIterator,
U: DoubleEndedIterator + ExactSizeIterator
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
match self.a.len().cmp(&self.b.len()) {
Equal => match (self.a.next_back(), self.b.next_back()) {
(None, None) => None,
(Some(a), Some(b)) => Some(EitherOrBoth::Both(a, b)),
// These can only happen if .len() is inconsistent with .next_back()
(Some(a), None) => Some(EitherOrBoth::Left(a)),
(None, Some(b)) => Some(EitherOrBoth::Right(b)),
},
Greater => self.a.next_back().map(EitherOrBoth::Left),
Less => self.b.next_back().map(EitherOrBoth::Right),
}
}
}
impl<T, U> ExactSizeIterator for ZipLongest<T, U>
where T: ExactSizeIterator,
U: ExactSizeIterator
{}

111
third_party/rust/itertools-0.8.0/src/ziptuple.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,111 @@
use super::size_hint;
/// See [`multizip`](../fn.multizip.html) for more information.
#[derive(Clone, Debug)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Zip<T> {
t: T,
}
/// An iterator that generalizes *.zip()* and allows running multiple iterators in lockstep.
///
/// The iterator `Zip<(I, J, ..., M)>` is formed from a tuple of iterators (or values that
/// implement `IntoIterator`) and yields elements
/// until any of the subiterators yields `None`.
///
/// The iterator element type is a tuple like like `(A, B, ..., E)` where `A` to `E` are the
/// element types of the subiterator.
///
/// **Note:** The result of this macro is a value of a named type (`Zip<(I, J,
/// ..)>` of each component iterator `I, J, ...`) if each component iterator is
/// nameable.
///
/// Prefer [`izip!()`] over `multizip` for the performance benefits of using the
/// standard library `.zip()`. Prefer `multizip` if a nameable type is needed.
///
/// [`izip!()`]: macro.izip.html
///
/// ```
/// use itertools::multizip;
///
/// // iterate over three sequences side-by-side
/// let mut results = [0, 0, 0, 0];
/// let inputs = [3, 7, 9, 6];
///
/// for (r, index, input) in multizip((&mut results, 0..10, &inputs)) {
/// *r = index * 10 + input;
/// }
///
/// assert_eq!(results, [0 + 3, 10 + 7, 29, 36]);
/// ```
pub fn multizip<T, U>(t: U) -> Zip<T>
where Zip<T>: From<U>,
Zip<T>: Iterator,
{
Zip::from(t)
}
macro_rules! impl_zip_iter {
($($B:ident),*) => (
#[allow(non_snake_case)]
impl<$($B: IntoIterator),*> From<($($B,)*)> for Zip<($($B::IntoIter,)*)> {
fn from(t: ($($B,)*)) -> Self {
let ($($B,)*) = t;
Zip { t: ($($B.into_iter(),)*) }
}
}
#[allow(non_snake_case)]
#[allow(unused_assignments)]
impl<$($B),*> Iterator for Zip<($($B,)*)>
where
$(
$B: Iterator,
)*
{
type Item = ($($B::Item,)*);
fn next(&mut self) -> Option<Self::Item>
{
let ($(ref mut $B,)*) = self.t;
// NOTE: Just like iter::Zip, we check the iterators
// for None in order. We may finish unevenly (some
// iterators gave n + 1 elements, some only n).
$(
let $B = match $B.next() {
None => return None,
Some(elt) => elt
};
)*
Some(($($B,)*))
}
fn size_hint(&self) -> (usize, Option<usize>)
{
let sh = (::std::usize::MAX, None);
let ($(ref $B,)*) = self.t;
$(
let sh = size_hint::min($B.size_hint(), sh);
)*
sh
}
}
#[allow(non_snake_case)]
impl<$($B),*> ExactSizeIterator for Zip<($($B,)*)> where
$(
$B: ExactSizeIterator,
)*
{ }
);
}
impl_zip_iter!(A);
impl_zip_iter!(A, B);
impl_zip_iter!(A, B, C);
impl_zip_iter!(A, B, C, D);
impl_zip_iter!(A, B, C, D, E);
impl_zip_iter!(A, B, C, D, E, F);
impl_zip_iter!(A, B, C, D, E, F, G);
impl_zip_iter!(A, B, C, D, E, F, G, H);

110
third_party/rust/itertools-0.8.0/tests/merge_join.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,110 @@
extern crate itertools;
use itertools::EitherOrBoth;
use itertools::free::merge_join_by;
#[test]
fn empty() {
let left: Vec<u32> = vec![];
let right: Vec<u32> = vec![];
let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![];
let actual_result = merge_join_by(left, right, |l, r| l.cmp(r))
.collect::<Vec<_>>();
assert_eq!(expected_result, actual_result);
}
#[test]
fn left_only() {
let left: Vec<u32> = vec![1,2,3];
let right: Vec<u32> = vec![];
let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![
EitherOrBoth::Left(1),
EitherOrBoth::Left(2),
EitherOrBoth::Left(3)
];
let actual_result = merge_join_by(left, right, |l, r| l.cmp(r))
.collect::<Vec<_>>();
assert_eq!(expected_result, actual_result);
}
#[test]
fn right_only() {
let left: Vec<u32> = vec![];
let right: Vec<u32> = vec![1,2,3];
let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![
EitherOrBoth::Right(1),
EitherOrBoth::Right(2),
EitherOrBoth::Right(3)
];
let actual_result = merge_join_by(left, right, |l, r| l.cmp(r))
.collect::<Vec<_>>();
assert_eq!(expected_result, actual_result);
}
#[test]
fn first_left_then_right() {
let left: Vec<u32> = vec![1,2,3];
let right: Vec<u32> = vec![4,5,6];
let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![
EitherOrBoth::Left(1),
EitherOrBoth::Left(2),
EitherOrBoth::Left(3),
EitherOrBoth::Right(4),
EitherOrBoth::Right(5),
EitherOrBoth::Right(6)
];
let actual_result = merge_join_by(left, right, |l, r| l.cmp(r))
.collect::<Vec<_>>();
assert_eq!(expected_result, actual_result);
}
#[test]
fn first_right_then_left() {
let left: Vec<u32> = vec![4,5,6];
let right: Vec<u32> = vec![1,2,3];
let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![
EitherOrBoth::Right(1),
EitherOrBoth::Right(2),
EitherOrBoth::Right(3),
EitherOrBoth::Left(4),
EitherOrBoth::Left(5),
EitherOrBoth::Left(6)
];
let actual_result = merge_join_by(left, right, |l, r| l.cmp(r))
.collect::<Vec<_>>();
assert_eq!(expected_result, actual_result);
}
#[test]
fn interspersed_left_and_right() {
let left: Vec<u32> = vec![1,3,5];
let right: Vec<u32> = vec![2,4,6];
let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![
EitherOrBoth::Left(1),
EitherOrBoth::Right(2),
EitherOrBoth::Left(3),
EitherOrBoth::Right(4),
EitherOrBoth::Left(5),
EitherOrBoth::Right(6)
];
let actual_result = merge_join_by(left, right, |l, r| l.cmp(r))
.collect::<Vec<_>>();
assert_eq!(expected_result, actual_result);
}
#[test]
fn overlapping_left_and_right() {
let left: Vec<u32> = vec![1,3,4,6];
let right: Vec<u32> = vec![2,3,4,5];
let expected_result: Vec<EitherOrBoth<u32, u32>> = vec![
EitherOrBoth::Left(1),
EitherOrBoth::Right(2),
EitherOrBoth::Both(3, 3),
EitherOrBoth::Both(4, 4),
EitherOrBoth::Right(5),
EitherOrBoth::Left(6)
];
let actual_result = merge_join_by(left, right, |l, r| l.cmp(r))
.collect::<Vec<_>>();
assert_eq!(expected_result, actual_result);
}

53
third_party/rust/itertools-0.8.0/tests/peeking_take_while.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,53 @@
extern crate itertools;
use itertools::Itertools;
use itertools::{put_back, put_back_n};
#[test]
fn peeking_take_while_peekable() {
let mut r = (0..10).peekable();
r.peeking_take_while(|x| *x <= 3).count();
assert_eq!(r.next(), Some(4));
}
#[test]
fn peeking_take_while_put_back() {
let mut r = put_back(0..10);
r.peeking_take_while(|x| *x <= 3).count();
assert_eq!(r.next(), Some(4));
r.peeking_take_while(|_| true).count();
assert_eq!(r.next(), None);
}
#[test]
fn peeking_take_while_put_back_n() {
let mut r = put_back_n(6..10);
for elt in (0..6).rev() {
r.put_back(elt);
}
r.peeking_take_while(|x| *x <= 3).count();
assert_eq!(r.next(), Some(4));
r.peeking_take_while(|_| true).count();
assert_eq!(r.next(), None);
}
#[test]
fn peeking_take_while_slice_iter() {
let v = [1, 2, 3, 4, 5, 6];
let mut r = v.iter();
r.peeking_take_while(|x| **x <= 3).count();
assert_eq!(r.next(), Some(&4));
r.peeking_take_while(|_| true).count();
assert_eq!(r.next(), None);
}
#[test]
fn peeking_take_while_slice_iter_rev() {
let v = [1, 2, 3, 4, 5, 6];
let mut r = v.iter().rev();
r.peeking_take_while(|x| **x >= 3).count();
assert_eq!(r.next(), Some(&2));
r.peeking_take_while(|_| true).count();
assert_eq!(r.next(), None);
}

1017
third_party/rust/itertools-0.8.0/tests/quick.rs поставляемый Normal file

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

246
third_party/rust/itertools-0.8.0/tests/test_core.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,246 @@
//! Licensed under the Apache License, Version 2.0
//! http://www.apache.org/licenses/LICENSE-2.0 or the MIT license
//! http://opensource.org/licenses/MIT, at your
//! option. This file may not be copied, modified, or distributed
//! except according to those terms.
#![no_std]
#[macro_use] extern crate itertools as it;
use core::iter;
use it::Itertools;
use it::interleave;
use it::multizip;
use it::free::put_back;
#[test]
fn product2() {
let s = "αβ";
let mut prod = iproduct!(s.chars(), 0..2);
assert!(prod.next() == Some(('α', 0)));
assert!(prod.next() == Some(('α', 1)));
assert!(prod.next() == Some(('β', 0)));
assert!(prod.next() == Some(('β', 1)));
assert!(prod.next() == None);
}
#[test]
fn product_temporary() {
for (_x, _y, _z) in iproduct!(
[0, 1, 2].iter().cloned(),
[0, 1, 2].iter().cloned(),
[0, 1, 2].iter().cloned())
{
// ok
}
}
#[test]
fn izip_macro() {
let mut zip = izip!(2..3);
assert!(zip.next() == Some(2));
assert!(zip.next().is_none());
let mut zip = izip!(0..3, 0..2, 0..2i8);
for i in 0..2 {
assert!((i as usize, i, i as i8) == zip.next().unwrap());
}
assert!(zip.next().is_none());
let xs: [isize; 0] = [];
let mut zip = izip!(0..3, 0..2, 0..2i8, &xs);
assert!(zip.next().is_none());
}
#[test]
fn izip2() {
let _zip1: iter::Zip<_, _> = izip!(1.., 2..);
let _zip2: iter::Zip<_, _> = izip!(1.., 2.., );
}
#[test]
fn izip3() {
let mut zip: iter::Map<iter::Zip<_, _>, _> = izip!(0..3, 0..2, 0..2i8);
for i in 0..2 {
assert!((i as usize, i, i as i8) == zip.next().unwrap());
}
assert!(zip.next().is_none());
}
#[test]
fn multizip3() {
let mut zip = multizip((0..3, 0..2, 0..2i8));
for i in 0..2 {
assert!((i as usize, i, i as i8) == zip.next().unwrap());
}
assert!(zip.next().is_none());
let xs: [isize; 0] = [];
let mut zip = multizip((0..3, 0..2, 0..2i8, xs.iter()));
assert!(zip.next().is_none());
for (_, _, _, _, _) in multizip((0..3, 0..2, xs.iter(), &xs, xs.to_vec())) {
/* test compiles */
}
}
#[test]
fn write_to() {
let xs = [7, 9, 8];
let mut ys = [0; 5];
let cnt = ys.iter_mut().set_from(xs.iter().map(|x| *x));
assert!(cnt == xs.len());
assert!(ys == [7, 9, 8, 0, 0]);
let cnt = ys.iter_mut().set_from(0..10);
assert!(cnt == ys.len());
assert!(ys == [0, 1, 2, 3, 4]);
}
#[test]
fn test_interleave() {
let xs: [u8; 0] = [];
let ys = [7u8, 9, 8, 10];
let zs = [2u8, 77];
let it = interleave(xs.iter(), ys.iter());
it::assert_equal(it, ys.iter());
let rs = [7u8, 2, 9, 77, 8, 10];
let it = interleave(ys.iter(), zs.iter());
it::assert_equal(it, rs.iter());
}
#[allow(deprecated)]
#[test]
fn foreach() {
let xs = [1i32, 2, 3];
let mut sum = 0;
xs.iter().foreach(|elt| sum += *elt);
assert!(sum == 6);
}
#[test]
fn dropping() {
let xs = [1, 2, 3];
let mut it = xs.iter().dropping(2);
assert_eq!(it.next(), Some(&3));
assert!(it.next().is_none());
let mut it = xs.iter().dropping(5);
assert!(it.next().is_none());
}
#[test]
fn batching() {
let xs = [0, 1, 2, 1, 3];
let ys = [(0, 1), (2, 1)];
// An iterator that gathers elements up in pairs
let pit = xs.iter().cloned().batching(|it| {
match it.next() {
None => None,
Some(x) => match it.next() {
None => None,
Some(y) => Some((x, y)),
}
}
});
it::assert_equal(pit, ys.iter().cloned());
}
#[test]
fn test_put_back() {
let xs = [0, 1, 1, 1, 2, 1, 3, 3];
let mut pb = put_back(xs.iter().cloned());
pb.next();
pb.put_back(1);
pb.put_back(0);
it::assert_equal(pb, xs.iter().cloned());
}
#[allow(deprecated)]
#[test]
fn step() {
it::assert_equal((0..10).step(1), 0..10);
it::assert_equal((0..10).step(2), (0..10).filter(|x: &i32| *x % 2 == 0));
it::assert_equal((0..10).step(10), 0..1);
}
#[allow(deprecated)]
#[test]
fn merge() {
it::assert_equal((0..10).step(2).merge((1..10).step(2)), 0..10);
}
#[test]
fn repeatn() {
let s = "α";
let mut it = it::repeat_n(s, 3);
assert_eq!(it.len(), 3);
assert_eq!(it.next(), Some(s));
assert_eq!(it.next(), Some(s));
assert_eq!(it.next(), Some(s));
assert_eq!(it.next(), None);
assert_eq!(it.next(), None);
}
#[test]
fn count_clones() {
// Check that RepeatN only clones N - 1 times.
use core::cell::Cell;
#[derive(PartialEq, Debug)]
struct Foo {
n: Cell<usize>
}
impl Clone for Foo
{
fn clone(&self) -> Self
{
let n = self.n.get();
self.n.set(n + 1);
Foo { n: Cell::new(n + 1) }
}
}
for n in 0..10 {
let f = Foo{n: Cell::new(0)};
let it = it::repeat_n(f, n);
// drain it
let last = it.last();
if n == 0 {
assert_eq!(last, None);
} else {
assert_eq!(last, Some(Foo{n: Cell::new(n - 1)}));
}
}
}
#[test]
fn part() {
let mut data = [7, 1, 1, 9, 1, 1, 3];
let i = it::partition(&mut data, |elt| *elt >= 3);
assert_eq!(i, 3);
assert_eq!(data, [7, 3, 9, 1, 1, 1, 1]);
let i = it::partition(&mut data, |elt| *elt == 1);
assert_eq!(i, 4);
assert_eq!(data, [1, 1, 1, 1, 9, 3, 7]);
let mut data = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let i = it::partition(&mut data, |elt| *elt % 3 == 0);
assert_eq!(i, 3);
assert_eq!(data, [9, 6, 3, 4, 5, 2, 7, 8, 1]);
}
#[test]
fn tree_fold1() {
for i in 0..100 {
assert_eq!((0..i).tree_fold1(|x, y| x + y), (0..i).fold1(|x, y| x + y));
}
}

735
third_party/rust/itertools-0.8.0/tests/test_std.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,735 @@
#[macro_use] extern crate itertools as it;
extern crate permutohedron;
use it::Itertools;
use it::multizip;
use it::multipeek;
use it::free::rciter;
use it::free::put_back_n;
use it::FoldWhile;
use it::cloned;
#[test]
fn product3() {
let prod = iproduct!(0..3, 0..2, 0..2);
assert_eq!(prod.size_hint(), (12, Some(12)));
let v = prod.collect_vec();
for i in 0..3 {
for j in 0..2 {
for k in 0..2 {
assert!((i, j, k) == v[(i * 2 * 2 + j * 2 + k) as usize]);
}
}
}
for (_, _, _, _) in iproduct!(0..3, 0..2, 0..2, 0..3) {
/* test compiles */
}
}
#[test]
fn interleave_shortest() {
let v0: Vec<i32> = vec![0, 2, 4];
let v1: Vec<i32> = vec![1, 3, 5, 7];
let it = v0.into_iter().interleave_shortest(v1.into_iter());
assert_eq!(it.size_hint(), (6, Some(6)));
assert_eq!(it.collect_vec(), vec![0, 1, 2, 3, 4, 5]);
let v0: Vec<i32> = vec![0, 2, 4, 6, 8];
let v1: Vec<i32> = vec![1, 3, 5];
let it = v0.into_iter().interleave_shortest(v1.into_iter());
assert_eq!(it.size_hint(), (7, Some(7)));
assert_eq!(it.collect_vec(), vec![0, 1, 2, 3, 4, 5, 6]);
let i0 = ::std::iter::repeat(0);
let v1: Vec<_> = vec![1, 3, 5];
let it = i0.interleave_shortest(v1.into_iter());
assert_eq!(it.size_hint(), (7, Some(7)));
let v0: Vec<_> = vec![0, 2, 4];
let i1 = ::std::iter::repeat(1);
let it = v0.into_iter().interleave_shortest(i1);
assert_eq!(it.size_hint(), (6, Some(6)));
}
#[test]
fn unique_by() {
let xs = ["aaa", "bbbbb", "aa", "ccc", "bbbb", "aaaaa", "cccc"];
let ys = ["aaa", "bbbbb", "ccc"];
it::assert_equal(ys.iter(), xs.iter().unique_by(|x| x[..2].to_string()));
}
#[test]
fn unique() {
let xs = [0, 1, 2, 3, 2, 1, 3];
let ys = [0, 1, 2, 3];
it::assert_equal(ys.iter(), xs.iter().unique());
let xs = [0, 1];
let ys = [0, 1];
it::assert_equal(ys.iter(), xs.iter().unique());
}
#[test]
fn intersperse() {
let xs = ["a", "", "b", "c"];
let v: Vec<&str> = xs.iter().map(|x| x.clone()).intersperse(", ").collect();
let text: String = v.concat();
assert_eq!(text, "a, , b, c".to_string());
let ys = [0, 1, 2, 3];
let mut it = ys[..0].iter().map(|x| *x).intersperse(1);
assert!(it.next() == None);
}
#[test]
fn dedup() {
let xs = [0, 1, 1, 1, 2, 1, 3, 3];
let ys = [0, 1, 2, 1, 3];
it::assert_equal(ys.iter(), xs.iter().dedup());
let xs = [0, 0, 0, 0, 0];
let ys = [0];
it::assert_equal(ys.iter(), xs.iter().dedup());
let xs = [0, 1, 1, 1, 2, 1, 3, 3];
let ys = [0, 1, 2, 1, 3];
let mut xs_d = Vec::new();
xs.iter().dedup().fold((), |(), &elt| xs_d.push(elt));
assert_eq!(&xs_d, &ys);
}
#[test]
fn all_equal() {
assert!(!"AABBCCC".chars().all_equal());
assert!("AAAAAAA".chars().all_equal());
for (_key, mut sub) in &"AABBCCC".chars().group_by(|&x| x) {
assert!(sub.all_equal());
}
}
#[test]
fn test_put_back_n() {
let xs = [0, 1, 1, 1, 2, 1, 3, 3];
let mut pb = put_back_n(xs.iter().cloned());
pb.next();
pb.next();
pb.put_back(1);
pb.put_back(0);
it::assert_equal(pb, xs.iter().cloned());
}
#[test]
fn tee() {
let xs = [0, 1, 2, 3];
let (mut t1, mut t2) = xs.iter().cloned().tee();
assert_eq!(t1.next(), Some(0));
assert_eq!(t2.next(), Some(0));
assert_eq!(t1.next(), Some(1));
assert_eq!(t1.next(), Some(2));
assert_eq!(t1.next(), Some(3));
assert_eq!(t1.next(), None);
assert_eq!(t2.next(), Some(1));
assert_eq!(t2.next(), Some(2));
assert_eq!(t1.next(), None);
assert_eq!(t2.next(), Some(3));
assert_eq!(t2.next(), None);
assert_eq!(t1.next(), None);
assert_eq!(t2.next(), None);
let (t1, t2) = xs.iter().cloned().tee();
it::assert_equal(t1, xs.iter().cloned());
it::assert_equal(t2, xs.iter().cloned());
let (t1, t2) = xs.iter().cloned().tee();
it::assert_equal(t1.zip(t2), xs.iter().cloned().zip(xs.iter().cloned()));
}
#[test]
fn test_rciter() {
let xs = [0, 1, 1, 1, 2, 1, 3, 5, 6];
let mut r1 = rciter(xs.iter().cloned());
let mut r2 = r1.clone();
assert_eq!(r1.next(), Some(0));
assert_eq!(r2.next(), Some(1));
let mut z = r1.zip(r2);
assert_eq!(z.next(), Some((1, 1)));
assert_eq!(z.next(), Some((2, 1)));
assert_eq!(z.next(), Some((3, 5)));
assert_eq!(z.next(), None);
// test intoiterator
let r1 = rciter(0..5);
let mut z = izip!(&r1, r1);
assert_eq!(z.next(), Some((0, 1)));
}
#[allow(deprecated)]
#[test]
fn trait_pointers() {
struct ByRef<'r, I: ?Sized>(&'r mut I) where I: 'r;
impl<'r, X, I: ?Sized> Iterator for ByRef<'r, I> where
I: 'r + Iterator<Item=X>
{
type Item = X;
fn next(&mut self) -> Option<X>
{
self.0.next()
}
}
let mut it = Box::new(0..10) as Box<Iterator<Item=i32>>;
assert_eq!(it.next(), Some(0));
{
/* make sure foreach works on non-Sized */
let jt: &mut Iterator<Item = i32> = &mut *it;
assert_eq!(jt.next(), Some(1));
{
let mut r = ByRef(jt);
assert_eq!(r.next(), Some(2));
}
assert_eq!(jt.find_position(|x| *x == 4), Some((1, 4)));
jt.foreach(|_| ());
}
}
#[test]
fn merge_by() {
let odd : Vec<(u32, &str)> = vec![(1, "hello"), (3, "world"), (5, "!")];
let even = vec![(2, "foo"), (4, "bar"), (6, "baz")];
let expected = vec![(1, "hello"), (2, "foo"), (3, "world"), (4, "bar"), (5, "!"), (6, "baz")];
let results = odd.iter().merge_by(even.iter(), |a, b| a.0 <= b.0);
it::assert_equal(results, expected.iter());
}
#[test]
fn merge_by_btree() {
use std::collections::BTreeMap;
let mut bt1 = BTreeMap::new();
bt1.insert("hello", 1);
bt1.insert("world", 3);
let mut bt2 = BTreeMap::new();
bt2.insert("foo", 2);
bt2.insert("bar", 4);
let results = bt1.into_iter().merge_by(bt2.into_iter(), |a, b| a.0 <= b.0 );
let expected = vec![("bar", 4), ("foo", 2), ("hello", 1), ("world", 3)];
it::assert_equal(results, expected.into_iter());
}
#[allow(deprecated)]
#[test]
fn kmerge() {
let its = (0..4).map(|s| (s..10).step(4));
it::assert_equal(its.kmerge(), 0..10);
}
#[allow(deprecated)]
#[test]
fn kmerge_2() {
let its = vec![3, 2, 1, 0].into_iter().map(|s| (s..10).step(4));
it::assert_equal(its.kmerge(), 0..10);
}
#[test]
fn kmerge_empty() {
let its = (0..4).map(|_| 0..0);
assert_eq!(its.kmerge().next(), None);
}
#[test]
fn kmerge_size_hint() {
let its = (0..5).map(|_| (0..10));
assert_eq!(its.kmerge().size_hint(), (50, Some(50)));
}
#[test]
fn kmerge_empty_size_hint() {
let its = (0..5).map(|_| (0..0));
assert_eq!(its.kmerge().size_hint(), (0, Some(0)));
}
#[test]
fn join() {
let many = [1, 2, 3];
let one = [1];
let none: Vec<i32> = vec![];
assert_eq!(many.iter().join(", "), "1, 2, 3");
assert_eq!( one.iter().join(", "), "1");
assert_eq!(none.iter().join(", "), "");
}
#[test]
fn sorted_by() {
let sc = [3, 4, 1, 2].iter().cloned().sorted_by(|&a, &b| {
a.cmp(&b)
});
it::assert_equal(sc, vec![1, 2, 3, 4]);
let v = (0..5).sorted_by(|&a, &b| a.cmp(&b).reverse());
it::assert_equal(v, vec![4, 3, 2, 1, 0]);
}
#[test]
fn sorted_by_key() {
let sc = [3, 4, 1, 2].iter().cloned().sorted_by_key(|&x| x);
it::assert_equal(sc, vec![1, 2, 3, 4]);
let v = (0..5).sorted_by_key(|&x| -x);
it::assert_equal(v, vec![4, 3, 2, 1, 0]);
}
#[test]
fn test_multipeek() {
let nums = vec![1u8,2,3,4,5];
let mp = multipeek(nums.iter().map(|&x| x));
assert_eq!(nums, mp.collect::<Vec<_>>());
let mut mp = multipeek(nums.iter().map(|&x| x));
assert_eq!(mp.peek(), Some(&1));
assert_eq!(mp.next(), Some(1));
assert_eq!(mp.peek(), Some(&2));
assert_eq!(mp.peek(), Some(&3));
assert_eq!(mp.next(), Some(2));
assert_eq!(mp.peek(), Some(&3));
assert_eq!(mp.peek(), Some(&4));
assert_eq!(mp.peek(), Some(&5));
assert_eq!(mp.peek(), None);
assert_eq!(mp.next(), Some(3));
assert_eq!(mp.next(), Some(4));
assert_eq!(mp.peek(), Some(&5));
assert_eq!(mp.peek(), None);
assert_eq!(mp.next(), Some(5));
assert_eq!(mp.next(), None);
assert_eq!(mp.peek(), None);
}
#[test]
fn test_multipeek_reset() {
let data = [1, 2, 3, 4];
let mut mp = multipeek(cloned(&data));
assert_eq!(mp.peek(), Some(&1));
assert_eq!(mp.next(), Some(1));
assert_eq!(mp.peek(), Some(&2));
assert_eq!(mp.peek(), Some(&3));
mp.reset_peek();
assert_eq!(mp.peek(), Some(&2));
assert_eq!(mp.next(), Some(2));
}
#[test]
fn test_multipeek_peeking_next() {
use it::PeekingNext;
let nums = vec![1u8,2,3,4,5,6,7];
let mut mp = multipeek(nums.iter().map(|&x| x));
assert_eq!(mp.peeking_next(|&x| x != 0), Some(1));
assert_eq!(mp.next(), Some(2));
assert_eq!(mp.peek(), Some(&3));
assert_eq!(mp.peek(), Some(&4));
assert_eq!(mp.peeking_next(|&x| x == 3), Some(3));
assert_eq!(mp.peek(), Some(&4));
assert_eq!(mp.peeking_next(|&x| x != 4), None);
assert_eq!(mp.peeking_next(|&x| x == 4), Some(4));
assert_eq!(mp.peek(), Some(&5));
assert_eq!(mp.peek(), Some(&6));
assert_eq!(mp.peeking_next(|&x| x != 5), None);
assert_eq!(mp.peek(), Some(&7));
assert_eq!(mp.peeking_next(|&x| x == 5), Some(5));
assert_eq!(mp.peeking_next(|&x| x == 6), Some(6));
assert_eq!(mp.peek(), Some(&7));
assert_eq!(mp.peek(), None);
assert_eq!(mp.next(), Some(7));
assert_eq!(mp.peek(), None);
}
#[test]
fn pad_using() {
it::assert_equal((0..0).pad_using(1, |_| 1), 1..2);
let v: Vec<usize> = vec![0, 1, 2];
let r = v.into_iter().pad_using(5, |n| n);
it::assert_equal(r, vec![0, 1, 2, 3, 4]);
let v: Vec<usize> = vec![0, 1, 2];
let r = v.into_iter().pad_using(1, |_| panic!());
it::assert_equal(r, vec![0, 1, 2]);
}
#[test]
fn group_by() {
for (ch1, sub) in &"AABBCCC".chars().group_by(|&x| x) {
for ch2 in sub {
assert_eq!(ch1, ch2);
}
}
for (ch1, sub) in &"AAABBBCCCCDDDD".chars().group_by(|&x| x) {
for ch2 in sub {
assert_eq!(ch1, ch2);
if ch1 == 'C' {
break;
}
}
}
let toupper = |ch: &char| ch.to_uppercase().nth(0).unwrap();
// try all possible orderings
for indices in permutohedron::Heap::new(&mut [0, 1, 2, 3]) {
let groups = "AaaBbbccCcDDDD".chars().group_by(&toupper);
let mut subs = groups.into_iter().collect_vec();
for &idx in &indices[..] {
let (key, text) = match idx {
0 => ('A', "Aaa".chars()),
1 => ('B', "Bbb".chars()),
2 => ('C', "ccCc".chars()),
3 => ('D', "DDDD".chars()),
_ => unreachable!(),
};
assert_eq!(key, subs[idx].0);
it::assert_equal(&mut subs[idx].1, text);
}
}
let groups = "AAABBBCCCCDDDD".chars().group_by(|&x| x);
let mut subs = groups.into_iter().map(|(_, g)| g).collect_vec();
let sd = subs.pop().unwrap();
let sc = subs.pop().unwrap();
let sb = subs.pop().unwrap();
let sa = subs.pop().unwrap();
for (a, b, c, d) in multizip((sa, sb, sc, sd)) {
assert_eq!(a, 'A');
assert_eq!(b, 'B');
assert_eq!(c, 'C');
assert_eq!(d, 'D');
}
// check that the key closure is called exactly n times
{
let mut ntimes = 0;
let text = "AABCCC";
for (_, sub) in &text.chars().group_by(|&x| { ntimes += 1; x}) {
for _ in sub {
}
}
assert_eq!(ntimes, text.len());
}
{
let mut ntimes = 0;
let text = "AABCCC";
for _ in &text.chars().group_by(|&x| { ntimes += 1; x}) {
}
assert_eq!(ntimes, text.len());
}
{
let text = "ABCCCDEEFGHIJJKK";
let gr = text.chars().group_by(|&x| x);
it::assert_equal(gr.into_iter().flat_map(|(_, sub)| sub), text.chars());
}
}
#[test]
fn group_by_lazy_2() {
let data = vec![0, 1];
let groups = data.iter().group_by(|k| *k);
let gs = groups.into_iter().collect_vec();
it::assert_equal(data.iter(), gs.into_iter().flat_map(|(_k, g)| g));
let data = vec![0, 1, 1, 0, 0];
let groups = data.iter().group_by(|k| *k);
let mut gs = groups.into_iter().collect_vec();
gs[1..].reverse();
it::assert_equal(&[0, 0, 0, 1, 1], gs.into_iter().flat_map(|(_, g)| g));
let grouper = data.iter().group_by(|k| *k);
let mut groups = Vec::new();
for (k, group) in &grouper {
if *k == 1 {
groups.push(group);
}
}
it::assert_equal(&mut groups[0], &[1, 1]);
let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3];
let grouper = data.iter().group_by(|k| *k);
let mut groups = Vec::new();
for (i, (_, group)) in grouper.into_iter().enumerate() {
if i < 2 {
groups.push(group);
} else if i < 4 {
for _ in group {
}
} else {
groups.push(group);
}
}
it::assert_equal(&mut groups[0], &[0, 0, 0]);
it::assert_equal(&mut groups[1], &[1, 1]);
it::assert_equal(&mut groups[2], &[3, 3]);
// use groups as chunks
let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3];
let mut i = 0;
let grouper = data.iter().group_by(move |_| { let k = i / 3; i += 1; k });
for (i, group) in &grouper {
match i {
0 => it::assert_equal(group, &[0, 0, 0]),
1 => it::assert_equal(group, &[1, 1, 0]),
2 => it::assert_equal(group, &[0, 2, 2]),
3 => it::assert_equal(group, &[3, 3]),
_ => unreachable!(),
}
}
}
#[test]
fn group_by_lazy_3() {
// test consuming each group on the lap after it was produced
let data = vec![0, 0, 0, 1, 1, 0, 0, 1, 1, 2, 2];
let grouper = data.iter().group_by(|elt| *elt);
let mut last = None;
for (key, group) in &grouper {
if let Some(gr) = last.take() {
for elt in gr {
assert!(elt != key && i32::abs(elt - key) == 1);
}
}
last = Some(group);
}
}
#[test]
fn chunks() {
let data = vec![0, 0, 0, 1, 1, 0, 0, 2, 2, 3, 3];
let grouper = data.iter().chunks(3);
for (i, chunk) in grouper.into_iter().enumerate() {
match i {
0 => it::assert_equal(chunk, &[0, 0, 0]),
1 => it::assert_equal(chunk, &[1, 1, 0]),
2 => it::assert_equal(chunk, &[0, 2, 2]),
3 => it::assert_equal(chunk, &[3, 3]),
_ => unreachable!(),
}
}
}
#[test]
fn concat_empty() {
let data: Vec<Vec<()>> = Vec::new();
assert_eq!(data.into_iter().concat(), Vec::new())
}
#[test]
fn concat_non_empty() {
let data = vec![vec![1,2,3], vec![4,5,6], vec![7,8,9]];
assert_eq!(data.into_iter().concat(), vec![1,2,3,4,5,6,7,8,9])
}
#[test]
fn combinations() {
assert!((1..3).combinations(5).next().is_none());
let it = (1..3).combinations(2);
it::assert_equal(it, vec![
vec![1, 2],
]);
let it = (1..5).combinations(2);
it::assert_equal(it, vec![
vec![1, 2],
vec![1, 3],
vec![1, 4],
vec![2, 3],
vec![2, 4],
vec![3, 4],
]);
it::assert_equal((0..0).tuple_combinations::<(_, _)>(), <Vec<_>>::new());
it::assert_equal((0..1).tuple_combinations::<(_, _)>(), <Vec<_>>::new());
it::assert_equal((0..2).tuple_combinations::<(_, _)>(), vec![(0, 1)]);
it::assert_equal((0..0).combinations(2), <Vec<Vec<_>>>::new());
it::assert_equal((0..1).combinations(1), vec![vec![0]]);
it::assert_equal((0..2).combinations(1), vec![vec![0], vec![1]]);
it::assert_equal((0..2).combinations(2), vec![vec![0, 1]]);
}
#[test]
fn combinations_of_too_short() {
for i in 1..10 {
assert!((0..0).combinations(i).next().is_none());
assert!((0..i - 1).combinations(i).next().is_none());
}
}
#[test]
fn combinations_zero() {
it::assert_equal((1..3).combinations(0), vec![vec![]]);
}
#[test]
fn diff_mismatch() {
let a = vec![1, 2, 3, 4];
let b = vec![1.0, 5.0, 3.0, 4.0];
let b_map = b.into_iter().map(|f| f as i32);
let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b);
assert!(match diff {
Some(it::Diff::FirstMismatch(1, _, from_diff)) =>
from_diff.collect::<Vec<_>>() == vec![5, 3, 4],
_ => false,
});
}
#[test]
fn diff_longer() {
let a = vec![1, 2, 3, 4];
let b = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
let b_map = b.into_iter().map(|f| f as i32);
let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b);
assert!(match diff {
Some(it::Diff::Longer(_, remaining)) =>
remaining.collect::<Vec<_>>() == vec![5, 6],
_ => false,
});
}
#[test]
fn diff_shorter() {
let a = vec![1, 2, 3, 4];
let b = vec![1.0, 2.0];
let b_map = b.into_iter().map(|f| f as i32);
let diff = it::diff_with(a.iter(), b_map, |a, b| *a == b);
assert!(match diff {
Some(it::Diff::Shorter(len, _)) => len == 2,
_ => false,
});
}
#[test]
fn minmax() {
use std::cmp::Ordering;
use it::MinMaxResult;
// A peculiar type: Equality compares both tuple items, but ordering only the
// first item. This is so we can check the stability property easily.
#[derive(Clone, Debug, PartialEq, Eq)]
struct Val(u32, u32);
impl PartialOrd<Val> for Val {
fn partial_cmp(&self, other: &Val) -> Option<Ordering> {
self.0.partial_cmp(&other.0)
}
}
impl Ord for Val {
fn cmp(&self, other: &Val) -> Ordering {
self.0.cmp(&other.0)
}
}
assert_eq!(None::<Option<u32>>.iter().minmax(), MinMaxResult::NoElements);
assert_eq!(Some(1u32).iter().minmax(), MinMaxResult::OneElement(&1));
let data = vec![Val(0, 1), Val(2, 0), Val(0, 2), Val(1, 0), Val(2, 1)];
let minmax = data.iter().minmax();
assert_eq!(minmax, MinMaxResult::MinMax(&Val(0, 1), &Val(2, 1)));
let (min, max) = data.iter().minmax_by_key(|v| v.1).into_option().unwrap();
assert_eq!(min, &Val(2, 0));
assert_eq!(max, &Val(0, 2));
let (min, max) = data.iter().minmax_by(|x, y| x.1.cmp(&y.1)).into_option().unwrap();
assert_eq!(min, &Val(2, 0));
assert_eq!(max, &Val(0, 2));
}
#[test]
fn format() {
let data = [0, 1, 2, 3];
let ans1 = "0, 1, 2, 3";
let ans2 = "0--1--2--3";
let t1 = format!("{}", data.iter().format(", "));
assert_eq!(t1, ans1);
let t2 = format!("{:?}", data.iter().format("--"));
assert_eq!(t2, ans2);
let dataf = [1.1, 2.71828, -22.];
let t3 = format!("{:.2e}", dataf.iter().format(", "));
assert_eq!(t3, "1.10e0, 2.72e0, -2.20e1");
}
#[test]
fn while_some() {
let ns = (1..10).map(|x| if x % 5 != 0 { Some(x) } else { None })
.while_some();
it::assert_equal(ns, vec![1, 2, 3, 4]);
}
#[allow(deprecated)]
#[test]
fn fold_while() {
let mut iterations = 0;
let vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let sum = vec.into_iter().fold_while(0, |acc, item| {
iterations += 1;
let new_sum = acc.clone() + item;
if new_sum <= 20 {
FoldWhile::Continue(new_sum)
} else {
FoldWhile::Done(acc)
}
}).into_inner();
assert_eq!(iterations, 6);
assert_eq!(sum, 15);
}
#[test]
fn tree_fold1() {
let x = [
"",
"0",
"0 1 x",
"0 1 x 2 x",
"0 1 x 2 3 x x",
"0 1 x 2 3 x x 4 x",
"0 1 x 2 3 x x 4 5 x x",
"0 1 x 2 3 x x 4 5 x 6 x x",
"0 1 x 2 3 x x 4 5 x 6 7 x x x",
"0 1 x 2 3 x x 4 5 x 6 7 x x x 8 x",
"0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x x",
"0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 x x",
"0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x x",
"0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 x x",
"0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 13 x x x",
"0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 13 x 14 x x x",
"0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 13 x 14 15 x x x x",
];
for (i, &s) in x.iter().enumerate() {
let expected = if s == "" { None } else { Some(s.to_string()) };
let num_strings = (0..i).map(|x| x.to_string());
let actual = num_strings.tree_fold1(|a, b| format!("{} {} x", a, b));
assert_eq!(actual, expected);
}
}

88
third_party/rust/itertools-0.8.0/tests/tuples.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,88 @@
extern crate itertools;
use itertools::Itertools;
#[test]
fn tuples() {
let v = [1, 2, 3, 4, 5];
let mut iter = v.iter().cloned().tuples();
assert_eq!(Some((1,)), iter.next());
assert_eq!(Some((2,)), iter.next());
assert_eq!(Some((3,)), iter.next());
assert_eq!(Some((4,)), iter.next());
assert_eq!(Some((5,)), iter.next());
assert_eq!(None, iter.next());
assert_eq!(None, iter.into_buffer().next());
let mut iter = v.iter().cloned().tuples();
assert_eq!(Some((1, 2)), iter.next());
assert_eq!(Some((3, 4)), iter.next());
assert_eq!(None, iter.next());
itertools::assert_equal(vec![5], iter.into_buffer());
let mut iter = v.iter().cloned().tuples();
assert_eq!(Some((1, 2, 3)), iter.next());
assert_eq!(None, iter.next());
itertools::assert_equal(vec![4, 5], iter.into_buffer());
let mut iter = v.iter().cloned().tuples();
assert_eq!(Some((1, 2, 3, 4)), iter.next());
assert_eq!(None, iter.next());
itertools::assert_equal(vec![5], iter.into_buffer());
}
#[test]
fn tuple_windows() {
let v = [1, 2, 3, 4, 5];
let mut iter = v.iter().cloned().tuple_windows();
assert_eq!(Some((1,)), iter.next());
assert_eq!(Some((2,)), iter.next());
assert_eq!(Some((3,)), iter.next());
let mut iter = v.iter().cloned().tuple_windows();
assert_eq!(Some((1, 2)), iter.next());
assert_eq!(Some((2, 3)), iter.next());
assert_eq!(Some((3, 4)), iter.next());
assert_eq!(Some((4, 5)), iter.next());
assert_eq!(None, iter.next());
let mut iter = v.iter().cloned().tuple_windows();
assert_eq!(Some((1, 2, 3)), iter.next());
assert_eq!(Some((2, 3, 4)), iter.next());
assert_eq!(Some((3, 4, 5)), iter.next());
assert_eq!(None, iter.next());
let mut iter = v.iter().cloned().tuple_windows();
assert_eq!(Some((1, 2, 3, 4)), iter.next());
assert_eq!(Some((2, 3, 4, 5)), iter.next());
assert_eq!(None, iter.next());
let v = [1, 2, 3];
let mut iter = v.iter().cloned().tuple_windows::<(_, _, _, _)>();
assert_eq!(None, iter.next());
}
#[test]
fn next_tuple() {
let v = [1, 2, 3, 4, 5];
let mut iter = v.iter();
assert_eq!(iter.next_tuple().map(|(&x, &y)| (x, y)), Some((1, 2)));
assert_eq!(iter.next_tuple().map(|(&x, &y)| (x, y)), Some((3, 4)));
assert_eq!(iter.next_tuple::<(_, _)>(), None);
}
#[test]
fn collect_tuple() {
let v = [1, 2];
let iter = v.iter().cloned();
assert_eq!(iter.collect_tuple(), Some((1, 2)));
let v = [1];
let iter = v.iter().cloned();
assert_eq!(iter.collect_tuple::<(_, _)>(), None);
let v = [1, 2, 3];
let iter = v.iter().cloned();
assert_eq!(iter.collect_tuple::<(_, _)>(), None);
}

65
third_party/rust/itertools-0.8.0/tests/zip.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,65 @@
extern crate itertools;
use itertools::Itertools;
use itertools::EitherOrBoth::{Both, Left, Right};
use itertools::free::zip_eq;
#[test]
fn zip_longest_fused() {
let a = [Some(1), None, Some(3), Some(4)];
let b = [1, 2, 3];
let unfused = a.iter().batching(|it| *it.next().unwrap())
.zip_longest(b.iter().cloned());
itertools::assert_equal(unfused,
vec![Both(1, 1), Right(2), Right(3)]);
}
#[test]
fn test_zip_longest_size_hint() {
let c = (1..10).cycle();
let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let v2 = &[10, 11, 12];
assert_eq!(c.zip_longest(v.iter()).size_hint(), (std::usize::MAX, None));
assert_eq!(v.iter().zip_longest(v2.iter()).size_hint(), (10, Some(10)));
}
#[test]
fn test_double_ended_zip_longest() {
let xs = [1, 2, 3, 4, 5, 6];
let ys = [1, 2, 3, 7];
let a = xs.iter().map(|&x| x);
let b = ys.iter().map(|&x| x);
let mut it = a.zip_longest(b);
assert_eq!(it.next(), Some(Both(1, 1)));
assert_eq!(it.next(), Some(Both(2, 2)));
assert_eq!(it.next_back(), Some(Left(6)));
assert_eq!(it.next_back(), Some(Left(5)));
assert_eq!(it.next_back(), Some(Both(4, 7)));
assert_eq!(it.next(), Some(Both(3, 3)));
assert_eq!(it.next(), None);
}
#[should_panic]
#[test]
fn zip_eq_panic1()
{
let a = [1, 2];
let b = [1, 2, 3];
zip_eq(&a, &b).count();
}
#[should_panic]
#[test]
fn zip_eq_panic2()
{
let a: [i32; 0] = [];
let b = [1, 2, 3];
zip_eq(&a, &b).count();
}

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

319
third_party/rust/itertools/CHANGELOG.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,319 @@
# Changelog
## 0.9.0
- Fix potential overflow in `MergeJoinBy::size_hint` (#385)
- Add `derive(Clone)` where possible (#382)
- Add `try_collect` method (#394)
- Add `HomogeneousTuple` trait (#389)
- Fix `combinations(0)` and `combinations_with_replacement(0)` (#383)
- Don't require `ParitalEq` to the `Item` of `DedupBy` (#397)
- Implement missing specializations on the `PutBack` adaptor and on the `MergeJoinBy` iterator (#372)
- Add `position_*` methods (#412)
- Derive `Hash` for `EitherOrBoth` (#417)
- Increase minimum supported Rust version to 1.32.0
## 0.8.2
- Use `slice::iter` instead of `into_iter` to avoid future breakage (#378, by @LukasKalbertodt)
## 0.8.1
- Added a [`.exactly_one()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.exactly_one) iterator method that, on success, extracts the single value of an iterator ; by @Xaeroxe
- Added combinatory iterator adaptors:
- [`.permutations(k)`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.permutations):
`[0, 1, 2].iter().permutations(2)` yields
```rust
[
vec![0, 1],
vec![0, 2],
vec![1, 0],
vec![1, 2],
vec![2, 0],
vec![2, 1],
]
```
; by @tobz1000
- [`.combinations_with_replacement(k)`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.combinations_with_replacement):
`[0, 1, 2].iter().combinations_with_replacement(2)` yields
```rust
[
vec![0, 0],
vec![0, 1],
vec![0, 2],
vec![1, 1],
vec![1, 2],
vec![2, 2],
]
```
; by @tommilligan
- For reference, these methods join the already existing [`.combinations(k)`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.combinations):
`[0, 1, 2].iter().combinations(2)` yields
```rust
[
vec![0, 1],
vec![0, 2],
vec![1, 2],
]
```
- Improved the performance of [`.fold()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.fold)-based internal iteration for the [`.intersperse()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.intersperse) iterator ; by @jswrenn
- Added [`.dedup_by()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.dedup_by), [`.merge_by()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.merge_by) and [`.kmerge_by()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.kmerge_by) adaptors that work like [`.dedup()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.dedup), [`.merge()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.merge) and [`.kmerge()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.kmerge), but taking an additional custom comparison closure parameter. ; by @phimuemue
- Improved the performance of [`.all_equal()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.all_equal) ; by @fyrchik
- Loosened the bounds on [`.partition_map()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.partition_map) to take just a `FnMut` closure rather than a `Fn` closure, and made its implementation use internal iteration for better performance ; by @danielhenrymantilla
- Added convenience methods to [`EitherOrBoth`](https://docs.rs/itertools/0.8.1/itertools/enum.EitherOrBoth.html) elements yielded from the [`.zip_longest()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.zip_longest) iterator adaptor ; by @Avi-D-coder
- Added [`.sum1()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.sum1) and [`.product1()`](https://docs.rs/itertools/0.8.1/itertools/trait.Itertools.html#method.product1) iterator methods that respectively try to return the sum and the product of the elements of an iterator **when it is not empty**, otherwise they return `None` ; by @Emerentius
## 0.8.0
- Added new adaptor `.map_into()` for conversions using `Into` by @vorner
- Improved `Itertools` docs by @JohnHeitmann
- The return type of `.sorted_by_by_key()` is now an iterator, not a Vec.
- The return type of the `izip!(x, y)` macro with exactly two arguments is now the usual `Iterator::zip`.
- Remove `.flatten()` in favour of std's `.flatten()`
- Deprecate `.foreach()` in favour of std's `.for_each()`
- Deprecate `.step()` in favour of std's `.step_by()`
- Deprecate `repeat_call` in favour of std's `repeat_with`
- Deprecate `.fold_while()` in favour of std's `.try_fold()`
- Require Rust 1.24 as minimal version.
## 0.7.11
- Add convenience methods to `EitherOrBoth`, making it more similar to `Option` and `Either` by @jethrogb
## 0.7.10
- No changes.
## 0.7.9
- New inclusion policy: See the readme about suggesting features for std before accepting them in itertools.
- The `FoldWhile` type now implements `Eq` and `PartialEq` by @jturner314
## 0.7.8
- Add new iterator method `.tree_fold1()` which is like `.fold1()` except items are combined in a tree structure (see its docs). By @scottmcm
- Add more `Debug` impls by @phimuemue: KMerge, KMergeBy, MergeJoinBy, ConsTuples, Intersperse, ProcessResults, RcIter, Tee, TupleWindows, Tee, ZipLongest, ZipEq, Zip.
## 0.7.7
- Add new iterator method `.into_group_map() -> HashMap<K, Vec<V>>` which turns an iterator of `(K, V)` elements into such a hash table, where values are grouped by key. By @tobz1000
- Add new free function `flatten` for the `.flatten()` adaptor. **NOTE:** recent Rust nightlies have `Iterator::flatten` and thus a clash with our flatten adaptor. One workaround is to use the itertools `flatten` free function.
## 0.7.6
- Add new adaptor `.multi_cartesian_product()` which is an n-ary product iterator by @tobz1000
- Add new method `.sorted_by_key()` by @Xion
- Provide simpler and faster `.count()` for `.unique()` and `.unique_by()`
## 0.7.5
- `.multipeek()` now implements `PeekingNext`, by @nicopap.
## 0.7.4
- Add new adaptor `.update()` by @lucasem; this adaptor is used to modify an element before passing it on in an iterator chain.
## 0.7.3
- Add new method `.collect_tuple()` by @matklad; it makes a tuple out of the iterator's elements if the number of them matches **exactly**.
- Implement `fold` and `collect` for `.map_results()` which means it reuses the code of the standard `.map()` for these methods.
## 0.7.2
- Add new adaptor `.merge_join_by` by @srijs; a heterogeneous merge join for two ordered sequences.
## 0.7.1
- Iterator adaptors and iterators in itertools now use the same `must_use` reminder that the standard library adaptors do, by @matematikaedit and @bluss *“iterator adaptors are lazy and do nothing unless consumed”*.
## 0.7.0
- Faster `izip!()` by @krdln
- `izip!()` is now a wrapper for repeated regular `.zip()` and a single `.map()`. This means it optimizes as well as the standard library `.zip()` it uses. **Note:** `multizip` and `izip!()` are now different! The former has a named type but the latter optimizes better.
- Faster `.unique()`
- `no_std` support, which is opt-in!
- Many lovable features are still there without std, like `izip!()` or `.format()` or `.merge()`, but not those that use collections.
- Trait bounds were required up front instead of just on the type: `group_by`'s `PartialEq` by @Phlosioneer and `repeat_call`'s `FnMut`.
- Removed deprecated constructor `Zip::new` — use `izip!()` or `multizip()`
## 0.6.5
- Fix bug in `.cartesian_product()`'s fold (which only was visible for unfused iterators).
## 0.6.4
- Add specific `fold` implementations for `.cartesian_product()` and `cons_tuples()`, which improves their performance in fold, foreach, and iterator consumers derived from them.
## 0.6.3
- Add iterator adaptor `.positions(predicate)` by @tmccombs
## 0.6.2
- Add function `process_results` which can “lift” a function of the regular values of an iterator so that it can process the `Ok` values from an iterator of `Results` instead, by @shepmaster
- Add iterator method `.concat()` which combines all iterator elements into a single collection using the `Extend` trait, by @srijs
## 0.6.1
- Better size hint testing and subsequent size hint bugfixes by @rkarp. Fixes bugs in product, `interleave_shortest` size hints.
- New iterator method `.all_equal()` by @phimuemue
## 0.6.0
- Deprecated names were removed in favour of their replacements
- `.flatten()` does not implement double ended iteration anymore
- `.fold_while()` uses `&mut self` and returns `FoldWhile<T>`, for composability #168
- `.foreach()` and `.fold1()` use `self`, like `.fold()` does.
- `.combinations(0)` now produces a single empty vector. #174
## 0.5.10
- Add itertools method `.kmerge_by()` (and corresponding free function)
- Relaxed trait requirement of `.kmerge()` and `.minmax()` to PartialOrd.
## 0.5.9
- Add multipeek method `.reset_peek()`
- Add categories
## 0.5.8
- Add iterator adaptor `.peeking_take_while()` and its trait `PeekingNext`.
## 0.5.7
- Add iterator adaptor `.with_position()`
- Fix multipeek's performance for long peeks by using `VecDeque`.
## 0.5.6
- Add `.map_results()`
## 0.5.5
- Many more adaptors now implement `Debug`
- Add free function constructor `repeat_n`. `RepeatN::new` is now deprecated.
## 0.5.4
- Add infinite generator function `iterate`, that takes a seed and a closure.
## 0.5.3
- Special-cased `.fold()` for flatten and put back. `.foreach()` now uses fold on the iterator, to pick up any iterator specific loop implementation.
- `.combinations(n)` asserts up front that `n != 0`, instead of running into an error on the second iterator element.
## 0.5.2
- Add `.tuples::<T>()` that iterates by two, three or four elements at a time (where `T` is a tuple type).
- Add `.tuple_windows::<T>()` that iterates using a window of the two, three or four most recent elements.
- Add `.next_tuple::<T>()` method, that picks the next two, three or four elements in one go.
- `.interleave()` now has an accurate size hint.
## 0.5.1
- Workaround module/function name clash that made racer crash on completing itertools. Only internal changes needed.
## 0.5.0
- [Release announcement](http://bluss.github.io/rust/2016/09/26/itertools-0.5.0/)
- Renamed:
- `combinations` is now `tuple_combinations`
- `combinations_n` to `combinations`
- `group_by_lazy`, `chunks_lazy` to `group_by`, `chunks`
- `Unfold::new` to `unfold()`
- `RepeatCall::new` to `repeat_call()`
- `Zip::new` to `multizip`
- `PutBack::new`, `PutBackN::new` to `put_back`, `put_back_n`
- `PutBack::with_value` is now a builder setter, not a constructor
- `MultiPeek::new`, `.multipeek()` to `multipeek()`
- `format` to `format_with` and `format_default` to `format`
- `.into_rc()` to `rciter`
- `Partition` enum is now `Either`
- Module reorganization:
- All iterator structs are under `itertools::structs` but also reexported to the top level, for backwards compatibility
- All free functions are reexported at the root, `itertools::free` will be removed in the next version
- Removed:
- `ZipSlices`, use `.zip()` instead
- `.enumerate_from()`, `ZipTrusted`, due to being unstable
- `.mend_slices()`, moved to crate `odds`
- Stride, StrideMut, moved to crate `odds`
- `linspace()`, moved to crate `itertools-num`
- `.sort_by()`, use `.sorted_by()`
- `.is_empty_hint()`, use `.size_hint()`
- `.dropn()`, use `.dropping()`
- `.map_fn()`, use `.map()`
- `.slice()`, use `.take()` / `.skip()`
- helper traits in `misc`
- `new` constructors on iterator structs, use `Itertools` trait or free functions instead
- `itertools::size_hint` is now private
- Behaviour changes:
- `format` and `format_with` helpers now panic if you try to format them more than once.
- `repeat_call` is not double ended anymore
- New features:
- tuple flattening iterator is constructible with `cons_tuples`
- itertools reexports `Either` from the `either` crate. `Either<L, R>` is an iterator when `L, R` are.
- `MinMaxResult` now implements `Copy` and `Clone`
- `tuple_combinations` supports 1-4 tuples of combinations (previously just 2)
## 0.4.19
- Add `.minmax_by()`
- Add `itertools::free::cloned`
- Add `itertools::free::rciter`
- Improve `.step(n)` slightly to take advantage of specialized Fuse better.
## 0.4.18
- Only changes related to the "unstable" crate feature. This feature is more or less deprecated.
- Use deprecated warnings when unstable is enabled. `.enumerate_from()` will be removed imminently since it's using a deprecated libstd trait.
## 0.4.17
- Fix bug in `.kmerge()` that caused it to often produce the wrong order #134
## 0.4.16
- Improve precision of the `interleave_shortest` adaptor's size hint (it is now computed exactly when possible).
## 0.4.15
- Fixup on top of the workaround in 0.4.14. A function in `itertools::free` was removed by mistake and now it is added back again.
## 0.4.14
- Workaround an upstream regression in a rust nightly build that broke compilation of of `itertools::free::{interleave, merge}`
## 0.4.13
- Add `.minmax()` and `.minmax_by_key()`, iterator methods for finding both minimum and maximum in one scan.
- Add `.format_default()`, a simpler version of `.format()` (lazy formatting for iterators).
## 0.4.12
- Add `.zip_eq()`, an adaptor like `.zip()` except it ensures iterators of inequal length don't pass silently (instead it panics).
- Add `.fold_while()`, an iterator method that is a fold that can short-circuit.
- Add `.partition_map()`, an iterator method that can separate elements into two collections.
## 0.4.11
- Add `.get()` for `Stride{,Mut}` and `.get_mut()` for `StrideMut`
## 0.4.10
- Improve performance of `.kmerge()`
## 0.4.9
- Add k-ary merge adaptor `.kmerge()`
- Fix a bug in `.islice()` with ranges `a..b` where a `> b`.
## 0.4.8
- Implement `Clone`, `Debug` for `Linspace`
## 0.4.7
- Add function `diff_with()` that compares two iterators
- Add `.combinations_n()`, an n-ary combinations iterator
- Add methods `PutBack::with_value` and `PutBack::into_parts`.
## 0.4.6
- Add method `.sorted()`
- Add module `itertools::free` with free function variants of common iterator adaptors and methods. For example `enumerate(iterable)`, `rev(iterable)`, and so on.
## 0.4.5
- Add `.flatten()`
## 0.4.4
- Allow composing `ZipSlices` with itself
## 0.4.3
- Write `iproduct!()` as a single expression; this allows temporary values in its arguments.
## 0.4.2
- Add `.fold_options()`
- Require Rust 1.1 or later
## 0.4.1
- Update `.dropping()` to take advantage of `.nth()`
## 0.4.0
- `.merge()`, `.unique()` and `.dedup()` now perform better due to not using function pointers
- Add free functions `enumerate()` and `rev()`
- Breaking changes:
- Return types of `.merge()` and `.merge_by()` renamed and changed
- Method `Merge::new` removed
- `.merge_by()` now takes a closure that returns bool.
- Return type of `.dedup()` changed
- Return type of `.mend_slices()` changed
- Return type of `.unique()` changed
- Removed function `times()`, struct `Times`: use a range instead
- Removed deprecated macro `icompr!()`
- Removed deprecated `FnMap` and method `.fn_map()`: use `.map_fn()`
- `.interleave_shortest()` is no longer guaranteed to act like fused
## 0.3.25
- Rename `.sort_by()` to `.sorted_by()`. Old name is deprecated.
- Fix well-formedness warnings from RFC 1214, no user visible impact
## 0.3.24
- Improve performance of `.merge()`'s ordering function slightly
## 0.3.23
- Added `.chunks()`, similar to (and based on) `.group_by_lazy()`.
- Tweak linspace to match numpy.linspace and make it double ended.
## 0.3.22
- Added `ZipSlices`, a fast zip for slices
## 0.3.21
- Remove `Debug` impl for `Format`, it will have different use later
## 0.3.20
- Optimize `.group_by_lazy()`
## 0.3.19
- Added `.group_by_lazy()`, a possibly nonallocating group by
- Added `.format()`, a nonallocating formatting helper for iterators
- Remove uses of `RandomAccessIterator` since it has been deprecated in rust.
## 0.3.17
- Added (adopted) `Unfold` from rust
## 0.3.16
- Added adaptors `.unique()`, `.unique_by()`
## 0.3.15
- Added method `.sort_by()`
## 0.3.14
- Added adaptor `.while_some()`
## 0.3.13
- Added adaptor `.interleave_shortest()`
- Added adaptor `.pad_using()`
## 0.3.11
- Added `assert_equal` function
## 0.3.10
- Bugfix `.combinations()` `size_hint`.
## 0.3.8
- Added source `RepeatCall`
## 0.3.7
- Added adaptor `PutBackN`
- Added adaptor `.combinations()`
## 0.3.6
- Added `itertools::partition`, partition a sequence in place based on a predicate.
- Deprecate `icompr!()` with no replacement.
## 0.3.5
- `.map_fn()` replaces deprecated `.fn_map()`.
## 0.3.4
- `.take_while_ref()` *by-ref adaptor*
- `.coalesce()` *adaptor*
- `.mend_slices()` *adaptor*
## 0.3.3
- `.dropping_back()` *method*
- `.fold1()` *method*
- `.is_empty_hint()` *method*

584
third_party/rust/itertools/Cargo.lock сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,584 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "autocfg"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "autocfg"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bstr"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "byteorder"
version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "c2-chacha"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cast"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "clap"
version = "2.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "criterion"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"criterion-plot 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"csv 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)",
"tinytemplate 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "criterion-plot"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-deque"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-epoch"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-queue"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-utils"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "csv"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bstr 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "csv-core"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "either"
version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "getrandom"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hermit-abi"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itertools"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itertools"
version = "0.9.0"
dependencies = [
"criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"permutohedron 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"quickcheck 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itoa"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memoffset"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-traits"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num_cpus"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "permutohedron"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ppv-lite86"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quickcheck"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_chacha"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_hc"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_os"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_xoshiro"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rayon"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rayon-core"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-automata"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ryu"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "scopeguard"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "1.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_derive"
version = "1.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_json"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tinytemplate"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-width"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "walkdir"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-util"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
"checksum bstr 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "502ae1441a0a5adb8fbd38a5955a6416b9493e92b465de5e4a9bde6a539c2c48"
"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
"checksum cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
"checksum criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "938703e165481c8d612ea3479ac8342e5615185db37765162e762ec3523e2fc6"
"checksum criterion-plot 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a01e15e0ea58e8234f96146b1f91fa9d0e4dd7a38da93ff7a75d42c0b9d3a545"
"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca"
"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac"
"checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db"
"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4"
"checksum csv 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "00affe7f6ab566df61b4be3ce8cf16bc2576bca0963ceb0955e45d514bf9a279"
"checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c"
"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
"checksum hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772"
"checksum itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484"
"checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
"checksum memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223"
"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9"
"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
"checksum num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6"
"checksum permutohedron 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b687ff7b5da449d39e418ad391e5e08da53ec334903ddbb921db208908fc372c"
"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
"checksum proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548"
"checksum quickcheck 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a44883e74aa97ad63db83c4bf8ca490f02b2fc02f92575e720c8551e843c945f"
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
"checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853"
"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
"checksum rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a788ae3edb696cfcba1c19bfd388cc4b8c21f8a408432b199c072825084da58a"
"checksum rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e18c91676f670f6f0312764c759405f13afb98d5d73819840cf72a518487bff"
"checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098"
"checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9"
"checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
"checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
"checksum serde_json 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "15913895b61e0be854afd32fd4163fcd2a3df34142cf2cb961b310ce694cbf90"
"checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum tinytemplate 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "57a3c6667d3e65eb1bc3aed6fd14011c6cbc3a0665218ab7f5daf040b9ec371a"
"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

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

@ -3,7 +3,7 @@
# 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
# 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
@ -11,8 +11,9 @@
# will likely look very different (and much more reasonable)
[package]
edition = "2018"
name = "itertools"
version = "0.8.0"
version = "0.9.0"
authors = ["bluss"]
exclude = ["/bors.toml"]
description = "Extra iterator adaptors, iterator methods, free functions, and macros."
@ -29,18 +30,45 @@ debug = true
[lib]
test = false
bench = false
[[bench]]
name = "tuple_combinations"
harness = false
[[bench]]
name = "tuples"
harness = false
[[bench]]
name = "fold_specialization"
harness = false
[[bench]]
name = "combinations_with_replacement"
harness = false
[[bench]]
name = "tree_fold1"
harness = false
[[bench]]
name = "bench1"
harness = false
[dependencies.either]
version = "1.0"
default-features = false
[dev-dependencies.criterion]
version = "=0.3.0"
[dev-dependencies.permutohedron]
version = "0.2"
[dev-dependencies.quickcheck]
version = "0.7"
version = "0.9"
default-features = false
[dev-dependencies.rand]
version = "0.6"
version = "0.7"
[features]
default = ["use_std"]

475
third_party/rust/itertools/README.rst поставляемый
Просмотреть файл

@ -10,8 +10,8 @@ __ https://docs.rs/itertools/
|build_status|_ |crates|_
.. |build_status| image:: https://travis-ci.org/bluss/rust-itertools.svg?branch=master
.. _build_status: https://travis-ci.org/bluss/rust-itertools
.. |build_status| image:: https://travis-ci.org/rust-itertools/itertools.svg?branch=master
.. _build_status: https://travis-ci.org/rust-itertools/itertools
.. |crates| image:: http://meritbadge.herokuapp.com/itertools
.. _crates: https://crates.io/crates/itertools
@ -27,8 +27,6 @@ How to use in your crate:
.. code:: rust
#[macro_use] extern crate itertools;
use itertools::Itertools;
How to contribute
@ -45,475 +43,6 @@ The reason for doing is this is so that we avoid future breakage as with ``.flat
However, if your feature involves heap allocation, such as storing elements in a ``Vec<T>``,
then it can't be accepted into ``libcore``, and you should propose it for ``itertools`` directly instead.
Recent Changes
--------------
- 0.8.0
- Added new adaptor ``.map_into()`` for conversions using ``Into`` by @vorner
- Improved ``Itertools`` docs by @JohnHeitmann
- The return type of ``.sorted/_by/_by_key()`` is now an iterator, not a Vec.
- The return type of the ``izip!(x, y)`` macro with exactly two arguments
is now the usual ``Iterator::zip``.
- Remove ``.flatten()`` in favour of std's ``.flatten()``
- Deprecate ``.foreach()`` in favour of std's ``.for_each()``
- Deprecate ``.step()`` in favour of std's ``.step_by()``
- Deprecate ``repeat_call`` in favour of std's ``repeat_with``
- Deprecate ``.fold_while()`` in favour of std's ``.try_fold()``
- Require Rust 1.24 as minimal version.
- 0.7.11
- Add convenience methods to ``EitherOrBoth``, making it more similar to ``Option``
and ``Either`` by @jethrogb
- 0.7.10
- No changes.
- 0.7.9
- New inclusion policy: See the readme about suggesting features for std before
accepting them in itertools.
- The ``FoldWhile`` type now implements ``Eq`` and ``PartialEq`` by @jturner314
- 0.7.8
- Add new iterator method ``.tree_fold1()`` which is like ``.fold1()``
except items are combined in a tree structure (see its docs).
By @scottmcm
- Add more ``Debug`` impls by @phimuemue: KMerge, KMergeBy, MergeJoinBy,
ConsTuples, Intersperse, ProcessResults, RcIter, Tee, TupleWindows, Tee,
ZipLongest, ZipEq, Zip.
- 0.7.7
- Add new iterator method ``.into_group_map() -> HashMap<K, Vec<V>>``
which turns an iterator of ``(K, V)`` elements into such a hash table,
where values are grouped by key. By @tobz1000
- Add new free function ``flatten`` for the ``.flatten()`` adaptor.
**NOTE:** recent Rust nightlies have ``Iterator::flatten`` and thus a clash
with our flatten adaptor. One workaround is to use the itertools ``flatten``
free function.
- 0.7.6
- Add new adaptor ``.multi_cartesian_product()`` which is an n-ary product
iterator by @tobz1000
- Add new method ``.sorted_by_key()`` by @Xion
- Provide simpler and faster ``.count()`` for ``.unique()`` and ``.unique_by()``
- 0.7.5
- ``.multipeek()`` now implements ``PeekingNext``, by @nicopap.
- 0.7.4
- Add new adaptor ``.update()`` by @lucasem; this adaptor is used
to modify an element before passing it on in an iterator chain.
- 0.7.3
- Add new method ``.collect_tuple()`` by @matklad; it makes a tuple out of
the iterator's elements if the number of them matches **exactly**.
- Implement ``fold`` and ``collect`` for ``.map_results()`` which means
it reuses the code of the standard ``.map()`` for these methods.
- 0.7.2
- Add new adaptor ``.merge_join_by`` by @srijs; a heterogeneous merge join
for two ordered sequences.
- 0.7.1
- Iterator adaptors and iterators in itertools now use the same ``must_use``
reminder that the standard library adaptors do, by @matematikaedit and @bluss
*“iterator adaptors are lazy and do nothing unless consumed”*.
- 0.7.0
- Faster ``izip!()`` by @krdln
- ``izip!()`` is now a wrapper for repeated regular ``.zip()`` and
a single ``.map()``. This means it optimizes as well as the standard
library ``.zip()`` it uses.
**Note:** ``multizip`` and ``izip!()`` are now different! The former
has a named type but the latter optimizes better.
- Faster ``.unique()``
- ``no_std`` support, which is opt-in!
- Many lovable features are still there without std, like ``izip!()``
or ``.format()`` or ``.merge()``, but not those that use collections.
- Trait bounds were required up front instead of just on the type:
``group_by``'s ``PartialEq`` by @Phlosioneer and ``repeat_call``'s
``FnMut``.
- Removed deprecated constructor ``Zip::new`` — use ``izip!()`` or ``multizip()``
- 0.6.5
- Fix bug in ``.cartesian_product()``'s fold (which only was visible for
unfused iterators).
- 0.6.4
- Add specific ``fold`` implementations for ``.cartesian_product()`` and
``cons_tuples()``, which improves their performance in fold, foreach, and
iterator consumers derived from them.
- 0.6.3
- Add iterator adaptor ``.positions(predicate)`` by @tmccombs
- 0.6.2
- Add function ``process_results`` which can “lift” a function of the regular
values of an iterator so that it can process the ``Ok`` values from an
iterator of ``Results`` instead, by @shepmaster
- Add iterator method ``.concat()`` which combines all iterator elements
into a single collection using the ``Extend`` trait, by @srijs
- 0.6.1
- Better size hint testing and subsequent size hint bugfixes by @rkarp.
Fixes bugs in product, interleave_shortest size hints.
- New iterator method ``.all_equal()`` by @phimuemue
- 0.6.0
- Deprecated names were removed in favour of their replacements
- ``.flatten()`` does not implement double ended iteration anymore
- ``.fold_while()`` uses ``&mut self`` and returns ``FoldWhile<T>``, for
composability (#168)
- ``.foreach()`` and ``.fold1()`` use ``self``, like ``.fold()`` does.
- ``.combinations(0)`` now produces a single empty vector. (#174)
- 0.5.10
- Add itertools method ``.kmerge_by()`` (and corresponding free function)
- Relaxed trait requirement of ``.kmerge()`` and ``.minmax()`` to PartialOrd.
- 0.5.9
- Add multipeek method ``.reset_peek()``
- Add categories
- 0.5.8
- Add iterator adaptor ``.peeking_take_while()`` and its trait ``PeekingNext``.
- 0.5.7
- Add iterator adaptor ``.with_position()``
- Fix multipeek's performance for long peeks by using ``VecDeque``.
- 0.5.6
- Add ``.map_results()``
- 0.5.5
- Many more adaptors now implement ``Debug``
- Add free function constructor ``repeat_n``. ``RepeatN::new`` is now
deprecated.
- 0.5.4
- Add infinite generator function ``iterate``, that takes a seed and a
closure.
- 0.5.3
- Special-cased ``.fold()`` for flatten and put back. ``.foreach()``
now uses fold on the iterator, to pick up any iterator specific loop
implementation.
- ``.combinations(n)`` asserts up front that ``n != 0``, instead of
running into an error on the second iterator element.
- 0.5.2
- Add ``.tuples::<T>()`` that iterates by two, three or four elements at
a time (where ``T`` is a tuple type).
- Add ``.tuple_windows::<T>()`` that iterates using a window of the
two, three or four most recent elements.
- Add ``.next_tuple::<T>()`` method, that picks the next two, three or four
elements in one go.
- ``.interleave()`` now has an accurate size hint.
- 0.5.1
- Workaround module/function name clash that made racer crash on completing
itertools. Only internal changes needed.
- 0.5.0
- `Release announcement <http://bluss.github.io/rust/2016/09/26/itertools-0.5.0/>`_
- Renamed:
- combinations is now tuple_combinations
- combinations_n to combinations
- group_by_lazy, chunks_lazy to group_by, chunks
- Unfold::new to unfold()
- RepeatCall::new to repeat_call()
- Zip::new to multizip
- PutBack::new, PutBackN::new to put_back, put_back_n
- PutBack::with_value is now a builder setter, not a constructor
- MultiPeek::new, .multipeek() to multipeek()
- format to format_with and format_default to format
- .into_rc() to rciter
- ``Partition`` enum is now ``Either``
- Module reorganization:
- All iterator structs are under ``itertools::structs`` but also
reexported to the top level, for backwards compatibility
- All free functions are reexported at the root, ``itertools::free`` will
be removed in the next version
- Removed:
- ZipSlices, use .zip() instead
- .enumerate_from(), ZipTrusted, due to being unstable
- .mend_slices(), moved to crate odds
- Stride, StrideMut, moved to crate odds
- linspace(), moved to crate itertools-num
- .sort_by(), use .sorted_by()
- .is_empty_hint(), use .size_hint()
- .dropn(), use .dropping()
- .map_fn(), use .map()
- .slice(), use .take() / .skip()
- helper traits in misc
- ``new`` constructors on iterator structs, use Itertools trait or free
functions instead
- ``itertools::size_hint`` is now private
- Behaviour changes:
- format and format_with helpers now panic if you try to format them more
than once.
- ``repeat_call`` is not double ended anymore
- New features:
- tuple flattening iterator is constructible with ``cons_tuples``
- itertools reexports ``Either`` from the ``either`` crate. ``Either<L, R>``
is an iterator when ``L, R`` are.
- ``MinMaxResult`` now implements Copy and Clone
- tuple_combinations supports 1-4 tuples of combinations (previously just 2)
- 0.4.19
- Add ``.minmax_by()``
- Add ``itertools::free::cloned``
- Add ``itertools::free::rciter``
- Improve ``.step(n)`` slightly to take advantage of specialized Fuse better.
- 0.4.18
- Only changes related to the "unstable" crate feature. This feature is more
or less deprecated.
- Use deprecated warnings when unstable is enabled. .enumerate_from() will
be removed imminently since it's using a deprecated libstd trait.
- 0.4.17
- Fix bug in .kmerge() that caused it to often produce the wrong order (#134)
- 0.4.16
- Improve precision of the interleave_shortest adaptor's size hint (it is
now computed exactly when possible).
- 0.4.15
- Fixup on top of the workaround in 0.4.14. A function in itertools::free was
removed by mistake and now it is added back again.
- 0.4.14
- Workaround an upstream regression in a rust nightly build that broke
compilation of of itertools::free::{interleave, merge}
- 0.4.13
- Add .minmax() and .minmax_by_key(), iterator methods for finding both minimum
and maximum in one scan.
- Add .format_default(), a simpler version of .format() (lazy formatting
for iterators).
- 0.4.12
- Add .zip_eq(), an adaptor like .zip() except it ensures iterators
of inequal length don't pass silently (instead it panics).
- Add .fold_while(), an iterator method that is a fold that
can short-circuit.
- Add .partition_map(), an iterator method that can separate elements
into two collections.
- 0.4.11
- Add .get() for Stride{,Mut} and .get_mut() for StrideMut
- 0.4.10
- Improve performance of .kmerge()
- 0.4.9
- Add k-ary merge adaptor .kmerge()
- Fix a bug in .islice() with ranges a..b where a > b.
- 0.4.8
- Implement Clone, Debug for Linspace
- 0.4.7
- Add function diff_with() that compares two iterators
- Add .combinations_n(), an n-ary combinations iterator
- Add methods PutBack::with_value and PutBack::into_parts.
- 0.4.6
- Add method .sorted()
- Add module ``itertools::free`` with free function variants of common
iterator adaptors and methods.
For example ``enumerate(iterable)``, ``rev(iterable)``, and so on.
- 0.4.5
- Add .flatten()
- 0.4.4
- Allow composing ZipSlices with itself
- 0.4.3
- Write iproduct!() as a single expression; this allows temporary values
in its arguments.
- 0.4.2
- Add .fold_options()
- Require Rust 1.1 or later
- 0.4.1
- Update .dropping() to take advantage of .nth()
- 0.4.0
- .merge(), .unique() and .dedup() now perform better due to not using
function pointers
- Add free functions enumerate() and rev()
- Breaking changes:
- Return types of .merge() and .merge_by() renamed and changed
- Method Merge::new removed
- .merge_by() now takes a closure that returns bool.
- Return type of .dedup() changed
- Return type of .mend_slices() changed
- Return type of .unique() changed
- Removed function times(), struct Times: use a range instead
- Removed deprecated macro icompr!()
- Removed deprecated FnMap and method .fn_map(): use .map_fn()
- .interleave_shortest() is no longer guaranteed to act like fused
- 0.3.25
- Rename .sort_by() to .sorted_by(). Old name is deprecated.
- Fix well-formedness warnings from RFC 1214, no user visible impact
- 0.3.24
- Improve performance of .merge()'s ordering function slightly
- 0.3.23
- Added .chunks(), similar to (and based on) .group_by_lazy().
- Tweak linspace to match numpy.linspace and make it double ended.
- 0.3.22
- Added ZipSlices, a fast zip for slices
- 0.3.21
- Remove `Debug` impl for `Format`, it will have different use later
- 0.3.20
- Optimize .group_by_lazy()
- 0.3.19
- Added .group_by_lazy(), a possibly nonallocating group by
- Added .format(), a nonallocating formatting helper for iterators
- Remove uses of RandomAccessIterator since it has been deprecated in rust.
- 0.3.17
- Added (adopted) Unfold from rust
- 0.3.16
- Added adaptors .unique(), .unique_by()
- 0.3.15
- Added method .sort_by()
- 0.3.14
- Added adaptor .while_some()
- 0.3.13
- Added adaptor .interleave_shortest()
- Added adaptor .pad_using()
- 0.3.11
- Added assert_equal function
- 0.3.10
- Bugfix .combinations() size_hint.
- 0.3.8
- Added source RepeatCall
- 0.3.7
- Added adaptor PutBackN
- Added adaptor .combinations()
- 0.3.6
- Added itertools::partition, partition a sequence in place based on a predicate.
- Deprecate icompr!() with no replacement.
- 0.3.5
- .map_fn() replaces deprecated .fn_map().
- 0.3.4
- .take_while_ref() *by-ref adaptor*
- .coalesce() *adaptor*
- .mend_slices() *adaptor*
- 0.3.3
- .dropping_back() *method*
- .fold1() *method*
- .is_empty_hint() *method*
License
-------

946
third_party/rust/itertools/benches/bench1.rs поставляемый

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

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

@ -0,0 +1,40 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use itertools::Itertools;
fn comb_replacement_n10_k5(c: &mut Criterion) {
c.bench_function("comb replacement n10k5", move |b| {
b.iter(|| {
for i in (0..10).combinations_with_replacement(5) {
black_box(i);
}
})
});
}
fn comb_replacement_n5_k10(c: &mut Criterion) {
c.bench_function("comb replacement n5 k10", move |b| {
b.iter(|| {
for i in (0..5).combinations_with_replacement(10) {
black_box(i);
}
})
});
}
fn comb_replacement_n10_k10(c: &mut Criterion) {
c.bench_function("comb replacement n10 k10", move |b| {
b.iter(|| {
for i in (0..10).combinations_with_replacement(10) {
black_box(i);
}
})
});
}
criterion_group!(
benches,
comb_replacement_n10_k5,
comb_replacement_n5_k10,
comb_replacement_n10_k10,
);
criterion_main!(benches);

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

@ -1,4 +1,2 @@
pub use self::zipslices::ZipSlices;
mod zipslices;

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

@ -186,4 +186,3 @@ fn zipslices() {
}
::itertools::assert_equal(&xs, &ys);
}

73
third_party/rust/itertools/benches/fold_specialization.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,73 @@
use criterion::{criterion_group, criterion_main, Criterion};
use itertools::Itertools;
struct Unspecialized<I>(I);
impl<I> Iterator for Unspecialized<I>
where I: Iterator
{
type Item = I::Item;
#[inline(always)]
fn next(&mut self) -> Option<I::Item> {
self.0.next()
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
mod specialization {
use super::*;
pub mod intersperse {
use super::*;
pub fn external(c: &mut Criterion)
{
let arr = [1; 1024];
c.bench_function("external", move |b| {
b.iter(|| {
let mut sum = 0;
for &x in arr.iter().intersperse(&0) {
sum += x;
}
sum
})
});
}
pub fn internal_specialized(c: &mut Criterion)
{
let arr = [1; 1024];
c.bench_function("internal specialized", move |b| {
b.iter(|| {
arr.iter().intersperse(&0).fold(0, |acc, x| acc + x)
})
});
}
pub fn internal_unspecialized(c: &mut Criterion)
{
let arr = [1; 1024];
c.bench_function("internal unspecialized", move |b| {
b.iter(|| {
Unspecialized(arr.iter().intersperse(&0)).fold(0, |acc, x| acc + x)
})
});
}
}
}
criterion_group!(
benches,
specialization::intersperse::external,
specialization::intersperse::internal_specialized,
specialization::intersperse::internal_unspecialized,
);
criterion_main!(benches);

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

@ -1,11 +1,5 @@
#![feature(test)]
extern crate test;
extern crate itertools;
use itertools::Itertools;
use itertools::cloned;
use test::Bencher;
use criterion::{criterion_group, criterion_main, Criterion};
use itertools::{Itertools, cloned};
trait IterEx : Iterator {
// Another efficient implementation against which to compare,
@ -17,7 +11,7 @@ trait IterEx : Iterator {
let hint = self.size_hint().0;
let cap = std::mem::size_of::<usize>() * 8 - hint.leading_zeros() as usize;
let mut stack = Vec::with_capacity(cap);
self.enumerate().foreach(|(mut i, mut x)| {
self.enumerate().for_each(|(mut i, mut x)| {
while (i & 1) != 0 {
x = f(stack.pop().unwrap(), x);
i >>= 1;
@ -35,39 +29,51 @@ macro_rules! def_benchs {
$BENCH_NAME:ident,
) => (
mod $BENCH_NAME {
use super::*;
use super::*;
#[bench]
fn sum(b: &mut Bencher) {
let v: Vec<u32> = (0.. $N).collect();
b.iter(|| {
cloned(&v).$FUN(|x, y| x + y)
});
pub fn sum(c: &mut Criterion) {
let v: Vec<u32> = (0.. $N).collect();
c.bench_function(&(stringify!($BENCH_NAME).replace('_', " ") + " sum"), move |b| {
b.iter(|| {
cloned(&v).$FUN(|x, y| x + y)
})
});
}
pub fn complex_iter(c: &mut Criterion) {
let u = (3..).take($N / 2);
let v = (5..).take($N / 2);
let it = u.chain(v);
c.bench_function(&(stringify!($BENCH_NAME).replace('_', " ") + " complex iter"), move |b| {
b.iter(|| {
it.clone().map(|x| x as f32).$FUN(f32::atan2)
})
});
}
pub fn string_format(c: &mut Criterion) {
// This goes quadratic with linear `fold1`, so use a smaller
// size to not waste too much time in travis. The allocations
// in here are so expensive anyway that it'll still take
// way longer per iteration than the other two benchmarks.
let v: Vec<u32> = (0.. ($N/4)).collect();
c.bench_function(&(stringify!($BENCH_NAME).replace('_', " ") + " string format"), move |b| {
b.iter(|| {
cloned(&v).map(|x| x.to_string()).$FUN(|x, y| format!("{} + {}", x, y))
})
});
}
}
#[bench]
fn complex_iter(b: &mut Bencher) {
let u = (3..).take($N / 2);
let v = (5..).take($N / 2);
let it = u.chain(v);
b.iter(|| {
it.clone().map(|x| x as f32).$FUN(f32::atan2)
});
}
#[bench]
fn string_format(b: &mut Bencher) {
// This goes quadratic with linear `fold1`, so use a smaller
// size to not waste too much time in travis. The allocations
// in here are so expensive anyway that it'll still take
// way longer per iteration than the other two benchmarks.
let v: Vec<u32> = (0.. ($N/4)).collect();
b.iter(|| {
cloned(&v).map(|x| x.to_string()).$FUN(|x, y| format!("{} + {}", x, y))
});
}
}
criterion_group!(
$BENCH_NAME,
$BENCH_NAME::sum,
$BENCH_NAME::complex_iter,
$BENCH_NAME::string_format,
);
)
}
@ -124,3 +130,15 @@ def_benchs!{
tree_fold1_vec,
tree_fold1_vec_08,
}
criterion_main!(
fold1_10k,
tree_fold1_stack_10k,
tree_fold1_vec_10k,
fold1_100,
tree_fold1_stack_100,
tree_fold1_vec_100,
fold1_08,
tree_fold1_stack_08,
tree_fold1_vec_08,
);

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

@ -1,9 +1,4 @@
#![feature(test)]
extern crate test;
extern crate itertools;
use test::{black_box, Bencher};
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use itertools::Itertools;
// approximate 100_000 iterations for each combination
@ -12,86 +7,107 @@ const N2: usize = 448;
const N3: usize = 86;
const N4: usize = 41;
#[bench]
fn comb_for1(b: &mut Bencher) {
b.iter(|| {
for i in 0..N1 {
black_box(i);
}
});
}
#[bench]
fn comb_for2(b: &mut Bencher) {
b.iter(|| {
for i in 0..N2 {
for j in (i + 1)..N2 {
black_box(i + j);
fn comb_for1(c: &mut Criterion) {
c.bench_function("comb for1", move |b| {
b.iter(|| {
for i in 0..N1 {
black_box(i);
}
}
})
});
}
#[bench]
fn comb_for3(b: &mut Bencher) {
b.iter(|| {
for i in 0..N3 {
for j in (i + 1)..N3 {
for k in (j + 1)..N3 {
black_box(i + j + k);
fn comb_for2(c: &mut Criterion) {
c.bench_function("comb for2", move |b| {
b.iter(|| {
for i in 0..N2 {
for j in (i + 1)..N2 {
black_box(i + j);
}
}
}
})
});
}
#[bench]
fn comb_for4(b: &mut Bencher) {
b.iter(|| {
for i in 0..N4 {
for j in (i + 1)..N4 {
for k in (j + 1)..N4 {
for l in (k + 1)..N4 {
black_box(i + j + k + l);
fn comb_for3(c: &mut Criterion) {
c.bench_function("comb for3", move |b| {
b.iter(|| {
for i in 0..N3 {
for j in (i + 1)..N3 {
for k in (j + 1)..N3 {
black_box(i + j + k);
}
}
}
}
})
});
}
#[bench]
fn comb_c1(b: &mut Bencher) {
b.iter(|| {
for (i,) in (0..N1).tuple_combinations() {
black_box(i);
}
fn comb_for4(c: &mut Criterion) {
c.bench_function("comb for4", move |b| {
b.iter(|| {
for i in 0..N4 {
for j in (i + 1)..N4 {
for k in (j + 1)..N4 {
for l in (k + 1)..N4 {
black_box(i + j + k + l);
}
}
}
}
})
});
}
#[bench]
fn comb_c2(b: &mut Bencher) {
b.iter(|| {
for (i, j) in (0..N2).tuple_combinations() {
black_box(i + j);
}
fn comb_c1(c: &mut Criterion) {
c.bench_function("comb c1", move |b| {
b.iter(|| {
for (i,) in (0..N1).tuple_combinations() {
black_box(i);
}
})
});
}
#[bench]
fn comb_c3(b: &mut Bencher) {
b.iter(|| {
for (i, j, k) in (0..N3).tuple_combinations() {
black_box(i + j + k);
}
fn comb_c2(c: &mut Criterion) {
c.bench_function("comb c2", move |b| {
b.iter(|| {
for (i, j) in (0..N2).tuple_combinations() {
black_box(i + j);
}
})
});
}
#[bench]
fn comb_c4(b: &mut Bencher) {
b.iter(|| {
for (i, j, k, l) in (0..N4).tuple_combinations() {
black_box(i + j + k + l);
}
fn comb_c3(c: &mut Criterion) {
c.bench_function("comb c3", move |b| {
b.iter(|| {
for (i, j, k) in (0..N3).tuple_combinations() {
black_box(i + j + k);
}
})
});
}
fn comb_c4(c: &mut Criterion) {
c.bench_function("comb c4", move |b| {
b.iter(|| {
for (i, j, k, l) in (0..N4).tuple_combinations() {
black_box(i + j + k + l);
}
})
});
}
criterion_group!(
benches,
comb_for1,
comb_for2,
comb_for3,
comb_for4,
comb_c1,
comb_c2,
comb_c3,
comb_c4,
);
criterion_main!(benches);

123
third_party/rust/itertools/benches/tuples.rs поставляемый
Просмотреть файл

@ -1,9 +1,4 @@
#![feature(test)]
extern crate test;
extern crate itertools;
use test::Bencher;
use criterion::{criterion_group, criterion_main, Criterion};
use itertools::Itertools;
fn s1(a: u32) -> u32 {
@ -56,6 +51,7 @@ fn sum_t4(s: &(&u32, &u32, &u32, &u32)) -> u32 {
macro_rules! def_benchs {
($N:expr;
$BENCH_GROUP:ident,
$TUPLE_FUN:ident,
$TUPLES:ident,
$TUPLE_WINDOWS:ident;
@ -65,84 +61,101 @@ macro_rules! def_benchs {
$FOR_CHUNKS:ident,
$FOR_WINDOWS:ident
) => (
#[bench]
fn $FOR_CHUNKS(b: &mut Bencher) {
fn $FOR_CHUNKS(c: &mut Criterion) {
let v: Vec<u32> = (0.. $N * 1_000).collect();
let mut s = 0;
b.iter(|| {
let mut j = 0;
for _ in 0..1_000 {
s += $SLICE_FUN(&v[j..(j + $N)]);
j += $N;
}
s
c.bench_function(&stringify!($FOR_CHUNKS).replace('_', " "), move |b| {
b.iter(|| {
let mut j = 0;
for _ in 0..1_000 {
s += $SLICE_FUN(&v[j..(j + $N)]);
j += $N;
}
s
})
});
}
#[bench]
fn $FOR_WINDOWS(b: &mut Bencher) {
fn $FOR_WINDOWS(c: &mut Criterion) {
let v: Vec<u32> = (0..1_000).collect();
let mut s = 0;
b.iter(|| {
for i in 0..(1_000 - $N) {
s += $SLICE_FUN(&v[i..(i + $N)]);
}
s
c.bench_function(&stringify!($FOR_WINDOWS).replace('_', " "), move |b| {
b.iter(|| {
for i in 0..(1_000 - $N) {
s += $SLICE_FUN(&v[i..(i + $N)]);
}
s
})
});
}
#[bench]
fn $TUPLES(b: &mut Bencher) {
fn $TUPLES(c: &mut Criterion) {
let v: Vec<u32> = (0.. $N * 1_000).collect();
let mut s = 0;
b.iter(|| {
for x in v.iter().tuples() {
s += $TUPLE_FUN(&x);
}
s
c.bench_function(&stringify!($TUPLES).replace('_', " "), move |b| {
b.iter(|| {
for x in v.iter().tuples() {
s += $TUPLE_FUN(&x);
}
s
})
});
}
#[bench]
fn $CHUNKS(b: &mut Bencher) {
fn $CHUNKS(c: &mut Criterion) {
let v: Vec<u32> = (0.. $N * 1_000).collect();
let mut s = 0;
b.iter(|| {
for x in v.chunks($N) {
s += $SLICE_FUN(x);
}
s
c.bench_function(&stringify!($CHUNKS).replace('_', " "), move |b| {
b.iter(|| {
for x in v.chunks($N) {
s += $SLICE_FUN(x);
}
s
})
});
}
#[bench]
fn $TUPLE_WINDOWS(b: &mut Bencher) {
fn $TUPLE_WINDOWS(c: &mut Criterion) {
let v: Vec<u32> = (0..1_000).collect();
let mut s = 0;
b.iter(|| {
for x in v.iter().tuple_windows() {
s += $TUPLE_FUN(&x);
}
s
c.bench_function(&stringify!($TUPLE_WINDOWS).replace('_', " "), move |b| {
b.iter(|| {
for x in v.iter().tuple_windows() {
s += $TUPLE_FUN(&x);
}
s
})
});
}
#[bench]
fn $WINDOWS(b: &mut Bencher) {
fn $WINDOWS(c: &mut Criterion) {
let v: Vec<u32> = (0..1_000).collect();
let mut s = 0;
b.iter(|| {
for x in v.windows($N) {
s += $SLICE_FUN(x);
}
s
c.bench_function(&stringify!($WINDOWS).replace('_', " "), move |b| {
b.iter(|| {
for x in v.windows($N) {
s += $SLICE_FUN(x);
}
s
})
});
}
criterion_group!(
$BENCH_GROUP,
$FOR_CHUNKS,
$FOR_WINDOWS,
$TUPLES,
$CHUNKS,
$TUPLE_WINDOWS,
$WINDOWS,
);
)
}
def_benchs!{
1;
benches_1,
sum_t1,
tuple_chunks_1,
tuple_windows_1;
@ -155,6 +168,7 @@ def_benchs!{
def_benchs!{
2;
benches_2,
sum_t2,
tuple_chunks_2,
tuple_windows_2;
@ -167,6 +181,7 @@ def_benchs!{
def_benchs!{
3;
benches_3,
sum_t3,
tuple_chunks_3,
tuple_windows_3;
@ -179,6 +194,7 @@ def_benchs!{
def_benchs!{
4;
benches_4,
sum_t4,
tuple_chunks_4,
tuple_windows_4;
@ -188,3 +204,10 @@ def_benchs!{
for_chunks_4,
for_windows_4
}
criterion_main!(
benches_1,
benches_2,
benches_3,
benches_4,
);

6
third_party/rust/itertools/examples/iris.rs поставляемый
Просмотреть файл

@ -3,10 +3,6 @@
/// and does some simple manipulations.
///
/// Iterators and itertools functionality are used throughout.
///
///
extern crate itertools;
use itertools::Itertools;
use std::collections::HashMap;
@ -44,7 +40,7 @@ impl FromStr for Iris {
// using Iterator::by_ref()
for (index, part) in parts.by_ref().take(4).enumerate() {
iris.data[index] = try!(part.parse::<f32>());
iris.data[index] = part.parse::<f32>()?;
}
if let Some(name) = parts.next() {
iris.name = name.into();

310
third_party/rust/itertools/src/adaptors/mod.rs поставляемый
Просмотреть файл

@ -12,17 +12,7 @@ use std::fmt;
use std::mem::replace;
use std::iter::{Fuse, Peekable, FromIterator};
use std::marker::PhantomData;
use size_hint;
macro_rules! clone_fields {
($name:ident, $base:expr, $($field:ident),+) => (
$name {
$(
$field : $base . $field .clone()
),*
}
);
}
use crate::size_hint;
/// An iterator adaptor that alternates elements from two iterators until both
/// run out.
@ -243,6 +233,28 @@ impl<I> Iterator for PutBack<I>
size_hint::add_scalar(self.iter.size_hint(), self.top.is_some() as usize)
}
fn count(self) -> usize {
self.iter.count() + (self.top.is_some() as usize)
}
fn last(self) -> Option<Self::Item> {
self.iter.last().or(self.top)
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
match self.top {
None => self.iter.nth(n),
ref mut some => {
if n == 0 {
some.take()
} else {
*some = None;
self.iter.nth(n - 1)
}
}
}
}
fn all<G>(&mut self, mut f: G) -> bool
where G: FnMut(Self::Item) -> bool
{
@ -380,7 +392,7 @@ impl<I, F> fmt::Debug for Batching<I, F> where I: fmt::Debug {
/// Create a new Batching iterator.
pub fn batching<I, F>(iter: I, f: F) -> Batching<I, F> {
Batching { f: f, iter: iter }
Batching { f, iter }
}
impl<B, F, I> Iterator for Batching<I, F>
@ -463,61 +475,16 @@ impl<I> ExactSizeIterator for Step<I>
where I: ExactSizeIterator
{}
struct MergeCore<I, J>
where I: Iterator,
J: Iterator<Item = I::Item>
{
a: Peekable<I>,
b: Peekable<J>,
fused: Option<bool>,
pub trait MergePredicate<T> {
fn merge_pred(&mut self, a: &T, b: &T) -> bool;
}
#[derive(Clone)]
pub struct MergeLte;
impl<I, J> Clone for MergeCore<I, J>
where I: Iterator,
J: Iterator<Item = I::Item>,
Peekable<I>: Clone,
Peekable<J>: Clone
{
fn clone(&self) -> Self {
clone_fields!(MergeCore, self, a, b, fused)
}
}
impl<I, J> MergeCore<I, J>
where I: Iterator,
J: Iterator<Item = I::Item>
{
fn next_with<F>(&mut self, mut less_than: F) -> Option<I::Item>
where F: FnMut(&I::Item, &I::Item) -> bool
{
let less_than = match self.fused {
Some(lt) => lt,
None => match (self.a.peek(), self.b.peek()) {
(Some(a), Some(b)) => less_than(a, b),
(Some(_), None) => {
self.fused = Some(true);
true
}
(None, Some(_)) => {
self.fused = Some(false);
false
}
(None, None) => return None,
}
};
if less_than {
self.a.next()
} else {
self.b.next()
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
// Not ExactSizeIterator because size may be larger than usize
size_hint::add(self.a.size_hint(), self.b.size_hint())
impl<T: PartialOrd> MergePredicate<T> for MergeLte {
fn merge_pred(&mut self, a: &T, b: &T) -> bool {
a <= b
}
}
@ -528,30 +495,7 @@ impl<I, J> MergeCore<I, J>
///
/// See [`.merge()`](../trait.Itertools.html#method.merge_by) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Merge<I, J>
where I: Iterator,
J: Iterator<Item = I::Item>
{
merge: MergeCore<I, J>,
}
impl<I, J> Clone for Merge<I, J>
where I: Iterator,
J: Iterator<Item = I::Item>,
Peekable<I>: Clone,
Peekable<J>: Clone
{
fn clone(&self) -> Self {
clone_fields!(Merge, self, merge)
}
}
impl<I, J> fmt::Debug for Merge<I, J>
where I: Iterator + fmt::Debug, J: Iterator<Item = I::Item> + fmt::Debug,
I::Item: fmt::Debug,
{
debug_fmt_fields!(Merge, merge.a, merge.b);
}
pub type Merge<I, J> = MergeBy<I, J, MergeLte>;
/// Create an iterator that merges elements in `i` and `j`.
///
@ -569,29 +513,7 @@ pub fn merge<I, J>(i: I, j: J) -> Merge<<I as IntoIterator>::IntoIter, <J as Int
J: IntoIterator<Item = I::Item>,
I::Item: PartialOrd
{
Merge {
merge: MergeCore {
a: i.into_iter().peekable(),
b: j.into_iter().peekable(),
fused: None,
},
}
}
impl<I, J> Iterator for Merge<I, J>
where I: Iterator,
J: Iterator<Item = I::Item>,
I::Item: PartialOrd
{
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
self.merge.next_with(|a, b| a <= b)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.merge.size_hint()
}
merge_by_new(i, j, MergeLte)
}
/// An iterator adaptor that merges the two base iterators in ascending order.
@ -605,7 +527,9 @@ pub struct MergeBy<I, J, F>
where I: Iterator,
J: Iterator<Item = I::Item>
{
merge: MergeCore<I, J>,
a: Peekable<I>,
b: Peekable<J>,
fused: Option<bool>,
cmp: F,
}
@ -613,21 +537,26 @@ impl<I, J, F> fmt::Debug for MergeBy<I, J, F>
where I: Iterator + fmt::Debug, J: Iterator<Item = I::Item> + fmt::Debug,
I::Item: fmt::Debug,
{
debug_fmt_fields!(MergeBy, merge.a, merge.b);
debug_fmt_fields!(MergeBy, a, b);
}
impl<T, F: FnMut(&T, &T)->bool> MergePredicate<T> for F {
fn merge_pred(&mut self, a: &T, b: &T) -> bool {
self(a, b)
}
}
/// Create a `MergeBy` iterator.
pub fn merge_by_new<I, J, F>(a: I, b: J, cmp: F) -> MergeBy<I, J, F>
where I: Iterator,
J: Iterator<Item = I::Item>
pub fn merge_by_new<I, J, F>(a: I, b: J, cmp: F) -> MergeBy<I::IntoIter, J::IntoIter, F>
where I: IntoIterator,
J: IntoIterator<Item = I::Item>,
F: MergePredicate<I::Item>,
{
MergeBy {
merge: MergeCore {
a: a.peekable(),
b: b.peekable(),
fused: None,
},
cmp: cmp,
a: a.into_iter().peekable(),
b: b.into_iter().peekable(),
fused: None,
cmp,
}
}
@ -638,24 +567,42 @@ impl<I, J, F> Clone for MergeBy<I, J, F>
Peekable<J>: Clone,
F: Clone
{
fn clone(&self) -> Self {
clone_fields!(MergeBy, self, merge, cmp)
}
clone_fields!(a, b, fused, cmp);
}
impl<I, J, F> Iterator for MergeBy<I, J, F>
where I: Iterator,
J: Iterator<Item = I::Item>,
F: FnMut(&I::Item, &I::Item) -> bool
F: MergePredicate<I::Item>
{
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
self.merge.next_with(&mut self.cmp)
let less_than = match self.fused {
Some(lt) => lt,
None => match (self.a.peek(), self.b.peek()) {
(Some(a), Some(b)) => self.cmp.merge_pred(a, b),
(Some(_), None) => {
self.fused = Some(true);
true
}
(None, Some(_)) => {
self.fused = Some(false);
false
}
(None, None) => return None,
}
};
if less_than {
self.a.next()
} else {
self.b.next()
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.merge.size_hint()
// Not ExactSizeIterator because size may be larger than usize
size_hint::add(self.a.size_hint(), self.b.size_hint())
}
}
@ -713,9 +660,7 @@ impl<I: Clone, F: Clone> Clone for Coalesce<I, F>
where I: Iterator,
I::Item: Clone
{
fn clone(&self) -> Self {
clone_fields!(Coalesce, self, iter, f)
}
clone_fields!(iter, f);
}
impl<I, F> fmt::Debug for Coalesce<I, F>
@ -732,9 +677,9 @@ pub fn coalesce<I, F>(mut iter: I, f: F) -> Coalesce<I, F>
Coalesce {
iter: CoalesceCore {
last: iter.next(),
iter: iter,
iter,
},
f: f,
f,
}
}
@ -753,53 +698,85 @@ impl<I, F> Iterator for Coalesce<I, F>
}
}
/// An iterator adaptor that removes repeated duplicates.
/// An iterator adaptor that removes repeated duplicates, determining equality using a comparison function.
///
/// See [`.dedup()`](../trait.Itertools.html#method.dedup) for more information.
/// See [`.dedup_by()`](../trait.Itertools.html#method.dedup_by) or [`.dedup()`](../trait.Itertools.html#method.dedup) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Dedup<I>
pub struct DedupBy<I, Pred>
where I: Iterator
{
iter: CoalesceCore<I>,
dedup_pred: Pred,
}
impl<I: Clone> Clone for Dedup<I>
pub trait DedupPredicate<T> { // TODO replace by Fn(&T, &T)->bool once Rust supports it
fn dedup_pair(&mut self, a: &T, b: &T) -> bool;
}
#[derive(Clone)]
pub struct DedupEq;
impl<T: PartialEq> DedupPredicate<T> for DedupEq {
fn dedup_pair(&mut self, a: &T, b: &T) -> bool {
a==b
}
}
impl<T, F: FnMut(&T, &T)->bool> DedupPredicate<T> for F {
fn dedup_pair(&mut self, a: &T, b: &T) -> bool {
self(a, b)
}
}
/// An iterator adaptor that removes repeated duplicates.
///
/// See [`.dedup()`](../trait.Itertools.html#method.dedup) for more information.
pub type Dedup<I>=DedupBy<I, DedupEq>;
impl<I: Clone, Pred: Clone> Clone for DedupBy<I, Pred>
where I: Iterator,
I::Item: Clone
I::Item: Clone,
{
fn clone(&self) -> Self {
clone_fields!(Dedup, self, iter)
clone_fields!(iter, dedup_pred);
}
/// Create a new `DedupBy`.
pub fn dedup_by<I, Pred>(mut iter: I, dedup_pred: Pred) -> DedupBy<I, Pred>
where I: Iterator,
{
DedupBy {
iter: CoalesceCore {
last: iter.next(),
iter,
},
dedup_pred,
}
}
/// Create a new `Dedup`.
pub fn dedup<I>(mut iter: I) -> Dedup<I>
pub fn dedup<I>(iter: I) -> Dedup<I>
where I: Iterator
{
Dedup {
iter: CoalesceCore {
last: iter.next(),
iter: iter,
},
}
dedup_by(iter, DedupEq)
}
impl<I> fmt::Debug for Dedup<I>
impl<I, Pred> fmt::Debug for DedupBy<I, Pred>
where I: Iterator + fmt::Debug,
I::Item: fmt::Debug,
{
debug_fmt_fields!(Dedup, iter);
}
impl<I> Iterator for Dedup<I>
impl<I, Pred> Iterator for DedupBy<I, Pred>
where I: Iterator,
I::Item: PartialEq
Pred: DedupPredicate<I::Item>,
{
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
let ref mut dedup_pred = self.dedup_pred;
self.iter.next_with(|x, y| {
if x == y { Ok(x) } else { Err((x, y)) }
if dedup_pred.dedup_pair(&x, &y) { Ok(x) } else { Err((x, y)) }
})
}
@ -811,8 +788,9 @@ impl<I> Iterator for Dedup<I>
where G: FnMut(Acc, Self::Item) -> Acc,
{
if let Some(mut last) = self.iter.last {
let mut dedup_pred = self.dedup_pred;
accum = self.iter.iter.fold(accum, |acc, elt| {
if elt == last {
if dedup_pred.dedup_pair(&elt, &last) {
acc
} else {
f(acc, replace(&mut last, elt))
@ -845,7 +823,7 @@ impl<'a, I, F> fmt::Debug for TakeWhileRef<'a, I, F>
pub fn take_while_ref<I, F>(iter: &mut I, f: F) -> TakeWhileRef<I, F>
where I: Iterator + Clone
{
TakeWhileRef { iter: iter, f: f }
TakeWhileRef { iter, f }
}
impl<'a, I, F> Iterator for TakeWhileRef<'a, I, F>
@ -887,7 +865,7 @@ pub struct WhileSome<I> {
/// Create a new `WhileSome<I>`.
pub fn while_some<I>(iter: I) -> WhileSome<I> {
WhileSome { iter: iter }
WhileSome { iter }
}
impl<I, A> Iterator for WhileSome<I>
@ -913,7 +891,7 @@ impl<I, A> Iterator for WhileSome<I>
///
/// See [`.tuple_combinations()`](../trait.Itertools.html#method.tuple_combinations) for more
/// information.
#[derive(Debug)]
#[derive(Clone, Debug)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct TupleCombinations<I, T>
where I: Iterator,
@ -952,14 +930,14 @@ impl<I, T> Iterator for TupleCombinations<I, T>
}
}
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct Tuple1Combination<I> {
iter: I,
}
impl<I> From<I> for Tuple1Combination<I> {
fn from(iter: I) -> Self {
Tuple1Combination { iter: iter }
Tuple1Combination { iter }
}
}
@ -977,7 +955,7 @@ impl<I: Iterator> HasCombination<I> for (I::Item,) {
macro_rules! impl_tuple_combination {
($C:ident $P:ident ; $A:ident, $($I:ident),* ; $($X:ident)*) => (
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct $C<I: Iterator> {
item: Option<I::Item>,
iter: I,
@ -1041,6 +1019,7 @@ impl_tuple_combination!(Tuple4Combination Tuple3Combination ; A, A, A, A, A; a b
/// An iterator adapter to apply `Into` conversion to each element.
///
/// See [`.map_into()`](../trait.Itertools.html#method.map_into) for more information.
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct MapInto<I, R> {
iter: I,
@ -1050,7 +1029,7 @@ pub struct MapInto<I, R> {
/// Create a new [`MapInto`](struct.MapInto.html) iterator.
pub fn map_into<I, R>(iter: I) -> MapInto<I, R> {
MapInto {
iter: iter,
iter,
_res: PhantomData,
}
}
@ -1098,6 +1077,7 @@ where
/// An iterator adapter to apply a transformation within a nested `Result`.
///
/// See [`.map_results()`](../trait.Itertools.html#method.map_results) for more information.
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct MapResults<I, F> {
iter: I,
@ -1110,8 +1090,8 @@ pub fn map_results<I, F, T, U, E>(iter: I, f: F) -> MapResults<I, F>
F: FnMut(T) -> U,
{
MapResults {
iter: iter,
f: f,
iter,
f,
}
}
@ -1147,6 +1127,7 @@ impl<I, F, T, U, E> Iterator for MapResults<I, F>
/// An iterator adapter to get the positions of each element that matches a predicate.
///
/// See [`.positions()`](../trait.Itertools.html#method.positions) for more information.
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Positions<I, F> {
iter: I,
@ -1160,8 +1141,8 @@ pub fn positions<I, F>(iter: I, f: F) -> Positions<I, F>
F: FnMut(I::Item) -> bool,
{
Positions {
iter: iter,
f: f,
iter,
f,
count: 0
}
}
@ -1205,6 +1186,7 @@ impl<I, F> DoubleEndedIterator for Positions<I, F>
/// An iterator adapter to apply a mutating function to each element before yielding it.
///
/// See [`.update()`](../trait.Itertools.html#method.update) for more information.
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Update<I, F> {
iter: I,
@ -1217,7 +1199,7 @@ where
I: Iterator,
F: FnMut(&mut I::Item),
{
Update { iter: iter, f: f }
Update { iter, f }
}
impl<I, F> Iterator for Update<I, F>

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

@ -1,7 +1,7 @@
#![cfg(feature = "use_std")]
use size_hint;
use Itertools;
use crate::size_hint;
use crate::Itertools;
#[derive(Clone)]
/// An iterator adaptor that iterates over the cartesian product of
@ -65,7 +65,7 @@ impl<I> MultiProduct<I>
let on_first_iter = match state {
StartOfIter => {
let on_first_iter = !last.in_progress();
state = MidIter { on_first_iter: on_first_iter };
state = MidIter { on_first_iter };
on_first_iter
},
MidIter { on_first_iter } => on_first_iter

124
third_party/rust/itertools/src/combinations.rs поставляемый
Просмотреть файл

@ -1,45 +1,46 @@
use std::ops::Index;
use std::fmt;
/// An iterator to iterate through all the `n`-length combinations in an iterator.
use super::lazy_buffer::LazyBuffer;
/// An iterator to iterate through all the `k`-length combinations in an iterator.
///
/// See [`.combinations()`](../trait.Itertools.html#method.combinations) for more information.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Combinations<I: Iterator> {
n: usize,
indices: Vec<usize>,
pool: LazyBuffer<I>,
first: bool,
}
impl<I> Clone for Combinations<I>
where I: Clone + Iterator,
I::Item: Clone,
{
clone_fields!(indices, pool, first);
}
impl<I> fmt::Debug for Combinations<I>
where I: Iterator + fmt::Debug,
I::Item: fmt::Debug,
{
debug_fmt_fields!(Combinations, n, indices, pool, first);
debug_fmt_fields!(Combinations, indices, pool, first);
}
/// Create a new `Combinations` from a clonable iterator.
pub fn combinations<I>(iter: I, n: usize) -> Combinations<I>
pub fn combinations<I>(iter: I, k: usize) -> Combinations<I>
where I: Iterator
{
let mut indices: Vec<usize> = Vec::with_capacity(n);
for i in 0..n {
indices.push(i);
}
let mut pool: LazyBuffer<I> = LazyBuffer::new(iter);
for _ in 0..n {
for _ in 0..k {
if !pool.get_next() {
break;
}
}
Combinations {
n: n,
indices: indices,
pool: pool,
indices: (0..k).collect(),
pool,
first: true,
}
}
@ -50,29 +51,23 @@ impl<I> Iterator for Combinations<I>
{
type Item = Vec<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
let mut pool_len = self.pool.len();
if self.pool.is_done() {
if pool_len == 0 || self.n > pool_len {
if self.first {
if self.pool.is_done() {
return None;
}
}
if self.first {
self.first = false;
} else if self.n == 0 {
} else if self.indices.len() == 0 {
return None;
} else {
// Scan from the end, looking for an index to increment
let mut i: usize = self.n - 1;
let mut i: usize = self.indices.len() - 1;
// Check if we need to consume more from the iterator
if self.indices[i] == pool_len - 1 && !self.pool.is_done() {
if self.pool.get_next() {
pool_len += 1;
}
if self.indices[i] == self.pool.len() - 1 {
self.pool.get_next(); // may change pool size
}
while self.indices[i] == i + pool_len - self.n {
while self.indices[i] == i + self.pool.len() - self.indices.len() {
if i > 0 {
i -= 1;
} else {
@ -83,83 +78,12 @@ impl<I> Iterator for Combinations<I>
// Increment index, and reset the ones to its right
self.indices[i] += 1;
let mut j = i + 1;
while j < self.n {
for j in i+1..self.indices.len() {
self.indices[j] = self.indices[j - 1] + 1;
j += 1;
}
}
// Create result vector based on the indices
let mut result = Vec::with_capacity(self.n);
for i in self.indices.iter() {
result.push(self.pool[*i].clone());
}
Some(result)
Some(self.indices.iter().map(|i| self.pool[*i].clone()).collect())
}
}
#[derive(Debug)]
struct LazyBuffer<I: Iterator> {
it: I,
done: bool,
buffer: Vec<I::Item>,
}
impl<I> LazyBuffer<I>
where I: Iterator
{
pub fn new(it: I) -> LazyBuffer<I> {
let mut it = it;
let mut buffer = Vec::new();
let done;
if let Some(first) = it.next() {
buffer.push(first);
done = false;
} else {
done = true;
}
LazyBuffer {
it: it,
done: done,
buffer: buffer,
}
}
pub fn len(&self) -> usize {
self.buffer.len()
}
pub fn is_done(&self) -> bool {
self.done
}
pub fn get_next(&mut self) -> bool {
if self.done {
return false;
}
let next_item = self.it.next();
match next_item {
Some(x) => {
self.buffer.push(x);
true
}
None => {
self.done = true;
false
}
}
}
}
impl<I> Index<usize> for LazyBuffer<I>
where I: Iterator,
I::Item: Sized
{
type Output = I::Item;
fn index<'b>(&'b self, _index: usize) -> &'b I::Item {
self.buffer.index(_index)
}
}

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

@ -0,0 +1,107 @@
use std::fmt;
use super::lazy_buffer::LazyBuffer;
/// An iterator to iterate through all the `n`-length combinations in an iterator, with replacement.
///
/// See [`.combinations_with_replacement()`](../trait.Itertools.html#method.combinations_with_replacement) for more information.
#[derive(Clone)]
pub struct CombinationsWithReplacement<I>
where
I: Iterator,
I::Item: Clone,
{
k: usize,
indices: Vec<usize>,
// The current known max index value. This increases as pool grows.
max_index: usize,
pool: LazyBuffer<I>,
first: bool,
}
impl<I> fmt::Debug for CombinationsWithReplacement<I>
where
I: Iterator + fmt::Debug,
I::Item: fmt::Debug + Clone,
{
debug_fmt_fields!(Combinations, k, indices, max_index, pool, first);
}
impl<I> CombinationsWithReplacement<I>
where
I: Iterator,
I::Item: Clone,
{
/// Map the current mask over the pool to get an output combination
fn current(&self) -> Vec<I::Item> {
self.indices.iter().map(|i| self.pool[*i].clone()).collect()
}
}
/// Create a new `CombinationsWithReplacement` from a clonable iterator.
pub fn combinations_with_replacement<I>(iter: I, k: usize) -> CombinationsWithReplacement<I>
where
I: Iterator,
I::Item: Clone,
{
let indices: Vec<usize> = vec![0; k];
let pool: LazyBuffer<I> = LazyBuffer::new(iter);
CombinationsWithReplacement {
k,
indices,
max_index: 0,
pool,
first: true,
}
}
impl<I> Iterator for CombinationsWithReplacement<I>
where
I: Iterator,
I::Item: Clone,
{
type Item = Vec<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
// If this is the first iteration, return early
if self.first {
// In empty edge cases, stop iterating immediately
return if self.k != 0 && !self.pool.get_next() {
None
// Otherwise, yield the initial state
} else {
self.first = false;
Some(self.current())
};
}
// Check if we need to consume more from the iterator
// This will run while we increment our first index digit
if self.pool.get_next() {
self.max_index = self.pool.len() - 1;
}
// Work out where we need to update our indices
let mut increment: Option<(usize, usize)> = None;
for (i, indices_int) in self.indices.iter().enumerate().rev() {
if indices_int < &self.max_index {
increment = Some((i, indices_int + 1));
break;
}
}
match increment {
// If we can update the indices further
Some((increment_from, increment_value)) => {
// We need to update the rightmost non-max value
// and all those to the right
for indices_index in increment_from..self.indices.len() {
self.indices[indices_index] = increment_value
}
Some(self.current())
}
// Otherwise, we're done
None => None,
}
}
}

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

@ -1,4 +1,4 @@
use Itertools;
use crate::Itertools;
/// Combine all an iterator's elements into one element by using `Extend`.
///

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

@ -52,11 +52,7 @@ pub struct ConsTuples<I, J>
impl<I, J> Clone for ConsTuples<I, J>
where I: Clone + Iterator<Item=J>,
{
fn clone(&self) -> Self {
ConsTuples {
iter: self.iter.clone(),
}
}
clone_fields!(iter);
}
/// Create an iterator that maps for example iterators of

4
third_party/rust/itertools/src/diff.rs поставляемый
Просмотреть файл

@ -5,8 +5,8 @@
//! describes the difference between two non-`Clone` iterators `I` and `J` after breaking ASAP from
//! a lock-step comparison.
use free::put_back;
use structs::PutBack;
use crate::free::put_back;
use crate::structs::PutBack;
/// A type returned by the [`diff_with`](./fn.diff_with.html) function.
///

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

@ -1,7 +1,9 @@
use EitherOrBoth::*;
use crate::EitherOrBoth::*;
use either::Either;
/// Value that either holds a single A or B, or both.
#[derive(Clone, PartialEq, Eq, Debug)]
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub enum EitherOrBoth<A, B> {
/// Both values are present.
Both(A, B),
@ -22,11 +24,35 @@ impl<A, B> EitherOrBoth<A, B> {
self.as_ref().right().is_some()
}
/// If Left, return true otherwise, return false.
/// Exclusive version of [`has_left`].
pub fn is_left(&self) -> bool {
match *self {
Left(_) => true,
_ => false,
}
}
/// If Right, return true otherwise, return false.
/// Exclusive version of [`has_right`].
pub fn is_right(&self) -> bool {
match *self {
Right(_) => true,
_ => false,
}
}
/// If Right, return true otherwise, return false.
/// Equivalent to `self.as_ref().both().is_some()`.
pub fn is_both(&self) -> bool {
self.as_ref().both().is_some()
}
/// If `Left`, or `Both`, return `Some` with the left value, otherwise, return `None`.
pub fn left(self) -> Option<A> {
match self {
Left(left) | Both(left, _) => Some(left),
_ => None
_ => None,
}
}
@ -34,7 +60,15 @@ impl<A, B> EitherOrBoth<A, B> {
pub fn right(self) -> Option<B> {
match self {
Right(right) | Both(_, right) => Some(right),
_ => None
_ => None,
}
}
/// If Both, return `Some` tuple containing left and right.
pub fn both(self) -> Option<(A, B)> {
match self {
Both(a, b) => Some((a, b)),
_ => None,
}
}
@ -55,4 +89,102 @@ impl<A, B> EitherOrBoth<A, B> {
Both(ref mut left, ref mut right) => Both(left, right),
}
}
/// Convert `EitherOrBoth<A, B>` to `EitherOrBoth<B, A>`.
pub fn flip(self) -> EitherOrBoth<B, A> {
match self {
Left(a) => Right(a),
Right(b) => Left(b),
Both(a, b) => Both(b, a),
}
}
/// Apply the function `f` on the value `a` in `Left(a)` or `Both(a, b)` variants. If it is
/// present rewrapping the result in `self`'s original variant.
pub fn map_left<F, M>(self, f: F) -> EitherOrBoth<M, B>
where
F: FnOnce(A) -> M,
{
match self {
Both(a, b) => Both(f(a), b),
Left(a) => Left(f(a)),
Right(b) => Right(b),
}
}
/// Apply the function `f` on the value `b` in `Right(b)` or `Both(a, b)` variants.
/// If it is present rewrapping the result in `self`'s original variant.
pub fn map_right<F, M>(self, f: F) -> EitherOrBoth<A, M>
where
F: FnOnce(B) -> M,
{
match self {
Left(a) => Left(a),
Right(b) => Right(f(b)),
Both(a, b) => Both(a, f(b)),
}
}
/// Apply the functions `f` and `g` on the value `a` and `b` respectively;
/// found in `Left(a)`, `Right(b)`, or `Both(a, b)` variants.
/// The Result is rewrapped `self`'s original variant.
pub fn map_any<F, L, G, R>(self, f: F, g: G) -> EitherOrBoth<L, R>
where
F: FnOnce(A) -> L,
G: FnOnce(B) -> R,
{
match self {
Left(a) => Left(f(a)),
Right(b) => Right(g(b)),
Both(a, b) => Both(f(a), g(b)),
}
}
/// Apply the function `f` on the value `b` in `Right(b)` or `Both(a, _)` variants if it is
/// present.
pub fn left_and_then<F, L>(self, f: F) -> EitherOrBoth<L, B>
where
F: FnOnce(A) -> EitherOrBoth<L, B>,
{
match self {
Left(a) | Both(a, _) => f(a),
Right(b) => Right(b),
}
}
/// Apply the function `f` on the value `a`
/// in `Left(a)` or `Both(a, _)` variants if it is present.
pub fn right_and_then<F, R>(self, f: F) -> EitherOrBoth<A, R>
where
F: FnOnce(B) -> EitherOrBoth<A, R>,
{
match self {
Left(a) => Left(a),
Right(b) | Both(_, b) => f(b),
}
}
}
impl<T> EitherOrBoth<T, T> {
/// Return either value of left, right, or the product of `f` applied where `Both` are present.
pub fn reduce<F>(self, f: F) -> T
where
F: FnOnce(T, T) -> T,
{
match self {
Left(a) => a,
Right(b) => b,
Both(a, b) => f(a, b),
}
}
}
impl<A, B> Into<Option<Either<A, B>>> for EitherOrBoth<A, B> {
fn into(self) -> Option<Either<A, B>> {
match self {
EitherOrBoth::Left(l) => Some(Either::Left(l)),
EitherOrBoth::Right(r) => Some(Either::Right(r)),
_ => None,
}
}
}

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

@ -0,0 +1,58 @@
use std::iter::ExactSizeIterator;
use crate::size_hint;
/// Iterator returned for the error case of `IterTools::exactly_one()`
/// This iterator yields exactly the same elements as the input iterator.
///
/// During the execution of exactly_one the iterator must be mutated. This wrapper
/// effectively "restores" the state of the input iterator when it's handed back.
///
/// This is very similar to PutBackN except this iterator only supports 0-2 elements and does not
/// use a `Vec`.
#[derive(Debug, Clone)]
pub struct ExactlyOneError<I>
where
I: Iterator,
{
first_two: (Option<I::Item>, Option<I::Item>),
inner: I,
}
impl<I> ExactlyOneError<I>
where
I: Iterator,
{
/// Creates a new `ExactlyOneErr` iterator.
pub(crate) fn new(first_two: (Option<I::Item>, Option<I::Item>), inner: I) -> Self {
Self { first_two, inner }
}
}
impl<I> Iterator for ExactlyOneError<I>
where
I: Iterator,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
self.first_two
.0
.take()
.or_else(|| self.first_two.1.take())
.or_else(|| self.inner.next())
}
fn size_hint(&self) -> (usize, Option<usize>) {
let mut additional_len = 0;
if self.first_two.0.is_some() {
additional_len += 1;
}
if self.first_two.1.is_some() {
additional_len += 1;
}
size_hint::add_scalar(self.inner.size_hint(), additional_len)
}
}
impl<I> ExactSizeIterator for ExactlyOneError<I> where I: ExactSizeIterator {}

17
third_party/rust/itertools/src/format.rs поставляемый
Просмотреть файл

@ -7,6 +7,7 @@ use std::cell::RefCell;
/// exhausted.
///
/// See [`.format_with()`](../trait.Itertools.html#method.format_with) for more information.
#[derive(Clone)]
pub struct FormatWith<'a, I, F> {
sep: &'a str,
/// FormatWith uses interior mutability because Display::fmt takes &self.
@ -29,7 +30,7 @@ pub struct Format<'a, I> {
pub fn new_format<'a, I, F>(iter: I, separator: &'a str, f: F) -> FormatWith<'a, I, F>
where I: Iterator,
F: FnMut(I::Item, &mut FnMut(&fmt::Display) -> fmt::Result) -> fmt::Result
F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result
{
FormatWith {
sep: separator,
@ -48,7 +49,7 @@ pub fn new_format_default<'a, I>(iter: I, separator: &'a str) -> Format<'a, I>
impl<'a, I, F> fmt::Display for FormatWith<'a, I, F>
where I: Iterator,
F: FnMut(I::Item, &mut FnMut(&fmt::Display) -> fmt::Result) -> fmt::Result
F: FnMut(I::Item, &mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (mut iter, mut format) = match self.inner.borrow_mut().take() {
@ -57,13 +58,13 @@ impl<'a, I, F> fmt::Display for FormatWith<'a, I, F>
};
if let Some(fst) = iter.next() {
try!(format(fst, &mut |disp: &fmt::Display| disp.fmt(f)));
format(fst, &mut |disp: &dyn fmt::Display| disp.fmt(f))?;
for elt in iter {
if self.sep.len() > 0 {
try!(f.write_str(self.sep));
f.write_str(self.sep)?;
}
try!(format(elt, &mut |disp: &fmt::Display| disp.fmt(f)));
format(elt, &mut |disp: &dyn fmt::Display| disp.fmt(f))?;
}
}
Ok(())
@ -82,12 +83,12 @@ impl<'a, I> Format<'a, I>
};
if let Some(fst) = iter.next() {
try!(cb(&fst, f));
cb(&fst, f)?;
for elt in iter {
if self.sep.len() > 0 {
try!(f.write_str(self.sep));
f.write_str(self.sep)?;
}
try!(cb(&elt, f));
cb(&elt, f)?;
}
}
Ok(())

16
third_party/rust/itertools/src/free.rs поставляемый
Просмотреть файл

@ -10,23 +10,23 @@ use std::iter::{self, Zip};
type VecIntoIter<T> = ::std::vec::IntoIter<T>;
#[cfg(feature = "use_std")]
use Itertools;
use crate::Itertools;
pub use adaptors::{
pub use crate::adaptors::{
interleave,
merge,
put_back,
};
#[cfg(feature = "use_std")]
pub use put_back_n_impl::put_back_n;
pub use crate::put_back_n_impl::put_back_n;
#[cfg(feature = "use_std")]
pub use multipeek_impl::multipeek;
pub use crate::multipeek_impl::multipeek;
#[cfg(feature = "use_std")]
pub use kmerge_impl::kmerge;
pub use zip_eq_impl::zip_eq;
pub use merge_join::merge_join_by;
pub use crate::kmerge_impl::kmerge;
pub use crate::zip_eq_impl::zip_eq;
pub use crate::merge_join::merge_join_by;
#[cfg(feature = "use_std")]
pub use rciter_impl::rciter;
pub use crate::rciter_impl::rciter;
/// Iterate `iterable` with a running index.
///

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

@ -30,7 +30,7 @@ impl ChunkIndex {
#[inline(always)]
fn new(size: usize) -> Self {
ChunkIndex {
size: size,
size,
index: 0,
key: 0,
}
@ -380,7 +380,7 @@ impl<'a, K, I, F> Iterator for Groups<'a, K, I, F>
let key = inner.group_key(index);
(key, Group {
parent: self.parent,
index: index,
index,
first: Some(elt),
})
})
@ -528,7 +528,7 @@ impl<'a, I> Iterator for Chunks<'a, I>
inner.step(index).map(|elt| {
Chunk {
parent: self.parent,
index: index,
index,
first: Some(elt),
}
})

10
third_party/rust/itertools/src/impl_macros.rs поставляемый
Просмотреть файл

@ -12,3 +12,13 @@ macro_rules! debug_fmt_fields {
}
}
}
macro_rules! clone_fields {
($($field:ident),*) => {
fn clone(&self) -> Self {
Self {
$($field: self.$field.clone(),)*
}
}
}
}

21
third_party/rust/itertools/src/intersperse.rs поставляемый
Просмотреть файл

@ -27,7 +27,7 @@ pub fn intersperse<I>(iter: I, elt: I::Item) -> Intersperse<I>
let mut iter = iter.fuse();
Intersperse {
peek: iter.next(),
iter: iter,
iter,
element: elt,
}
}
@ -57,4 +57,23 @@ impl<I> Iterator for Intersperse<I>
let sh = self.iter.size_hint();
size_hint::add_scalar(size_hint::add(sh, sh), has_peek)
}
fn fold<B, F>(mut self, init: B, mut f: F) -> B where
Self: Sized, F: FnMut(B, Self::Item) -> B,
{
let mut accum = init;
if let Some(x) = self.peek.take() {
accum = f(accum, x);
}
let element = &self.element;
self.iter.fold(accum,
|accum, x| {
let accum = f(accum, element.clone());
let accum = f(accum, x);
accum
})
}
}

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