1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//! Constants and functions for CoAP options
//!
//! Option numbers are expressed as u16 values as that is the range assigned at IANA, and also the
//! practicably expressible range.

/// Classification of options by their default end-point behavior
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Criticality {
    /// Servers that receive such an option and do not know it MUST return 4.02 Bad Option, and
    /// clients MUST reject responses carrying any such.
    Critical,
    /// Endpoints receiving an unrecognized option oif this kind MUST silently ignore them.
    Elective
}

/// Extract the option's critical/elective bit
///
/// ```
/// # use coap_numbers::option::*;
/// assert_eq!(get_criticality(OBSERVE), Criticality::Elective);
/// assert_eq!(get_criticality(URI_HOST), Criticality::Critical);
/// ```
#[inline]
pub fn get_criticality(option: u16) -> Criticality {
    if option & 1 == 1 {
        Criticality::Critical
    } else {
        Criticality::Elective
    }
}

/// Classification of options by their default proxy behavior
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ProxySafety {
    /// A proxy can just forward such messages if it does not recognize them.
    ///
    /// The cache_key parameter is true for options that are part of the cache key, and false for
    /// those that are not.
    SafeToForward { cache_key: bool },
    /// A proxy MUST reject forwarding such messages with 4.02 Bad Option if it does not know them
    Unsafe,
}

/// Extract the option's proxy safety bit(s)
///
/// ```
/// # use coap_numbers::option::*;
/// assert_eq!(get_proxy_safety(ETAG), ProxySafety::SafeToForward { cache_key: true });
/// assert_eq!(get_proxy_safety(SIZE1), ProxySafety::SafeToForward { cache_key: false });
/// assert_eq!(get_proxy_safety(BLOCK1), ProxySafety::Unsafe);
/// ```
#[inline]
pub fn get_proxy_safety(option: u16) -> ProxySafety {
    if option & 0x02 == 0x02 {
        ProxySafety::Unsafe
    } else {
        ProxySafety::SafeToForward { cache_key: option & 0x1e != 0x1c }
    }
}

macro_rules! options {
    ( $( $num:tt $constname:ident $name:tt ) , * ) => { $(
            #[doc=$name]
            pub const $constname: u16 = $num;
        )*

        /// Find the name for a CoAP option, if any is known
        ///
        /// Returns the registered name for an option, or None if it is not known.
        ///
        /// ```
        /// # use coap_numbers::option::*;
        /// assert_eq!(to_name(URI_HOST), Some("Uri-Host"));
        /// assert_eq!(to_name(65000), None);
        /// ```
        pub fn to_name(option: u16) -> Option<&'static str> {
            match option {
                $(
                $constname => Some($name),
                )*
                _ => None
            }
        }
    }
}


options!(
    1 IF_MATCH "If-Match",
    3 URI_HOST "Uri-Host",
    4 ETAG "ETag",
    5 IF_NONE_MATCH "If-None-Match",
    6 OBSERVE "Observe",
    7 URI_PORT "Uri-Port",
    8 LOCATION_PATH "Location-Path",
    9 OSCORE "OSCORE",
    11 URI_PATH "Uri-Path",
    12 CONTENT_FORMAT "Content-Format",
    14 MAX_AGE "Max-Age",
    15 URI_QUERY "Uri-Query",
    16 HOP_LIMIT "Hop-Limit",
    17 ACCEPT "Accept",
    19 Q_BLOCK1 "Q-Block1",
    20 LOCATION_QUERY "Location-Query",
    21 EDHOC "EDHOC",
    23 BLOCK2 "Block2",
    27 BLOCK1 "Block1",
    28 SIZE2 "Size2",
    31 Q_BLOCK2 "Q-Block2",
    35 PROXY_URI "Proxy-Uri",
    39 PROXY_SCHEME "Proxy-Scheme",
    60 SIZE1 "Size1",
    252 ECHO "Echo",
    258 NO_RESPONSE "No-Response",
    292 REQUEST_TAG "Request-Tag",
    2049 OCF_ACCEPT_CONTENT_FORMAT_VERSION "OCF-Accept-Content-Format-Version",
    2053 OCF_CONTENT_FORMAT_VERSION "OCF-Content-Format-Version",
    2055 SCP82_PARAMS "SCP82-Params"
);