async_coap/
content_format.rs

1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15
16use std::borrow::Cow;
17
18/// A type for representing a CoAP Content Format value.
19#[derive(Debug, Copy, Eq, PartialEq, Hash, Clone, Ord, PartialOrd)]
20pub struct ContentFormat(pub u16);
21
22impl ContentFormat {
23    /// From IETF-RFC7252.
24    pub const TEXT_PLAIN_UTF8: ContentFormat = ContentFormat(0);
25
26    /// From IETF-RFC8152
27    pub const APPLICATION_COSE_COSE_ENCRYPT0: ContentFormat = ContentFormat(16);
28
29    /// From IETF-RFC8152
30    pub const APPLICATION_COSE_COSE_MAC0: ContentFormat = ContentFormat(17);
31
32    /// From IETF-RFC8152
33    pub const APPLICATION_COSE_COSE_SIGN1: ContentFormat = ContentFormat(18);
34
35    /// From IETF-RFC7252.
36    pub const APPLICATION_LINK_FORMAT: ContentFormat = ContentFormat(40);
37
38    /// From IETF-RFC7252.
39    pub const APPLICATION_XML: ContentFormat = ContentFormat(41);
40
41    /// From IETF-RFC7252.
42    pub const APPLICATION_OCTET_STREAM: ContentFormat = ContentFormat(42);
43
44    /// From IETF-RFC7252.
45    pub const APPLICATION_EXI: ContentFormat = ContentFormat(47);
46
47    /// From IETF-RFC7252.
48    pub const APPLICATION_JSON: ContentFormat = ContentFormat(50);
49
50    /// From IETF-RFC6902 JavaScript Object Notation (JSON) Patch
51    pub const APPLICATION_JSON_PATCH_JSON: ContentFormat = ContentFormat(51);
52
53    /// From IETF-RFC7396 JSON Merge Patch
54    pub const APPLICATION_MERGE_PATCH_JSON: ContentFormat = ContentFormat(52);
55
56    /// From IETF-RFC7049 Concise Binary Object Representation (CBOR)
57    pub const APPLICATION_CBOR: ContentFormat = ContentFormat(60);
58
59    /// From IETF-RFC8392 CBOR Web Token
60    pub const APPLICATION_CWT: ContentFormat = ContentFormat(61);
61
62    /// From IETF-RFC8152
63    pub const APPLICATION_COSE_COSE_ENCRYPT: ContentFormat = ContentFormat(96);
64
65    /// From IETF-RFC8152
66    pub const APPLICATION_COSE_COSE_MAC: ContentFormat = ContentFormat(97);
67
68    /// From IETF-RFC8152
69    pub const APPLICATION_COSE_COSE_SIGN: ContentFormat = ContentFormat(98);
70
71    /// From IETF-RFC8152
72    pub const APPLICATION_COSE_KEY: ContentFormat = ContentFormat(101);
73
74    /// From IETF-RFC8152
75    pub const APPLICATION_COSE_KEY_SET: ContentFormat = ContentFormat(102);
76
77    /// JSON-formatted RFC8428 Sensor Measurement Lists (SenML)
78    pub const APPLICATION_SENML_JSON: ContentFormat = ContentFormat(110);
79
80    /// JSON-formatted RFC8428 Sensor Streaming Measurement List (SenSML)
81    pub const APPLICATION_SENSML_JSON: ContentFormat = ContentFormat(111);
82
83    /// CBOR-formatted RFC8428 Sensor Measurement Lists (SenML)
84    pub const APPLICATION_SENML_CBOR: ContentFormat = ContentFormat(112);
85
86    /// CBOR-formatted RFC8428 Sensor Streaming Measurement List (SenSML)
87    pub const APPLICATION_SENSML_CBOR: ContentFormat = ContentFormat(113);
88
89    /// EXI-formatted RFC8428 Sensor Measurement Lists (SenML)
90    pub const APPLICATION_SENML_EXI: ContentFormat = ContentFormat(114);
91
92    /// EXI-formatted RFC8428 Sensor Streaming Measurement List (SenSML)
93    pub const APPLICATION_SENSML_EXI: ContentFormat = ContentFormat(115);
94
95    /// XML-formatted RFC8428 Sensor Measurement Lists (SenML)
96    pub const APPLICATION_SENML_XML: ContentFormat = ContentFormat(310);
97
98    /// XML-formatted RFC8428 Sensor Streaming Measurement List (SenSML)
99    pub const APPLICATION_SENSML_XML: ContentFormat = ContentFormat(311);
100
101    /// [IETF-RFC7389] Group Communication for the Constrained Application Protocol
102    ///
103    /// [IETF-RFC7389]: https://tools.ietf.org/html/rfc7390#section-6.2
104    pub const APPLICATION_COAP_GROUP_JSON: ContentFormat = ContentFormat(256);
105
106    /// From RFC-ietf-core-object-security-16
107    pub const APPLICATION_OSCORE: ContentFormat = ContentFormat(10001);
108
109    /// Same as `application/json`, but with *deflate* compression.
110    pub const APPLICATION_JSON_DEFLATE: ContentFormat = ContentFormat(11050);
111
112    /// Same as `application/cbor`, but with *deflate* compression.
113    pub const APPLICATION_CBOR_DEFLATE: ContentFormat = ContentFormat(11060);
114
115    /// Returns the MIME name of this content format as a `&'static str`, if possible.
116    pub fn static_name(self) -> Option<&'static str> {
117        Some(match self {
118            Self::TEXT_PLAIN_UTF8 => "text/plain;charset=utf-8",
119            Self::APPLICATION_LINK_FORMAT => "application/link-format",
120            Self::APPLICATION_XML => "application/xml",
121            Self::APPLICATION_OCTET_STREAM => "application/octet-stream",
122            Self::APPLICATION_EXI => "application/exi",
123            Self::APPLICATION_JSON => "application/json",
124            Self::APPLICATION_CBOR => "application/cbor",
125            Self::APPLICATION_COSE_COSE_ENCRYPT0 => "application/cose;cose-type=\"cose-encrypt0\"",
126            Self::APPLICATION_COSE_COSE_MAC0 => "application/cose;cose-type=\"cose-mac0\"",
127            Self::APPLICATION_COSE_COSE_SIGN1 => "application/cose;cose-type=\"cose-sign1\"",
128            Self::APPLICATION_COSE_COSE_ENCRYPT => "application/cose;cose-type=\"cose-encrypt\"",
129            Self::APPLICATION_COSE_COSE_MAC => "application/cose;cose-type=\"cose-mac\"",
130            Self::APPLICATION_COSE_COSE_SIGN => "application/cose;cose-type=\"cose-sign\"",
131            Self::APPLICATION_COSE_KEY => "application/cose-key",
132            Self::APPLICATION_COSE_KEY_SET => "application/cose-key-set",
133
134            Self::APPLICATION_JSON_PATCH_JSON => "application/json-patch+json",
135            Self::APPLICATION_MERGE_PATCH_JSON => "application/merge-patch+json",
136            Self::APPLICATION_CWT => "application/cwt",
137
138            Self::APPLICATION_SENML_JSON => "application/senml+json",
139            Self::APPLICATION_SENSML_JSON => "application/sensml+json",
140            Self::APPLICATION_SENML_CBOR => "application/senml+cbor",
141            Self::APPLICATION_SENSML_CBOR => "application/sensml+cbor",
142            Self::APPLICATION_SENML_EXI => "application/senml+exi",
143            Self::APPLICATION_SENSML_EXI => "application/sensml+exi",
144            Self::APPLICATION_SENML_XML => "application/senml+xml",
145            Self::APPLICATION_SENSML_XML => "application/sensml+xml",
146
147            Self::APPLICATION_COAP_GROUP_JSON => "application/coap-group+json",
148
149            Self::APPLICATION_OSCORE => "application/oscore",
150
151            Self::APPLICATION_JSON_DEFLATE => "application/json;deflate",
152            Self::APPLICATION_CBOR_DEFLATE => "application/cbor;deflate",
153            _ => return None,
154        })
155    }
156
157    /// Returns a MIME name for this content format.
158    pub fn name(&self) -> Cow<'static, str> {
159        if let Some(name) = self.static_name() {
160            Cow::from(name)
161        } else {
162            Cow::from(self.to_string())
163        }
164    }
165
166    /// Experimental.
167    #[doc(hidden)]
168    pub fn is_deflated(self) -> Option<ContentFormat> {
169        if self.0 >= 11000 && self.0 <= 11500 {
170            Some(ContentFormat(self.0 - 11000))
171        } else {
172            None
173        }
174    }
175
176    /// Returns true if this content format is known to contain UTF8.
177    pub fn is_utf8(self) -> bool {
178        match self {
179            Self::TEXT_PLAIN_UTF8 => true,
180            Self::APPLICATION_LINK_FORMAT => true,
181            _ => self.is_xml() || self.is_json(),
182        }
183    }
184
185    /// Returns true if this content format is known to contain JSON.
186    pub fn is_json(self) -> bool {
187        match self {
188            Self::APPLICATION_JSON => true,
189            Self::APPLICATION_JSON_PATCH_JSON => true,
190            Self::APPLICATION_MERGE_PATCH_JSON => true,
191            Self::APPLICATION_SENML_JSON => true,
192            Self::APPLICATION_SENSML_JSON => true,
193            Self::APPLICATION_COAP_GROUP_JSON => true,
194
195            _ => false,
196        }
197    }
198
199    /// Returns true if this content format is known to contain XML.
200    pub fn is_xml(self) -> bool {
201        match self {
202            Self::APPLICATION_XML => true,
203            Self::APPLICATION_SENML_XML => true,
204            Self::APPLICATION_SENSML_XML => true,
205            _ => false,
206        }
207    }
208
209    /// Returns true if this content format is known to contain EXI.
210    pub fn is_exi(self) -> bool {
211        match self {
212            Self::APPLICATION_EXI => true,
213            Self::APPLICATION_SENML_EXI => true,
214            Self::APPLICATION_SENSML_EXI => true,
215            _ => false,
216        }
217    }
218
219    /// Returns true if this content format is known to contain CBOR.
220    pub fn is_cbor(self) -> bool {
221        match self {
222            Self::APPLICATION_CBOR => true,
223            Self::APPLICATION_CWT => true,
224            Self::APPLICATION_SENML_CBOR => true,
225            Self::APPLICATION_SENSML_CBOR => true,
226            Self::APPLICATION_OSCORE => true,
227            _ => false,
228        }
229    }
230}
231
232impl core::fmt::Display for ContentFormat {
233    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
234        if let Some(n) = self.static_name() {
235            f.write_str(n)
236        } else {
237            write!(f, "application/x-coap-{}", self.0)
238        }
239    }
240}