Snap for 8512216 from c6cf201b6a75bbc6f0d33cfb27007753fd64817a to tm-frc-adbd-release

Change-Id: I8578502185e17d07b04d1e7a0397cebc760ae4bb
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 3d0fa1e..6772581 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "7518868e4b9c802b214ce393f79f82fa13bef251"
-  }
-}
+    "sha1": "1ef53f632b9cb6f2e7ff603586f4472317b9a25c"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index 16bf072..050e70d 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -11,6 +11,7 @@
       matrix:

         rust:

         - 1.34.0

+        - 1.36.0

         - stable

         - beta

         - nightly

@@ -25,10 +26,17 @@
       uses: actions-rs/cargo@v1

       with:

         command: build

-    - name: Test on Stable/Beta

+    - name: Build the crate on 1.36 with features.

       if: matrix.rust != '1.34.0'

       uses: actions-rs/cargo@v1

       with:

+        command: build

+        # Using `extern crate alloc` is only possible after 1.36

+        args: --features=alloc,std,grab_spare_slice

+    - name: Test on Stable/Beta

+      if: matrix.rust != '1.34.0' && matrix.rust != '1.36.0'

+      uses: actions-rs/cargo@v1

+      with:

         command: test

         args: --features=alloc --features=grab_spare_slice --features=rustc_1_40

     - name: Test on Nightly with All Features

diff --git a/Android.bp b/Android.bp
index 15a216e..3888f8c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -44,7 +44,7 @@
     host_supported: true,
     crate_name: "tinyvec",
     cargo_env_compat: true,
-    cargo_pkg_version: "1.4.0",
+    cargo_pkg_version: "1.5.1",
     srcs: ["src/lib.rs"],
     edition: "2018",
     features: [
@@ -62,47 +62,29 @@
     min_sdk_version: "29",
 }
 
