#chaining #nested #result #error #no-alloc

no-std only_one

Provides the OnlyOne trait, which allows less nesting when chaining results

1 unstable release

Uses new Rust 2024

0.1.0 Oct 25, 2025

#1954 in Rust patterns

MIT/Apache

11KB
144 lines

Only One

Extra functionality to reduce nesting with result chaining.

How to use with Cargo:

[dependencies]
only_one = "0.1.0"

How to use in your crate:

use only_one::OnlyOne;

License

Dual-licensed to be compatible with the Rust project.

Licensed under the Apache License, Version 2.0 https://www.apache.org/licenses/LICENSE-2.0 or the MIT license https://opensource.org/licenses/MIT, at your option. This file may not be copied, modified, or distributed except according to those terms.


lib.rs:

A Crate that defines the OnlyOne trait. This traits allows for result chaining in a way that reduces nesting

Examples

This is a contrived example, because realistically you would just call std::fs::read_to_string.

use only_one::OnlyOne;

#[derive(Debug, PartialEq, thiserror::Error)]
#[error(":shrug:")]
struct SomeError;

impl From<std::io::Error> for SomeError {
    fn from(_e: std::io::Error) -> Self {
        SomeError
    }
}

/// This function is equivalent to `chain`
fn question_mark() -> Result<usize, SomeError> {
    let path = "src/main.rs";
    let mut v = vec![];
    let f = std::fs::exists(path)?;
    if f {
        let mut file = std::fs::File::open(path)?;
        let read = file.read_to_end(&mut v)?;
        let bytes = v.get(0..read).ok_or(SomeError)?;
        let v = Vec::from(bytes);
        let s = String::from_utf8(v).map_err(|_| SomeError)?;
        Ok(s.lines().count())
    } else {
        Err(SomeError)
    }
}

fn chain() -> Result<usize, SomeError> {
    let path = "src/main.rs";
    let mut v = vec![];
    if let Ok(f) = std::fs::exists(path)
        && f
    {
        std::fs::File::open(path)
            .map_err(|_| SomeError)
            .only(|mut file| file.read_to_end(&mut v))
            .only_or(|read| v.get(0..read), SomeError)
            .only(|bytes| {
                let v = Vec::from(bytes);
                String::from_utf8(v).map_err(|_| SomeError)
            })
            .map(|s| s.lines().count())
    } else {
        Err(SomeError)
    }
}

assert_eq!(question_mark(), chain());

No runtime deps