Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 57 additions & 34 deletions .github/workflows/actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
161 changes: 161 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ authors = ["Alexis Sellier <self@cloudhead.io>"]
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" }
Expand Down
35 changes: 35 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,25 @@ impl<A> Extend<A> for NonEmpty<A> {
}
}

impl<T, const S: usize> From<[T; S]> for NonEmpty<T> {
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};
Expand Down Expand Up @@ -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]));
Expand Down