-rust_defaults {
-    name: "tinyvec_test_defaults",
-    crate_name: "tinyvec",
+rust_test {
+    name: "tinyvec_test_tests_arrayvec",
+    host_supported: true,
+    crate_name: "arrayvec",
     cargo_env_compat: true,
-    cargo_pkg_version: "1.4.0",
+    cargo_pkg_version: "1.5.1",
+    srcs: ["tests/arrayvec.rs"],
     test_suites: ["general-tests"],
     auto_gen_config: true,
+    test_options: {
+        unit_test: true,
+    },
     edition: "2018",
     features: [
         "alloc",
         "default",
         "tinyvec_macros",
     ],
-    flags: [
-        "-C debug-assertions=on",
-        "-C opt-level=3",
-    ],
     rustlibs: [
         "libcriterion",
         "libserde_test",
+        "libsmallvec",
         "libtinyvec",
         "libtinyvec_macros",
     ],
 }
-
-rust_test {
-    name: "tinyvec_test_tests_arrayvec",
-    defaults: ["tinyvec_test_defaults"],
-    host_supported: true,
-    srcs: ["tests/arrayvec.rs"],
-    test_options: {
-        unit_test: true,
-    },
-}
-
-rust_test {
-    name: "tinyvec_test_tests_tinyvec",
-    defaults: ["tinyvec_test_defaults"],
-    host_supported: true,
-    srcs: ["tests/tinyvec.rs"],
-    test_options: {
-        unit_test: true,
-    },
-}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1bcc2a1..93ef808 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,16 @@
 # Changelog

 

+## 1.5.1

+

+* [madsmtm](https://github.com/madsmtm) fixed an error with the `alloc` feature on very old rustc versions.

+  [pr 154](https://github.com/Lokathor/tinyvec/pull/154)

+

+## 1.5.0

+

+* [eeeebbbbrrrr](https://github.com/eeeebbbbrrrr) added an impl for [std::io::Write](https://doc.rust-lang.org/std/io/trait.Write.html) to `TinyVec` when the element type is `u8`.

+  This is gated behind the new `std` feature.

+  [pr 152](https://github.com/Lokathor/tinyvec/pull/152)

+

 ## 1.4.0

 

 * [saethlin](https://github.com/saethlin) stabilized the usage of const generics and array map with the `rustc_1_55` feature.

diff --git a/Cargo.toml b/Cargo.toml
index 3ab13bd..24dfa0d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,7 +12,7 @@
 [package]
 edition = "2018"
 name = "tinyvec"
-version = "1.4.0"
+version = "1.5.1"
 authors = ["Lokathor <zefria@gmail.com>"]
 description = "`tinyvec` provides 100% safe vec-like data structures."
 keywords = ["vec", "no_std", "no-std"]
@@ -20,22 +20,30 @@
 license = "Zlib OR Apache-2.0 OR MIT"
 repository = "https://github.com/Lokathor/tinyvec"
 [package.metadata.docs.rs]
-features = ["alloc", "grab_spare_slice", "rustc_1_40", "rustc_1_55", "serde"]
+features = ["alloc", "std", "grab_spare_slice", "rustc_1_40", "rustc_1_55", "serde"]
 rustdoc-args = ["--cfg", "docs_rs"]
 
 [package.metadata.playground]
-features = ["alloc", "grab_spare_slice", "rustc_1_40", "rustc_1_55", "serde"]
+features = ["alloc", "std", "grab_spare_slice", "rustc_1_40", "rustc_1_55", "serde"]
+[profile.bench]
+debug = 2
+
 [profile.test]
 opt-level = 3
 
 [[test]]
 name = "tinyvec"
-required-features = ["alloc"]
+required-features = ["alloc", "std"]
 
 [[bench]]
 name = "macros"
 harness = false
 required-features = ["alloc"]
+
+[[bench]]
+name = "smallvec"
+harness = false
+required-features = ["alloc", "real_blackbox"]
 [dependencies.arbitrary]
 version = "1"
 optional = true
@@ -54,11 +62,16 @@
 [dev-dependencies.serde_test]
 version = "1.0"
 
+[dev-dependencies.smallvec]
+version = "1"
+
 [features]
 alloc = ["tinyvec_macros"]
 default = []
 experimental_write_impl = []
 grab_spare_slice = []
 nightly_slice_partition_dedup = []
+real_blackbox = ["criterion/real_blackbox"]
 rustc_1_40 = []
 rustc_1_55 = ["rustc_1_40"]
+std = []
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index a262ed1..28a5874 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,73 +1,90 @@
 [package]
 name = "tinyvec"
 description = "`tinyvec` provides 100% safe vec-like data structures."
-version = "1.4.0"
+version = "1.5.1"
 authors = ["Lokathor <zefria@gmail.com>"]
 edition = "2018"
 license = "Zlib OR Apache-2.0 OR MIT"
 keywords = ["vec", "no_std", "no-std"]
 categories = ["data-structures", "no-std"]
 repository = "https://github.com/Lokathor/tinyvec"
-

+
 [dependencies]
 tinyvec_macros = { version = "0.1", optional = true }
 # Provides `Serialize` and `Deserialize` implementations
 serde = { version = "1.0", optional = true, default-features = false }
 # Provides derived `Arbitrary` implementations
 arbitrary = { version = "1", optional = true }
-

+
 [features]
 default = []
-

+
 # Provide things that utilize the `alloc` crate, namely `TinyVec`.
 alloc = ["tinyvec_macros"]
-

+
+# Provide things that require Rust's `std` module
+std = []
+
 # (not part of Vec!) Extra methods to let you grab the slice of memory after the
 # "active" portion of an `ArrayVec` or `SliceVec`.
 grab_spare_slice = []
-

+
 # features that require rustc 1.40
 # use Vec::append if possible in TinyVec::append - 1.37
 # DoubleEndedIterator::nth_back - 1.40
 rustc_1_40 = []
-

+
 # features that require rustc 1.55
 # use const generics to implement Array for all array lengths
 rustc_1_55 = ["rustc_1_40"]
-

+
 # allow use of nightly feature `slice_partition_dedup`,
 # will become useless once that is stabilized:
 # https://github.com/rust-lang/rust/issues/54279
 nightly_slice_partition_dedup = []
-

+
 # EXPERIMENTAL: Not part of SemVer. It adds `core::fmt::Write` to `ArrayVec`
 # and `SliceVec`. It works on Stable Rust, but Vec normally supports the
 # `std::io::Write` trait instead of `core::fmt::Write`, so we're keeping it as
 # an experimental impl only for now.
 experimental_write_impl = []
-

+
+# Some benchmarks are optimized away with the stable black_box function
+# which is based on read_volatile. This feature requires inline assembly
+# and thus a nightly compiler, but is only used in benchmarks.
+real_blackbox = ["criterion/real_blackbox"]
+
 [package.metadata.docs.rs]
-features = ["alloc", "grab_spare_slice", "rustc_1_40", "rustc_1_55", "serde"]
+features = ["alloc", "std", "grab_spare_slice", "rustc_1_40", "rustc_1_55", "serde"]
 rustdoc-args = ["--cfg","docs_rs"]
-

+
 [package.metadata.playground]
-features = ["alloc", "grab_spare_slice", "rustc_1_40", "rustc_1_55", "serde"]
-

+features = ["alloc", "std", "grab_spare_slice", "rustc_1_40", "rustc_1_55", "serde"]
+
 [profile.test]
 opt-level = 3
-

+
+[profile.bench]
+debug = 2
+
 [workspace]
 members = ["fuzz"]
-

+
 [dev-dependencies]
 criterion = "0.3.0"
 serde_test = "1.0"
-

+smallvec = "1"
+
 [[test]]
 name = "tinyvec"
-required-features = ["alloc"]
-

+required-features = ["alloc", "std"]
+
 [[bench]]
 name = "macros"
 harness = false
 required-features = ["alloc"]
+
+[[bench]]
+name = "smallvec"
+harness = false
+required-features = ["alloc", "real_blackbox"]
diff --git a/METADATA b/METADATA
index 8445b96..a632067 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/tinyvec/tinyvec-1.4.0.crate"
+    value: "https://static.crates.io/crates/tinyvec/tinyvec-1.5.1.crate"
   }
-  version: "1.4.0"
+  version: "1.5.1"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2021
-    month: 9
-    day: 22
+    year: 2022
+    month: 3
+    day: 1
   }
 }
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 45f8bcc..88d573d 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -17,9 +17,6 @@
     },
     {
       "name": "tinyvec_test_tests_arrayvec"
-    },
-    {
-      "name": "tinyvec_test_tests_tinyvec"
     }
   ],
   "presubmit-rust": [
@@ -28,9 +25,6 @@
     },
     {
       "name": "tinyvec_test_tests_arrayvec"
-    },
-    {
-      "name": "tinyvec_test_tests_tinyvec"
     }
   ]
 }
