clap_clap/
id.rs

1use std::fmt::{Display, Formatter};
2
3use crate::ffi::{self, CLAP_INVALID_ID};
4
5/// A type that corresponds to CLAP's `clap_id`.
6///
7/// It is either a `u32` value less that [`u32::MAX`], or a value that
8/// represents an invalid id.
9///
10/// # Example
11///
12/// ```rust
13/// # use clap_clap::id::ClapId;
14/// let id = ClapId::from(3);
15///
16/// assert!(id.is_valid());
17/// assert_ne!(id, ClapId::invalid_id());
18/// ```
19#[derive(Default, Debug, Copy, Clone, Hash, PartialEq)]
20pub struct ClapId(Option<u32>);
21
22impl ClapId {
23    /// The value representing an invalid id.
24    pub const fn invalid_id() -> Self {
25        Self(None)
26    }
27
28    pub const fn is_valid(&self) -> bool {
29        self.0.is_some()
30    }
31}
32
33impl TryFrom<u32> for ClapId {
34    type Error = Error;
35
36    fn try_from(value: u32) -> Result<Self, Self::Error> {
37        (value != CLAP_INVALID_ID)
38            .then_some(Self(Some(value)))
39            .ok_or(Error::InvalidId)
40    }
41}
42
43impl TryFrom<i32> for ClapId {
44    type Error = Error;
45
46    fn try_from(value: i32) -> Result<Self, Self::Error> {
47        if value >= 0 {
48            (value as u32).try_into()
49        } else {
50            Err(Error::Underflow)
51        }
52    }
53}
54
55impl From<u16> for ClapId {
56    fn from(value: u16) -> Self {
57        Self(Some(value as u32))
58    }
59}
60
61impl TryFrom<usize> for ClapId {
62    type Error = Error;
63
64    fn try_from(value: usize) -> Result<Self, Self::Error> {
65        match u32::try_from(value).map_err(|_| Error::Overflow) {
66            Ok(v) => v.try_into(),
67            Err(e) => Err(e),
68        }
69    }
70}
71
72impl From<ClapId> for ffi::clap_id {
73    fn from(value: ClapId) -> Self {
74        value.0.unwrap_or(CLAP_INVALID_ID)
75    }
76}
77
78impl From<ClapId> for usize {
79    fn from(value: ClapId) -> Self {
80        u32::from(value) as usize
81    }
82}
83
84#[derive(Debug, Copy, Clone, PartialEq)]
85pub enum Error {
86    InvalidId,
87    Overflow,
88    Underflow,
89}
90
91impl Display for Error {
92    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
93        match self {
94            Error::InvalidId => write!(f, "invalid ID"),
95            Error::Overflow => write!(f, "overflow during type conversion"),
96            Error::Underflow => write!(f, "underflow during type conversion"),
97        }
98    }
99}
100
101impl std::error::Error for Error {}
102
103impl From<Error> for crate::Error {
104    fn from(value: Error) -> Self {
105        Self::Id(value)
106    }
107}