async_coap_uri/
macros.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
16//! Module containing all of macro definitions for `async-coap-uri`.
17
18pub use super::{impl_uri_buf_traits, impl_uri_traits};
19pub use super::{rel_ref, uri, uri_ref};
20pub use super::{rel_ref_format, uri_format, uri_ref_format};
21
22// Internal macros.
23#[doc(hidden)]
24pub use super::{_impl_uri_buf_traits_base, _impl_uri_traits, _impl_uri_traits_base};
25
26#[doc(hidden)]
27#[macro_export]
28macro_rules! _uri_const {
29    ( $S:expr, $C:ty ) => {{
30        const __CONST_S: &'static str = $S;
31        // We do this weird casting thing here to make sure that we
32        // don't end up using unstable features, while still allowing
33        // these macros to be used to assign constants.
34        unsafe {
35            union Slices<'a> {
36                str: &'a str,
37                uri: &'a $C,
38            }
39            Slices { str: __CONST_S }.uri
40        }
41    }};
42}
43
44/// Creates a `&'static UriRef` from a string literal.
45///
46/// Accepts only string constants and literals. The given string *MUST* be well-formed.
47///
48/// Examples:
49///
50/// ```
51/// # use async_coap_uri::prelude::*;
52/// let x = uri_ref!("a/b/c?q=foobar#frag");
53/// assert_eq!(x.scheme(),None);
54/// assert_eq!(x.raw_authority(),None);
55/// assert_eq!(x.raw_path(),"a/b/c");
56/// assert_eq!(x.raw_query(),Some("q=foobar"));
57/// assert_eq!(x.raw_fragment(),Some("frag"));
58/// ```
59///
60/// ```
61/// # use async_coap_uri::prelude::*;
62/// let x = uri_ref!("http://example.com");
63/// assert_eq!(x.scheme(),Some("http"));
64/// assert_eq!(x.raw_authority(),Some("example.com"));
65/// assert_eq!(x.raw_path(),"");
66/// assert_eq!(x.raw_query(),None);
67/// assert_eq!(x.raw_fragment(),None);
68/// ```
69///
70/// Checks for correctness are performed at compile time:
71///
72/// ```compile_fail
73/// # use async_coap_uri::prelude::*;
74/// // This will not compile.
75/// let x = uri_ref!("%00 invalid %ff");
76/// ```
77///
78#[macro_export]
79macro_rules! uri_ref {
80    ( unsafe $S:expr ) => {{
81        // We don't do any correctness checks when $S is preceded by `unsafe`.
82        $crate::_uri_const!($S, $crate::UriRef)
83    }};
84    ( $S:expr ) => {{
85        assert_uri_ref_literal!($S);
86        $crate::_uri_const!($S, $crate::UriRef)
87    }};
88    ( ) => {
89        $crate::uri_ref!("")
90    };
91}
92
93/// Creates a `&'static RelRef` from a string literal.
94///
95/// Accepts only string constants and literals. The given string *MUST* be well-formed.
96///
97/// Example:
98///
99/// ```
100/// # use async_coap_uri::prelude::*;
101/// let x = rel_ref!("a/b/c?q=foobar#frag");
102/// assert_eq!(x.raw_path(),"a/b/c");
103/// assert_eq!(x.raw_query(),Some("q=foobar"));
104/// assert_eq!(x.raw_fragment(),Some("frag"));
105/// ```
106///
107/// Checks for correctness are performed at compile time:
108///
109/// ```compile_fail
110/// # use async_coap_uri::prelude::*;
111/// // This will not compile.
112/// let x = rel_ref!("%00 invalid %ff");
113/// ```
114///
115/// Degenerate cases (strings that could be confused with URIs if parsed as URI-Refs)
116/// will also not compile:
117///
118/// ```compile_fail
119/// # use async_coap_uri::prelude::*;
120/// // This will not compile because `//a/b/c` is
121/// // a degenerate relative reference.
122/// let x = rel_ref!("//a/b/c");
123/// ```
124///
125/// ```compile_fail
126/// # use async_coap_uri::prelude::*;
127/// // This will not compile because `g:a:b:c` is
128/// // a degenerate relative reference.
129/// let x = rel_ref!("g:a:b:c");
130/// ```
131///
132/// Both of those cases can be made to compile by adjusting them to no longer be degenerate:
133///
134/// ```
135/// # use async_coap_uri::prelude::*;
136/// let b = rel_ref!("/.//a/b/c"); // Prepending "/."
137/// let a = rel_ref!("./g:a:b:c"); // Prepending "./"
138/// let a = rel_ref!("g%3Aa:b:c"); // Convert first colon to "%3A"
139/// ```
140///
141/// At runtime, `UriRef::from_str("g:a:b:c")` is allowed since in some circumstances it cannot
142/// be avoided, but there is usually no good reason to have a degenerate `RelRef` literal.
143/// In the rare case where such a thing is warranted (unit tests, for example), you can disable
144/// compile-time verification by prepending the keyword `unsafe` to the string:
145///
146/// ```
147/// # use async_coap_uri::prelude::*;
148/// // Both of these will compile because the `unsafe` keyword
149/// // disables the compile-time validity checks:
150/// assert!(rel_ref!(unsafe "//a/b/c").is_degenerate());
151/// assert!(rel_ref!(unsafe "g:a:b:c").is_degenerate());
152/// ```
153#[macro_export]
154macro_rules! rel_ref {
155    ( unsafe $S:expr ) => {{
156        // We don't do any correctness checks when $S is preceded by `unsafe`.
157        $crate::_uri_const!($S, $crate::RelRef)
158    }};
159    ( $S:expr ) => {{
160        assert_rel_ref_literal!($S);
161        $crate::_uri_const!($S, $crate::RelRef)
162    }};
163    ( ) => {
164        $crate::rel_ref!("")
165    };
166}
167
168/// Creates a `&'static Uri` from a string literal.
169///
170/// Accepts only string constants and literals. The given string *MUST* be well-formed.
171///
172/// Example:
173///
174/// ```
175/// # use async_coap_uri::prelude::*;
176/// let x = uri!("http://example.com");
177/// assert_eq!(x.scheme(),Some("http"));
178/// assert_eq!(x.raw_authority(),Some("example.com"));
179/// ```
180///
181/// Checks for correctness are performed at compile time:
182///
183/// ```compile_fail
184/// # use async_coap_uri::prelude::*;
185/// // This will not compile.
186/// let x = uri!("%00 invalid %ff");
187/// ```
188///
189/// Passing something that is a valid URI-Reference but not a valid URI (i.e.: Missing scheme)
190/// will also not compile:
191///
192/// ```compile_fail
193/// # use async_coap_uri::prelude::*;
194/// // This will not compile because "a/b/c" isn't a valid URI.
195/// let x = uri!("a/b/c");
196/// ```
197///
198#[macro_export]
199macro_rules! uri {
200    ( unsafe $S:expr ) => {{
201        // We don't do any correctness checks when $S is preceded by `unsafe`.
202        $crate::_uri_const!($S, $crate::Uri)
203    }};
204    ( $S:expr ) => {{
205        assert_uri_literal!($S);
206        $crate::_uri_const!($S, $crate::Uri)
207    }};
208    ( ) => {
209        $crate::uri!("")
210    };
211}
212
213/// Creates a `Option<UriRefBuf>` from the given string format and arguments.
214///
215/// The resulting string is checked at runtime to ensure it is well-formed.
216#[cfg(feature = "std")]
217#[macro_export]
218macro_rules! uri_ref_format {
219    ($($arg:tt)*) => ($crate::UriRefBuf::from_string(format!($($arg)*)))
220}
221
222/// Creates a `Option<UriBuf>` from the given string format and arguments.
223///
224/// The resulting string is checked at runtime to ensure it is well-formed.
225#[cfg(feature = "std")]
226#[macro_export]
227macro_rules! uri_format {
228    ($($arg:tt)*) => ($crate::UriBuf::from_string(format!($($arg)*)))
229}
230
231/// Creates a `Option<RelRefBuf>` from the given string format and arguments.
232///
233/// The resulting string is checked at runtime to ensure it is well-formed.
234#[cfg(feature = "std")]
235#[macro_export]
236macro_rules! rel_ref_format {
237    ($($arg:tt)*) => ($crate::RelRefBuf::from_string(format!($($arg)*)))
238}
239
240#[doc(hidden)]
241#[macro_export]
242macro_rules! _impl_uri_traits {
243    ( $C:ty ) => {
244        impl<T: AsRef<str> + ?Sized> core::cmp::PartialEq<T> for $C {
245            fn eq(&self, other: &T) -> bool {
246                core::cmp::PartialEq::eq(self.as_str(), other.as_ref())
247            }
248        }
249
250        impl<T: AsRef<str> + ?Sized> core::cmp::PartialOrd<T> for $C {
251            fn partial_cmp(&self, other: &T) -> Option<::std::cmp::Ordering> {
252                core::cmp::PartialOrd::partial_cmp(self.as_str(), other.as_ref())
253            }
254        }
255
256        impl core::cmp::Ord for $C {
257            fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
258                core::cmp::Ord::cmp(self.as_str(), other.as_str())
259            }
260        }
261
262        impl std::fmt::Debug for $C {
263            fn fmt(
264                &self,
265                f: &mut std::fmt::Formatter<'_>,
266            ) -> std::result::Result<(), std::fmt::Error> {
267                f.write_str(concat!(stringify!($C), "<"))?;
268                std::fmt::Display::fmt(self.as_str(), f)?;
269                f.write_str(">")
270            }
271        }
272        impl AsRef<str> for $C {
273            fn as_ref(&self) -> &str {
274                self.as_str()
275            }
276        }
277        impl AsRef<$C> for $C {
278            fn as_ref(&self) -> &$C {
279                &self
280            }
281        }
282    };
283}
284
285#[doc(hidden)]
286#[macro_export]
287macro_rules! _impl_uri_traits_base {
288    ( $C:ty ) => {
289        _impl_uri_traits!($C);
290
291        impl core::convert::From<&$C> for std::string::String {
292            fn from(x: &$C) -> Self {
293                String::from(&x.0)
294            }
295        }
296
297        impl core::convert::From<&$C> for $crate::UriRefBuf {
298            fn from(x: &$C) -> Self {
299                unsafe { $crate::UriRefBuf::from_string_unchecked(String::from(&x.0)) }
300            }
301        }
302    };
303}
304
305#[doc(hidden)]
306#[macro_export]
307macro_rules! impl_uri_traits {
308    ( $C:ty ) => {
309        _impl_uri_traits_base!($C);
310
311        impl $crate::AnyUriRef for $C {
312            fn components(&self) -> UriRawComponents<'_> {
313                self.0.components()
314            }
315
316            fn write_to<W: core::fmt::Write + ?Sized>(
317                &self,
318                write: &mut W,
319            ) -> Result<(), core::fmt::Error> {
320                self.0.write_to(write)
321            }
322
323            fn is_empty(&self) -> bool {
324                self.0.is_empty()
325            }
326
327            fn uri_type(&self) -> $crate::UriType {
328                self.0.uri_type()
329            }
330
331            fn to_uri_ref_buf(&self) -> $crate::UriRefBuf {
332                self.0.to_uri_ref_buf()
333            }
334
335            fn write_resolved<W: core::fmt::Write + ?Sized, D: $crate::AnyUriRef + ?Sized>(
336                &self,
337                dest: &D,
338                output: &mut W,
339            ) -> Result<(), $crate::ResolveError> {
340                self.0.write_resolved(dest, output)
341            }
342
343            fn resolved<W: $crate::AnyUriRef + ?Sized>(
344                &self,
345                dest: &W,
346            ) -> Result<$crate::UriRefBuf, $crate::ResolveError> {
347                self.0.resolved(dest)
348            }
349        }
350    };
351}
352
353#[doc(hidden)]
354#[macro_export]
355macro_rules! _impl_uri_buf_traits_base {
356    ( $C:ty , $B:ty ) => {
357        _impl_uri_traits!($C);
358
359        impl core::convert::From<$C> for std::string::String {
360            fn from(x: $C) -> Self {
361                String::from(x.0)
362            }
363        }
364
365        impl core::convert::From<&$C> for $C {
366            fn from(x: &$C) -> Self {
367                x.clone()
368            }
369        }
370
371        impl std::borrow::ToOwned for $B {
372            type Owned = $C;
373
374            fn to_owned(&self) -> Self::Owned {
375                unsafe { <$C>::from_string_unchecked(self.to_string()) }
376            }
377        }
378
379        impl core::borrow::Borrow<$B> for $C {
380            fn borrow(&self) -> &$B {
381                unsafe { <$B>::from_str_unchecked(self.as_str()) }
382            }
383        }
384
385        impl $crate::AnyUriRef for $C {
386            fn components(&self) -> UriRawComponents<'_> {
387                use core::borrow::Borrow;
388                let b: &$B = self.borrow();
389                b.components()
390            }
391
392            fn write_to<W: core::fmt::Write + ?Sized>(
393                &self,
394                write: &mut W,
395            ) -> Result<(), core::fmt::Error> {
396                use core::borrow::Borrow;
397                let b: &$B = self.borrow();
398                b.write_to(write)
399            }
400
401            fn is_empty(&self) -> bool {
402                use core::borrow::Borrow;
403                let b: &$B = self.borrow();
404                b.is_empty()
405            }
406
407            fn uri_type(&self) -> $crate::UriType {
408                use core::borrow::Borrow;
409                let b: &$B = self.borrow();
410                b.uri_type()
411            }
412
413            fn to_uri_ref_buf(&self) -> $crate::UriRefBuf {
414                use core::borrow::Borrow;
415                let b: &$B = self.borrow();
416                b.to_uri_ref_buf()
417            }
418
419            fn write_resolved<W: core::fmt::Write + ?Sized, D: $crate::AnyUriRef + ?Sized>(
420                &self,
421                dest: &D,
422                output: &mut W,
423            ) -> Result<(), $crate::ResolveError> {
424                use core::borrow::Borrow;
425                let b: &$B = self.borrow();
426                b.write_resolved(dest, output)
427            }
428
429            fn resolved<W: $crate::AnyUriRef + ?Sized>(
430                &self,
431                dest: &W,
432            ) -> Result<$crate::UriRefBuf, $crate::ResolveError> {
433                use core::borrow::Borrow;
434                let b: &$B = self.borrow();
435                b.resolved(dest)
436            }
437        }
438    };
439}
440
441#[doc(hidden)]
442#[macro_export]
443macro_rules! impl_uri_buf_traits {
444    ( $C:ty , $B:ty) => {
445        _impl_uri_buf_traits_base!($C, $B);
446
447        impl AsRef<std::string::String> for $C {
448            fn as_ref(&self) -> &std::string::String {
449                AsRef::<std::string::String>::as_ref(&self.0)
450            }
451        }
452
453        impl AsRef<$crate::UriRefBuf> for $C {
454            fn as_ref(&self) -> &$crate::UriRefBuf {
455                AsRef::<$crate::UriRefBuf>::as_ref(&self.0)
456            }
457        }
458
459        impl core::convert::From<$C> for $crate::UriRefBuf {
460            fn from(x: $C) -> Self {
461                x.0.into()
462            }
463        }
464    };
465}