diff --git a/benches/smallvec.rs b/benches/smallvec.rs
new file mode 100644
index 0000000..8cd16d3
--- /dev/null
+++ b/benches/smallvec.rs
@@ -0,0 +1,500 @@
+//! Benchmarks that compare TinyVec to SmallVec

+//!

+//! All the following commentary is based on the latest nightly at the time:

+//! rustc 1.55.0 (c8dfcfe04 2021-09-06).

+//!

+//! Some of these benchmarks are just a few instructions, so we put our own for loop inside

+//! the criterion::Bencher::iter call. This seems to improve the stability of measurements, and it

+//! has the wonderful side effect of making the emitted assembly easier to follow. Some of these

+//! benchmarks are totally inlined so that there are no calls at all in the hot path, so finding

+//! this for loop is an easy way to find your way around the emitted assembly.

+//!

+//! The clear method is cheaper to call for arrays of elements without a Drop impl, so wherever

+//! possible we reuse a single object in the benchmark loop, with a clear + black_box on each

+//! iteration in an attempt to not make that visible to the optimizer.

+//!

+//! We always call black_box(&v), instead of v = black_box(v) because the latter does a move of the

+//! inline array, which is linear in the size of the array and thus varies based on the array type

+//! being benchmarked, and this move can be more expensive than the function we're trying to

