Skip to content
This repository has been archived by the owner on Aug 15, 2021. It is now read-only.

Commit

Permalink
Add the cbor!() macro
Browse files Browse the repository at this point in the history
The cbor!() macro is inspired by serde_json::json!(), but the
implementation is simpler and the macro should be more useful. In
particular, the cbor!() macro returns Result<Value, Error>, so it can be
used in places that need careful error handling.
  • Loading branch information
npmccallum committed Jul 6, 2020
1 parent a218403 commit a18e4be
Show file tree
Hide file tree
Showing 4 changed files with 492 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ serde = { version = "1.0.14", default-features = false }

[dev-dependencies]
serde_derive = { version = "1.0.14", default-features = false }
serde_bytes = { version = "0.11", default-features = false }

[features]
default = ["std"]
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,9 @@ extern crate std;
#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(feature = "std")]
mod macros;

pub mod de;
pub mod error;
mod read;
Expand Down
122 changes: 122 additions & 0 deletions src/macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/// Build a `Value` conveniently.
///
/// The syntax should be intuitive if you are familiar with JSON. You can also
/// inline simple Rust expressions, including custom values that implement
/// `serde::Serialize`. Note that this macro returns `Result<Value, Error>`,
/// so you should handle the error appropriately.
///
/// ```
/// use serde_cbor::cbor;
///
/// let bytes = serde_bytes::Bytes::new(b"\x00\x01\x02");
/// let value = cbor!({
/// "code" => 415,
/// "message" => null,
/// "continue" => false,
/// "extra" => { "numbers" => [8.2341e+4, 0.251425] },
/// "data" => bytes,
/// }).unwrap();
/// ```
#[macro_export]
macro_rules! cbor {
(@map {$($key:expr => $val:expr),*} $(,)?) => {{
#[allow(unused_mut)]
let mut map = ::std::collections::BTreeMap::new();

$(
map.insert(
$crate::value::to_value(cbor!( $key )?)?,
$crate::value::to_value(cbor!( $val )?)?,
);
)*

$crate::Value::Map(map)
}};

(@map {$($key:expr => $val:expr),*} { $($nkey:tt)* } => $($next:tt)*) => {
cbor!(
@map
{ $($key => $val),* }
cbor!({ $($nkey)* })? =>
$($next)*
)
};

(@map {$($key:expr => $val:expr),*} [ $($nkey:tt)* ] => $($next:tt)*) => {
cbor!(
@map
{ $($key => $val),* }
cbor!([ $($nkey)* ])? =>
$($next)*
)
};

(@map {$($key:expr => $val:expr),*} $nkey:expr => { $($nval:tt)* }, $($next:tt)*) => {
cbor!(
@map
{ $($key => $val,)* $nkey => cbor!({ $($nval)* })? }
$($next)*
)
};

(@map {$($key:expr => $val:expr),*} $nkey:expr => [ $($nval:tt)* ], $($next:tt)*) => {
cbor!(
@map
{ $($key => $val,)* $nkey => cbor!([ $($nval)* ])? }
$($next)*
)
};

(@map {$($key:expr => $val:expr),*} $nkey:expr => $nval:expr, $($next:tt)*) => {
cbor!(
@map
{ $($key => $val,)* $nkey => cbor!($nval)? }
$($next)*
)
};

(@array [$($val:expr),*] $(,)?) => {
$crate::Value::Array(
vec![$( cbor!($val)? ),*]
)
};

(@array [$($val:expr),*] { $($item:tt)* }, $($next:tt)*) => {
cbor!(
@array
[ $($val,)* cbor!({ $($item)* })? ]
$($next)*
)
};

(@array [$($val:expr),*] [ $($item:tt)* ], $($next:tt)*) => {
cbor!(
@array
[ $($val,)* cbor!([ $($item)* ])? ]
$($next)*
)
};

(@array [$($val:expr),*] $item:expr, $($next:tt)*) => {
cbor!(
@array
[ $($val,)* $item ]
$($next)*
)
};

({ $($next:tt)* }) => {(||{
::core::result::Result::<_, $crate::Error>::from(Ok(cbor!(@map {} $($next)* ,)))
})()};

([ $($next:tt)* ]) => {(||{
::core::result::Result::<_, $crate::Error>::from(Ok(cbor!(@array [] $($next)* ,)))
})()};

($val:expr) => {{
#[allow(unused_imports)]
use $crate::Value::Null as null;
$crate::value::to_value(&$val)
}};
}
Loading

0 comments on commit a18e4be

Please sign in to comment.