# query.QueryIteratorExt.one_or_none

- **Module:** query
- **Package:** libtmux
- **Language:** Rust
- **Kind:** method
- **Source:** https://github.com/libtmux/libtmux-rs/blob/84de9258a07d10bdd5f6da01b016a9ae06fe1210/crates/libtmux/src/query.rs#L606
- **Page:** https://libtmux.org/en/rs/latest/reference/query-queryiteratorext-one_or_none/

```
#[allow(clippy::module_name_repetitions)]
pub trait QueryIteratorExt: Iterator + Sized
fn one_or_none(mut self) -> Result<
    Option<Self::Item>,
    MultipleItemsError
>
```

Return zero or one item, or an error for multiple items.

At most two items are pulled from the iterator.

# Errors

Returns [`MultipleItemsError`] when a second item is present.

## Examples

```rust
use libtmux::query::QueryIteratorExt;

let empty: Vec<i32> = Vec::new();
assert_eq!(empty.iter().one_or_none(), Ok(None));

let values = [7];
assert_eq!(values.iter().one_or_none(), Ok(Some(&values[0])));
```

Handle missing and ambiguous matches. Compare exactly_one and one_or_none for no match, one match and multiple matches. Use a Unix environment with Git, rustup, and tmux 3.3a or newer. The toolchain file below pins Rust 1.97.1. In an empty directory, fetch the documented source:

```console
$ git clone https://github.com/libtmux/libtmux-rs.git libtmux-source &&
  git -C libtmux-source checkout --detach 84de9258a07d10bdd5f6da01b016a9ae06fe1210
```

Save this complete consumer setup as Cargo.toml:

[Source example](https://github.com/libtmux/libtmux-rs/blob/84de9258a07d10bdd5f6da01b016a9ae06fe1210/crates/libtmux/examples/api/consumer.toml).

```toml
[package]
name = "libtmux-api-example"
version = "0.0.0"
edition = "2024"
publish = false

[workspace]
exclude = ["libtmux-source"]

[dependencies]
libtmux = { path = "libtmux-source/crates/libtmux" }
tempfile = "3.20"
tokio = { version = "1.40", features = ["macros", "rt", "time"] }
```

Save this complete consumer setup as rust-toolchain.toml:

[Source example](https://github.com/libtmux/libtmux-rs/blob/84de9258a07d10bdd5f6da01b016a9ae06fe1210/rust-toolchain.toml).

```toml
[toolchain]
channel = "1.97.1"
components = ["clippy", "rust-src", "rustfmt"]
profile = "minimal"
```

Save this complete program as src/main.rs. It owns a private tmux socket, applies a ten-second task deadline, and reports both task and cleanup errors. Server::kill stops its daemon; Server::shutdown closes its client executor. Successful cleanup removes the temporary directory even when the task fails.

[Source example](https://github.com/libtmux/libtmux-rs/blob/84de9258a07d10bdd5f6da01b016a9ae06fe1210/crates/libtmux/examples/api_cardinality.rs).

```rust
//! Distinguish no match, one match and multiple matches.

use std::error::Error;
use std::time::Duration;

use libtmux::query::{ExactlyOneError, Filterable as _, MultipleItemsError, QueryIteratorExt as _};
use libtmux::{NewSessionOptions, Server, Session};

type ExampleError = Box<dyn Error>;

fn check(condition: bool, message: &str) -> Result<(), ExampleError> {
    if condition {
        Ok(())
    } else {
        Err(message.into())
    }
}

async fn demonstrate(server: &Server) -> Result<(), ExampleError> {
    server
        .new_session(NewSessionOptions::new("work").command("cat"))
        .await?;
    server
        .new_session(NewSessionOptions::new("review").command("cat"))
        .await?;
    let sessions = server.sessions().await?;
    let fields = Session::filter_fields();
    let work = fields.session_name.eq("work");
    let missing = fields.session_name.eq("missing");
    check(
        sessions
            .iter()
            .matching(&work)
            .exactly_one()?
            .name()
            .as_bytes()
            == b"work",
        "wrong single match",
    )?;
    check(
        sessions.iter().matching(&missing).one_or_none()?.is_none(),
        "missing match was present",
    )?;
    check(
        matches!(
            sessions.iter().matching(&missing).exactly_one(),
            Err(ExactlyOneError::NoItems)
        ),
        "missing match did not report NoItems",
    )?;
    check(
        matches!(
            sessions.iter().exactly_one(),
            Err(ExactlyOneError::MultipleItems)
        ),
        "ambiguous match was accepted",
    )?;
    check(
        matches!(sessions.iter().one_or_none(), Err(MultipleItemsError)),
        "optional lookup accepted multiple matches",
    )?;
    println!("cardinality: none, one, multiple");
    Ok(())
}

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), ExampleError> {
    let root = std::path::Path::new("/tmp/libtmux-rs-dev");
    std::fs::create_dir_all(root)?;
    let directory = tempfile::Builder::new()
        .prefix("api-cardinality-")
        .tempdir_in(root)?;
    std::fs::write(
        directory.path().join("owner"),
        std::process::id().to_string(),
    )?;
    let server = Server::builder()
        .socket_path(directory.path().join("tmux.sock"))
        .config_file("/dev/null")
        .default_timeout(Duration::from_secs(5))
        .build()?;
    let outcome = tokio::time::timeout(Duration::from_secs(10), demonstrate(&server)).await;

    // Stop the owned daemon before closing the client executor.
    let killed = server.kill().await;
    let closed = server.shutdown().await;
    let cleanup_failed = killed.is_err() || closed.is_err();
    let mut failures = Vec::new();
    match outcome {
        Ok(Ok(())) => {}
        Ok(Err(error)) => failures.push(format!("example failed: {error}")),
        Err(error) => failures.push(format!("example deadline: {error}")),
    }
    if let Err(error) = killed {
        failures.push(format!("daemon cleanup: {error}"));
    }
    if let Err(error) = closed {
        failures.push(format!("executor cleanup: {error}"));
    }
    if cleanup_failed {
        let retained = directory.keep();
        failures.push(format!("inspect retained directory {}", retained.display()));
    } else if let Err(error) = directory.close() {
        failures.push(format!("directory cleanup: {error}"));
    }
    if failures.is_empty() {
        Ok(())
    } else {
        Err(failures.join("; ").into())
    }
}
```

Copy the complete files from the pinned checkout and run the consumer. This also creates src for the displayed program. Success exits with status 0; setup, operation, deadline or cleanup failures exit unsuccessfully and print diagnostics to stderr:

```console
$ mkdir -p src &&
  cp libtmux-source/crates/libtmux/examples/api/consumer.toml Cargo.toml &&
  cp libtmux-source/rust-toolchain.toml rust-toolchain.toml &&
  cp libtmux-source/crates/libtmux/examples/api_cardinality.rs src/main.rs &&
  cargo run --quiet
```

Expected output:

```text
cardinality: none, one, multiple
```

## Parameters

- `mut self`