+//! benchmark.

+//!

+//! We also black_box the input to each method call. This has a significant effect on the assembly

+//! emitted, for example if we do not black_box the range we iterate over in the ::push benchmarks,

+//! the loop is unrolled. It's not entirely clear if it's better to black_box the iterator that

+//! yields the items being pushed, or to black_box at a deeper level: v.push(black_box(i)) for

+//! example. Anecdotally, it seems like the latter approach produces unreasonably bad assembly.

+//!

+

+use criterion::{black_box, criterion_group, criterion_main, Criterion};

+use smallvec::SmallVec;

+use std::iter::FromIterator;

+use tinyvec::TinyVec;

+

+const ITERS: usize = 10_000;

+

+macro_rules! tinyvec_benches {

+  ($c:expr, $type:ty ; $len:expr) => {{

+    let mut g = $c.benchmark_group(concat!(

+      "TinyVec_",

+      stringify!($type),

+      "_",

+      stringify!($len)

+    ));

+

+    g.bench_function(

+      concat!(

+        "TinyVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::default"

+      ),

+      |b| {

+        b.iter(|| {

+          for _ in 0..ITERS {

+            let v: TinyVec<[$type; $len]> = TinyVec::default();

+            black_box(&v);

+          }

+        });

+      },

+    );

+

+    g.bench_function(

+      concat!(

+        "TinyVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::clone"

+      ),

+      |b| {

+        b.iter(|| {

+          let outer: TinyVec<[$type; $len]> =

+            black_box(TinyVec::from_iter(0..=($len as usize - 1) as _));

+          for _ in 0..ITERS {

+            let v = outer.clone();

+            black_box(&v);

+          }

+        });

+      },

+    );

+

+    g.bench_function(

+      concat!(

+        "TinyVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::clear"

+      ),

+      |b| {

+        b.iter(|| {

+          let mut v: TinyVec<[$type; $len]> = TinyVec::default();

+          for _ in 0..ITERS {

+            v.clear();

+            black_box(&v);

+          }

+        });

+      },

+    );

+

+    g.bench_function(

+      concat!(

+        "TinyVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::push"

+      ),

+      |b| {

+        b.iter(|| {

+          let mut v: TinyVec<[$type; $len]> = TinyVec::default();

+          for _ in 0..ITERS {

+            v.clear();

+            black_box(&v);

+            for i in black_box(0..=($len as usize - 1) as _) {

+              v.push(i);

+            }

+            black_box(&v);

+          }

+        });

+      },

+    );

+

+    g.bench_function(

+      concat!(

+        "TinyVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::from_iter"

+      ),

+      |b| {

+        b.iter(|| {

+          for _ in 0..ITERS {

+            let v: TinyVec<[$type; $len]> =

+              TinyVec::from_iter(black_box(0..=($len as usize - 1) as _));

+            black_box(&v);

+          }

+        });

+      },

+    );

+

+    g.bench_function(

+      concat!(

+        "TinyVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::from_slice"

+      ),

+      |b| {

+        b.iter(|| {

+          let data: &[$type] = &[0, 1, 2, 3, 4, 5, 6, 7];

+          for _ in 0..ITERS {

+            let v: TinyVec<[$type; $len]> = TinyVec::from(black_box(data));

+            black_box(&v);

+          }

+        });

+      },

+    );

+

+    g.bench_function(

+      concat!(

+        "TinyVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::extend"

+      ),

+      |b| {

+        b.iter(|| {

+          let mut v: TinyVec<[$type; $len]> = black_box(TinyVec::default());

+          for _ in 0..ITERS {

+            v.clear();

+            black_box(&v);

+            v.extend(black_box(0..=($len as usize - 1) as _));

+            black_box(&v);

+          }

+        });

+      },

+    );

+

+    g.bench_function(

+      concat!(

+        "TinyVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::extend_from_slice"

+      ),

+      |b| {

+        b.iter(|| {

+          let data: &[$type] = black_box(&[0, 1, 2, 3, 4, 5, 6, 7]);

+          let mut v: TinyVec<[$type; $len]> = black_box(TinyVec::default());

+          for _ in 0..ITERS {

+            v.clear();

+            black_box(&v);

+            v.extend_from_slice(data);

+            black_box(&v);

+          }

+        });

+      },

+    );

+

+    g.bench_function(

+      concat!(

+        "TinyVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::insert"

+      ),

+      |b| {

+        b.iter(|| {

+          let mut v: TinyVec<[$type; $len]> = TinyVec::default();

+          for _ in 0..ITERS {

+            v.clear();

+            black_box(&v);

+            for i in black_box(0..=($len as usize - 1) as _) {

+              v.insert(i as usize, i);

+            }

+            black_box(&v);

+          }

+        });

+      },

+    );

+

+    g.bench_function(

+      concat!(

+        "TinyVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::remove"

+      ),

+      |b| {

+        b.iter(|| {

+          let outer: TinyVec<[$type; $len]> =

+            black_box(TinyVec::from_iter(0..=($len as usize - 1) as _));

+          for _ in 0..ITERS {

+            let mut v = outer.clone();

+            for i in black_box((0..=($len as usize - 1) as _).rev()) {

+              v.remove(i);

+            }

+            black_box(&v);

+          }

+        });

+      },

+    );

+  }};

+}

