Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--lib/smol_str/.github/ci.rs116
-rw-r--r--lib/smol_str/.github/workflows/ci.yaml38
-rw-r--r--lib/smol_str/.gitignore3
-rw-r--r--lib/smol_str/.travis.yml4
-rw-r--r--lib/smol_str/Cargo.toml13
-rw-r--r--lib/smol_str/benches/building.rs44
-rw-r--r--lib/smol_str/bors.toml4
-rw-r--r--lib/smol_str/src/lib.rs79
-rw-r--r--lib/smol_str/tests/test.rs17
9 files changed, 194 insertions, 124 deletions
diff --git a/lib/smol_str/.github/ci.rs b/lib/smol_str/.github/ci.rs
new file mode 100644
index 0000000000..b293ebbcb7
--- /dev/null
+++ b/lib/smol_str/.github/ci.rs
@@ -0,0 +1,116 @@
+use std::{
+ env, fs,
+ process::{self, Command, ExitStatus, Stdio},
+ time::Instant,
+};
+
+type Error = Box<dyn std::error::Error>;
+type Result<T> = std::result::Result<T, Error>;
+
+fn main() {
+ if let Err(err) = try_main() {
+ eprintln!("{}", err);
+ process::exit(1);
+ }
+}
+
+fn try_main() -> Result<()> {
+ let cwd = env::current_dir()?;
+ let cargo_toml = cwd.join("Cargo.toml");
+ assert!(
+ cargo_toml.exists(),
+ "Cargo.toml not found, cwd: {}",
+ cwd.display()
+ );
+
+ {
+ let _s = Section::new("BUILD");
+ shell("cargo test --all-features --workspace --no-run")?;
+ }
+
+ {
+ let _s = Section::new("TEST");
+ shell("cargo test --all-features --workspace")?;
+ }
+
+ let current_branch = shell_output("git branch --show-current")?;
+ if &current_branch == "master" {
+ let _s = Section::new("PUBLISH");
+ let manifest = fs::read_to_string(&cargo_toml)?;
+ let version = get_field(&manifest, "version")?;
+ let tag = format!("v{}", version);
+ let tags = shell_output("git tag --list")?;
+
+ if !tags.contains(&tag) {
+ let token = env::var("CRATES_IO_TOKEN").unwrap();
+ shell(&format!("git tag v{}", version))?;
+ shell(&format!("cargo publish --token {}", token))?;
+ shell("git push --tags")?;
+ }
+ }
+ Ok(())
+}
+
+fn get_field<'a>(text: &'a str, name: &str) -> Result<&'a str> {
+ for line in text.lines() {
+ let words = line.split_ascii_whitespace().collect::<Vec<_>>();
+ match words.as_slice() {
+ [n, "=", v, ..] if n.trim() == name => {
+ assert!(v.starts_with('"') && v.ends_with('"'));
+ return Ok(&v[1..v.len() - 1]);
+ }
+ _ => (),
+ }
+ }
+ Err(format!("can't find `{}` in\n----\n{}\n----\n", name, text))?
+}
+
+fn shell(cmd: &str) -> Result<()> {
+ let status = command(cmd).status()?;
+ check_status(status)
+}
+
+fn shell_output(cmd: &str) -> Result<String> {
+ let output = command(cmd).stderr(Stdio::inherit()).output()?;
+ check_status(output.status)?;
+ let res = String::from_utf8(output.stdout)?;
+ let res = res.trim().to_string();
+ println!("{}", res);
+ Ok(res)
+}
+
+fn command(cmd: &str) -> Command {
+ eprintln!("> {}", cmd);
+ let words = cmd.split_ascii_whitespace().collect::<Vec<_>>();
+ let (cmd, args) = words.split_first().unwrap();
+ let mut res = Command::new(cmd);
+ res.args(args);
+ res
+}
+
+fn check_status(status: ExitStatus) -> Result<()> {
+ if !status.success() {
+ Err(format!("$status: {}", status))?;
+ }
+ Ok(())
+}
+
+struct Section {
+ name: &'static str,
+ start: Instant,
+}
+
+impl Section {
+ fn new(name: &'static str) -> Section {
+ println!("::group::{}", name);
+ let start = Instant::now();
+ Section { name, start }
+ }
+}
+
+impl Drop for Section {
+ fn drop(&mut self) {
+ eprintln!("{}: {:.2?}", self.name, self.start.elapsed());
+ println!("::endgroup::");
+ }
+}
diff --git a/lib/smol_str/.github/workflows/ci.yaml b/lib/smol_str/.github/workflows/ci.yaml
new file mode 100644
index 0000000000..b1bc2175ca
--- /dev/null
+++ b/lib/smol_str/.github/workflows/ci.yaml
@@ -0,0 +1,38 @@
+name: CI
+on:
+ pull_request:
+ push:
+ branches:
+ - master
+ - staging
+ - trying
+
+env:
+ CARGO_INCREMENTAL: 0
+ CARGO_NET_RETRY: 10
+ CI: 1
+ RUST_BACKTRACE: short
+ RUSTFLAGS: -D warnings
+ RUSTUP_MAX_RETRIES: 10
+
+jobs:
+ rust:
+ name: Rust
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+
+ - name: Install Rust toolchain
+ uses: actions-rs/toolchain@v1
+ with:
+ toolchain: stable
+ profile: minimal
+ override: true
+
+ - run: rustc ./.github/ci.rs && ./ci
+ env:
+ CRATES_IO_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}
diff --git a/lib/smol_str/.gitignore b/lib/smol_str/.gitignore
index 4470988469..6b500aacba 100644
--- a/lib/smol_str/.gitignore
+++ b/lib/smol_str/.gitignore
@@ -1,2 +1,3 @@
-target/
+/target
+/ci
Cargo.lock \ No newline at end of file
diff --git a/lib/smol_str/.travis.yml b/lib/smol_str/.travis.yml
deleted file mode 100644
index 56abf36895..0000000000
--- a/lib/smol_str/.travis.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-language: rust
-
-script:
- - cargo test --all-features
diff --git a/lib/smol_str/Cargo.toml b/lib/smol_str/Cargo.toml
index eeb3b1b092..fee00ec2ba 100644
--- a/lib/smol_str/Cargo.toml
+++ b/lib/smol_str/Cargo.toml
@@ -1,21 +1,16 @@
[package]
name = "smol_str"
-version = "0.1.16"
-authors = ["Aleksey Kladov <[email protected]>"]
-repository = "https://github.com/matklad/smol_str"
+version = "0.1.17"
description = "small-string optimized string type with O(1) clone"
license = "MIT OR Apache-2.0"
+repository = "https://github.com/matklad/smol_str"
+authors = ["Aleksey Kladov <[email protected]>"]
edition = "2018"
[dependencies]
serde = { version = "1", optional = true, default_features = false, features = [ "std" ] }
[dev-dependencies]
-proptest = "0.8.3"
+proptest = "0.10"
serde_json = "1"
serde = { version = "1", features = [ "derive" ] }
-criterion = "0.2"
-
-[[bench]]
-name = "building"
-harness = false
diff --git a/lib/smol_str/benches/building.rs b/lib/smol_str/benches/building.rs
deleted file mode 100644
index 1983314676..0000000000
--- a/lib/smol_str/benches/building.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-#[macro_use]
-extern crate criterion;
-extern crate smol_str;
-
-use criterion::{Criterion, ParameterizedBenchmark, Throughput};
-use smol_str::SmolStr;
-
-fn from_str_iter(c: &mut Criterion) {
- use std::iter::FromIterator;
-
- const SIZES: &[usize] = &[0, 5, 10, 15, 20, 2 << 4, 2 << 5, 2 << 6, 2 << 7, 2 << 8];
-
- fn test_data(input: &str, size: usize) -> Vec<&str> {
- std::iter::repeat(input).take(size / input.len()).collect()
- }
-
- c.bench(
- "FromIterator",
- ParameterizedBenchmark::new(
- "SmolStr, one byte elements",
- |b, &&size| {
- let src = test_data("x", size);
- b.iter(|| SmolStr::from_iter(src.iter().cloned()).len())
- },
- SIZES,
- )
- .with_function("SmolStr, five byte elements", |b, &&size| {
- let src = test_data("helloo", size);
- b.iter(|| SmolStr::from_iter(src.iter().cloned()).len())
- })
- .with_function("String, one byte elements", |b, &&size| {
- let src = test_data("x", size);
- b.iter(|| String::from_iter(src.iter().cloned()).len())
- })
- .with_function("String, five byte elements", |b, &&size| {
- let src = test_data("hello", size);
- b.iter(|| String::from_iter(src.iter().cloned()).len())
- })
- .throughput(|elems| Throughput::Bytes(**elems as u32)),
- );
-}
-
-criterion_group!(benches, from_str_iter);
-criterion_main!(benches);
diff --git a/lib/smol_str/bors.toml b/lib/smol_str/bors.toml
index 574c56320f..b92b99ac30 100644
--- a/lib/smol_str/bors.toml
+++ b/lib/smol_str/bors.toml
@@ -1,4 +1,2 @@
-status = [
- "continuous-integration/travis-ci/push",
-]
+status = [ "Rust" ]
delete_merged_branches = true
diff --git a/lib/smol_str/src/lib.rs b/lib/smol_str/src/lib.rs
index 945bbc9d70..6136878b3e 100644
--- a/lib/smol_str/src/lib.rs
+++ b/lib/smol_str/src/lib.rs
@@ -25,67 +25,7 @@ use std::{
pub struct SmolStr(Repr);
impl SmolStr {
- /// Constructs an inline variant of `SmolStr` at compile time.
- ///
- /// # Parameters
- ///
- /// - `len`: Must be short (≤ 22 bytes)
- /// - `bytes`: Must be ASCII bytes, and there must be at least `len` of
- /// them. If `len` is smaller than the actual len of `bytes`, the string
- /// is truncated.
- ///
- /// # Returns
- ///
- /// A constant `SmolStr` with inline data.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use smol_str::SmolStr;
- /// const IDENT: SmolStr = SmolStr::new_inline_from_ascii(5, b"hello");
- /// ```
- ///
- /// Given a `len` smaller than the number of bytes in `bytes`, the string is
- /// cut off:
- ///
- /// ```rust
- /// # use smol_str::SmolStr;
- /// const SHORT: SmolStr = SmolStr::new_inline_from_ascii(5, b"hello world");
- /// assert_eq!(SHORT.as_str(), "hello");
- /// ```
- ///
- /// ## Compile-time errors
- ///
- /// This will **fail** at compile-time with a message like "index out of
- /// bounds" on a `_len_is_short` because the string is too large:
- ///
- /// ```rust,compile_fail
- /// # use smol_str::SmolStr;
- /// const IDENT: SmolStr = SmolStr::new_inline_from_ascii(
- /// 49,
- /// b"hello world, how are you doing this fine morning?",
- /// );
- /// ```
- ///
- /// Similarly, this will **fail** to compile with "index out of bounds" on
- /// an `_is_ascii` binding because it contains non-ASCII characters:
- ///
- /// ```rust,compile_fail
- /// # use smol_str::SmolStr;
- /// const IDENT: SmolStr = SmolStr::new_inline_from_ascii(
- /// 2,
- /// &[209, 139],
- /// );
- /// ```
- ///
- /// Last but not least, given a `len` that is larger than the number of
- /// bytes in `bytes`, it will fail to compile with "index out of bounds: the
- /// len is 5 but the index is 5" on a binding called `byte`:
- ///
- /// ```rust,compile_fail
- /// # use smol_str::SmolStr;
- /// const IDENT: SmolStr = SmolStr::new_inline_from_ascii(10, b"hello");
- /// ```
+ #[deprecated = "Use `new_inline` instead"]
pub const fn new_inline_from_ascii(len: usize, bytes: &[u8]) -> SmolStr {
let _len_is_short = [(); INLINE_CAP + 1][len];
@@ -108,6 +48,23 @@ impl SmolStr {
})
}
+ /// Constructs inline variant of `SmolStr`.
+ ///
+ /// Panics if `text.len() > 22`.
+ #[inline]
+ pub const fn new_inline(text: &str) -> SmolStr {
+ let mut buf = [0; INLINE_CAP];
+ let mut i = 0;
+ while i < text.len() {
+ buf[i] = text.as_bytes()[i];
+ i += 1
+ }
+ SmolStr(Repr::Inline {
+ len: text.len() as u8,
+ buf,
+ })
+ }
+
pub fn new<T>(text: T) -> SmolStr
where
T: AsRef<str>,
diff --git a/lib/smol_str/tests/test.rs b/lib/smol_str/tests/test.rs
index 57c0e8447f..537df8ddb2 100644
--- a/lib/smol_str/tests/test.rs
+++ b/lib/smol_str/tests/test.rs
@@ -1,5 +1,4 @@
-#[macro_use]
-extern crate proptest;
+use proptest::{prop_assert, prop_assert_eq, proptest};
use smol_str::SmolStr;
@@ -27,6 +26,20 @@ fn conversions() {
#[test]
fn const_fn_ctor() {
+ const EMPTY: SmolStr = SmolStr::new_inline("");
+ const A: SmolStr = SmolStr::new_inline("A");
+ const HELLO: SmolStr = SmolStr::new_inline("HELLO");
+ const LONG: SmolStr = SmolStr::new_inline("ABCDEFGHIZKLMNOPQRSTUV");
+
+ assert_eq!(EMPTY, SmolStr::from(""));
+ assert_eq!(A, SmolStr::from("A"));
+ assert_eq!(HELLO, SmolStr::from("HELLO"));
+ assert_eq!(LONG, SmolStr::from("ABCDEFGHIZKLMNOPQRSTUV"));
+}
+
+#[allow(deprecated)]
+#[test]
+fn old_const_fn_ctor() {
const EMPTY: SmolStr = SmolStr::new_inline_from_ascii(0, b"");
const A: SmolStr = SmolStr::new_inline_from_ascii(1, b"A");
const HELLO: SmolStr = SmolStr::new_inline_from_ascii(5, b"HELLO");