1use std::fmt::{Display, Formatter};
2
3use crate::ffi::{self, CLAP_INVALID_ID};
4
5#[derive(Default, Debug, Copy, Clone, Hash, PartialEq)]
20pub struct ClapId(Option<u32>);
21
22impl ClapId {
23 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}