+

+fn tinyvec_benches(c: &mut Criterion) {

+  tinyvec_benches!(c, u8; 8);

+  tinyvec_benches!(c, u8; 16);

+  tinyvec_benches!(c, u8; 32);

+  tinyvec_benches!(c, u8; 64);

+  tinyvec_benches!(c, u8; 128);

+  tinyvec_benches!(c, u8; 256);

+  tinyvec_benches!(c, u64; 2);

+  tinyvec_benches!(c, u64; 4);

+  tinyvec_benches!(c, u64; 8);

+  tinyvec_benches!(c, u64; 16);

+  tinyvec_benches!(c, u64; 32);

+}

+

+macro_rules! smallvec_benches {

+  ($c:expr, $type:ty ; $len:expr) => {{

+    let mut g = $c.benchmark_group(concat!(

+      "SmallVec_",

+      stringify!($type),

+      "_",

+      stringify!($len)

+    ));

+

+    g.bench_function(

+      concat!(

+        "SmallVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::default"

+      ),

+      |b| {

+        b.iter(|| {

+          for _ in 0..ITERS {

+            let v: SmallVec<[$type; $len]> = SmallVec::default();

+            black_box(&v);

+          }

+        });

+      },

+    );

+

+    g.bench_function(

+      concat!(

+        "SmallVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::clone"

+      ),

+      |b| {

+        b.iter(|| {

+          let outer: SmallVec<[$type; $len]> =

+            black_box(SmallVec::from_iter(0..=($len as usize - 1) as _));

+          for _ in 0..ITERS {

+            let v = outer.clone();

+            black_box(&v);

+          }

+        });

+      },

+    );

+

+    g.bench_function(

+      concat!(

+        "SmallVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::clear"

+      ),

+      |b| {

+        b.iter(|| {

+          let mut v: SmallVec<[$type; $len]> = SmallVec::default();

+          for _ in 0..ITERS {

+            v.clear();

+            black_box(&v);

+          }

+        });

+      },

+    );

+

+    g.bench_function(

+      concat!(

+        "SmallVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::push"

+      ),

+      |b| {

+        b.iter(|| {

+          let mut v: SmallVec<[$type; $len]> = SmallVec::default();

+          for _ in 0..ITERS {

+            v.clear();

+            black_box(&v);

+            for i in black_box(0..=($len as usize - 1) as _) {

+              v.push(i);

+            }

+            black_box(&v);

+          }

+        });

+      },

+    );

+

+    g.bench_function(

+      concat!(

+        "SmallVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::from_iter"

+      ),

+      |b| {

+        b.iter(|| {

+          for _ in 0..ITERS {

+            let v: SmallVec<[$type; $len]> =

+              SmallVec::from_iter(black_box(0..=($len as usize - 1) as _));

+            black_box(&v);

+          }

+        });

+      },

+    );

+

+    g.bench_function(

+      concat!(

+        "SmallVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::from_slice"

+      ),

+      |b| {

+        b.iter(|| {

+          let data: &[$type] = &[0, 1, 2, 3, 4, 5, 6, 7];

+          for _ in 0..ITERS {

+            let v: SmallVec<[$type; $len]> = SmallVec::from(black_box(data));

+            black_box(&v);

+          }

+        });

+      },

+    );

+

+    g.bench_function(

+      concat!(

+        "SmallVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::extend"

+      ),

+      |b| {

+        b.iter(|| {

+          let mut v: SmallVec<[$type; $len]> = black_box(SmallVec::default());

+          for _ in 0..ITERS {

+            v.clear();

+            black_box(&v);

+            v.extend(black_box(0..=($len as usize - 1) as _));

+            black_box(&v);

+          }

+        });

+      },

+    );

+

+    g.bench_function(

+      concat!(

+        "SmallVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::extend_from_slice"

+      ),

+      |b| {

+        b.iter(|| {

+          let data: &[$type] = black_box(&[0, 1, 2, 3, 4, 5, 6, 7]);

+          let mut v: SmallVec<[$type; $len]> = black_box(SmallVec::default());

+          for _ in 0..ITERS {

+            v.clear();

+            black_box(&v);

+            v.extend_from_slice(data);

+            black_box(&v);

+          }

+        });

+      },

+    );

+

+    g.bench_function(

+      concat!(

+        "SmallVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::insert"

+      ),

+      |b| {

+        b.iter(|| {

+          let mut v: SmallVec<[$type; $len]> = SmallVec::default();

+          for _ in 0..ITERS {

+            v.clear();

+            black_box(&v);

+            for i in black_box(0..=($len as usize - 1) as _) {

+              v.insert(i as usize, i);

+            }

+            black_box(&v);

+          }

+        });

+      },

+    );

+

+    g.bench_function(

+      concat!(

+        "SmallVec<[",

+        stringify!($type),

+        "; ",

+        stringify!($len),

+        "]>::remove"

+      ),

+      |b| {

+        b.iter(|| {

+          let outer: SmallVec<[$type; $len]> =

+            black_box(SmallVec::from_iter(0..=($len as usize - 1) as _));

+          for _ in 0..ITERS {

+            let mut v = outer.clone();

+            for i in black_box((0..=($len as usize - 1) as _).rev()) {

+              v.remove(i);

+            }

+            black_box(&v);

+          }

+        });

+      },

+    );

+  }};

+}

