From 57009caabd2a45a6efa4d36149feec39ab0a0658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 24 Mar 2017 23:00:21 -0700 Subject: [PATCH 01/19] Identify missing item category in `impl`s ```rust struct S; impl S { pub hello_method(&self) { println!("Hello"); } } fn main() { S.hello_method(); } ``` ```rust error: can't qualify macro invocation with `pub` --> file.rs:3:4 | 3 | pub hello_method(&self) { | ^^^- - expected `!` here for a macro invocation | | | did you mean to write `fn` here for a method declaration? | = help: try adjusting the macro to put `pub` inside the invocation ``` --- src/libsyntax/parse/parser.rs | 62 ++++++++++++++++----- src/test/ui/did_you_mean/issue-40006.rs | 21 +++++++ src/test/ui/did_you_mean/issue-40006.stderr | 12 ++++ 3 files changed, 80 insertions(+), 15 deletions(-) create mode 100644 src/test/ui/did_you_mean/issue-40006.rs create mode 100644 src/test/ui/did_you_mean/issue-40006.stderr diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index df4ccc94c0421..a19339f8cc1c1 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4660,25 +4660,30 @@ impl<'a> Parser<'a> { }) } - fn complain_if_pub_macro(&mut self, visa: &Visibility, span: Span) { - match *visa { - Visibility::Inherited => (), + fn complain_if_pub_macro(&mut self, vis: &Visibility, sp: Span) { + if let Err(mut err) = self.complain_if_pub_macro_diag(vis, sp) { + err.emit(); + } + } + + fn complain_if_pub_macro_diag(&mut self, vis: &Visibility, sp: Span) -> PResult<'a, ()> { + match *vis { + Visibility::Inherited => Ok(()), _ => { let is_macro_rules: bool = match self.token { token::Ident(sid) => sid.name == Symbol::intern("macro_rules"), _ => false, }; if is_macro_rules { - self.diagnostic().struct_span_err(span, "can't qualify macro_rules \ - invocation with `pub`") - .help("did you mean #[macro_export]?") - .emit(); + let mut err = self.diagnostic() + .struct_span_err(sp, "can't qualify macro_rules invocation with `pub`"); + err.help("did you mean #[macro_export]?"); + Err(err) } else { - self.diagnostic().struct_span_err(span, "can't qualify macro \ - invocation with `pub`") - .help("try adjusting the macro to put `pub` \ - inside the invocation") - .emit(); + let mut err = self.diagnostic() + .struct_span_err(sp, "can't qualify macro invocation with `pub`"); + err.help("try adjusting the macro to put `pub` inside the invocation"); + Err(err) } } } @@ -4689,14 +4694,41 @@ impl<'a> Parser<'a> { -> PResult<'a, (Ident, Vec, ast::ImplItemKind)> { // code copied from parse_macro_use_or_failure... abstraction! if self.token.is_path_start() { - // method macro. + // Method macro. let prev_span = self.prev_span; - self.complain_if_pub_macro(&vis, prev_span); + // Before complaining about trying to set a macro as `pub`, + // check if `!` comes after the path. + let err = self.complain_if_pub_macro_diag(&vis, prev_span); let lo = self.span.lo; let pth = self.parse_path(PathStyle::Mod)?; - self.expect(&token::Not)?; + let bang_err = self.expect(&token::Not); + if let Err(mut err) = err { + if let Err(mut bang_err) = bang_err { + // Given this code `pub path(`, it seems like this is not setting the + // visibility of a macro invocation, but rather a mistyped method declaration. + // Keep the macro diagnostic, but also provide a hint that `fn` might be + // missing. Don't complain about the missing `!` as a separate diagnostic, add + // label in the appropriate place as part of one unified diagnostic. + // + // x | pub path(&self) { + // | ^^^- - expected `!` here for a macro invocation + // | | + // | did you mean to write `fn` here for a method declaration? + + bang_err.cancel(); + err.span_label(self.span, &"expected `!` here for a macro invocation"); + // pub path( + // ^^ `sp` below will point to this + let sp = mk_sp(prev_span.hi, self.prev_span.lo); + err.span_label(sp, + &"did you mean to write `fn` here for a method declaration?"); + } + return Err(err); + } else if let Err(bang_err) = bang_err { + return Err(bang_err); + } // eat a matched-delimiter token tree: let (delim, tts) = self.expect_delimited_token_tree()?; diff --git a/src/test/ui/did_you_mean/issue-40006.rs b/src/test/ui/did_you_mean/issue-40006.rs new file mode 100644 index 0000000000000..cf75929bae20c --- /dev/null +++ b/src/test/ui/did_you_mean/issue-40006.rs @@ -0,0 +1,21 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct S; + +impl S { + pub hello_method(&self) { + println!("Hello"); + } +} + +fn main() { + S.hello_method(); +} diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr new file mode 100644 index 0000000000000..93a0c58f91a57 --- /dev/null +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -0,0 +1,12 @@ +error: can't qualify macro invocation with `pub` + --> $DIR/issue-40006.rs:14:5 + | +14 | pub hello_method(&self) { + | ^^^- - expected `!` here for a macro invocation + | | + | did you mean to write `fn` here for a method declaration? + | + = help: try adjusting the macro to put `pub` inside the invocation + +error: aborting due to previous error + From c963d613a2275d5c9b31cd7124dda2f2af61deb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 27 Mar 2017 17:15:16 -0700 Subject: [PATCH 02/19] Simplify error output --- src/libsyntax/parse/parser.rs | 17 ++++++----------- src/test/ui/did_you_mean/issue-40006.stderr | 10 +++------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a19339f8cc1c1..2603b3302c610 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4708,26 +4708,21 @@ impl<'a> Parser<'a> { if let Err(mut bang_err) = bang_err { // Given this code `pub path(`, it seems like this is not setting the // visibility of a macro invocation, but rather a mistyped method declaration. - // Keep the macro diagnostic, but also provide a hint that `fn` might be - // missing. Don't complain about the missing `!` as a separate diagnostic, add - // label in the appropriate place as part of one unified diagnostic. + // Create a diagnostic pointing out that `fn` is missing. // // x | pub path(&self) { - // | ^^^- - expected `!` here for a macro invocation - // | | - // | did you mean to write `fn` here for a method declaration? + // | ^ missing `fn` for method declaration + err.cancel(); bang_err.cancel(); - err.span_label(self.span, &"expected `!` here for a macro invocation"); // pub path( // ^^ `sp` below will point to this let sp = mk_sp(prev_span.hi, self.prev_span.lo); - err.span_label(sp, - &"did you mean to write `fn` here for a method declaration?"); + err = self.diagnostic() + .struct_span_err(sp, "missing `fn` for method declaration"); + err.span_label(sp, &"missing `fn`"); } return Err(err); - } else if let Err(bang_err) = bang_err { - return Err(bang_err); } // eat a matched-delimiter token tree: diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index 93a0c58f91a57..460958027ad0f 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -1,12 +1,8 @@ -error: can't qualify macro invocation with `pub` - --> $DIR/issue-40006.rs:14:5 +error: missing `fn` for method declaration + --> $DIR/issue-40006.rs:14:8 | 14 | pub hello_method(&self) { - | ^^^- - expected `!` here for a macro invocation - | | - | did you mean to write `fn` here for a method declaration? - | - = help: try adjusting the macro to put `pub` inside the invocation + | ^ missing `fn` error: aborting due to previous error From 1e3bc5ac4fcacac584a39a061e9b1cffbcb9f713 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Wed, 29 Mar 2017 23:01:34 +0300 Subject: [PATCH 03/19] Allow using Vec::::place_back for T: !Clone The place_back was likely put into block with `T: Clone` bound by mistake. --- src/libcollections/vec.rs | 46 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 56b60a3e00341..59186a2d50185 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -972,6 +972,29 @@ impl Vec { } } + /// Returns a place for insertion at the back of the `Vec`. + /// + /// Using this method with placement syntax is equivalent to [`push`](#method.push), + /// but may be more efficient. + /// + /// # Examples + /// + /// ``` + /// #![feature(collection_placement)] + /// #![feature(placement_in_syntax)] + /// + /// let mut vec = vec![1, 2]; + /// vec.place_back() <- 3; + /// vec.place_back() <- 4; + /// assert_eq!(&vec, &[1, 2, 3, 4]); + /// ``` + #[unstable(feature = "collection_placement", + reason = "placement protocol is subject to change", + issue = "30172")] + pub fn place_back(&mut self) -> PlaceBack { + PlaceBack { vec: self } + } + /// Removes the last element from a vector and returns it, or [`None`] if it /// is empty. /// @@ -1266,29 +1289,6 @@ impl Vec { pub fn extend_from_slice(&mut self, other: &[T]) { self.spec_extend(other.iter()) } - - /// Returns a place for insertion at the back of the `Vec`. - /// - /// Using this method with placement syntax is equivalent to [`push`](#method.push), - /// but may be more efficient. - /// - /// # Examples - /// - /// ``` - /// #![feature(collection_placement)] - /// #![feature(placement_in_syntax)] - /// - /// let mut vec = vec![1, 2]; - /// vec.place_back() <- 3; - /// vec.place_back() <- 4; - /// assert_eq!(&vec, &[1, 2, 3, 4]); - /// ``` - #[unstable(feature = "collection_placement", - reason = "placement protocol is subject to change", - issue = "30172")] - pub fn place_back(&mut self) -> PlaceBack { - PlaceBack { vec: self } - } } // Set the length of the vec when the `SetLenOnDrop` value goes out of scope. From 3fa28cc11eb5559b169f0d2fc7523f933e188e13 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Thu, 30 Mar 2017 16:08:13 +0200 Subject: [PATCH 04/19] Add a note about overflow for fetch_add/fetch_sub --- src/libcore/sync/atomic.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 743e3c41170a3..cde98a670367f 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -1171,6 +1171,8 @@ macro_rules! atomic_int { /// Add to the current value, returning the previous value. /// + /// This operation wraps around on overflow. + /// /// # Examples /// /// ``` @@ -1188,6 +1190,8 @@ macro_rules! atomic_int { /// Subtract from the current value, returning the previous value. /// + /// This operation wraps around on overflow. + /// /// # Examples /// /// ``` From 2946c41c05c8bfbad04a431c4a4603127630367d Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Thu, 30 Mar 2017 16:23:46 +0200 Subject: [PATCH 05/19] More consistent wording --- src/libcore/sync/atomic.rs | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index cde98a670367f..12c1287b4f65c 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -296,7 +296,7 @@ impl AtomicBool { } } - /// Stores a value into the bool, returning the old value. + /// Stores a value into the bool, returning the previous value. /// /// `swap` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. @@ -703,7 +703,7 @@ impl AtomicPtr { } } - /// Stores a value into the pointer, returning the old value. + /// Stores a value into the pointer, returning the previous value. /// /// `swap` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. @@ -1015,7 +1015,7 @@ macro_rules! atomic_int { unsafe { atomic_store(self.v.get(), val, order); } } - /// Stores a value into the atomic integer, returning the old value. + /// Stores a value into the atomic integer, returning the previous value. /// /// `swap` takes an [`Ordering`] argument which describes the memory ordering of this /// operation. @@ -1169,7 +1169,7 @@ macro_rules! atomic_int { } } - /// Add to the current value, returning the previous value. + /// Adds to the current value, returning the previous value. /// /// This operation wraps around on overflow. /// @@ -1188,7 +1188,7 @@ macro_rules! atomic_int { unsafe { atomic_add(self.v.get(), val, order) } } - /// Subtract from the current value, returning the previous value. + /// Subtracts from the current value, returning the previous value. /// /// This operation wraps around on overflow. /// @@ -1207,7 +1207,12 @@ macro_rules! atomic_int { unsafe { atomic_sub(self.v.get(), val, order) } } - /// Bitwise and with the current value, returning the previous value. + /// Bitwise "and" with the current value. + /// + /// Performs a bitwise "and" operation on the current value and the argument `val`, and + /// sets the new value to the result. + /// + /// Returns the previous value. /// /// # Examples /// @@ -1223,7 +1228,12 @@ macro_rules! atomic_int { unsafe { atomic_and(self.v.get(), val, order) } } - /// Bitwise or with the current value, returning the previous value. + /// Bitwise "or" with the current value. + /// + /// Performs a bitwise "or" operation on the current value and the argument `val`, and + /// sets the new value to the result. + /// + /// Returns the previous value. /// /// # Examples /// @@ -1239,7 +1249,12 @@ macro_rules! atomic_int { unsafe { atomic_or(self.v.get(), val, order) } } - /// Bitwise xor with the current value, returning the previous value. + /// Bitwise "xor" with the current value. + /// + /// Performs a bitwise "xor" operation on the current value and the argument `val`, and + /// sets the new value to the result. + /// + /// Returns the previous value. /// /// # Examples /// @@ -1387,7 +1402,7 @@ unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { } } -/// Returns the old value (like __sync_fetch_and_add). +/// Returns the previous value (like __sync_fetch_and_add). #[inline] unsafe fn atomic_add(dst: *mut T, val: T, order: Ordering) -> T { match order { @@ -1400,7 +1415,7 @@ unsafe fn atomic_add(dst: *mut T, val: T, order: Ordering) -> T { } } -/// Returns the old value (like __sync_fetch_and_sub). +/// Returns the previous value (like __sync_fetch_and_sub). #[inline] unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T { match order { From 09ac56d6efd41c02cbb7f8714d59bdd43f663ec8 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sun, 2 Apr 2017 16:18:39 +0300 Subject: [PATCH 06/19] mark build::cfg::start_new_block as inline(never) LLVM has a bug - PR32488 - where it fails to deduplicate allocas in some circumstances. The function `start_new_block` has allocas totalling 1216 bytes, and when LLVM inlines several copies of that function into the recursive function `expr::into`, that function's stack space usage goes into tens of kiBs, causing stack overflows. Mark `start_new_block` as inline(never) to keep it from being inlined, getting stack usage under control. Fixes #40493. Fixes #40573. --- src/librustc_mir/build/cfg.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index 71e97e4bfe0d3..c503b8c7fe06f 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -25,6 +25,9 @@ impl<'tcx> CFG<'tcx> { &mut self.basic_blocks[blk] } + // llvm.org/PR32488 makes this function use an excess of stack space. Mark + // it as #[inline(never)] to keep rustc's stack use in check. + #[inline(never)] pub fn start_new_block(&mut self) -> BasicBlock { self.basic_blocks.push(BasicBlockData::new(None)) } From 29a6a9e8d23e9dc178851f0bc49e2b46afcc8c49 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Mon, 3 Apr 2017 02:03:12 +0200 Subject: [PATCH 07/19] iter: Use underlying find/rfind for the same methods in Rev --- src/libcore/iter/mod.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 04394e0a3a876..273f9d0e6f6d3 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -358,12 +358,24 @@ impl Iterator for Rev where I: DoubleEndedIterator { fn next(&mut self) -> Option<::Item> { self.iter.next_back() } #[inline] fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + + fn find

(&mut self, predicate: P) -> Option + where P: FnMut(&Self::Item) -> bool + { + self.iter.rfind(predicate) + } } #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for Rev where I: DoubleEndedIterator { #[inline] fn next_back(&mut self) -> Option<::Item> { self.iter.next() } + + fn rfind

(&mut self, predicate: P) -> Option + where P: FnMut(&Self::Item) -> bool + { + self.iter.find(predicate) + } } #[stable(feature = "rust1", since = "1.0.0")] From 74f8ea263e119f947264f373229a8f1a940ae877 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Mon, 3 Apr 2017 02:03:12 +0200 Subject: [PATCH 08/19] iter: Simplification in rfind's provided implementation - Prefer simpler constructs instead of going through &mut I's Iterator implementation. --- src/libcore/iter/traits.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 34f14ef53f893..798dda1992813 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -467,7 +467,7 @@ pub trait DoubleEndedIterator: Iterator { Self: Sized, P: FnMut(&Self::Item) -> bool { - for x in self.by_ref().rev() { + while let Some(x) = self.next_back() { if predicate(&x) { return Some(x) } } None From 7b89bd7ccacd0908d7e22a5cf383c8cc147bc3d5 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 31 Mar 2017 13:52:46 +0100 Subject: [PATCH 09/19] Add ptr::offset_to --- src/doc/unstable-book/src/SUMMARY.md | 1 + src/doc/unstable-book/src/offset-to.md | 7 +++ src/libcollections/lib.rs | 1 + src/libcollections/vec.rs | 12 ++-- src/libcore/ptr.rs | 76 ++++++++++++++++++++++++++ src/libcore/slice/mod.rs | 7 ++- 6 files changed, 93 insertions(+), 11 deletions(-) create mode 100644 src/doc/unstable-book/src/offset-to.md diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index fe491d7f9018e..0c3b7990c93b8 100644 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@ -123,6 +123,7 @@ - [no_debug](no-debug.md) - [non_ascii_idents](non-ascii-idents.md) - [nonzero](nonzero.md) +- [offset_to](offset-to.md) - [omit_gdb_pretty_printer_section](omit-gdb-pretty-printer-section.md) - [on_unimplemented](on-unimplemented.md) - [once_poison](once-poison.md) diff --git a/src/doc/unstable-book/src/offset-to.md b/src/doc/unstable-book/src/offset-to.md new file mode 100644 index 0000000000000..376f3ff5d2199 --- /dev/null +++ b/src/doc/unstable-book/src/offset-to.md @@ -0,0 +1,7 @@ +# `offset_to` + +The tracking issue for this feature is: [#0] + +[#0]: https://github.com/rust-lang/rust/issues/0 + +------------------------ diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 72e950bc91fa9..2b345e3d0a59f 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -61,6 +61,7 @@ #![feature(unique)] #![feature(untagged_unions)] #![cfg_attr(test, feature(rand, test))] +#![feature(offset_to)] #![no_std] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 56b60a3e00341..f12380a9ea535 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -2073,14 +2073,10 @@ impl Iterator for IntoIter { #[inline] fn size_hint(&self) -> (usize, Option) { - let diff = (self.end as usize) - (self.ptr as usize); - let size = mem::size_of::(); - let exact = diff / - (if size == 0 { - 1 - } else { - size - }); + let exact = match self.ptr.offset_to(self.end) { + Some(x) => x as usize, + None => (self.end as usize).wrapping_sub(self.ptr as usize), + }; (exact, Some(exact)) } diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index d2830a6d00cec..6bcce76af04e3 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -500,6 +500,44 @@ impl *const T { intrinsics::arith_offset(self, count) } } + + /// Calculates the distance between two pointers. The returned value is in + /// units of T: the distance in bytes is divided by `mem::size_of::()`. + /// + /// If the address different between the two pointers ia not a multiple of + /// `mem::size_of::()` then the result of the division is rounded towards + /// zero. + /// + /// This function returns `None` if `T` is a zero-sized typed. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(offset_to)] + /// + /// fn main() { + /// let a = [0; 5]; + /// let ptr1: *const i32 = &a[1]; + /// let ptr2: *const i32 = &a[3]; + /// assert_eq!(ptr1.offset_to(ptr2), Some(2)); + /// assert_eq!(ptr2.offset_to(ptr1), Some(-2)); + /// assert_eq!(unsafe { ptr1.offset(2) }, ptr2); + /// assert_eq!(unsafe { ptr2.offset(-2) }, ptr1); + /// } + /// ``` + #[unstable(feature = "offset_to", issue = "0")] + #[inline] + pub fn offset_to(self, other: *const T) -> Option where T: Sized { + let size = mem::size_of::(); + if size == 0 { + None + } else { + let diff = (other as isize).wrapping_sub(self as isize); + Some(diff / size as isize) + } + } } #[lang = "mut_ptr"] @@ -653,6 +691,44 @@ impl *mut T { Some(&mut *self) } } + + /// Calculates the distance between two pointers. The returned value is in + /// units of T: the distance in bytes is divided by `mem::size_of::()`. + /// + /// If the address different between the two pointers ia not a multiple of + /// `mem::size_of::()` then the result of the division is rounded towards + /// zero. + /// + /// This function returns `None` if `T` is a zero-sized typed. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(offset_to)] + /// + /// fn main() { + /// let mut a = [0; 5]; + /// let ptr1: *mut i32 = &mut a[1]; + /// let ptr2: *mut i32 = &mut a[3]; + /// assert_eq!(ptr1.offset_to(ptr2), Some(2)); + /// assert_eq!(ptr2.offset_to(ptr1), Some(-2)); + /// assert_eq!(unsafe { ptr1.offset(2) }, ptr2); + /// assert_eq!(unsafe { ptr2.offset(-2) }, ptr1); + /// } + /// ``` + #[unstable(feature = "offset_to", issue = "0")] + #[inline] + pub fn offset_to(self, other: *const T) -> Option where T: Sized { + let size = mem::size_of::(); + if size == 0 { + None + } else { + let diff = (other as isize).wrapping_sub(self as isize); + Some(diff / size as isize) + } + } } // Equality for pointers diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index af492b3c63976..5a978ccc74153 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1502,9 +1502,10 @@ unsafe impl<'a, T> TrustedLen for IterMut<'a, T> {} // Return the arithmetic difference if `T` is zero size. #[inline(always)] fn ptrdistance(start: *const T, end: *const T) -> usize { - let diff = (end as usize).wrapping_sub(start as usize); - let size = mem::size_of::(); - diff / (if size == 0 { 1 } else { size }) + match start.offset_to(end) { + Some(x) => x as usize, + None => (end as usize).wrapping_sub(start as usize), + } } // Extension methods for raw pointers, used by the iterators From 018c5c929820af8e8b455a64a9d7d5456b01b1ed Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 4 Apr 2017 10:43:16 +0900 Subject: [PATCH 10/19] Make 'overlapping_inherent_impls' lint a hard error --- .../coherence/inherent_impls_overlap.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index 4b36072243c81..33280fb931aaf 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -11,7 +11,6 @@ use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::hir; use rustc::hir::itemlikevisit::ItemLikeVisitor; -use rustc::lint; use rustc::traits::{self, Reveal}; use rustc::ty::{self, TyCtxt}; @@ -53,12 +52,16 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> { for &item2 in &impl_items2[..] { if (name, namespace) == name_and_namespace(item2) { - let msg = format!("duplicate definitions with name `{}`", name); - let node_id = self.tcx.hir.as_local_node_id(item1).unwrap(); - self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS, - node_id, - self.tcx.span_of_impl(item1).unwrap(), - msg); + struct_span_err!(self.tcx.sess, + self.tcx.span_of_impl(item1).unwrap(), + E0592, + "duplicate definitions with name `{}`", + name) + .span_label(self.tcx.span_of_impl(item1).unwrap(), + &format!("duplicate definitions for `{}`", name)) + .span_label(self.tcx.span_of_impl(item2).unwrap(), + &format!("other definition for `{}`", name)) + .emit(); } } } From 6132fb83b45cc9c519c2fee29e497460db06ba2a Mon Sep 17 00:00:00 2001 From: Anatol Pomozov Date: Mon, 3 Apr 2017 22:41:55 -0700 Subject: [PATCH 11/19] Replace magic number with readable sig constant SIG_ERR is defined as 'pub const SIG_ERR: sighandler_t = !0 as sighandler_t;' --- src/libstd/sys/unix/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index c57751a01d7c1..854d380d128c9 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -92,7 +92,7 @@ pub fn init() { #[cfg(not(any(target_os = "nacl", target_os = "emscripten", target_os="fuchsia")))] unsafe fn reset_sigpipe() { - assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0); + assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR); } #[cfg(any(target_os = "nacl", target_os = "emscripten", target_os="fuchsia"))] unsafe fn reset_sigpipe() {} From 09f42ee3331815347767b5a821813a927758a421 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 4 Apr 2017 21:00:56 +0900 Subject: [PATCH 12/19] Move 'overlapping_inherent_impls' test to ui --- .../overlapping_inherent_impls.rs} | 6 ++-- .../overlapping_inherent_impls.stderr | 29 +++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) rename src/test/{compile-fail/inherent-overlap.rs => ui/codemap_tests/overlapping_inherent_impls.rs} (84%) create mode 100644 src/test/ui/codemap_tests/overlapping_inherent_impls.stderr diff --git a/src/test/compile-fail/inherent-overlap.rs b/src/test/ui/codemap_tests/overlapping_inherent_impls.rs similarity index 84% rename from src/test/compile-fail/inherent-overlap.rs rename to src/test/ui/codemap_tests/overlapping_inherent_impls.rs index 18e77ddfd2c5b..a626b63b31ba0 100644 --- a/src/test/compile-fail/inherent-overlap.rs +++ b/src/test/ui/codemap_tests/overlapping_inherent_impls.rs @@ -16,7 +16,7 @@ struct Foo; impl Foo { - fn id() {} //~ ERROR duplicate definitions + fn id() {} } impl Foo { @@ -26,7 +26,7 @@ impl Foo { struct Bar(T); impl Bar { - fn bar(&self) {} //~ ERROR duplicate definitions + fn bar(&self) {} } impl Bar { @@ -36,7 +36,7 @@ impl Bar { struct Baz(T); impl Baz { - fn baz(&self) {} //~ ERROR duplicate definitions + fn baz(&self) {} } impl Baz> { diff --git a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr new file mode 100644 index 0000000000000..de8a24cf33f44 --- /dev/null +++ b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr @@ -0,0 +1,29 @@ +error[E0592]: duplicate definitions with name `id` + --> $DIR/overlapping_inherent_impls.rs:19:5 + | +19 | fn id() {} + | ^^^^^^^^^^ duplicate definitions for `id` +... +23 | fn id() {} + | ---------- other definition for `id` + +error[E0592]: duplicate definitions with name `bar` + --> $DIR/overlapping_inherent_impls.rs:29:5 + | +29 | fn bar(&self) {} + | ^^^^^^^^^^^^^^^^ duplicate definitions for `bar` +... +33 | fn bar(&self) {} + | ---------------- other definition for `bar` + +error[E0592]: duplicate definitions with name `baz` + --> $DIR/overlapping_inherent_impls.rs:39:5 + | +39 | fn baz(&self) {} + | ^^^^^^^^^^^^^^^^ duplicate definitions for `baz` +... +43 | fn baz(&self) {} + | ---------------- other definition for `baz` + +error: aborting due to 3 previous errors + From db60b0b374ef4999e3c960a7230b18bcddf82ea0 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 4 Apr 2017 21:08:56 +0900 Subject: [PATCH 13/19] Move 'coherence-overlapping-inherent-impl-trait' test to ui --- .../coherence-overlapping-inherent-impl-trait.rs | 2 +- .../coherence-overlapping-inherent-impl-trait.stderr | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) rename src/test/{compile-fail => ui/codemap_tests}/coherence-overlapping-inherent-impl-trait.rs (88%) create mode 100644 src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr diff --git a/src/test/compile-fail/coherence-overlapping-inherent-impl-trait.rs b/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.rs similarity index 88% rename from src/test/compile-fail/coherence-overlapping-inherent-impl-trait.rs rename to src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.rs index 158d3606104a9..a72ad0351e33b 100644 --- a/src/test/compile-fail/coherence-overlapping-inherent-impl-trait.rs +++ b/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.rs @@ -11,6 +11,6 @@ #![allow(dead_code)] trait C {} -impl C { fn f() {} } //~ ERROR duplicate definitions with name `f` +impl C { fn f() {} } impl C { fn f() {} } fn main() { } diff --git a/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr b/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr new file mode 100644 index 0000000000000..7f1ab929c6fc2 --- /dev/null +++ b/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr @@ -0,0 +1,10 @@ +error[E0592]: duplicate definitions with name `f` + --> $DIR/coherence-overlapping-inherent-impl-trait.rs:14:10 + | +14 | impl C { fn f() {} } + | ^^^^^^^^^ duplicate definitions for `f` +15 | impl C { fn f() {} } + | --------- other definition for `f` + +error: aborting due to previous error + From 2e3f0d845113995c26a9d59dd69146975a692516 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Mon, 3 Apr 2017 15:25:30 -0500 Subject: [PATCH 14/19] add [T]::rsplit() and rsplit_mut() #41020 --- src/doc/unstable-book/src/SUMMARY.md | 1 + src/doc/unstable-book/src/slice-rsplit.md | 10 ++ src/libcollections/lib.rs | 1 + src/libcollections/slice.rs | 68 +++++++++++ src/libcore/slice/mod.rs | 139 ++++++++++++++++++++++ 5 files changed, 219 insertions(+) create mode 100644 src/doc/unstable-book/src/slice-rsplit.md diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index 292f5a1ec816a..52f33244695ea 100644 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@ -171,6 +171,7 @@ - [slice_concat_ext](slice-concat-ext.md) - [slice_get_slice](slice-get-slice.md) - [slice_patterns](slice-patterns.md) +- [slice_rsplit](slice-rsplit.md) - [sort_internals](sort-internals.md) - [sort_unstable](sort-unstable.md) - [specialization](specialization.md) diff --git a/src/doc/unstable-book/src/slice-rsplit.md b/src/doc/unstable-book/src/slice-rsplit.md new file mode 100644 index 0000000000000..8c2954f7294e0 --- /dev/null +++ b/src/doc/unstable-book/src/slice-rsplit.md @@ -0,0 +1,10 @@ +# `slice_rsplit` + +The tracking issue for this feature is: [#41020] + +[#41020]: https://github.com/rust-lang/rust/issues/41020 + +------------------------ + +The `slice_rsplit` feature enables two methods on slices: +`slice.rsplit(predicate)` and `slice.rsplit_mut(predicate)`. diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 00448b6abb2cf..ff020f53e0e77 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -52,6 +52,7 @@ #![feature(shared)] #![feature(slice_get_slice)] #![feature(slice_patterns)] +#![feature(slice_rsplit)] #![cfg_attr(not(test), feature(sort_unstable))] #![feature(specialization)] #![feature(staged_api)] diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 6f8843c2374bc..6cff315a6ccd9 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -115,6 +115,8 @@ pub use core::slice::{Iter, IterMut}; pub use core::slice::{SplitMut, ChunksMut, Split}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut}; +#[unstable(feature = "slice_rsplit", issue = "41020")] +pub use core::slice::{RSplit, RSplitMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{from_raw_parts, from_raw_parts_mut}; #[unstable(feature = "slice_get_slice", issue = "35729")] @@ -779,6 +781,72 @@ impl [T] { core_slice::SliceExt::split_mut(self, pred) } + /// Returns an iterator over subslices separated by elements that match + /// `pred`, starting at the end of the slice and working backwards. + /// The matched element is not contained in the subslices. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_rsplit)] + /// + /// let slice = [11, 22, 33, 0, 44, 55]; + /// let mut iter = slice.rsplit(|num| *num == 0); + /// + /// assert_eq!(iter.next().unwrap(), &[44, 55]); + /// assert_eq!(iter.next().unwrap(), &[11, 22, 33]); + /// assert_eq!(iter.next(), None); + /// ``` + /// + /// As with `split()`, if the first or last element is matched, an empty + /// slice will be the first (or last) item returned by the iterator. + /// + /// ``` + /// #![feature(slice_rsplit)] + /// + /// let v = &[0, 1, 1, 2, 3, 5, 8]; + /// let mut it = v.rsplit(|n| *n % 2 == 0); + /// assert_eq!(it.next().unwrap(), &[]); + /// assert_eq!(it.next().unwrap(), &[3, 5]); + /// assert_eq!(it.next().unwrap(), &[1, 1]); + /// assert_eq!(it.next().unwrap(), &[]); + /// assert_eq!(it.next(), None); + /// ``` + #[unstable(feature = "slice_rsplit", issue = "41020")] + #[inline] + pub fn rsplit(&self, pred: F) -> RSplit + where F: FnMut(&T) -> bool + { + core_slice::SliceExt::rsplit(self, pred) + } + + /// Returns an iterator over mutable subslices separated by elements that + /// match `pred`, starting at the end of the slice and working + /// backwards. The matched element is not contained in the subslices. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_rsplit)] + /// + /// let mut v = [100, 400, 300, 200, 600, 500]; + /// + /// let mut count = 0; + /// for group in v.rsplit_mut(|num| *num % 3 == 0) { + /// count += 1; + /// group[0] = count; + /// } + /// assert_eq!(v, [3, 400, 300, 2, 600, 1]); + /// ``` + /// + #[unstable(feature = "slice_rsplit", issue = "41020")] + #[inline] + pub fn rsplit_mut(&mut self, pred: F) -> RSplitMut + where F: FnMut(&T) -> bool + { + core_slice::SliceExt::rsplit_mut(self, pred) + } + /// Returns an iterator over subslices separated by elements that match /// `pred`, limited to returning at most `n` items. The matched element is /// not contained in the subslices. diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 45667bb42993d..1e0037755c1ab 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -81,6 +81,10 @@ pub trait SliceExt { fn split

