Skip to content

Commit

Permalink
borError wraps coset::CoseError and impl std::Error and Display, and …
Browse files Browse the repository at this point in the history
…other changes

- use dtolnay/rust-toolchain@stable to setup Rus when running in act
- use Into where possible
  • Loading branch information
radumarias committed Sep 22, 2024
1 parent 890a199 commit 323e62b
Show file tree
Hide file tree
Showing 15 changed files with 115 additions and 208 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: setup Rust
uses: dtolnay/rust-toolchain@stable
if: ${{ github.event.act }}
with:
toolchain: stable
components: rustfmt, clippy

- name: Build
run: cargo build --all-targets

Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/event.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"act": true
}
2 changes: 1 addition & 1 deletion macros/src/to_cbor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ fn named_fields(isomdl_path: Ident, ident: Ident, input: FieldsNamed) -> TokenSt
fn to_cbor(self) -> Value {
let map = self.to_ns_map()
.into_iter()
.map(|(k, v)| (ciborium::Value::Text(k), v.try_into().unwrap()))
.map(|(k, v)| (Value::Text(k), v.try_into().unwrap()))
.collect();
Value::Map(map)
}
Expand Down
143 changes: 37 additions & 106 deletions src/cbor.rs
Original file line number Diff line number Diff line change
@@ -1,136 +1,67 @@
use std::io::Cursor;

use ciborium::Value;
use coset::{cbor, CoseError, EndOfFile};
use coset::{cbor, CoseError};
use serde::{de, Serialize};
use thiserror::Error;

#[derive(Debug, Error)]
pub enum CborError {
/// CBOR decoding failure.
#[error("CBOR decoding failure: {0}")]
DecodeFailed(cbor::de::Error<EndOfFile>),
/// Duplicate map key detected.
#[error("duplicate map key")]
DuplicateMapKey,
/// CBOR encoding failure.
#[error("CBOR encoding failure")]
EncodeFailed,
/// CBOR input had extra data.
#[error("extraneous data")]
ExtraneousData,
/// Integer value on the wire is outside the range of integers representable in this crate.
/// See <https://crates.io/crates/coset/#integer-ranges>.
#[error("integer value out of range")]
OutOfRangeIntegerValue,
/// Unexpected CBOR item encountered (got, want).
#[error("unexpected item: {0}, want {1}")]
UnexpectedItem(&'static str, &'static str),
/// Unrecognized value in IANA-controlled range (with no private range).
#[error("unregistered IANA value")]
UnregisteredIanaValue,
/// Unrecognized value in neither IANA-controlled range nor private range.
#[error("unregistered non-private IANA value")]
UnregisteredIanaNonPrivateValue,
/// Value contains non-finite float (NaN or Infinity).
#[error("non finite floats")]
NonFiniteFloats,
}

impl PartialEq for CborError {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::DecodeFailed(_), Self::DecodeFailed(_)) => true,
(Self::DuplicateMapKey, Self::DuplicateMapKey) => true,
(Self::EncodeFailed, Self::EncodeFailed) => true,
(Self::ExtraneousData, Self::ExtraneousData) => true,
(Self::OutOfRangeIntegerValue, Self::OutOfRangeIntegerValue) => true,
(Self::UnexpectedItem(l_msg, l_want), Self::UnexpectedItem(r_msg, r_want)) => {
l_msg == r_msg && l_want == r_want
}
(Self::UnregisteredIanaValue, Self::UnregisteredIanaValue) => true,
(Self::UnregisteredIanaNonPrivateValue, Self::UnregisteredIanaNonPrivateValue) => true,
(Self::NonFiniteFloats, Self::NonFiniteFloats) => true,
_ => false,
}
}
}

impl Eq for CborError {}

impl Clone for CborError {
fn clone(&self) -> Self {
match self {
CborError::DecodeFailed(_) => panic!("cannot clone"),
CborError::DuplicateMapKey => CborError::DuplicateMapKey,
CborError::EncodeFailed => CborError::EncodeFailed,
CborError::ExtraneousData => CborError::ExtraneousData,
CborError::OutOfRangeIntegerValue => CborError::OutOfRangeIntegerValue,
CborError::UnexpectedItem(msg, want) => CborError::UnexpectedItem(msg, want),
CborError::UnregisteredIanaValue => CborError::UnregisteredIanaValue,
CborError::UnregisteredIanaNonPrivateValue => {
CborError::UnregisteredIanaNonPrivateValue
}
CborError::NonFiniteFloats => CborError::NonFiniteFloats,
}
}
}

