-
Notifications
You must be signed in to change notification settings - Fork 0
fix(rust/catalyst-types): Convert UUID types to cbor #148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
569e287
fix(rust/catalyst-types): convert UUID types to cbor::Value
saibatizoku 95aa947
fix(rust/catalyst-types): use minicbor and remove coset
saibatizoku f47590e
fix(rust/catalyst-types): fix uuid cbor
saibatizoku 257c0ff
fix(rust/catalyst-types): fix uuid cbor and add tests
saibatizoku c6b0446
fix(rust/catalyst-types): fix decode error
saibatizoku 1a430ec
fix(rust/signed-doc): fix decode error
saibatizoku 4ee015b
Merge branch 'main' into fix/serialize-uuid-types
stevenj fc732df
fix UUID decoding
Mr-Leshiy 08ec6a4
fix(rust/catalyst-types): encode UUID types with context
saibatizoku ff80c79
feat(rust/catalyst-types): CBOR encode and decode for UUID types with…
saibatizoku 3d7b314
Merge remote-tracking branch 'origin/main' into fix/serialize-uuid-types
saibatizoku 2a8210f
fix(rust/catalyst-types): remove redundant tests
saibatizoku File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,47 +1,148 @@ | ||
//! `UUID` types. | ||
|
||
use displaydoc::Display; | ||
use thiserror::Error; | ||
use uuid::Uuid; | ||
|
||
mod uuid_v4; | ||
mod uuid_v7; | ||
|
||
use minicbor::data::Tag; | ||
pub use uuid_v4::UuidV4 as V4; | ||
pub use uuid_v7::UuidV7 as V7; | ||
|
||
/// Invalid Doc Type UUID | ||
pub const INVALID_UUID: uuid::Uuid = uuid::Uuid::from_bytes([0x00; 16]); | ||
|
||
/// CBOR tag for UUID content. | ||
pub const UUID_CBOR_TAG: u64 = 37; | ||
|
||
/// Errors that can occur when decoding CBOR-encoded UUIDs. | ||
#[derive(Display, Debug, Error)] | ||
pub enum CborUuidError { | ||
/// Invalid CBOR encoded UUID type | ||
InvalidCborType, | ||
/// Invalid CBOR encoded UUID type: invalid bytes size | ||
InvalidByteSize, | ||
/// UUID {uuid} is not `v{expected_version}` | ||
InvalidVersion { | ||
/// The decoded UUID that was checked. | ||
uuid: Uuid, | ||
/// The expected version of the UUID, which did not match the decoded one. | ||
expected_version: usize, | ||
}, | ||
/// UUID CBOR tag <https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml/>. | ||
#[allow(dead_code)] | ||
const UUID_CBOR_TAG: u64 = 37; | ||
|
||
/// Context for `CBOR` encoding and decoding | ||
pub enum CborContext { | ||
/// Untagged bytes | ||
Untagged, | ||
/// IANA CBOR tag and bytes | ||
Tagged, | ||
/// Optional tag | ||
Optional, | ||
} | ||
|
||
/// Decode `CBOR` encoded `UUID`. | ||
pub(crate) fn decode_cbor_uuid(val: &coset::cbor::Value) -> Result<uuid::Uuid, CborUuidError> { | ||
let Some((UUID_CBOR_TAG, coset::cbor::Value::Bytes(bytes))) = val.as_tag() else { | ||
return Err(CborUuidError::InvalidCborType); | ||
/// Validate UUID CBOR Tag. | ||
fn validate_uuid_tag(tag: u64) -> Result<(), minicbor::decode::Error> { | ||
if UUID_CBOR_TAG != tag { | ||
return Err(minicbor::decode::Error::message(format!( | ||
"tag value must be: {UUID_CBOR_TAG}, provided: {tag}" | ||
))); | ||
} | ||
Ok(()) | ||
} | ||
|
||
/// Decode from `CBOR` into `UUID` | ||
fn decode_cbor_uuid( | ||
d: &mut minicbor::Decoder<'_>, ctx: &mut CborContext, | ||
) -> Result<uuid::Uuid, minicbor::decode::Error> { | ||
let bytes = match ctx { | ||
CborContext::Untagged => d.bytes()?, | ||
CborContext::Tagged => { | ||
let tag = d.tag()?; | ||
validate_uuid_tag(tag.as_u64())?; | ||
d.bytes()? | ||
}, | ||
CborContext::Optional => { | ||
let pos = d.position(); | ||
if let Ok(tag) = d.tag() { | ||
validate_uuid_tag(tag.as_u64())?; | ||
d.bytes()? | ||
} else { | ||
d.set_position(pos); | ||
d.bytes()? | ||
} | ||
}, | ||
}; | ||
let uuid = uuid::Uuid::from_bytes( | ||
bytes | ||
.clone() | ||
.try_into() | ||
.map_err(|_| CborUuidError::InvalidByteSize)?, | ||
); | ||
let decoded: [u8; 16] = bytes.try_into().map_err(|_| { | ||
minicbor::decode::Error::message("Invalid CBOR encoded UUID type: invalid bytes size") | ||
})?; | ||
let uuid = uuid::Uuid::from_bytes(decoded); | ||
Ok(uuid) | ||
} | ||
|
||
/// Encode `UUID` into `CBOR` | ||
fn encode_cbor_uuid<W: minicbor::encode::Write>( | ||
uuid: uuid::Uuid, e: &mut minicbor::Encoder<W>, ctx: &mut CborContext, | ||
) -> Result<(), minicbor::encode::Error<W::Error>> { | ||
if let CborContext::Tagged = ctx { | ||
e.tag(Tag::new(UUID_CBOR_TAG))?; | ||
} | ||
e.bytes(uuid.as_bytes())?; | ||
Ok(()) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
|
||
use super::{V4, V7}; | ||
use crate::uuid::CborContext; | ||
|
||
#[test] | ||
fn test_cbor_uuid_v4_roundtrip() { | ||
let uuid: V4 = uuid::Uuid::new_v4().into(); | ||
let mut bytes = Vec::new(); | ||
minicbor::encode_with(uuid, &mut bytes, &mut CborContext::Untagged).unwrap(); | ||
let decoded = minicbor::decode_with(bytes.as_slice(), &mut CborContext::Untagged).unwrap(); | ||
assert_eq!(uuid, decoded); | ||
} | ||
|
||
#[test] | ||
fn test_cbor_uuid_v7_roundtrip() { | ||
let uuid: V7 = uuid::Uuid::now_v7().into(); | ||
let mut bytes = Vec::new(); | ||
minicbor::encode_with(uuid, &mut bytes, &mut CborContext::Untagged).unwrap(); | ||
let decoded = minicbor::decode_with(bytes.as_slice(), &mut CborContext::Untagged).unwrap(); | ||
assert_eq!(uuid, decoded); | ||
} | ||
|
||
#[test] | ||
fn test_tagged_cbor_uuid_v4_roundtrip() { | ||
let uuid: V4 = uuid::Uuid::new_v4().into(); | ||
let mut bytes = Vec::new(); | ||
minicbor::encode_with(uuid, &mut bytes, &mut CborContext::Tagged).unwrap(); | ||
let decoded = minicbor::decode_with(bytes.as_slice(), &mut CborContext::Tagged).unwrap(); | ||
assert_eq!(uuid, decoded); | ||
} | ||
|
||
#[test] | ||
fn test_tagged_cbor_uuid_v7_roundtrip() { | ||
let uuid: V7 = uuid::Uuid::now_v7().into(); | ||
let mut bytes = Vec::new(); | ||
minicbor::encode_with(uuid, &mut bytes, &mut CborContext::Tagged).unwrap(); | ||
let decoded = minicbor::decode_with(bytes.as_slice(), &mut CborContext::Tagged).unwrap(); | ||
assert_eq!(uuid, decoded); | ||
} | ||
|
||
#[test] | ||
fn test_optional_cbor_uuid_v4_roundtrip() { | ||
let uuid: V4 = uuid::Uuid::new_v4().into(); | ||
|
||
let mut bytes = Vec::new(); | ||
minicbor::encode_with(uuid, &mut bytes, &mut CborContext::Untagged).unwrap(); | ||
let decoded = minicbor::decode_with(bytes.as_slice(), &mut CborContext::Optional).unwrap(); | ||
assert_eq!(uuid, decoded); | ||
|
||
let mut bytes = Vec::new(); | ||
minicbor::encode_with(uuid, &mut bytes, &mut CborContext::Tagged).unwrap(); | ||
let decoded = minicbor::decode_with(bytes.as_slice(), &mut CborContext::Optional).unwrap(); | ||
assert_eq!(uuid, decoded); | ||
} | ||
|
||
#[test] | ||
fn test_optional_cbor_uuid_v7_roundtrip() { | ||
let uuid: V7 = uuid::Uuid::now_v7().into(); | ||
|
||
let mut bytes = Vec::new(); | ||
minicbor::encode_with(uuid, &mut bytes, &mut CborContext::Untagged).unwrap(); | ||
let decoded = minicbor::decode_with(bytes.as_slice(), &mut CborContext::Optional).unwrap(); | ||
assert_eq!(uuid, decoded); | ||
|
||
let mut bytes = Vec::new(); | ||
minicbor::encode_with(uuid, &mut bytes, &mut CborContext::Tagged).unwrap(); | ||
let decoded = minicbor::decode_with(bytes.as_slice(), &mut CborContext::Optional).unwrap(); | ||
assert_eq!(uuid, decoded); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.