(&self, pred: P) -> Split where P: FnMut(&Self::Item) -> bool; + #[unstable(feature = "slice_rsplit", issue = "41020")] + fn rsplit

(&self, pred: P) -> RSplit + where P: FnMut(&Self::Item) -> bool; + #[stable(feature = "core", since = "1.6.0")] fn splitn

(&self, n: usize, pred: P) -> SplitN where P: FnMut(&Self::Item) -> bool; @@ -159,6 +163,10 @@ pub trait SliceExt { fn split_mut

(&mut self, pred: P) -> SplitMut where P: FnMut(&Self::Item) -> bool; + #[unstable(feature = "slice_rsplit", issue = "41020")] + fn rsplit_mut

(&mut self, pred: P) -> RSplitMut + where P: FnMut(&Self::Item) -> bool; + #[stable(feature = "core", since = "1.6.0")] fn splitn_mut

(&mut self, n: usize, pred: P) -> SplitNMut where P: FnMut(&Self::Item) -> bool; @@ -293,6 +301,13 @@ impl SliceExt for [T] { } } + #[inline] + fn rsplit

(&self, pred: P) -> RSplit + where P: FnMut(&T) -> bool + { + RSplit { inner: self.split(pred) } + } + #[inline] fn splitn

(&self, n: usize, pred: P) -> SplitN where P: FnMut(&T) -> bool @@ -475,6 +490,13 @@ impl SliceExt for [T] { SplitMut { v: self, pred: pred, finished: false } } + #[inline] + fn rsplit_mut