impl From<CoseError> for CborError {
fn from(e: CoseError) -> Self {
match e {
CoseError::DecodeFailed(e) => CborError::DecodeFailed(e),
CoseError::DuplicateMapKey => CborError::DuplicateMapKey,
CoseError::EncodeFailed => CborError::EncodeFailed,
CoseError::ExtraneousData => CborError::ExtraneousData,
CoseError::OutOfRangeIntegerValue => CborError::OutOfRangeIntegerValue,
CoseError::UnexpectedItem(s, s2) => CborError::UnexpectedItem(s, s2),
CoseError::UnregisteredIanaValue => CborError::UnregisteredIanaValue,
CoseError::UnregisteredIanaNonPrivateValue => {
CborError::UnregisteredIanaNonPrivateValue
}
}
}
}
use std::error::Error;
use std::fmt;

pub fn to_vec<T>(value: &T) -> Result<Vec<u8>, CborError>
where
T: serde::Serialize,
{
let mut buf = Vec::new();
ciborium::into_writer(value, &mut buf)
.map_err(coset::CoseError::from)
.map_err(CborError::from)?;
ciborium::into_writer(value, &mut buf).map_err(|_| CborError(CoseError::EncodeFailed))?;
Ok(buf)
}

pub fn from_slice<T>(slice: &[u8]) -> Result<T, CborError>
where
T: de::DeserializeOwned,
{
ciborium::from_reader(Cursor::new(&slice))
.map_err(|e| CoseError::DecodeFailed(ciborium::de::Error::Semantic(None, e.to_string())))
.map_err(CborError::from)
ciborium::from_reader(Cursor::new(&slice)).map_err(|e| {
CborError(CoseError::DecodeFailed(ciborium::de::Error::Semantic(
None,
e.to_string(),
)))
})
}

/// Convert a `ciborium::Value` into a type `T`
#[allow(clippy::needless_pass_by_value)]
pub fn from_value<T>(value: ciborium::Value) -> Result<T, CborError>
pub fn from_value<T>(value: Value) -> Result<T, CoseError>
where
T: de::DeserializeOwned,
{
// TODO implement in a way that doesn't require
// roundtrip through buffer (i.e. by implementing
// `serde::de::Deserializer` for `Value` and then doing
// `T::deserialize(value)`).
let buf = to_vec(&value)?;
from_slice(buf.as_slice())
Value::deserialized(&value).map_err(|_| {
CoseError::DecodeFailed(cbor::de::Error::Semantic(
None,
"cannot deserialize".to_string(),
))
})
}

pub fn into_value<S>(v: S) -> Result<Value, CborError>
pub fn into_value<S>(v: S) -> Result<Value, CoseError>
where
S: Serialize,
{
let bytes = to_vec(&v)?;
from_slice(&bytes)
Value::serialized(&v).map_err(|_| CoseError::EncodeFailed)
}

// Wrapper struct to implement Error for CoseError
#[derive(Debug)]
pub struct CborError(pub CoseError);

impl From<CoseError> for CborError {
fn from(err: CoseError) -> CborError {
CborError(err)
}
}

impl fmt::Display for CborError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.0)
}
}

impl Error for CborError {}
10 changes: 10 additions & 0 deletions src/cose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ where
pub fn new(tagged: bool, inner: T) -> Self {
Self { tagged, inner }
}

/// If we are serialized as tagged.
pub fn is_tagged(&self) -> bool {
self.tagged
}

/// Set serialization to tagged.
pub fn set_tagged(&mut self) {
self.tagged = true;
}
}

impl<T> Deref for MaybeTagged<T>
Expand Down
10 changes: 0 additions & 10 deletions src/cose/mac0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,16 +209,6 @@ impl MaybeTagged<CoseMac0> {
),
}
}

/// If we are serialized as tagged.
pub fn is_tagged(&self) -> bool {
self.tagged
}

/// Set serialization to tagged.
pub fn set_tagged(&mut self) {
self.tagged = true;
}
}

mod hmac {
Expand Down
10 changes: 0 additions & 10 deletions src/cose/sign1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,16 +223,6 @@ impl MaybeTagged<CoseSign1> {
),
}
}

/// If we are serialized as tagged.
pub fn is_tagged(&self) -> bool {
self.tagged
}

/// Set serialization to tagged.
pub fn set_tagged(&mut self) {
self.tagged = true;
}
}

mod p256 {
Expand Down
Loading

0 comments on commit 323e62b

Please sign in to comment.