Skip to main content

freeswitch_types/sofia/
sip_user.rs

1//! SIP user ping status enum.
2
3use std::fmt;
4use std::str::FromStr;
5
6/// Error returned when parsing an unrecognized SIP user ping status.
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct ParseSipUserPingStatusError(pub String);
9
10impl fmt::Display for ParseSipUserPingStatusError {
11    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12        write!(f, "unknown sip user ping status: {}", self.0)
13    }
14}
15
16impl std::error::Error for ParseSipUserPingStatusError {}
17
18/// SIP user ping status from `sofia::sip_user_state` events.
19///
20/// The `Ping-Status` header value, mapping to `sofia_sip_user_status_name()`.
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23#[non_exhaustive]
24#[allow(missing_docs)]
25pub enum SipUserPingStatus {
26    Unreachable,
27    Reachable,
28    Invalid,
29}
30
31impl SipUserPingStatus {
32    /// Wire-format string.
33    pub const fn as_str(&self) -> &'static str {
34        match self {
35            Self::Unreachable => "UNREACHABLE",
36            Self::Reachable => "REACHABLE",
37            Self::Invalid => "INVALID",
38        }
39    }
40}
41
42impl fmt::Display for SipUserPingStatus {
43    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44        f.write_str(self.as_str())
45    }
46}
47
48impl FromStr for SipUserPingStatus {
49    type Err = ParseSipUserPingStatusError;
50
51    fn from_str(s: &str) -> Result<Self, Self::Err> {
52        match s {
53            "UNREACHABLE" => Ok(Self::Unreachable),
54            "REACHABLE" => Ok(Self::Reachable),
55            "INVALID" => Ok(Self::Invalid),
56            _ => Err(ParseSipUserPingStatusError(s.to_string())),
57        }
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    const ALL: &[SipUserPingStatus] = &[
66        SipUserPingStatus::Unreachable,
67        SipUserPingStatus::Reachable,
68        SipUserPingStatus::Invalid,
69    ];
70
71    #[test]
72    fn round_trip() {
73        for &status in ALL {
74            let wire = status.to_string();
75            let parsed: SipUserPingStatus = wire
76                .parse()
77                .unwrap();
78            assert_eq!(parsed, status, "round-trip failed for {wire}");
79        }
80    }
81
82    #[test]
83    fn rejects_unknown() {
84        assert!("BOGUS"
85            .parse::<SipUserPingStatus>()
86            .is_err());
87        assert!("reachable"
88            .parse::<SipUserPingStatus>()
89            .is_err());
90    }
91}