(&mut self, pred: P) -> RSplitMut + where P: FnMut(&T) -> bool + { + RSplitMut { inner: self.split_mut(pred) } + } + #[inline] fn splitn_mut

(&mut self, n: usize, pred: P) -> SplitNMut where P: FnMut(&T) -> bool @@ -1735,6 +1757,123 @@ impl<'a, T, P> DoubleEndedIterator for SplitMut<'a, T, P> where #[unstable(feature = "fused", issue = "35602")] impl<'a, T, P> FusedIterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {} +/// An iterator over subslices separated by elements that match a predicate +/// function, starting from the end of the slice. +/// +/// This struct is created by the [`rsplit`] method on [slices]. +/// +/// [`rsplit`]: ../../std/primitive.slice.html#method.rsplit +/// [slices]: ../../std/primitive.slice.html +#[unstable(feature = "slice_rsplit", issue = "41020")] +#[derive(Clone)] // Is this correct, or does it incorrectly require `T: Clone`? +pub struct RSplit<'a, T:'a, P> where P: FnMut(&T) -> bool { + inner: Split<'a, T, P> +} + +#[unstable(feature = "slice_rsplit", issue = "41020")] +impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplit<'a, T, P> where P: FnMut(&T) -> bool { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("RSplit") + .field("v", &self.inner.v) + .field("finished", &self.inner.finished) + .finish() + } +} + +#[unstable(feature = "slice_rsplit", issue = "41020")] +impl<'a, T, P> Iterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool { + type Item = &'a [T]; + + #[inline] + fn next(&mut self) -> Option<&'a [T]> { + self.inner.next_back() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } +} + +#[unstable(feature = "slice_rsplit", issue = "41020")] +impl<'a, T, P> DoubleEndedIterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool { + #[inline] + fn next_back(&mut self) -> Option<&'a [T]> { + self.inner.next() + } +} + +#[unstable(feature = "slice_rsplit", issue = "41020")] +impl<'a, T, P> SplitIter for RSplit<'a, T, P> where P: FnMut(&T) -> bool { + #[inline] + fn finish(&mut self) -> Option<&'a [T]> { + self.inner.finish() + } +} + +//#[unstable(feature = "fused", issue = "35602")] +#[unstable(feature = "slice_rsplit", issue = "41020")] +impl<'a, T, P> FusedIterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {} + +/// An iterator over the subslices of the vector which are separated +/// by elements that match `pred`, starting from the end of the slice. +/// +/// This struct is created by the [`rsplit_mut`] method on [slices]. +/// +/// [`rsplit_mut`]: ../../std/primitive.slice.html#method.rsplit_mut +/// [slices]: ../../std/primitive.slice.html +#[unstable(feature = "slice_rsplit", issue = "41020")] +pub struct RSplitMut<'a, T:'a, P> where P: FnMut(&T) -> bool { + inner: SplitMut<'a, T, P> +} + +#[unstable(feature = "slice_rsplit", issue = "41020")] +impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("RSplitMut") + .field("v", &self.inner.v) + .field("finished", &self.inner.finished) + .finish() + } +} + +#[unstable(feature = "slice_rsplit", issue = "41020")] +impl<'a, T, P> SplitIter for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool { + #[inline] + fn finish(&mut self) -> Option<&'a mut [T]> { + self.inner.finish() + } +} + +#[unstable(feature = "slice_rsplit", issue = "41020")] +impl<'a, T, P> Iterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool { + type Item = &'a mut [T]; + + #[inline] + fn next(&mut self) -> Option<&'a mut [T]> { + self.inner.next_back() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } +} + +#[unstable(feature = "slice_rsplit", issue = "41020")] +impl<'a, T, P> DoubleEndedIterator for RSplitMut<'a, T, P> where + P: FnMut(&T) -> bool, +{ + #[inline] + fn next_back(&mut self) -> Option<&'a mut [T]> { + self.inner.next() + } +} + +//#[unstable(feature = "fused", issue = "35602")] +#[unstable(feature = "slice_rsplit", issue = "41020")] +impl<'a, T, P> FusedIterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {} + /// An private iterator over subslices separated by elements that /// match a predicate function, splitting at most a fixed number of /// times. From a45fedfa384fba4f972c2af26adb9cf7a0522725 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Mon, 3 Apr 2017 15:27:42 -0500 Subject: [PATCH 15/19] simplify implementation of [T]::splitn and friends #41020 --- src/libcore/slice/mod.rs | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 1e0037755c1ab..6e3f11ec7fbae 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -315,8 +315,7 @@ impl SliceExt for [T] { SplitN { inner: GenericSplitN { iter: self.split(pred), - count: n, - invert: false + count: n } } } @@ -327,9 +326,8 @@ impl SliceExt for [T] { { RSplitN { inner: GenericSplitN { - iter: self.split(pred), - count: n, - invert: true + iter: self.rsplit(pred), + count: n } } } @@ -504,8 +502,7 @@ impl SliceExt for [T] { SplitNMut { inner: GenericSplitN { iter: self.split_mut(pred), - count: n, - invert: false + count: n } } } @@ -516,9 +513,8 @@ impl SliceExt for [T] { { RSplitNMut { inner: GenericSplitN { - iter: self.split_mut(pred), - count: n, - invert: true + iter: self.rsplit_mut(pred), + count: n } } } @@ -1881,7 +1877,6 @@ impl<'a, T, P> FusedIterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool struct GenericSplitN { iter: I, count: usize, - invert: bool } impl> Iterator for GenericSplitN { @@ -1892,10 +1887,7 @@ impl> Iterator for GenericSplitN { match self.count { 0 => None, 1 => { self.count -= 1; self.iter.finish() } - _ => { - self.count -= 1; - if self.invert {self.iter.next_back()} else {self.iter.next()} - } + _ => { self.count -= 1; self.iter.next() } } } @@ -1937,7 +1929,7 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for SplitN<'a, T, P> where P: FnMut(& /// [slices]: ../../std/primitive.slice.html #[stable(feature = "rust1", since = "1.0.0")] pub struct RSplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool { - inner: GenericSplitN> + inner: GenericSplitN> } #[stable(feature = "core_impl_debug", since = "1.9.0")] @@ -1980,7 +1972,7 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for SplitNMut<'a, T, P> where P: FnMu /// [slices]: ../../std/primitive.slice.html #[stable(feature = "rust1", since = "1.0.0")] pub struct RSplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool { - inner: GenericSplitN> + inner: GenericSplitN> } #[stable(feature = "core_impl_debug", since = "1.9.0")] From f07ebd609796226e672737e502525fbbf5e27940 Mon Sep 17 00:00:00 2001 From: arthurprs Date: Wed, 15 Mar 2017 23:26:27 +0100 Subject: [PATCH 16/19] Simplify HashMap Bucket interface * Store capacity_mask instead of capacity * Move bucket index into RawBucket * Bucket index is now always within [0..table_capacity) * Clone RawTable using RawBucket * Simplify iterators by moving logic into RawBuckets * Make retain aware of the number of elements --- src/libstd/collections/hash/map.rs | 32 ++- src/libstd/collections/hash/table.rs | 324 +++++++++++++-------------- 2 files changed, 165 insertions(+), 191 deletions(-) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 5733217008146..a06299eaefe0a 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -472,7 +472,7 @@ fn pop_internal(starting_bucket: FullBucketMut) } // Now we've done all our shifting. Return the value we grabbed earlier. - (retkey, retval, gap.into_bucket().into_table()) + (retkey, retval, gap.into_table()) } /// Perform robin hood bucket stealing at the given `bucket`. You must @@ -485,14 +485,14 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>, mut key: K, mut val: V) -> FullBucketMut<'a, K, V> { - let start_index = bucket.index(); let size = bucket.table().size(); - // Save the *starting point*. - let mut bucket = bucket.stash(); + let raw_capacity = bucket.table().capacity(); // There can be at most `size - dib` buckets to displace, because // in the worst case, there are `size` elements and we already are // `displacement` buckets away from the initial one. - let idx_end = start_index + size - bucket.displacement(); + let idx_end = (bucket.index() + size - bucket.displacement()) % raw_capacity; + // Save the *starting point*. + let mut bucket = bucket.stash(); loop { let (old_hash, old_key, old_val) = bucket.replace(hash, key, val); @@ -568,11 +568,8 @@ impl HashMap // The caller should ensure that invariants by Robin Hood Hashing hold // and that there's space in the underlying table. fn insert_hashed_ordered(&mut self, hash: SafeHash, k: K, v: V) { - let raw_cap = self.raw_capacity(); let mut buckets = Bucket::new(&mut self.table, hash); - // note that buckets.index() keeps increasing - // even if the pointer wraps back to the first bucket. - let limit_bucket = buckets.index() + raw_cap; + let start_index = buckets.index(); loop { // We don't need to compare hashes for value swap. @@ -585,7 +582,7 @@ impl HashMap Full(b) => b.into_bucket(), }; buckets.next(); - debug_assert!(buckets.index() < limit_bucket); + debug_assert!(buckets.index() != start_index); } } } @@ -1244,24 +1241,25 @@ impl HashMap pub fn retain(&mut self, mut f: F) where F: FnMut(&K, &mut V) -> bool { - if self.table.capacity() == 0 || self.table.size() == 0 { + if self.table.size() == 0 { return; } + let mut elems_left = self.table.size(); let mut bucket = Bucket::head_bucket(&mut self.table); bucket.prev(); - let tail = bucket.index(); - loop { + let start_index = bucket.index(); + while elems_left != 0 { bucket = match bucket.peek() { Full(mut full) => { + elems_left -= 1; let should_remove = { let (k, v) = full.read_mut(); !f(k, v) }; if should_remove { - let prev_idx = full.index(); let prev_raw = full.raw(); let (_, _, t) = pop_internal(full); - Bucket::new_from(prev_raw, prev_idx, t) + Bucket::new_from(prev_raw, t) } else { full.into_bucket() } @@ -1271,9 +1269,7 @@ impl HashMap } }; bucket.prev(); // reverse iteration - if bucket.index() == tail { - break; - } + debug_assert!(elems_left == 0 || bucket.index() != start_index); } } } diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index da5fb1a47333e..9623706548b32 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -113,7 +113,7 @@ impl TaggedHashUintPtr { /// when the RawTable is created and is accessible with the `tag` and `set_tag` /// functions. pub struct RawTable { - capacity: usize, + capacity_mask: usize, size: usize, hashes: TaggedHashUintPtr, @@ -125,10 +125,13 @@ pub struct RawTable { unsafe impl Send for RawTable {} unsafe impl Sync for RawTable {} +// An unsafe view of a RawTable bucket +// Valid indexes are within [0..table_capacity) pub struct RawBucket { - hash: *mut HashUint, + hash_start: *mut HashUint, // We use *const to ensure covariance with respect to K and V - pair: *const (K, V), + pair_start: *const (K, V), + idx: usize, _marker: marker::PhantomData<(K, V)>, } @@ -141,7 +144,6 @@ impl Clone for RawBucket { pub struct Bucket { raw: RawBucket, - idx: usize, table: M, } @@ -154,13 +156,11 @@ impl Clone for Bucket { pub struct EmptyBucket { raw: RawBucket, - idx: usize, table: M, } pub struct FullBucket { raw: RawBucket, - idx: usize, table: M, } @@ -232,13 +232,17 @@ fn can_alias_safehash_as_hash() { assert_eq!(size_of::(), size_of::()) } +// RawBucket methods are unsafe as it's possible to +// make a RawBucket point to invalid memory using safe code. impl RawBucket { - unsafe fn offset(self, count: isize) -> RawBucket { - RawBucket { - hash: self.hash.offset(count), - pair: self.pair.offset(count), - _marker: marker::PhantomData, - } + unsafe fn hash(&self) -> *mut HashUint { + self.hash_start.offset(self.idx as isize) + } + unsafe fn pair(&self) -> *mut (K, V) { + self.pair_start.offset(self.idx as isize) as *mut (K, V) + } + unsafe fn hash_pair(&self) -> (*mut HashUint, *mut (K, V)) { + (self.hash(), self.pair()) } } @@ -258,7 +262,7 @@ impl FullBucket { } /// Get the raw index. pub fn index(&self) -> usize { - self.idx + self.raw.idx } /// Get the raw bucket. pub fn raw(&self) -> RawBucket { @@ -280,7 +284,7 @@ impl EmptyBucket { impl Bucket { /// Get the raw index. pub fn index(&self) -> usize { - self.idx + self.raw.idx } /// get the table. pub fn into_table(self) -> M { @@ -331,12 +335,11 @@ impl>> Bucket { Bucket::at_index(table, hash.inspect() as usize) } - pub fn new_from(r: RawBucket, i: usize, t: M) + pub fn new_from(r: RawBucket, t: M) -> Bucket { Bucket { raw: r, - idx: i, table: t, } } @@ -346,18 +349,16 @@ impl>> Bucket { // This is an uncommon case though, so avoid it in release builds. debug_assert!(table.capacity() > 0, "Table should have capacity at this point"); - let ib_index = ib_index & (table.capacity() - 1); + let ib_index = ib_index & table.capacity_mask; Bucket { - raw: unsafe { table.first_bucket_raw().offset(ib_index as isize) }, - idx: ib_index, + raw: table.raw_bucket_at(ib_index), table: table, } } pub fn first(table: M) -> Bucket { Bucket { - raw: table.first_bucket_raw(), - idx: 0, + raw: table.raw_bucket_at(0), table: table, } } @@ -401,48 +402,30 @@ impl>> Bucket { /// the appropriate types to call most of the other functions in /// this module. pub fn peek(self) -> BucketState { - match unsafe { *self.raw.hash } { + match unsafe { *self.raw.hash() } { EMPTY_BUCKET => { Empty(EmptyBucket { raw: self.raw, - idx: self.idx, table: self.table, }) } _ => { Full(FullBucket { raw: self.raw, - idx: self.idx, table: self.table, }) } } } - /// Modifies the bucket pointer in place to make it point to the next slot. + /// Modifies the bucket in place to make it point to the next slot. pub fn next(&mut self) { - self.idx += 1; - let range = self.table.capacity(); - // This code is branchless thanks to a conditional move. - let dist = if self.idx & (range - 1) == 0 { - 1 - range as isize - } else { - 1 - }; - unsafe { - self.raw = self.raw.offset(dist); - } + self.raw.idx = self.raw.idx.wrapping_add(1) & self.table.capacity_mask; } - /// Modifies the bucket pointer in place to make it point to the previous slot. + /// Modifies the bucket in place to make it point to the previous slot. pub fn prev(&mut self) { - let range = self.table.capacity(); - let new_idx = self.idx.wrapping_sub(1) & (range - 1); - let dist = (new_idx as isize).wrapping_sub(self.idx as isize); - self.idx = new_idx; - unsafe { - self.raw = self.raw.offset(dist); - } + self.raw.idx = self.raw.idx.wrapping_sub(1) & self.table.capacity_mask; } } @@ -458,7 +441,6 @@ impl>> EmptyBucket { pub fn into_bucket(self) -> Bucket { Bucket { raw: self.raw, - idx: self.idx, table: self.table, } } @@ -466,7 +448,6 @@ impl>> EmptyBucket { pub fn gap_peek(self) -> Result, Bucket> { let gap = EmptyBucket { raw: self.raw, - idx: self.idx, table: (), }; @@ -494,15 +475,14 @@ impl EmptyBucket /// Use `make_hash` to construct a `SafeHash` to pass to this function. pub fn put(mut self, hash: SafeHash, key: K, value: V) -> FullBucket { unsafe { - *self.raw.hash = hash.inspect(); - ptr::write(self.raw.pair as *mut (K, V), (key, value)); + *self.raw.hash() = hash.inspect(); + ptr::write(self.raw.pair(), (key, value)); self.table.borrow_table_mut().size += 1; } FullBucket { raw: self.raw, - idx: self.idx, table: self.table, } } @@ -510,15 +490,14 @@ impl EmptyBucket /// Puts given key, remain value uninitialized. /// It is only used for inplacement insertion. pub unsafe fn put_key(mut self, hash: SafeHash, key: K) -> FullBucket { - *self.raw.hash = hash.inspect(); - let pair_mut = self.raw.pair as *mut (K, V); - ptr::write(&mut (*pair_mut).0, key); + *self.raw.hash() = hash.inspect(); + let pair_ptr = self.raw.pair(); + ptr::write(&mut (*pair_ptr).0, key); self.table.borrow_table_mut().size += 1; FullBucket { raw: self.raw, - idx: self.idx, table: self.table, } } @@ -536,7 +515,6 @@ impl>> FullBucket { pub fn into_bucket(self) -> Bucket { Bucket { raw: self.raw, - idx: self.idx, table: self.table, } } @@ -546,7 +524,6 @@ impl>> FullBucket { pub fn stash(self) -> FullBucket { FullBucket { raw: self.raw, - idx: self.idx, table: self, } } @@ -560,17 +537,20 @@ impl>> FullBucket { // Calculates the distance one has to travel when going from // `hash mod capacity` onwards to `idx mod capacity`, wrapping around // if the destination is not reached before the end of the table. - (self.idx.wrapping_sub(self.hash().inspect() as usize)) & (self.table.capacity() - 1) + (self.raw.idx.wrapping_sub(self.hash().inspect() as usize)) & self.table.capacity_mask } #[inline] pub fn hash(&self) -> SafeHash { - unsafe { SafeHash { hash: *self.raw.hash } } + unsafe { SafeHash { hash: *self.raw.hash() } } } /// Gets references to the key and value at a given index. pub fn read(&self) -> (&K, &V) { - unsafe { (&(*self.raw.pair).0, &(*self.raw.pair).1) } + unsafe { + let pair_ptr = self.raw.pair(); + (&(*pair_ptr).0, &(*pair_ptr).1) + } } } @@ -586,11 +566,10 @@ impl<'t, K, V> FullBucket> { self.table.size -= 1; unsafe { - *self.raw.hash = EMPTY_BUCKET; - let (k, v) = ptr::read(self.raw.pair); + *self.raw.hash() = EMPTY_BUCKET; + let (k, v) = ptr::read(self.raw.pair()); (EmptyBucket { raw: self.raw, - idx: self.idx, table: self.table, }, k, @@ -604,9 +583,9 @@ impl<'t, K, V> FullBucket> { pub unsafe fn remove_key(&mut self) { self.table.size -= 1; - *self.raw.hash = EMPTY_BUCKET; - let pair_mut = self.raw.pair as *mut (K, V); - ptr::drop_in_place(&mut (*pair_mut).0); // only drop key + *self.raw.hash() = EMPTY_BUCKET; + let pair_ptr = self.raw.pair(); + ptr::drop_in_place(&mut (*pair_ptr).0); // only drop key } } @@ -617,8 +596,8 @@ impl FullBucket { pub fn replace(&mut self, h: SafeHash, k: K, v: V) -> (SafeHash, K, V) { unsafe { - let old_hash = ptr::replace(self.raw.hash as *mut SafeHash, h); - let (old_key, old_val) = ptr::replace(self.raw.pair as *mut (K, V), (k, v)); + let old_hash = ptr::replace(self.raw.hash() as *mut SafeHash, h); + let (old_key, old_val) = ptr::replace(self.raw.pair(), (k, v)); (old_hash, old_key, old_val) } @@ -630,8 +609,10 @@ impl FullBucket { /// Gets mutable references to the key and value at a given index. pub fn read_mut(&mut self) -> (&mut K, &mut V) { - let pair_mut = self.raw.pair as *mut (K, V); - unsafe { (&mut (*pair_mut).0, &mut (*pair_mut).1) } + unsafe { + let pair_ptr = self.raw.pair(); + (&mut (*pair_ptr).0, &mut (*pair_ptr).1) + } } } @@ -644,7 +625,10 @@ impl<'t, K, V, M> FullBucket /// in exchange for this, the returned references have a longer lifetime /// than the references returned by `read()`. pub fn into_refs(self) -> (&'t K, &'t V) { - unsafe { (&(*self.raw.pair).0, &(*self.raw.pair).1) } + unsafe { + let pair_ptr = self.raw.pair(); + (&(*pair_ptr).0, &(*pair_ptr).1) + } } } @@ -654,8 +638,10 @@ impl<'t, K, V, M> FullBucket /// This works similarly to `into_refs`, exchanging a bucket state /// for mutable references into the table. pub fn into_mut_refs(self) -> (&'t mut K, &'t mut V) { - let pair_mut = self.raw.pair as *mut (K, V); - unsafe { (&mut (*pair_mut).0, &mut (*pair_mut).1) } + unsafe { + let pair_ptr = self.raw.pair(); + (&mut (*pair_ptr).0, &mut (*pair_ptr).1) + } } } @@ -667,22 +653,23 @@ impl GapThenFull &self.full } - pub fn into_bucket(self) -> Bucket { - self.full.into_bucket() + pub fn into_table(self) -> M { + self.full.into_table() } pub fn shift(mut self) -> Result, Bucket> { unsafe { - *self.gap.raw.hash = mem::replace(&mut *self.full.raw.hash, EMPTY_BUCKET); - ptr::copy_nonoverlapping(self.full.raw.pair, self.gap.raw.pair as *mut (K, V), 1); + let (gap_hash, gap_pair) = self.gap.raw.hash_pair(); + let (full_hash, full_pair) = self.full.raw.hash_pair(); + *gap_hash = mem::replace(&mut *full_hash, EMPTY_BUCKET); + ptr::copy_nonoverlapping(full_pair, gap_pair, 1); } - let FullBucket { raw: prev_raw, idx: prev_idx, .. } = self.full; + let FullBucket { raw: prev_raw, .. } = self.full; match self.full.next().peek() { Full(bucket) => { self.gap.raw = prev_raw; - self.gap.idx = prev_idx; self.full = bucket; @@ -761,7 +748,7 @@ impl RawTable { if capacity == 0 { return RawTable { size: 0, - capacity: 0, + capacity_mask: capacity.wrapping_sub(1), hashes: TaggedHashUintPtr::new(EMPTY as *mut HashUint), marker: marker::PhantomData, }; @@ -801,25 +788,27 @@ impl RawTable { let hashes = buffer.offset(hash_offset as isize) as *mut HashUint; RawTable { - capacity: capacity, + capacity_mask: capacity.wrapping_sub(1), size: 0, hashes: TaggedHashUintPtr::new(hashes), marker: marker::PhantomData, } } - fn first_bucket_raw(&self) -> RawBucket { - let hashes_size = self.capacity * size_of::(); - let pairs_size = self.capacity * size_of::<(K, V)>(); + fn raw_bucket_at(&self, index: usize) -> RawBucket { + let hashes_size = self.capacity() * size_of::(); + let pairs_size = self.capacity() * size_of::<(K, V)>(); - let buffer = self.hashes.ptr() as *mut u8; let (pairs_offset, _, oflo) = calculate_offsets(hashes_size, pairs_size, align_of::<(K, V)>()); debug_assert!(!oflo, "capacity overflow"); + + let buffer = self.hashes.ptr() as *mut u8; unsafe { RawBucket { - hash: self.hashes.ptr(), - pair: buffer.offset(pairs_offset as isize) as *const _, + hash_start: buffer as *mut HashUint, + pair_start: buffer.offset(pairs_offset as isize) as *const (K, V), + idx: index, _marker: marker::PhantomData, } } @@ -837,7 +826,7 @@ impl RawTable { /// The hashtable's capacity, similar to a vector's. pub fn capacity(&self) -> usize { - self.capacity + self.capacity_mask.wrapping_add(1) } /// The number of elements ever `put` in the hashtable, minus the number @@ -848,8 +837,8 @@ impl RawTable { fn raw_buckets(&self) -> RawBuckets { RawBuckets { - raw: self.first_bucket_raw(), - hashes_end: unsafe { self.hashes.ptr().offset(self.capacity as isize) }, + raw: self.raw_bucket_at(0), + elems_left: self.size, marker: marker::PhantomData, } } @@ -857,25 +846,23 @@ impl RawTable { pub fn iter(&self) -> Iter { Iter { iter: self.raw_buckets(), - elems_left: self.size(), } } pub fn iter_mut(&mut self) -> IterMut { IterMut { iter: self.raw_buckets(), - elems_left: self.size(), _marker: marker::PhantomData, } } pub fn into_iter(self) -> IntoIter { - let RawBuckets { raw, hashes_end, .. } = self.raw_buckets(); + let RawBuckets { raw, elems_left, .. } = self.raw_buckets(); // Replace the marker regardless of lifetime bounds on parameters. IntoIter { iter: RawBuckets { raw: raw, - hashes_end: hashes_end, + elems_left: elems_left, marker: marker::PhantomData, }, table: self, @@ -883,12 +870,12 @@ impl RawTable { } pub fn drain(&mut self) -> Drain { - let RawBuckets { raw, hashes_end, .. } = self.raw_buckets(); + let RawBuckets { raw, elems_left, .. } = self.raw_buckets(); // Replace the marker regardless of lifetime bounds on parameters. Drain { iter: RawBuckets { raw: raw, - hashes_end: hashes_end, + elems_left: elems_left, marker: marker::PhantomData, }, table: unsafe { Shared::new(self) }, @@ -900,18 +887,16 @@ impl RawTable { /// state and should only be used for dropping the table's remaining /// entries. It's used in the implementation of Drop. unsafe fn rev_drop_buckets(&mut self) { - let first_raw = self.first_bucket_raw(); - let mut raw = first_raw.offset(self.capacity as isize); + // initialize the raw bucket past the end of the table + let mut raw = self.raw_bucket_at(self.capacity()); let mut elems_left = self.size; while elems_left != 0 { - debug_assert!(raw.hash != first_raw.hash); + raw.idx -= 1; - raw = raw.offset(-1); - - if *raw.hash != EMPTY_BUCKET { + if *raw.hash() != EMPTY_BUCKET { elems_left -= 1; - ptr::drop_in_place(raw.pair as *mut (K, V)); + ptr::drop_in_place(raw.pair()); } } } @@ -931,7 +916,7 @@ impl RawTable { /// this interface is safe, it's not used outside this module. struct RawBuckets<'a, K, V> { raw: RawBucket, - hashes_end: *mut HashUint, + elems_left: usize, // Strictly speaking, this should be &'a (K,V), but that would // require that K:'a, and we often use RawBuckets<'static...> for @@ -946,7 +931,7 @@ impl<'a, K, V> Clone for RawBuckets<'a, K, V> { fn clone(&self) -> RawBuckets<'a, K, V> { RawBuckets { raw: self.raw, - hashes_end: self.hashes_end, + elems_left: self.elems_left, marker: marker::PhantomData, } } @@ -957,25 +942,36 @@ impl<'a, K, V> Iterator for RawBuckets<'a, K, V> { type Item = RawBucket; fn next(&mut self) -> Option> { - while self.raw.hash != self.hashes_end { + if self.elems_left == 0 { + return None; + } + + loop { unsafe { - // We are swapping out the pointer to a bucket and replacing - // it with the pointer to the next one. - let prev = ptr::replace(&mut self.raw, self.raw.offset(1)); - if *prev.hash != EMPTY_BUCKET { - return Some(prev); + let item = self.raw; + self.raw.idx += 1; + if *item.hash() != EMPTY_BUCKET { + self.elems_left -= 1; + return Some(item); } } } + } + + fn size_hint(&self) -> (usize, Option) { + (self.elems_left, Some(self.elems_left)) + } +} - None +impl<'a, K, V> ExactSizeIterator for RawBuckets<'a, K, V> { + fn len(&self) -> usize { + self.elems_left } } /// Iterator over shared references to entries in a table. pub struct Iter<'a, K: 'a, V: 'a> { iter: RawBuckets<'a, K, V>, - elems_left: usize, } unsafe impl<'a, K: Sync, V: Sync> Sync for Iter<'a, K, V> {} @@ -986,16 +982,13 @@ impl<'a, K, V> Clone for Iter<'a, K, V> { fn clone(&self) -> Iter<'a, K, V> { Iter { iter: self.iter.clone(), - elems_left: self.elems_left, } } } - /// Iterator over mutable references to entries in a table. pub struct IterMut<'a, K: 'a, V: 'a> { iter: RawBuckets<'a, K, V>, - elems_left: usize, // To ensure invariance with respect to V _marker: marker::PhantomData<&'a mut V>, } @@ -1009,7 +1002,6 @@ impl<'a, K: 'a, V: 'a> IterMut<'a, K, V> { pub fn iter(&self) -> Iter { Iter { iter: self.iter.clone(), - elems_left: self.elems_left, } } } @@ -1027,7 +1019,6 @@ impl IntoIter { pub fn iter(&self) -> Iter { Iter { iter: self.iter.clone(), - elems_left: self.table.size, } } } @@ -1044,11 +1035,8 @@ unsafe impl<'a, K: Send, V: Send> Send for Drain<'a, K, V> {} impl<'a, K, V> Drain<'a, K, V> { pub fn iter(&self) -> Iter { - unsafe { - Iter { - iter: self.iter.clone(), - elems_left: (**self.table).size, - } + Iter { + iter: self.iter.clone(), } } } @@ -1057,19 +1045,20 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> { type Item = (&'a K, &'a V); fn next(&mut self) -> Option<(&'a K, &'a V)> { - self.iter.next().map(|bucket| { - self.elems_left -= 1; - unsafe { (&(*bucket.pair).0, &(*bucket.pair).1) } + self.iter.next().map(|raw| unsafe { + let pair_ptr = raw.pair(); + (&(*pair_ptr).0, &(*pair_ptr).1) }) } fn size_hint(&self) -> (usize, Option) { - (self.elems_left, Some(self.elems_left)) + self.iter.size_hint() } } + impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> { fn len(&self) -> usize { - self.elems_left + self.iter.len() } } @@ -1077,20 +1066,20 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> { type Item = (&'a K, &'a mut V); fn next(&mut self) -> Option<(&'a K, &'a mut V)> { - self.iter.next().map(|bucket| { - self.elems_left -= 1; - let pair_mut = bucket.pair as *mut (K, V); - unsafe { (&(*pair_mut).0, &mut (*pair_mut).1) } + self.iter.next().map(|raw| unsafe { + let pair_ptr = raw.pair(); + (&(*pair_ptr).0, &mut (*pair_ptr).1) }) } fn size_hint(&self) -> (usize, Option) { - (self.elems_left, Some(self.elems_left)) + self.iter.size_hint() } } + impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> { fn len(&self) -> usize { - self.elems_left + self.iter.len() } } @@ -1098,23 +1087,23 @@ impl Iterator for IntoIter { type Item = (SafeHash, K, V); fn next(&mut self) -> Option<(SafeHash, K, V)> { - self.iter.next().map(|bucket| { + self.iter.next().map(|raw| { self.table.size -= 1; unsafe { - let (k, v) = ptr::read(bucket.pair); - (SafeHash { hash: *bucket.hash }, k, v) + let (k, v) = ptr::read(raw.pair()); + (SafeHash { hash: *raw.hash() }, k, v) } }) } fn size_hint(&self) -> (usize, Option) { - let size = self.table.size(); - (size, Some(size)) + self.iter.size_hint() } } + impl ExactSizeIterator for IntoIter { fn len(&self) -> usize { - self.table.size() + self.iter().len() } } @@ -1123,23 +1112,21 @@ impl<'a, K, V> Iterator for Drain<'a, K, V> { #[inline] fn next(&mut self) -> Option<(SafeHash, K, V)> { - self.iter.next().map(|bucket| { - unsafe { - (*self.table.as_mut_ptr()).size -= 1; - let (k, v) = ptr::read(bucket.pair); - (SafeHash { hash: ptr::replace(bucket.hash, EMPTY_BUCKET) }, k, v) - } + self.iter.next().map(|raw| unsafe { + (*self.table.as_mut_ptr()).size -= 1; + let (k, v) = ptr::read(raw.pair()); + (SafeHash { hash: ptr::replace(&mut *raw.hash(), EMPTY_BUCKET) }, k, v) }) } fn size_hint(&self) -> (usize, Option) { - let size = unsafe { (**self.table).size() }; - (size, Some(size)) + self.iter.size_hint() } } + impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> { fn len(&self) -> usize { - unsafe { (**self.table).size() } + self.iter.len() } } @@ -1152,30 +1139,21 @@ impl<'a, K: 'a, V: 'a> Drop for Drain<'a, K, V> { impl Clone for RawTable { fn clone(&self) -> RawTable { unsafe { - let mut new_ht = RawTable::new_uninitialized(self.capacity()); - - { - let cap = self.capacity(); - let mut new_buckets = Bucket::first(&mut new_ht); - let mut buckets = Bucket::first(self); - while buckets.index() != cap { - match buckets.peek() { - Full(full) => { - let (h, k, v) = { - let (k, v) = full.read(); - (full.hash(), k.clone(), v.clone()) - }; - *new_buckets.raw.hash = h.inspect(); - ptr::write(new_buckets.raw.pair as *mut (K, V), (k, v)); - } - Empty(..) => { - *new_buckets.raw.hash = EMPTY_BUCKET; - } - } - new_buckets.next(); - buckets.next(); + let cap = self.capacity(); + let mut new_ht = RawTable::new_uninitialized(cap); + + let mut new_buckets = new_ht.raw_bucket_at(0); + let mut buckets = self.raw_bucket_at(0); + while buckets.idx < cap { + *new_buckets.hash() = *buckets.hash(); + if *new_buckets.hash() != EMPTY_BUCKET { + let pair_ptr = buckets.pair(); + let kv = ((*pair_ptr).0.clone(), (*pair_ptr).1.clone()); + ptr::write(new_buckets.pair(), kv); } - }; + buckets.idx += 1; + new_buckets.idx += 1; + } new_ht.size = self.size(); @@ -1186,7 +1164,7 @@ impl Clone for RawTable { unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable { fn drop(&mut self) { - if self.capacity == 0 { + if self.capacity() == 0 { return; } @@ -1202,8 +1180,8 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable { } } - let hashes_size = self.capacity * size_of::(); - let pairs_size = self.capacity * size_of::<(K, V)>(); + let hashes_size = self.capacity() * size_of::(); + let pairs_size = self.capacity() * size_of::<(K, V)>(); let (align, _, size, oflo) = calculate_allocation(hashes_size, align_of::(), pairs_size, From 56902fbe71b9b0a9b327972412fca085a8770e61 Mon Sep 17 00:00:00 2001 From: GitLab Date: Mon, 13 Mar 2017 14:44:54 -0300 Subject: [PATCH 17/19] Fixes other targets rustlibs installation When the user select more than one target to generate rustlibs for, rustbuild will only install the host one. This patch fixes it, more info in https://github.com/rust-lang/rust/issues/39235#issuecomment-285878858 --- src/bootstrap/install.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 249f241a151bb..25082e3a9d095 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -49,12 +49,17 @@ pub fn install(build: &Build, stage: u32, host: &str) { install_sh(&build, "docs", "rust-docs", stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir); } + + for target in build.config.target.iter() { + install_sh(&build, "std", "rust-std", stage, target, &prefix, + &docdir, &libdir, &mandir, &empty_dir); + } + if build.config.rust_save_analysis { install_sh(&build, "analysis", "rust-analysis", stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir); } - install_sh(&build, "std", "rust-std", stage, host, &prefix, - &docdir, &libdir, &mandir, &empty_dir); + install_sh(&build, "rustc", "rustc", stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir); t!(fs::remove_dir_all(&empty_dir)); From 1f70247446914a8b58bd088f32bcca792d30d75f Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Wed, 5 Apr 2017 07:45:44 +0100 Subject: [PATCH 18/19] Add tracking issue for offset_to --- src/doc/unstable-book/src/offset-to.md | 4 ++-- src/libcore/ptr.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/unstable-book/src/offset-to.md b/src/doc/unstable-book/src/offset-to.md index 376f3ff5d2199..03d990eb4ae97 100644 --- a/src/doc/unstable-book/src/offset-to.md +++ b/src/doc/unstable-book/src/offset-to.md @@ -1,7 +1,7 @@ # `offset_to` -The tracking issue for this feature is: [#0] +The tracking issue for this feature is: [#41079] -[#0]: https://github.com/rust-lang/rust/issues/0 +[#41079]: https://github.com/rust-lang/rust/issues/41079 ------------------------ diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 6bcce76af04e3..04480fc5d31da 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -527,7 +527,7 @@ impl *const T { /// assert_eq!(unsafe { ptr2.offset(-2) }, ptr1); /// } /// ``` - #[unstable(feature = "offset_to", issue = "0")] + #[unstable(feature = "offset_to", issue = "41079")] #[inline] pub fn offset_to(self, other: *const T) -> Option where T: Sized { let size = mem::size_of::(); @@ -718,7 +718,7 @@ impl *mut T { /// assert_eq!(unsafe { ptr2.offset(-2) }, ptr1); /// } /// ``` - #[unstable(feature = "offset_to", issue = "0")] + #[unstable(feature = "offset_to", issue = "41079")] #[inline] pub fn offset_to(self, other: *const T) -> Option where T: Sized { let size = mem::size_of::(); From 44bcd261a7fa2a4ad873a77b67ac88b0cf09f111 Mon Sep 17 00:00:00 2001 From: Kang Seonghoon Date: Wed, 22 Mar 2017 03:27:06 +0900 Subject: [PATCH 19/19] Reduce a table used for `Debug` impl of `str`. This commit shrinks the size of the aforementioned table from 2,102 bytes to 1,197 bytes. This is achieved by an observation that most u16 entries are common in its upper byte. Specifically: - SINGLETONS now uses two tables, one for (upper byte, lower count) and another for a series of lower bytes. For each upper byte given number of lower bytes are read and compared. - NORMAL now uses a variable length format for the count of "true" codepoints and "false" codepoints (one byte with MSB unset, or two big-endian bytes with the first MSB set). The code size and relative performance roughly remains same as this commit tries to optimize for both. The new table and algorithm has been verified for the equivalence to older ones. --- src/etc/char_private.py | 132 +++- src/libcore/char_private.rs | 1238 +++++++++++++---------------------- 2 files changed, 565 insertions(+), 805 deletions(-) diff --git a/src/etc/char_private.py b/src/etc/char_private.py index 9d15f98e06709..75ab3f1a17be4 100644 --- a/src/etc/char_private.py +++ b/src/etc/char_private.py @@ -76,6 +76,66 @@ def get_codepoints(f): for c in range(prev_codepoint + 1, NUM_CODEPOINTS): yield Codepoint(c, None) +def compress_singletons(singletons): + uppers = [] # (upper, # items in lowers) + lowers = [] + + for i in singletons: + upper = i >> 8 + lower = i & 0xff + if len(uppers) == 0 or uppers[-1][0] != upper: + uppers.append((upper, 1)) + else: + upper, count = uppers[-1] + uppers[-1] = upper, count + 1 + lowers.append(lower) + + return uppers, lowers + +def compress_normal(normal): + # lengths 0x00..0x7f are encoded as 00, 01, ..., 7e, 7f + # lengths 0x80..0x7fff are encoded as 80 80, 80 81, ..., ff fe, ff ff + compressed = [] # [truelen, (truelenaux), falselen, (falselenaux)] + + prev_start = 0 + for start, count in normal: + truelen = start - prev_start + falselen = count + prev_start = start + count + + assert truelen < 0x8000 and falselen < 0x8000 + entry = [] + if truelen > 0x7f: + entry.append(0x80 | (truelen >> 8)) + entry.append(truelen & 0xff) + else: + entry.append(truelen & 0x7f) + if falselen > 0x7f: + entry.append(0x80 | (falselen >> 8)) + entry.append(falselen & 0xff) + else: + entry.append(falselen & 0x7f) + + compressed.append(entry) + + return compressed + +def print_singletons(uppers, lowers, uppersname, lowersname): + print("const {}: &'static [(u8, u8)] = &[".format(uppersname)) + for u, c in uppers: + print(" ({:#04x}, {}),".format(u, c)) + print("];") + print("const {}: &'static [u8] = &[".format(lowersname)) + for i in range(0, len(lowers), 8): + print(" {}".format(" ".join("{:#04x},".format(l) for l in lowers[i:i+8]))) + print("];") + +def print_normal(normal, normalname): + print("const {}: &'static [u8] = &[".format(normalname)) + for v in normal: + print(" {}".format(" ".join("{:#04x},".format(i) for i in v))) + print("];") + def main(): file = get_file("http://www.unicode.org/Public/UNIDATA/UnicodeData.txt") @@ -111,6 +171,11 @@ def main(): else: normal0.append((a, b - a)) + singletons0u, singletons0l = compress_singletons(singletons0) + singletons1u, singletons1l = compress_singletons(singletons1) + normal0 = compress_normal(normal0) + normal1 = compress_normal(normal1) + print("""\ // Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at @@ -125,38 +190,49 @@ def main(): // NOTE: The following code was generated by "src/etc/char_private.py", // do not edit directly! -use slice::SliceExt; - -fn check(x: u16, singletons: &[u16], normal: &[u16]) -> bool { - for &s in singletons { - if x == s { - return false; - } else if x < s { +fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8], + normal: &[u8]) -> bool { + let xupper = (x >> 8) as u8; + let mut lowerstart = 0; + for &(upper, lowercount) in singletonuppers { + let lowerend = lowerstart + lowercount as usize; + if xupper == upper { + for &lower in &singletonlowers[lowerstart..lowerend] { + if lower == x as u8 { + return false; + } + } + } else if xupper < upper { break; } + lowerstart = lowerend; } - for w in normal.chunks(2) { - let start = w[0]; - let len = w[1]; - let difference = (x as i32) - (start as i32); - if 0 <= difference { - if difference < len as i32 { - return false; - } + + let mut x = x as i32; + let mut normal = normal.iter().cloned(); + let mut current = true; + while let Some(v) = normal.next() { + let len = if v & 0x80 != 0 { + ((v & 0x7f) as i32) << 8 | normal.next().unwrap() as i32 } else { + v as i32 + }; + x -= len; + if x < 0 { break; } + current = !current; } - true + current } pub fn is_printable(x: char) -> bool { let x = x as u32; let lower = x as u16; if x < 0x10000 { - check(lower, SINGLETONS0, NORMAL0) + check(lower, SINGLETONS0U, SINGLETONS0L, NORMAL0) } else if x < 0x20000 { - check(lower, SINGLETONS1, NORMAL1) + check(lower, SINGLETONS1U, SINGLETONS1L, NORMAL1) } else {\ """) for a, b in extra: @@ -169,22 +245,10 @@ def main(): }\ """) print() - print("const SINGLETONS0: &'static [u16] = &[") - for s in singletons0: - print(" 0x{:x},".format(s)) - print("];") - print("const SINGLETONS1: &'static [u16] = &[") - for s in singletons1: - print(" 0x{:x},".format(s)) - print("];") - print("const NORMAL0: &'static [u16] = &[") - for a, b in normal0: - print(" 0x{:x}, 0x{:x},".format(a, b)) - print("];") - print("const NORMAL1: &'static [u16] = &[") - for a, b in normal1: - print(" 0x{:x}, 0x{:x},".format(a, b)) - print("];") + print_singletons(singletons0u, singletons0l, 'SINGLETONS0U', 'SINGLETONS0L') + print_singletons(singletons1u, singletons1l, 'SINGLETONS1U', 'SINGLETONS1L') + print_normal(normal0, 'NORMAL0') + print_normal(normal1, 'NORMAL1') if __name__ == '__main__': main() diff --git a/src/libcore/char_private.rs b/src/libcore/char_private.rs index ddc473592a260..2c0f449b27601 100644 --- a/src/libcore/char_private.rs +++ b/src/libcore/char_private.rs @@ -11,38 +11,49 @@ // NOTE: The following code was generated by "src/etc/char_private.py", // do not edit directly! -use slice::SliceExt; - -fn check(x: u16, singletons: &[u16], normal: &[u16]) -> bool { - for &s in singletons { - if x == s { - return false; - } else if x < s { +fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8], + normal: &[u8]) -> bool { + let xupper = (x >> 8) as u8; + let mut lowerstart = 0; + for &(upper, lowercount) in singletonuppers { + let lowerend = lowerstart + lowercount as usize; + if xupper == upper { + for &lower in &singletonlowers[lowerstart..lowerend] { + if lower == x as u8 { + return false; + } + } + } else if xupper < upper { break; } + lowerstart = lowerend; } - for w in normal.chunks(2) { - let start = w[0]; - let len = w[1]; - let difference = (x as i32) - (start as i32); - if 0 <= difference { - if difference < len as i32 { - return false; - } + + let mut x = x as i32; + let mut normal = normal.iter().cloned(); + let mut current = true; + while let Some(v) = normal.next() { + let len = if v & 0x80 != 0 { + ((v & 0x7f) as i32) << 8 | normal.next().unwrap() as i32 } else { + v as i32 + }; + x -= len; + if x < 0 { break; } + current = !current; } - true + current } pub fn is_printable(x: char) -> bool { let x = x as u32; let lower = x as u16; if x < 0x10000 { - check(lower, SINGLETONS0, NORMAL0) + check(lower, SINGLETONS0U, SINGLETONS0L, NORMAL0) } else if x < 0x20000 { - check(lower, SINGLETONS1, NORMAL1) + check(lower, SINGLETONS1U, SINGLETONS1L, NORMAL1) } else { if 0x2a6d7 <= x && x < 0x2a700 { return false; @@ -66,761 +77,446 @@ pub fn is_printable(x: char) -> bool { } } -const SINGLETONS0: &'static [u16] = &[ - 0xad, - 0x378, - 0x379, - 0x38b, - 0x38d, - 0x3a2, - 0x530, - 0x557, - 0x558, - 0x560, - 0x588, - 0x58b, - 0x58c, - 0x590, - 0x61c, - 0x61d, - 0x6dd, - 0x70e, - 0x70f, - 0x74b, - 0x74c, - 0x82e, - 0x82f, - 0x83f, - 0x85c, - 0x85d, - 0x8b5, - 0x8e2, - 0x984, - 0x98d, - 0x98e, - 0x991, - 0x992, - 0x9a9, - 0x9b1, - 0x9ba, - 0x9bb, - 0x9c5, - 0x9c6, - 0x9c9, - 0x9ca, - 0x9de, - 0x9e4, - 0x9e5, - 0xa04, - 0xa11, - 0xa12, - 0xa29, - 0xa31, - 0xa34, - 0xa37, - 0xa3a, - 0xa3b, - 0xa3d, - 0xa49, - 0xa4a, - 0xa5d, - 0xa84, - 0xa8e, - 0xa92, - 0xaa9, - 0xab1, - 0xab4, - 0xaba, - 0xabb, - 0xac6, - 0xaca, - 0xace, - 0xacf, - 0xae4, - 0xae5, - 0xb04, - 0xb0d, - 0xb0e, - 0xb11, - 0xb12, - 0xb29, - 0xb31, - 0xb34, - 0xb3a, - 0xb3b, - 0xb45, - 0xb46, - 0xb49, - 0xb4a, - 0xb5e, - 0xb64, - 0xb65, - 0xb84, - 0xb91, - 0xb9b, - 0xb9d, - 0xbc9, - 0xbce, - 0xbcf, - 0xc04, - 0xc0d, - 0xc11, - 0xc29, - 0xc45, - 0xc49, - 0xc57, - 0xc64, - 0xc65, - 0xc84, - 0xc8d, - 0xc91, - 0xca9, - 0xcb4, - 0xcba, - 0xcbb, - 0xcc5, - 0xcc9, - 0xcdf, - 0xce4, - 0xce5, - 0xcf0, - 0xd04, - 0xd0d, - 0xd11, - 0xd3b, - 0xd3c, - 0xd45, - 0xd49, - 0xd64, - 0xd65, - 0xd80, - 0xd81, - 0xd84, - 0xdb2, - 0xdbc, - 0xdbe, - 0xdbf, - 0xdd5, - 0xdd7, - 0xdf0, - 0xdf1, - 0xe83, - 0xe85, - 0xe86, - 0xe89, - 0xe8b, - 0xe8c, - 0xe98, - 0xea0, - 0xea4, - 0xea6, - 0xea8, - 0xea9, - 0xeac, - 0xeba, - 0xebe, - 0xebf, - 0xec5, - 0xec7, - 0xece, - 0xecf, - 0xeda, - 0xedb, - 0xf48, - 0xf98, - 0xfbd, - 0xfcd, - 0x10c6, - 0x10ce, - 0x10cf, - 0x1249, - 0x124e, - 0x124f, - 0x1257, - 0x1259, - 0x125e, - 0x125f, - 0x1289, - 0x128e, - 0x128f, - 0x12b1, - 0x12b6, - 0x12b7, - 0x12bf, - 0x12c1, - 0x12c6, - 0x12c7, - 0x12d7, - 0x1311, - 0x1316, - 0x1317, - 0x135b, - 0x135c, - 0x13f6, - 0x13f7, - 0x13fe, - 0x13ff, - 0x1680, - 0x170d, - 0x176d, - 0x1771, - 0x17de, - 0x17df, - 0x180e, - 0x180f, - 0x191f, - 0x196e, - 0x196f, - 0x1a1c, - 0x1a1d, - 0x1a5f, - 0x1a7d, - 0x1a7e, - 0x1aae, - 0x1aaf, - 0x1cf7, - 0x1f16, - 0x1f17, - 0x1f1e, - 0x1f1f, - 0x1f46, - 0x1f47, - 0x1f4e, - 0x1f4f, - 0x1f58, - 0x1f5a, - 0x1f5c, - 0x1f5e, - 0x1f7e, - 0x1f7f, - 0x1fb5, - 0x1fc5, - 0x1fd4, - 0x1fd5, - 0x1fdc, - 0x1ff0, - 0x1ff1, - 0x1ff5, - 0x2072, - 0x2073, - 0x208f, - 0x23ff, - 0x2b74, - 0x2b75, - 0x2b96, - 0x2b97, - 0x2bc9, - 0x2c2f, - 0x2c5f, - 0x2d26, - 0x2d2e, - 0x2d2f, - 0x2da7, - 0x2daf, - 0x2db7, - 0x2dbf, - 0x2dc7, - 0x2dcf, - 0x2dd7, - 0x2ddf, - 0x2e9a, - 0x3040, - 0x3097, - 0x3098, - 0x318f, - 0x321f, - 0x32ff, - 0xa7af, - 0xa8fe, - 0xa8ff, - 0xa9ce, - 0xa9ff, - 0xaa4e, - 0xaa4f, - 0xaa5a, - 0xaa5b, - 0xab07, - 0xab08, - 0xab0f, - 0xab10, - 0xab27, - 0xab2f, - 0xabee, - 0xabef, - 0xfa6e, - 0xfa6f, - 0xfb37, - 0xfb3d, - 0xfb3f, - 0xfb42, - 0xfb45, - 0xfd90, - 0xfd91, - 0xfdfe, - 0xfdff, - 0xfe53, - 0xfe67, - 0xfe75, - 0xffc8, - 0xffc9, - 0xffd0, - 0xffd1, - 0xffd8, - 0xffd9, - 0xffe7, - 0xfffe, - 0xffff, +const SINGLETONS0U: &'static [(u8, u8)] = &[ + (0x00, 1), + (0x03, 5), + (0x05, 8), + (0x06, 3), + (0x07, 4), + (0x08, 7), + (0x09, 16), + (0x0a, 27), + (0x0b, 24), + (0x0c, 22), + (0x0d, 20), + (0x0e, 22), + (0x0f, 4), + (0x10, 3), + (0x12, 18), + (0x13, 9), + (0x16, 1), + (0x17, 5), + (0x18, 2), + (0x19, 3), + (0x1a, 7), + (0x1c, 1), + (0x1f, 22), + (0x20, 3), + (0x23, 1), + (0x2b, 5), + (0x2c, 2), + (0x2d, 11), + (0x2e, 1), + (0x30, 3), + (0x31, 1), + (0x32, 2), + (0xa7, 1), + (0xa8, 2), + (0xa9, 2), + (0xaa, 4), + (0xab, 8), + (0xfa, 2), + (0xfb, 5), + (0xfd, 4), + (0xfe, 3), + (0xff, 9), ]; -const SINGLETONS1: &'static [u16] = &[ - 0xc, - 0x27, - 0x3b, - 0x3e, - 0x4e, - 0x4f, - 0x18f, - 0x39e, - 0x49e, - 0x49f, - 0x806, - 0x807, - 0x809, - 0x836, - 0x83d, - 0x83e, - 0x856, - 0x8f3, - 0x9d0, - 0x9d1, - 0xa04, - 0xa14, - 0xa18, - 0xb56, - 0xb57, - 0x10bd, - 0x1135, - 0x11ce, - 0x11cf, - 0x11e0, - 0x1212, - 0x1287, - 0x1289, - 0x128e, - 0x129e, - 0x1304, - 0x130d, - 0x130e, - 0x1311, - 0x1312, - 0x1329, - 0x1331, - 0x1334, - 0x133a, - 0x133b, - 0x1345, - 0x1346, - 0x1349, - 0x134a, - 0x134e, - 0x134f, - 0x1364, - 0x1365, - 0x145a, - 0x145c, - 0x15b6, - 0x15b7, - 0x1c09, - 0x1c37, - 0x1c90, - 0x1c91, - 0x1ca8, - 0x246f, - 0x6a5f, - 0x6aee, - 0x6aef, - 0x6b5a, - 0x6b62, - 0xbc9a, - 0xbc9b, - 0xd127, - 0xd128, - 0xd455, - 0xd49d, - 0xd4a0, - 0xd4a1, - 0xd4a3, - 0xd4a4, - 0xd4a7, - 0xd4a8, - 0xd4ad, - 0xd4ba, - 0xd4bc, - 0xd4c4, - 0xd506, - 0xd50b, - 0xd50c, - 0xd515, - 0xd51d, - 0xd53a, - 0xd53f, - 0xd545, - 0xd551, - 0xd6a6, - 0xd6a7, - 0xd7cc, - 0xd7cd, - 0xdaa0, - 0xe007, - 0xe019, - 0xe01a, - 0xe022, - 0xe025, - 0xe8c5, - 0xe8c6, - 0xee04, - 0xee20, - 0xee23, - 0xee25, - 0xee26, - 0xee28, - 0xee33, - 0xee38, - 0xee3a, - 0xee48, - 0xee4a, - 0xee4c, - 0xee50, - 0xee53, - 0xee55, - 0xee56, - 0xee58, - 0xee5a, - 0xee5c, - 0xee5e, - 0xee60, - 0xee63, - 0xee65, - 0xee66, - 0xee6b, - 0xee73, - 0xee78, - 0xee7d, - 0xee7f, - 0xee8a, - 0xeea4, - 0xeeaa, - 0xf0af, - 0xf0b0, - 0xf0c0, - 0xf0d0, - 0xf12f, - 0xf91f, - 0xf931, - 0xf932, - 0xf93f, +const SINGLETONS0L: &'static [u8] = &[ + 0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57, + 0x58, 0x60, 0x88, 0x8b, 0x8c, 0x90, 0x1c, 0x1d, + 0xdd, 0x0e, 0x0f, 0x4b, 0x4c, 0x2e, 0x2f, 0x3f, + 0x5c, 0x5d, 0xb5, 0xe2, 0x84, 0x8d, 0x8e, 0x91, + 0x92, 0xa9, 0xb1, 0xba, 0xbb, 0xc5, 0xc6, 0xc9, + 0xca, 0xde, 0xe4, 0xe5, 0x04, 0x11, 0x12, 0x29, + 0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, 0x4a, + 0x5d, 0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, 0xba, + 0xbb, 0xc6, 0xca, 0xce, 0xcf, 0xe4, 0xe5, 0x04, + 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a, + 0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, 0x64, 0x65, + 0x84, 0x91, 0x9b, 0x9d, 0xc9, 0xce, 0xcf, 0x04, + 0x0d, 0x11, 0x29, 0x45, 0x49, 0x57, 0x64, 0x65, + 0x84, 0x8d, 0x91, 0xa9, 0xb4, 0xba, 0xbb, 0xc5, + 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x04, 0x0d, 0x11, + 0x3b, 0x3c, 0x45, 0x49, 0x64, 0x65, 0x80, 0x81, + 0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5, 0xd7, 0xf0, + 0xf1, 0x83, 0x85, 0x86, 0x89, 0x8b, 0x8c, 0x98, + 0xa0, 0xa4, 0xa6, 0xa8, 0xa9, 0xac, 0xba, 0xbe, + 0xbf, 0xc5, 0xc7, 0xce, 0xcf, 0xda, 0xdb, 0x48, + 0x98, 0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49, 0x4e, + 0x4f, 0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, 0x8f, + 0xb1, 0xb6, 0xb7, 0xbf, 0xc1, 0xc6, 0xc7, 0xd7, + 0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7, 0xfe, + 0xff, 0x80, 0x0d, 0x6d, 0x71, 0xde, 0xdf, 0x0e, + 0x0f, 0x1f, 0x6e, 0x6f, 0x1c, 0x1d, 0x5f, 0x7d, + 0x7e, 0xae, 0xaf, 0xf7, 0x16, 0x17, 0x1e, 0x1f, + 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e, + 0x7e, 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0, + 0xf1, 0xf5, 0x72, 0x73, 0x8f, 0xff, 0x74, 0x75, + 0x96, 0x97, 0xc9, 0x2f, 0x5f, 0x26, 0x2e, 0x2f, + 0xa7, 0xaf, 0xb7, 0xbf, 0xc7, 0xcf, 0xd7, 0xdf, + 0x9a, 0x40, 0x97, 0x98, 0x8f, 0x1f, 0xff, 0xaf, + 0xfe, 0xff, 0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b, + 0x07, 0x08, 0x0f, 0x10, 0x27, 0x2f, 0xee, 0xef, + 0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45, 0x90, + 0x91, 0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9, + 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, 0xfe, 0xff, ]; -const NORMAL0: &'static [u16] = &[ - 0x0, 0x20, - 0x7f, 0x22, - 0x380, 0x4, - 0x5c8, 0x8, - 0x5eb, 0x5, - 0x5f5, 0x11, - 0x7b2, 0xe, - 0x7fb, 0x5, - 0x85f, 0x41, - 0x8be, 0x16, - 0x9b3, 0x3, - 0x9cf, 0x8, - 0x9d8, 0x4, - 0x9fc, 0x5, - 0xa0b, 0x4, - 0xa43, 0x4, - 0xa4e, 0x3, - 0xa52, 0x7, - 0xa5f, 0x7, - 0xa76, 0xb, - 0xad1, 0xf, - 0xaf2, 0x7, - 0xafa, 0x7, - 0xb4e, 0x8, - 0xb58, 0x4, - 0xb78, 0xa, - 0xb8b, 0x3, - 0xb96, 0x3, - 0xba0, 0x3, - 0xba5, 0x3, - 0xbab, 0x3, - 0xbba, 0x4, - 0xbc3, 0x3, - 0xbd1, 0x6, - 0xbd8, 0xe, - 0xbfb, 0x5, - 0xc3a, 0x3, - 0xc4e, 0x7, - 0xc5b, 0x5, - 0xc70, 0x8, - 0xcce, 0x7, - 0xcd7, 0x7, - 0xcf3, 0xe, - 0xd50, 0x4, - 0xd97, 0x3, - 0xdc7, 0x3, - 0xdcb, 0x4, - 0xde0, 0x6, - 0xdf5, 0xc, - 0xe3b, 0x4, - 0xe5c, 0x25, - 0xe8e, 0x6, - 0xee0, 0x20, - 0xf6d, 0x4, - 0xfdb, 0x25, - 0x10c8, 0x5, - 0x137d, 0x3, - 0x139a, 0x6, - 0x169d, 0x3, - 0x16f9, 0x7, - 0x1715, 0xb, - 0x1737, 0x9, - 0x1754, 0xc, - 0x1774, 0xc, - 0x17ea, 0x6, - 0x17fa, 0x6, - 0x181a, 0x6, - 0x1878, 0x8, - 0x18ab, 0x5, - 0x18f6, 0xa, - 0x192c, 0x4, - 0x193c, 0x4, - 0x1941, 0x3, - 0x1975, 0xb, - 0x19ac, 0x4, - 0x19ca, 0x6, - 0x19db, 0x3, - 0x1a8a, 0x6, - 0x1a9a, 0x6, - 0x1abf, 0x41, - 0x1b4c, 0x4, - 0x1b7d, 0x3, - 0x1bf4, 0x8, - 0x1c38, 0x3, - 0x1c4a, 0x3, - 0x1c89, 0x37, - 0x1cc8, 0x8, - 0x1cfa, 0x6, - 0x1df6, 0x5, - 0x1fff, 0x11, - 0x2028, 0x8, - 0x205f, 0x11, - 0x209d, 0x3, - 0x20bf, 0x11, - 0x20f1, 0xf, - 0x218c, 0x4, - 0x2427, 0x19, - 0x244b, 0x15, - 0x2bba, 0x3, - 0x2bd2, 0x1a, - 0x2bf0, 0x10, - 0x2cf4, 0x5, - 0x2d28, 0x5, - 0x2d68, 0x7, - 0x2d71, 0xe, - 0x2d97, 0x9, - 0x2e45, 0x3b, - 0x2ef4, 0xc, - 0x2fd6, 0x1a, - 0x2ffc, 0x5, - 0x3100, 0x5, - 0x312e, 0x3, - 0x31bb, 0x5, - 0x31e4, 0xc, - 0x4db6, 0xa, - 0x9fd6, 0x2a, - 0xa48d, 0x3, - 0xa4c7, 0x9, - 0xa62c, 0x14, - 0xa6f8, 0x8, - 0xa7b8, 0x3f, - 0xa82c, 0x4, - 0xa83a, 0x6, - 0xa878, 0x8, - 0xa8c6, 0x8, - 0xa8da, 0x6, - 0xa954, 0xb, - 0xa97d, 0x3, - 0xa9da, 0x4, - 0xaa37, 0x9, - 0xaac3, 0x18, - 0xaaf7, 0xa, - 0xab17, 0x9, - 0xab66, 0xa, - 0xabfa, 0x6, - 0xd7a4, 0xc, - 0xd7c7, 0x4, - 0xd7fc, 0x2104, - 0xfada, 0x26, - 0xfb07, 0xc, - 0xfb18, 0x5, - 0xfbc2, 0x11, - 0xfd40, 0x10, - 0xfdc8, 0x28, - 0xfe1a, 0x6, - 0xfe6c, 0x4, - 0xfefd, 0x4, - 0xffbf, 0x3, - 0xffdd, 0x3, - 0xffef, 0xd, +const SINGLETONS1U: &'static [(u8, u8)] = &[ + (0x00, 6), + (0x01, 1), + (0x03, 1), + (0x04, 2), + (0x08, 8), + (0x09, 2), + (0x0a, 3), + (0x0b, 2), + (0x10, 1), + (0x11, 4), + (0x12, 5), + (0x13, 18), + (0x14, 2), + (0x15, 2), + (0x1c, 5), + (0x24, 1), + (0x6a, 3), + (0x6b, 2), + (0xbc, 2), + (0xd1, 2), + (0xd4, 12), + (0xd5, 9), + (0xd6, 2), + (0xd7, 2), + (0xda, 1), + (0xe0, 5), + (0xe8, 2), + (0xee, 32), + (0xf0, 4), + (0xf1, 1), + (0xf9, 4), ]; -const NORMAL1: &'static [u16] = &[ +const SINGLETONS1L: &'static [u8] = &[ + 0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e, + 0x9e, 0x9f, 0x06, 0x07, 0x09, 0x36, 0x3d, 0x3e, + 0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, 0x56, + 0x57, 0xbd, 0x35, 0xce, 0xcf, 0xe0, 0x12, 0x87, + 0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e, 0x11, 0x12, + 0x29, 0x31, 0x34, 0x3a, 0x3b, 0x45, 0x46, 0x49, + 0x4a, 0x4e, 0x4f, 0x64, 0x65, 0x5a, 0x5c, 0xb6, + 0xb7, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x6f, 0x5f, + 0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27, 0x28, + 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, + 0xad, 0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c, 0x15, + 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, 0xcc, + 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0xc5, + 0xc6, 0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33, + 0x38, 0x3a, 0x48, 0x4a, 0x4c, 0x50, 0x53, 0x55, + 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65, + 0x66, 0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4, + 0xaa, 0xaf, 0xb0, 0xc0, 0xd0, 0x2f, 0x1f, 0x31, + 0x32, 0x3f, +]; +const NORMAL0: &'static [u8] = &[ + 0x00, 0x20, + 0x5f, 0x22, + 0x82, 0xdf, 0x04, + 0x82, 0x44, 0x08, + 0x1b, 0x05, + 0x05, 0x11, + 0x81, 0xac, 0x0e, + 0x3b, 0x05, + 0x5f, 0x41, + 0x1e, 0x16, + 0x80, 0xdf, 0x03, + 0x19, 0x08, + 0x01, 0x04, + 0x20, 0x05, + 0x0a, 0x04, + 0x34, 0x04, + 0x07, 0x03, + 0x01, 0x07, + 0x06, 0x07, + 0x10, 0x0b, + 0x50, 0x0f, + 0x12, 0x07, + 0x01, 0x07, + 0x4d, 0x08, + 0x02, 0x04, + 0x1c, 0x0a, + 0x09, 0x03, + 0x08, 0x03, + 0x07, 0x03, + 0x02, 0x03, + 0x03, 0x03, + 0x0c, 0x04, + 0x05, 0x03, + 0x0b, 0x06, + 0x01, 0x0e, + 0x15, 0x05, + 0x3a, 0x03, + 0x11, 0x07, + 0x06, 0x05, + 0x10, 0x08, + 0x56, 0x07, + 0x02, 0x07, + 0x15, 0x0e, + 0x4f, 0x04, + 0x43, 0x03, + 0x2d, 0x03, + 0x01, 0x04, + 0x11, 0x06, + 0x0f, 0x0c, + 0x3a, 0x04, + 0x1d, 0x25, + 0x0d, 0x06, + 0x4c, 0x20, + 0x6d, 0x04, + 0x6a, 0x25, + 0x80, 0xc8, 0x05, + 0x82, 0xb0, 0x03, + 0x1a, 0x06, + 0x82, 0xfd, 0x03, + 0x59, 0x07, + 0x15, 0x0b, + 0x17, 0x09, + 0x14, 0x0c, + 0x14, 0x0c, + 0x6a, 0x06, + 0x0a, 0x06, + 0x1a, 0x06, + 0x58, 0x08, + 0x2b, 0x05, + 0x46, 0x0a, + 0x2c, 0x04, + 0x0c, 0x04, + 0x01, 0x03, + 0x31, 0x0b, + 0x2c, 0x04, + 0x1a, 0x06, + 0x0b, 0x03, + 0x80, 0xac, 0x06, + 0x0a, 0x06, + 0x1f, 0x41, + 0x4c, 0x04, + 0x2d, 0x03, + 0x74, 0x08, + 0x3c, 0x03, + 0x0f, 0x03, + 0x3c, 0x37, + 0x08, 0x08, + 0x2a, 0x06, + 0x80, 0xf6, 0x05, + 0x82, 0x04, 0x11, + 0x18, 0x08, + 0x2f, 0x11, + 0x2d, 0x03, + 0x1f, 0x11, + 0x21, 0x0f, + 0x80, 0x8c, 0x04, + 0x82, 0x97, 0x19, + 0x0b, 0x15, + 0x87, 0x5a, 0x03, + 0x15, 0x1a, + 0x04, 0x10, + 0x80, 0xf4, 0x05, + 0x2f, 0x05, + 0x3b, 0x07, + 0x02, 0x0e, + 0x18, 0x09, + 0x80, 0xa5, 0x3b, + 0x74, 0x0c, + 0x80, 0xd6, 0x1a, + 0x0c, 0x05, + 0x80, 0xff, 0x05, + 0x29, 0x03, + 0x80, 0x8a, 0x05, + 0x24, 0x0c, + 0x9b, 0xc6, 0x0a, + 0xd2, 0x16, 0x2a, + 0x84, 0x8d, 0x03, + 0x37, 0x09, + 0x81, 0x5c, 0x14, + 0x80, 0xb8, 0x08, + 0x80, 0xb8, 0x3f, + 0x35, 0x04, + 0x0a, 0x06, + 0x38, 0x08, + 0x46, 0x08, + 0x0c, 0x06, + 0x74, 0x0b, + 0x1e, 0x03, + 0x5a, 0x04, + 0x59, 0x09, + 0x80, 0x83, 0x18, + 0x1c, 0x0a, + 0x16, 0x09, + 0x46, 0x0a, + 0x80, 0x8a, 0x06, + 0xab, 0xa4, 0x0c, + 0x17, 0x04, + 0x31, 0xa1, 0x04, + 0x81, 0xda, 0x26, + 0x07, 0x0c, + 0x05, 0x05, + 0x80, 0xa5, 0x11, + 0x81, 0x6d, 0x10, + 0x78, 0x28, + 0x2a, 0x06, + 0x4c, 0x04, + 0x80, 0x8d, 0x04, + 0x80, 0xbe, 0x03, + 0x1b, 0x03, + 0x0f, 0x0d, +]; +const NORMAL1: &'static [u8] = &[ + 0x5e, 0x22, + 0x7b, 0x05, + 0x03, 0x04, + 0x2d, 0x03, + 0x65, 0x04, + 0x01, 0x2f, + 0x2e, 0x80, 0x82, + 0x1d, 0x03, + 0x31, 0x0f, + 0x1c, 0x04, + 0x24, 0x0c, + 0x1b, 0x05, + 0x2b, 0x05, + 0x44, 0x04, + 0x0e, 0x2a, + 0x80, 0xaa, 0x06, + 0x24, 0x04, + 0x24, 0x04, + 0x28, 0x08, + 0x34, 0x0b, + 0x01, 0x80, 0x90, + 0x81, 0x37, 0x09, + 0x16, 0x0a, + 0x08, 0x80, 0x98, + 0x39, 0x03, + 0x63, 0x08, + 0x09, 0x30, + 0x16, 0x05, + 0x21, 0x03, + 0x1b, 0x05, + 0x01, 0x40, + 0x38, 0x04, + 0x4b, 0x05, + 0x28, 0x04, + 0x03, 0x04, + 0x09, 0x08, + 0x09, 0x07, + 0x40, 0x20, + 0x27, 0x04, + 0x0c, 0x09, + 0x36, 0x03, + 0x3a, 0x05, + 0x1a, 0x07, + 0x04, 0x0c, + 0x07, 0x50, + 0x49, 0x37, + 0x33, 0x0d, + 0x33, 0x07, + 0x06, 0x81, 0x60, + 0x1f, 0x81, 0x81, + 0x4e, 0x04, + 0x1e, 0x0f, + 0x43, 0x0e, + 0x19, 0x07, + 0x0a, 0x06, + 0x44, 0x0c, + 0x27, 0x09, + 0x75, 0x0b, + 0x3f, 0x41, + 0x2a, 0x06, + 0x3b, 0x05, + 0x0a, 0x06, + 0x51, 0x06, + 0x01, 0x05, + 0x10, 0x03, + 0x05, 0x80, 0x8b, + 0x5e, 0x22, + 0x48, 0x08, + 0x0a, 0x80, 0xa6, 0x5e, 0x22, - 0xfb, 0x5, - 0x103, 0x4, - 0x134, 0x3, - 0x19c, 0x4, - 0x1a1, 0x2f, - 0x1fe, 0x82, - 0x29d, 0x3, - 0x2d1, 0xf, - 0x2fc, 0x4, - 0x324, 0xc, - 0x34b, 0x5, - 0x37b, 0x5, - 0x3c4, 0x4, - 0x3d6, 0x2a, - 0x4aa, 0x6, - 0x4d4, 0x4, - 0x4fc, 0x4, - 0x528, 0x8, - 0x564, 0xb, - 0x570, 0x90, - 0x737, 0x9, - 0x756, 0xa, - 0x768, 0x98, - 0x839, 0x3, - 0x89f, 0x8, - 0x8b0, 0x30, - 0x8f6, 0x5, - 0x91c, 0x3, - 0x93a, 0x5, - 0x940, 0x40, - 0x9b8, 0x4, - 0xa07, 0x5, - 0xa34, 0x4, - 0xa3b, 0x4, - 0xa48, 0x8, - 0xa59, 0x7, - 0xaa0, 0x20, - 0xae7, 0x4, - 0xaf7, 0x9, - 0xb36, 0x3, - 0xb73, 0x5, - 0xb92, 0x7, - 0xb9d, 0xc, - 0xbb0, 0x50, - 0xc49, 0x37, - 0xcb3, 0xd, - 0xcf3, 0x7, - 0xd00, 0x160, - 0xe7f, 0x181, - 0x104e, 0x4, - 0x1070, 0xf, - 0x10c2, 0xe, - 0x10e9, 0x7, - 0x10fa, 0x6, - 0x1144, 0xc, - 0x1177, 0x9, - 0x11f5, 0xb, - 0x123f, 0x41, - 0x12aa, 0x6, - 0x12eb, 0x5, - 0x12fa, 0x6, - 0x1351, 0x6, - 0x1358, 0x5, - 0x136d, 0x3, - 0x1375, 0x8b, - 0x145e, 0x22, - 0x14c8, 0x8, - 0x14da, 0xa6, - 0x15de, 0x22, - 0x1645, 0xb, - 0x165a, 0x6, - 0x166d, 0x13, - 0x16b8, 0x8, - 0x16ca, 0x36, - 0x171a, 0x3, - 0x172c, 0x4, - 0x1740, 0x160, - 0x18f3, 0xc, - 0x1900, 0x1c0, - 0x1af9, 0x107, - 0x1c46, 0xa, - 0x1c6d, 0x3, - 0x1cb7, 0x349, - 0x239a, 0x66, - 0x2475, 0xb, - 0x2544, 0xabc, - 0x342f, 0xfd1, - 0x4647, 0x21b9, - 0x6a39, 0x7, - 0x6a6a, 0x4, - 0x6a70, 0x60, - 0x6af6, 0xa, - 0x6b46, 0xa, - 0x6b78, 0x5, - 0x6b90, 0x370, - 0x6f45, 0xb, - 0x6f7f, 0x10, - 0x6fa0, 0x40, - 0x6fe1, 0x1f, - 0x87ed, 0x13, - 0x8af3, 0x250d, - 0xb002, 0xbfe, - 0xbc6b, 0x5, - 0xbc7d, 0x3, - 0xbc89, 0x7, - 0xbca0, 0x1360, - 0xd0f6, 0xa, - 0xd173, 0x8, - 0xd1e9, 0x17, - 0xd246, 0xba, - 0xd357, 0x9, - 0xd372, 0x8e, - 0xd547, 0x3, - 0xda8c, 0xf, - 0xdab0, 0x550, - 0xe02b, 0x7d5, - 0xe8d7, 0x29, - 0xe94b, 0x5, - 0xe95a, 0x4, - 0xe960, 0x4a0, - 0xee3c, 0x6, - 0xee43, 0x4, - 0xee9c, 0x5, - 0xeebc, 0x34, - 0xeef2, 0x10e, - 0xf02c, 0x4, - 0xf094, 0xc, - 0xf0f6, 0xa, - 0xf10d, 0x3, - 0xf16c, 0x4, - 0xf1ad, 0x39, - 0xf203, 0xd, - 0xf23c, 0x4, - 0xf249, 0x7, - 0xf252, 0xae, - 0xf6d3, 0xd, - 0xf6ed, 0x3, - 0xf6f7, 0x9, - 0xf774, 0xc, - 0xf7d5, 0x2b, - 0xf80c, 0x4, - 0xf848, 0x8, - 0xf85a, 0x6, - 0xf888, 0x8, - 0xf8ae, 0x62, - 0xf928, 0x8, - 0xf94c, 0x4, - 0xf95f, 0x21, - 0xf992, 0x2e, - 0xf9c1, 0x63f, + 0x45, 0x0b, + 0x0a, 0x06, + 0x0d, 0x13, + 0x38, 0x08, + 0x0a, 0x36, + 0x1a, 0x03, + 0x0f, 0x04, + 0x10, 0x81, 0x60, + 0x53, 0x0c, + 0x01, 0x81, 0xc0, + 0x39, 0x81, 0x07, + 0x46, 0x0a, + 0x1d, 0x03, + 0x47, 0x83, 0x49, + 0x83, 0x9a, 0x66, + 0x75, 0x0b, + 0x80, 0xc4, 0x8a, 0xbc, + 0x84, 0x2f, 0x8f, 0xd1, + 0x82, 0x47, 0xa1, 0xb9, + 0x82, 0x39, 0x07, + 0x2a, 0x04, + 0x02, 0x60, + 0x26, 0x0a, + 0x46, 0x0a, + 0x28, 0x05, + 0x13, 0x83, 0x70, + 0x45, 0x0b, + 0x2f, 0x10, + 0x11, 0x40, + 0x01, 0x1f, + 0x97, 0xed, 0x13, + 0x82, 0xf3, 0xa5, 0x0d, + 0x02, 0x8b, 0xfe, + 0x6b, 0x05, + 0x0d, 0x03, + 0x09, 0x07, + 0x10, 0x93, 0x60, + 0x80, 0xf6, 0x0a, + 0x73, 0x08, + 0x6e, 0x17, + 0x46, 0x80, 0xba, + 0x57, 0x09, + 0x12, 0x80, 0x8e, + 0x81, 0x47, 0x03, + 0x85, 0x42, 0x0f, + 0x15, 0x85, 0x50, + 0x2b, 0x87, 0xd5, + 0x80, 0xd7, 0x29, + 0x4b, 0x05, + 0x0a, 0x04, + 0x02, 0x84, 0xa0, + 0x3c, 0x06, + 0x01, 0x04, + 0x55, 0x05, + 0x1b, 0x34, + 0x02, 0x81, 0x0e, + 0x2c, 0x04, + 0x64, 0x0c, + 0x56, 0x0a, + 0x0d, 0x03, + 0x5c, 0x04, + 0x3d, 0x39, + 0x1d, 0x0d, + 0x2c, 0x04, + 0x09, 0x07, + 0x02, 0x80, 0xae, + 0x83, 0xd3, 0x0d, + 0x0d, 0x03, + 0x07, 0x09, + 0x74, 0x0c, + 0x55, 0x2b, + 0x0c, 0x04, + 0x38, 0x08, + 0x0a, 0x06, + 0x28, 0x08, + 0x1e, 0x62, + 0x18, 0x08, + 0x1c, 0x04, + 0x0f, 0x21, + 0x12, 0x2e, + 0x01, 0x86, 0x3f, ];