diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index 184a2ca..c8c0dc4 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -8,59 +8,82 @@ on: jobs: build: - name: Build and test + name: MSRV strategy: matrix: os: ['ubuntu-latest', 'macos-latest'] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@1.79.0 + with: + components: rustfmt, clippy + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: ~/.cargo/registry + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} - name: Build run: cargo build --verbose env: RUSTFLAGS: -D warnings - - name: Run tests + - name: Clippy + run: cargo clippy --all --tests + env: + RUSTFLAGS: -D warnings + - name: Test + run: cargo test --all --verbose + - name: Formatting + run: cargo fmt --all -- --check + - name: Docs + run: cargo doc --workspace --no-deps + env: + RUSTFLAGS: -D warnings + + build-serde: + name: Serde Build + strategy: + matrix: + os: ['ubuntu-latest', 'macos-latest'] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@1.81.0 + - name: Build + run: cargo build --verbose --features serialize + env: + RUSTFLAGS: -D warnings + - name: Test run: cargo test --all --verbose --features serialize,arbitrary - no-std: - name: no-std build and test + + build-bincode: + name: Bincode Build strategy: matrix: os: ['ubuntu-latest', 'macos-latest'] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@1.85.1 - name: Build - run: cargo build --verbose --no-default-features + run: cargo build --verbose --features serialize env: RUSTFLAGS: -D warnings - - name: Run tests - run: cargo test --all --verbose --no-default-features + - name: Test + run: cargo test --all --verbose --features bincode,arbitrary - rustfmt_and_clippy: - name: Check rustfmt style && run clippy - runs-on: ubuntu-latest + no-std: + name: no-std + strategy: + matrix: + os: ['ubuntu-latest', 'macos-latest'] + runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - profile: minimal - components: clippy, rustfmt - override: true - - name: Cache cargo registry - uses: actions/cache@v4 - with: - path: ~/.cargo/registry - key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} - - name: Run clippy - uses: actions-rs/cargo@v1 - with: - command: clippy - args: --all --tests --features serialize,arbitrary + - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@1.79.0 + - name: Build + run: cargo build --verbose --no-default-features env: RUSTFLAGS: -D warnings - - name: Check formating - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check + - name: Test + run: cargo test --all --verbose --no-default-features diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..b65e95d --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,161 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" +dependencies = [ + "derive_arbitrary", +] + +[[package]] +name = "bincode" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" +dependencies = [ + "bincode_derive", + "serde", + "unty", +] + +[[package]] +name = "bincode_derive" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09" +dependencies = [ + "virtue", +] + +[[package]] +name = "derive_arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "nonempty" +version = "0.12.0" +dependencies = [ + "arbitrary", + "bincode", + "serde", + "serde_json", +] + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "unty" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" + +[[package]] +name = "virtue" +version = "0.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" diff --git a/Cargo.toml b/Cargo.toml index a8b581a..743ca20 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ authors = ["Alexis Sellier "] edition = "2021" license = "MIT" repository = "https://github.com/cloudhead/nonempty" +rust-version = "1.79" [dependencies] serde = { features = ["derive", "alloc"], default-features = false, optional = true, version = "1" } diff --git a/src/lib.rs b/src/lib.rs index 07465bb..bdeeafe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1056,6 +1056,25 @@ impl Extend for NonEmpty { } } +impl From<[T; S]> for NonEmpty { + fn from(array: [T; S]) -> Self { + use alloc::collections::VecDeque; + const { + if S == 0 { + panic!("tried to construct NonEmpty from an empty array") + } + } + + let mut vec = VecDeque::from(array); + + // SAFETY: we know that S is not 0, so we can safely unwrap + NonEmpty { + head: vec.pop_front().unwrap(), + tail: vec.into(), + } + } +} + #[cfg(feature = "serialize")] pub mod serialize { use core::{convert::TryFrom, fmt}; @@ -1094,6 +1113,22 @@ mod tests { use crate::NonEmpty; + #[test] + fn test_const_array_construction() { + let xs: [usize; 2] = [1, 2]; + let expected = nonempty![1, 2]; + assert_eq!(NonEmpty::from(xs), expected); + + // N.b. uncommenting this below, rightfully, panics the evaluation of + // the program. This being left here for anyone to prove to themselves + // that this does indeed panic. Unfortunately, `#[should_panic]` does + // not work in this case, since the panic happens at evaluation time – + // due to the `const` – rather than run time. + + // let xs: [usize; 0] = []; + // let _ = NonEmpty::from(xs); + } + #[test] fn test_from_conversion() { let result = NonEmpty::from((1, vec![2, 3, 4, 5]));