+

+fn smallvec_benches(c: &mut Criterion) {

+  smallvec_benches!(c, u8; 8);

+  smallvec_benches!(c, u8; 16);

+  smallvec_benches!(c, u8; 32);

+  smallvec_benches!(c, u8; 64);

+  smallvec_benches!(c, u8; 128);

+  smallvec_benches!(c, u8; 256);

+  smallvec_benches!(c, u64; 2);

+  smallvec_benches!(c, u64; 4);

+  smallvec_benches!(c, u64; 8);

+  smallvec_benches!(c, u64; 16);

+  smallvec_benches!(c, u64; 32);

+}

+

+criterion_group!(benches, tinyvec_benches, smallvec_benches);

+criterion_main!(benches);

diff --git a/compare_benchmarks.py b/compare_benchmarks.py
new file mode 100644
index 0000000..86eb7e8
--- /dev/null
+++ b/compare_benchmarks.py
@@ -0,0 +1,30 @@
+import os

+import os.path

+import json

+

+comparisons = []

+

+for (root, _dirs, files) in os.walk('target/criterion'):

+    for file in files:

+        if file == 'estimates.json' and root.endswith(

+                'new') and 'TinyVec' in root:

+            path = os.path.join(root, file)

+

+            bench_name = path.split('/')[3]

+            tinyvec_time = json.load(open(path))['mean']['point_estimate']

+

+            path = path.replace('TinyVec', 'SmallVec')

+

+            smallvec_time = json.load(open(path))['mean']['point_estimate']

+

+            comparisons.append((bench_name, tinyvec_time / smallvec_time))

+

+comparisons.sort(key=lambda x: x[1])

+longest_name = max(len(c[0]) for c in comparisons)

+for (name, ratio) in comparisons:

+    # Undo the criterion name mangling

+    name = name.replace('_[', '<[')

+    name = name.replace(']___', ']>::')

+

+    name = name.ljust(longest_name)

+    print(f"{name} {ratio:.2f}")

diff --git a/src/lib.rs b/src/lib.rs
index b3ee259..c66705d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,4 @@
-#![no_std]

+#![cfg_attr(not(feature = "std"), no_std)]

 #![forbid(unsafe_code)]

 #![cfg_attr(

   feature = "nightly_slice_partition_dedup",

diff --git a/src/tinyvec.rs b/src/tinyvec.rs
index 3e884fc..1e11a47 100644
--- a/src/tinyvec.rs
+++ b/src/tinyvec.rs
@@ -107,8 +107,8 @@
   #[inline]

   fn clone(&self) -> Self {

     match self {

-      Self::Heap(v) => Self::Heap(v.clone()),

-      Self::Inline(v) => Self::Inline(v.clone()),

+      TinyVec::Heap(v) => TinyVec::Heap(v.clone()),

+      TinyVec::Inline(v) => TinyVec::Inline(v.clone()),

     }

   }

 

@@ -172,6 +172,21 @@
   }

 }

 

+#[cfg(feature = "std")]

+#[cfg_attr(docs_rs, doc(cfg(feature = "std")))]

+impl<A: Array<Item = u8>> std::io::Write for TinyVec<A> {

+  #[inline(always)]

+  fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {

+    self.extend_from_slice(buf);

+    Ok(buf.len())

+  }

+

+  #[inline(always)]

+  fn flush(&mut self) -> std::io::Result<()> {

+    Ok(())

+  }

+}

+

 #[cfg(feature = "serde")]

 #[cfg_attr(docs_rs, doc(cfg(feature = "serde")))]

 impl<A: Array> Serialize for TinyVec<A>

diff --git a/tests/tinyvec.rs b/tests/tinyvec.rs
index e59a83b..ab4d9bd 100644
--- a/tests/tinyvec.rs
+++ b/tests/tinyvec.rs
@@ -394,3 +394,18 @@
 

   assert_eq!(s, expected);

 }

+

+#[cfg(feature = "std")]

+#[test]

+fn TinyVec_std_io_write() {

+  use std::io::Write;

+  let mut tv: TinyVec<[u8; 3]> = TinyVec::new();

+

+  tv.write_all(b"foo").ok();

+  assert!(tv.is_inline());

+  assert_eq!(tv, tiny_vec![b'f', b'o', b'o']);

+

+  tv.write_all(b"bar").ok();

+  assert!(tv.is_heap());

+  assert_eq!(tv, tiny_vec![b'f', b'o', b'o', b'b', b'a', b'r']);

+}