From 05a3a9fc97378a4cc55a59b438a98e93ff560829 Mon Sep 17 00:00:00 2001 From: Kai Hudalla Date: Tue, 23 Jan 2024 11:22:51 +0100 Subject: [PATCH] Use rust-protobuf instead of prost The library now uses the rust-protobuf crate instead of prost to generate structs from the uProtocol proto files. All of the library's code has been adapted to the changed API while trying to maintain the library's existing external behavior. --- Cargo.toml | 28 +-- build.rs | 99 ++++---- src/cloudevent/builder/ucloudeventbuilder.rs | 170 +++++++------ src/cloudevent/builder/ucloudeventutils.rs | 136 +++++----- .../datamodel/ucloudeventattributes.rs | 24 +- .../serializer/cloudeventjsonserializer.rs | 11 +- .../cloudeventprotobufserializer.rs | 75 +++--- .../validator/cloudeventvalidator.rs | 214 +++++++--------- src/lib.rs | 73 ++---- src/proto/cloudevents/protocloudevent.rs | 50 ++-- src/proto/uprotocol/uauthority.rs | 32 +-- src/proto/uprotocol/uentity.rs | 2 +- src/proto/uprotocol/umessagetype.rs | 18 +- src/proto/uprotocol/upayload.rs | 53 ++-- src/proto/uprotocol/uresource.rs | 3 +- src/proto/uprotocol/ustatus.rs | 23 +- src/proto/uprotocol/uuid.rs | 43 ++-- src/proto/uprotocol/uuri.rs | 11 +- src/rpc/rpcclient.rs | 6 +- src/rpc/rpcmapper.rs | 113 +++++---- src/rpc/rpcresult.rs | 81 +++--- src/transport/builder/uattributesbuilder.rs | 29 ++- src/transport/datamodel/utransport.rs | 5 +- .../validator/uattributesvalidator.rs | 232 ++++++++---------- src/uri/builder/resourcebuilder.rs | 5 +- src/uri/serializer/longuriserializer.rs | 206 ++++++++++------ src/uri/serializer/microuriserializer.rs | 132 ++++++---- src/uri/serializer/uriserializer.rs | 21 +- src/uri/validator/urivalidator.rs | 148 ++++++----- src/uuid/builder/uuidbuilder.rs | 2 +- 30 files changed, 1036 insertions(+), 1009 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9f5a4fbc..04d581ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,24 +34,22 @@ rust-version = "1.66" version = "0.1.5" [dependencies] -async-trait = "0.1" -byteorder = "1.4" -bytes = "1.4" -chrono = "0.4" +async-trait = { version = "0.1" } +bytes = { version = "1.5" } +chrono = { version = "0.4" } cloudevents-sdk = { version = "0.7" } -prost = "0.12" -prost-types = "0.12" -rand = "0.8" -regex = "1" +protobuf = { version = "3.3" } +rand = { version = "0.8" } +regex = { version = "1.10" } serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -url = "2" -uuid = { version = "1.6", features = ["v8"] } +serde_json = { version = "1.0" } +url = { version = "2.5" } +uuid = { version = "1.7", features = ["v8"] } [build-dependencies] -prost-build = { version = "0.12" } -protoc-bin-vendored = { version = "3" } -ureq = "2.7" +protobuf-codegen = { version = "3.3" } +protoc-bin-vendored = { version = "3.0" } +ureq = { version = "2.7" } [dev-dependencies] -test-case = "3.3" +test-case = { version = "3.3" } diff --git a/build.rs b/build.rs index 938f0780..edc8522c 100644 --- a/build.rs +++ b/build.rs @@ -11,94 +11,99 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -use prost_build::Config; use std::env; use std::fs; use std::path::Path; +use std::path::PathBuf; -fn main() -> std::io::Result<()> { - // use vendored protoc instead of relying on user provided protobuf installation - std::env::set_var("PROTOC", protoc_bin_vendored::protoc_bin_path().unwrap()); +const UPROTOCOL_BASE_URI: &str = "https://raw.githubusercontent.com/eclipse-uprotocol/uprotocol-core-api/uprotocol-core-api-1.5.4/uprotocol"; - if let Err(err) = get_and_build_protos( +fn main() -> Result<(), Box> { + get_and_build_protos( &[ // cloudevent proto definitions "https://raw.githubusercontent.com/cloudevents/spec/main/cloudevents/formats/cloudevents.proto", + ], + "cloudevents", + )?; + get_and_build_protos( + &[ // uProtocol-project proto definitions - "https://raw.githubusercontent.com/eclipse-uprotocol/uprotocol-core-api/uprotocol-core-api-1.5.3/src/main/proto/uuid.proto", - "https://raw.githubusercontent.com/eclipse-uprotocol/uprotocol-core-api/uprotocol-core-api-1.5.3/src/main/proto/uri.proto", - "https://raw.githubusercontent.com/eclipse-uprotocol/uprotocol-core-api/uprotocol-core-api-1.5.3/src/main/proto/uattributes.proto", - "https://raw.githubusercontent.com/eclipse-uprotocol/uprotocol-core-api/uprotocol-core-api-1.5.3/src/main/proto/upayload.proto", - "https://raw.githubusercontent.com/eclipse-uprotocol/uprotocol-core-api/uprotocol-core-api-1.5.3/src/main/proto/umessage.proto", - "https://raw.githubusercontent.com/eclipse-uprotocol/uprotocol-core-api/uprotocol-core-api-1.5.3/src/main/proto/ustatus.proto", - + format!("{}/uuid.proto", UPROTOCOL_BASE_URI).as_str(), + format!("{}/uri.proto", UPROTOCOL_BASE_URI).as_str(), + format!("{}/uattributes.proto", UPROTOCOL_BASE_URI).as_str(), + format!("{}/upayload.proto", UPROTOCOL_BASE_URI).as_str(), + format!("{}/umessage.proto", UPROTOCOL_BASE_URI).as_str(), + format!("{}/ustatus.proto", UPROTOCOL_BASE_URI).as_str(), // not used in the SDK yet, but for completeness sake - "https://raw.githubusercontent.com/eclipse-uprotocol/uprotocol-core-api/uprotocol-core-api-1.5.3/src/main/proto/file.proto", - "https://raw.githubusercontent.com/eclipse-uprotocol/uprotocol-core-api/uprotocol-core-api-1.5.3/src/main/proto/uprotocol_options.proto", - "https://raw.githubusercontent.com/eclipse-uprotocol/uprotocol-core-api/uprotocol-core-api-1.5.3/src/main/proto/core/udiscovery/v3/udiscovery.proto", - "https://raw.githubusercontent.com/eclipse-uprotocol/uprotocol-core-api/uprotocol-core-api-1.5.3/src/main/proto/core/usubscription/v3/usubscription.proto", - "https://raw.githubusercontent.com/eclipse-uprotocol/uprotocol-core-api/uprotocol-core-api-1.5.3/src/main/proto/core/utwin/v1/utwin.proto", - ] - ) { - let error_message = format!("Failed to fetch and build protobuf file: {err:?}"); - return Err(std::io::Error::new(std::io::ErrorKind::Other, error_message)); - } + format!("{}/file.proto", UPROTOCOL_BASE_URI).as_str(), + format!("{}/uprotocol_options.proto", UPROTOCOL_BASE_URI).as_str(), + format!("{}/core/udiscovery/v3/udiscovery.proto", UPROTOCOL_BASE_URI).as_str(), + format!( + "{}/core/usubscription/v3/usubscription.proto", + UPROTOCOL_BASE_URI + ) + .as_str(), + format!("{}/core/utwin/v1/utwin.proto", UPROTOCOL_BASE_URI).as_str(), + ], + "uprotocol", + )?; Ok(()) } // Fetch protobuf definitions from `url`, and build them with prost_build -fn get_and_build_protos(urls: &[&str]) -> core::result::Result<(), Box> { +fn get_and_build_protos( + urls: &[&str], + output_folder: &str, +) -> core::result::Result<(), Box> { let out_dir = env::var_os("OUT_DIR").unwrap(); + let proto_folder = Path::new(&out_dir).join("proto"); let mut proto_files = Vec::new(); for url in urls { // Extract filename from the URL let filename = url.rsplit('/').next().unwrap_or_default(); - let dest_path = Path::new(&out_dir).join(filename); + let dest_path = proto_folder.join(filename); // Download the .proto file - if let Err(err) = download_and_write_file(url, filename) { - panic!("Failed to download and write file: {err:?}"); - } + download_and_write_file(url, &dest_path)?; proto_files.push(dest_path); } - // Compile all .proto files together - let mut config = Config::new(); - - // Some proto files contain comments that will be interpreted as rustdoc comments (and fail to compile) - config.disable_comments(["."]); - - config.compile_protos(&proto_files, &[&out_dir])?; + protobuf_codegen::Codegen::new() + .protoc() + // use vendored protoc instead of relying on user provided protobuf installation + .protoc_path(&protoc_bin_vendored::protoc_bin_path().unwrap()) + .include(proto_folder) + .inputs(proto_files) + .cargo_out_dir(output_folder) + .run_from_script(); Ok(()) } -// Retreives a file from `url` (from GitHub, for instance) and places it in the build directory (`OUT_DIR`) with the name +// Retrieves a file from `url` (from GitHub, for instance) and places it in the build directory (`OUT_DIR`) with the name // provided by `destination` parameter. fn download_and_write_file( url: &str, - destination: &str, + dest_path: &PathBuf, ) -> core::result::Result<(), Box> { // Send a GET request to the URL - let resp = ureq::get(url).call(); - match resp { - Err(error) => Err(Box::new(std::io::Error::new( - std::io::ErrorKind::Other, - error.to_string(), - ))), + match ureq::get(url).call() { + Err(error) => Err(Box::from(error)), Ok(response) => { - let out_dir = env::var_os("OUT_DIR").unwrap(); - let dest_path = Path::new(&out_dir).join(destination); + if let Some(parent_path) = dest_path.parent() { + std::fs::create_dir_all(parent_path)?; + } let mut out_file = fs::File::create(dest_path)?; // Write the response body directly to the file - let _ = std::io::copy(&mut response.into_reader(), &mut out_file); - - Ok(()) + std::io::copy(&mut response.into_reader(), &mut out_file) + .map(|_| ()) + .map_err(Box::from) } } } diff --git a/src/cloudevent/builder/ucloudeventbuilder.rs b/src/cloudevent/builder/ucloudeventbuilder.rs index 8f40480a..adaee3d0 100644 --- a/src/cloudevent/builder/ucloudeventbuilder.rs +++ b/src/cloudevent/builder/ucloudeventbuilder.rs @@ -13,11 +13,12 @@ use chrono::Utc; use cloudevents::{Event, EventBuilder, EventBuilderV10}; -use prost_types::Any; +use protobuf::well_known_types::any::Any; +use protobuf::Enum; use url::{ParseError, Url}; use crate::cloudevent::datamodel::UCloudEventAttributes; -use crate::uprotocol::UMessageType; +use crate::uprotocol::uattributes::UMessageType; use crate::uuid::builder::UUIDv8Builder; pub struct UCloudEventBuilder; @@ -60,20 +61,21 @@ impl UCloudEventBuilder { /// # Example /// /// ```rust - /// use prost_types::Any; + /// use protobuf::well_known_types::any::Any; /// use uprotocol_sdk::cloudevent::datamodel::{UCloudEventAttributes}; /// use uprotocol_sdk::cloudevent::builder::UCloudEventBuilder; - /// use uprotocol_sdk::uprotocol::UPriority; + /// use uprotocol_sdk::uprotocol::uattributes::UPriority; /// /// let rpc_uri = "http://myapp.com/rpc"; /// let service_method_uri = ":/body.access/1/rpc.UpdateDoor"; /// let proto_payload = Any { /// type_url: "type.googleapis.com/google.protobuf.StringValue".to_string(), /// value: vec![104, 101, 108, 108, 111], // 'hello' in ASCII + /// ..Default::default() /// }; /// let attributes = UCloudEventAttributes { /// ttl: Some(60), - /// priority: Some(UPriority::UpriorityCs0), + /// priority: Some(UPriority::UPRIORITY_CS0), /// hash: Some("123456".to_string()), /// token: Some("abcdef".to_string()), /// }; @@ -94,7 +96,7 @@ impl UCloudEventBuilder { attributes, ) .extension("sink", service_method_uri) - .ty(UMessageType::UmessageTypeRequest) + .ty(UMessageType::UMESSAGE_TYPE_REQUEST) .build(); bce.unwrap() @@ -123,7 +125,7 @@ impl UCloudEventBuilder { /// ``` /// use uprotocol_sdk::cloudevent::builder::UCloudEventBuilder; /// use uprotocol_sdk::cloudevent::datamodel::UCloudEventAttributes; - /// use prost_types::Any; + /// use protobuf::well_known_types::any::Any; /// /// let rpc_uri = "https://example.com/rpc"; /// let service_method_uri = "https://example.com/service_method"; @@ -131,6 +133,7 @@ impl UCloudEventBuilder { /// let proto_payload = &Any { /// type_url: "type".to_string(), /// value: vec![], + /// ..Default::default() /// }; /// let attributes = &UCloudEventAttributes::default(); /// @@ -158,7 +161,7 @@ impl UCloudEventBuilder { ) .extension("sink", rpc_uri) .extension("reqid", request_id) - .ty(UMessageType::UmessageTypeResponse) + .ty(UMessageType::UMESSAGE_TYPE_RESPONSE) .build(); bce.unwrap() @@ -187,7 +190,7 @@ impl UCloudEventBuilder { /// ```rust /// use uprotocol_sdk::cloudevent::builder::UCloudEventBuilder; /// use uprotocol_sdk::cloudevent::datamodel::UCloudEventAttributes; - /// use prost_types::Any; + /// use protobuf::well_known_types::any::Any; /// /// let application_uri = "http://myapplication.com/rpc"; /// let service_method_uri = ":/body.access/1/rpc.UpdateDoor"; @@ -224,7 +227,7 @@ impl UCloudEventBuilder { .extension("sink", rpc_uri) .extension("reqid", request_id) .extension("commstatus", i64::from(communication_status)) - .ty(UMessageType::UmessageTypeResponse) + .ty(UMessageType::UMESSAGE_TYPE_RESPONSE) .build(); bce.unwrap() @@ -251,7 +254,7 @@ impl UCloudEventBuilder { /// ```rust /// use uprotocol_sdk::cloudevent::builder::UCloudEventBuilder; /// use uprotocol_sdk::cloudevent::datamodel::UCloudEventAttributes; - /// use prost_types::Any; + /// use protobuf::well_known_types::any::Any; /// /// let source = "http://myapplication.com/topic"; /// let attributes = UCloudEventAttributes::default(); // Populate with real data @@ -271,7 +274,7 @@ impl UCloudEventBuilder { &payload.type_url, attributes, ) - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .build(); bce.unwrap() @@ -301,7 +304,7 @@ impl UCloudEventBuilder { /// ```rust /// use uprotocol_sdk::cloudevent::builder::UCloudEventBuilder; /// use uprotocol_sdk::cloudevent::datamodel::UCloudEventAttributes; - /// use prost_types::Any; + /// use protobuf::well_known_types::any::Any; /// /// let source = "http://myapplication.com/topic"; /// let sink = "http://myapplication.com/destination"; @@ -329,7 +332,7 @@ impl UCloudEventBuilder { attributes, ) .extension("sink", sink) - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .build(); bce.unwrap() @@ -357,7 +360,7 @@ impl UCloudEventBuilder { /// # use cloudevents::{Event, EventBuilder, EventBuilderV10}; /// # use uprotocol_sdk::cloudevent::builder::UCloudEventBuilder; /// # use uprotocol_sdk::cloudevent::datamodel::UCloudEventAttributes; - /// # use prost_types::Any; + /// # use protobuf::well_known_types::any::Any; /// /// let id = "unique_id"; /// let source = "source_url"; @@ -395,7 +398,7 @@ impl UCloudEventBuilder { eb = eb.extension("ttl", i64::from(ttl_value)); } if let Some(priority_value) = &attributes.priority { - eb = eb.extension("priority", priority_value.as_str_name()); + eb = eb.extension("priority", priority_value.value() as i64); } if let Some(hash_value) = &attributes.hash { eb = eb.extension("hash", hash_value.clone()); @@ -422,7 +425,10 @@ mod tests { use super::*; use crate::cloudevent::builder::UCloudEventUtils; - use crate::uprotocol::{Remote, UAuthority, UCode, UEntity, UPriority, UResource, UUri}; + use crate::uprotocol::uattributes::UPriority; + use crate::uprotocol::uri::uauthority::Remote; + use crate::uprotocol::uri::{UAuthority, UEntity, UResource, UUri}; + use crate::uprotocol::ustatus::UCode; use crate::uri::builder::resourcebuilder::UResourceBuilder; use crate::uri::serializer::{LongUriSerializer, UriSerializer}; @@ -434,11 +440,13 @@ mod tests { entity: Some(UEntity { name: "body.access".to_string(), ..Default::default() - }), + }) + .into(), resource: Some(UResource { name: "door".to_string(), ..Default::default() - }), + }) + .into(), ..Default::default() }; @@ -447,7 +455,7 @@ mod tests { let ucloud_event_attributes = UCloudEventAttributes::builder() .with_hash("somehash".to_string()) - .with_priority(UPriority::UpriorityCs0) + .with_priority(UPriority::UPRIORITY_CS0) .with_ttl(3) .with_token("someOAuthToken".to_string()) .build(); @@ -459,7 +467,7 @@ mod tests { &proto_payload.type_url, &ucloud_event_attributes, ) - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .build() .unwrap(); @@ -467,7 +475,7 @@ mod tests { assert_eq!("testme", cloud_event.id()); assert_eq!(source, cloud_event.source().to_string()); assert_eq!( - UMessageType::UmessageTypePublish.to_string(), + UMessageType::UMESSAGE_TYPE_PUBLISH.to_string(), cloud_event.ty() ); assert!(!cloud_event @@ -489,8 +497,8 @@ mod tests { cloud_event.extension("hash").unwrap().to_string() ); assert_eq!( - UPriority::UpriorityCs0.as_str_name(), - cloud_event.extension("priority").unwrap().to_string() + UPriority::UPRIORITY_CS0, + UCloudEventUtils::get_priority(&cloud_event).unwrap() ); assert_eq!("3", cloud_event.extension("ttl").unwrap().to_string()); assert_eq!( @@ -509,11 +517,13 @@ mod tests { entity: Some(UEntity { name: "body.access".to_string(), ..Default::default() - }), + }) + .into(), resource: Some(UResource { name: "door".to_string(), ..Default::default() - }), + }) + .into(), ..Default::default() }; let source = uri.to_string(); @@ -526,7 +536,7 @@ mod tests { &proto_payload.type_url, &ucloud_event_attributes, ) - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .build() .unwrap(); @@ -534,7 +544,7 @@ mod tests { assert_eq!("testme", cloud_event.id()); assert_eq!(source, cloud_event.source().to_string()); assert_eq!( - UMessageType::UmessageTypePublish.to_string(), + UMessageType::UMESSAGE_TYPE_PUBLISH.to_string(), cloud_event.ty() ); assert!(!cloud_event @@ -572,11 +582,13 @@ mod tests { entity: Some(UEntity { name: "body.access".to_string(), ..Default::default() - }), + }) + .into(), resource: Some(UResource { name: "door".to_string(), ..Default::default() - }), + }) + .into(), ..Default::default() }; let source = uri.to_string(); @@ -587,7 +599,7 @@ mod tests { // additional attributes let ucloud_event_attributes = UCloudEventAttributes { hash: Some("somehash".to_string()), - priority: Some(UPriority::UpriorityCs0), + priority: Some(UPriority::UPRIORITY_CS0), ttl: Some(3), token: None, }; @@ -599,7 +611,7 @@ mod tests { assert!(!cloud_event.id().is_empty()); assert_eq!(source, cloud_event.source().to_string()); assert_eq!( - UMessageType::UmessageTypePublish.to_string(), + UMessageType::UMESSAGE_TYPE_PUBLISH.to_string(), cloud_event.ty() ); assert!(!cloud_event @@ -621,8 +633,8 @@ mod tests { cloud_event.extension("hash").unwrap().to_string() ); assert_eq!( - UPriority::UpriorityCs0.as_str_name(), - cloud_event.extension("priority").unwrap().to_string() + UPriority::UPRIORITY_CS0, + UCloudEventUtils::get_priority(&cloud_event).unwrap() ); assert_eq!( 3, @@ -641,11 +653,13 @@ mod tests { entity: Some(UEntity { name: "body.access".to_string(), ..Default::default() - }), + }) + .into(), resource: Some(UResource { name: "door".to_string(), ..Default::default() - }), + }) + .into(), ..Default::default() }; let source = uri.to_string(); @@ -654,15 +668,20 @@ mod tests { let sink_uri = UUri { authority: Some(UAuthority { remote: Some(Remote::Name("com.gm.bo".into())), - }), + ..Default::default() + }) + .into(), entity: Some(UEntity { name: "petapp".to_string(), ..Default::default() - }), + }) + .into(), resource: Some(UResource { name: "OK".to_string(), ..Default::default() - }), + }) + .into(), + ..Default::default() }; let sink = sink_uri.to_string(); @@ -672,7 +691,7 @@ mod tests { // additional attributes let ucloud_event_attributes = UCloudEventAttributes { hash: Some("somehash".to_string()), - priority: Some(UPriority::UpriorityCs2), + priority: Some(UPriority::UPRIORITY_CS2), ttl: Some(3), token: None, }; @@ -688,7 +707,7 @@ mod tests { .any(|(name, _value)| name.contains("sink"))); assert_eq!(sink, cloud_event.extension("sink").unwrap().to_string()); assert_eq!( - UMessageType::UmessageTypePublish.to_string(), + UMessageType::UMESSAGE_TYPE_PUBLISH.to_string(), cloud_event.ty() ); assert_eq!( @@ -707,8 +726,8 @@ mod tests { cloud_event.extension("hash").unwrap().to_string() ); assert_eq!( - UPriority::UpriorityCs2.as_str_name(), - cloud_event.extension("priority").unwrap().to_string() + UPriority::UPRIORITY_CS2, + UCloudEventUtils::get_priority(&cloud_event).unwrap() ); assert_eq!( 3, @@ -734,7 +753,7 @@ mod tests { // additional attributes let ucloud_event_attributes = UCloudEventAttributes { hash: Some("somehash".to_string()), - priority: Some(UPriority::UpriorityCs2), + priority: Some(UPriority::UPRIORITY_CS2), ttl: Some(3), token: Some("someOAuthToken".to_string()), }; @@ -762,8 +781,8 @@ mod tests { cloud_event.extension("hash").unwrap().to_string() ); assert_eq!( - UPriority::UpriorityCs2.as_str_name(), - cloud_event.extension("priority").unwrap().to_string() + UPriority::UPRIORITY_CS2, + UCloudEventUtils::get_priority(&cloud_event).unwrap() ); assert_eq!( 3, @@ -787,8 +806,9 @@ mod tests { name: "petapp".to_string(), version_major: Some(1), ..Default::default() - }), - resource: Some(UResourceBuilder::for_rpc_response()), + }) + .into(), + resource: Some(UResourceBuilder::for_rpc_response()).into(), ..Default::default() }; let application_uri_for_rpc = LongUriSerializer::serialize(&rpc_uri).unwrap(); @@ -799,11 +819,13 @@ mod tests { name: "body.access".to_string(), version_major: Some(1), ..Default::default() - }), + }) + .into(), resource: Some(UResourceBuilder::for_rpc_request( Some("UpdateDoor".into()), None, - )), + )) + .into(), ..Default::default() }; let service_method_uri = LongUriSerializer::serialize(&method_uri).unwrap(); @@ -814,7 +836,7 @@ mod tests { // additional attributes let ucloud_event_attributes = UCloudEventAttributes { hash: Some("somehash".to_string()), - priority: Some(UPriority::UpriorityCs2), + priority: Some(UPriority::UPRIORITY_CS2), ttl: Some(3), token: None, }; @@ -857,8 +879,8 @@ mod tests { cloud_event.extension("hash").unwrap().to_string() ); assert_eq!( - UPriority::UpriorityCs2.as_str_name(), - cloud_event.extension("priority").unwrap().to_string() + UPriority::UPRIORITY_CS2, + UCloudEventUtils::get_priority(&cloud_event).unwrap() ); assert_eq!( 3, @@ -882,8 +904,9 @@ mod tests { name: "petapp".to_string(), version_major: Some(1), ..Default::default() - }), - resource: Some(UResourceBuilder::for_rpc_response()), + }) + .into(), + resource: Some(UResourceBuilder::for_rpc_response()).into(), ..Default::default() }; let application_uri_for_rpc = LongUriSerializer::serialize(&rpc_uri).unwrap(); @@ -894,11 +917,13 @@ mod tests { name: "body.access".to_string(), version_major: Some(1), ..Default::default() - }), + }) + .into(), resource: Some(UResourceBuilder::for_rpc_request( Some("UpdateDoor".into()), None, - )), + )) + .into(), ..Default::default() }; let service_method_uri = LongUriSerializer::serialize(&method_uri).unwrap(); @@ -906,7 +931,7 @@ mod tests { // Additional attributes let ucloud_event_attributes = UCloudEventAttributes { hash: Some("somehash".to_string()), - priority: Some(UPriority::UpriorityCs2), + priority: Some(UPriority::UPRIORITY_CS2), ttl: Some(3), token: None, }; @@ -915,7 +940,7 @@ mod tests { &application_uri_for_rpc, &service_method_uri, "requestIdFromRequestCloudEvent", - UCode::InvalidArgument as u32, + UCode::INVALID_ARGUMENT as u32, &ucloud_event_attributes, ); @@ -945,15 +970,15 @@ mod tests { cloud_event.extension("hash").unwrap().to_string() ); assert_eq!( - UPriority::UpriorityCs2.as_str_name(), - cloud_event.extension("priority").unwrap().to_string() + UPriority::UPRIORITY_CS2, + UCloudEventUtils::get_priority(&cloud_event).unwrap() ); assert_eq!( 3, UCloudEventUtils::extract_integer_value_from_extension(&cloud_event, "ttl").unwrap() ); assert_eq!( - UCode::InvalidArgument as i32, + UCode::INVALID_ARGUMENT as i32, UCloudEventUtils::extract_integer_value_from_extension(&cloud_event, "commstatus") .unwrap() ); @@ -974,7 +999,7 @@ mod tests { // Additional attributes let ucloud_event_attributes = UCloudEventAttributes { hash: Some("somehash".to_string()), - priority: Some(UPriority::UpriorityCs2), + priority: Some(UPriority::UPRIORITY_CS2), ttl: Some(3), token: None, }; @@ -983,7 +1008,7 @@ mod tests { &application_uri_for_rpc, &service_method_uri, "requestIdFromRequestCloudEvent", - UCode::InvalidArgument as u32, + UCode::INVALID_ARGUMENT as u32, &ucloud_event_attributes, ); @@ -1003,15 +1028,15 @@ mod tests { cloud_event.extension("hash").unwrap().to_string() ); assert_eq!( - UPriority::UpriorityCs2.as_str_name(), - cloud_event.extension("priority").unwrap().to_string() + UPriority::UPRIORITY_CS2, + UCloudEventUtils::get_priority(&cloud_event).unwrap() ); assert_eq!( 3, UCloudEventUtils::extract_integer_value_from_extension(&cloud_event, "ttl").unwrap() ); assert_eq!( - UCode::InvalidArgument as i32, + UCode::INVALID_ARGUMENT as i32, UCloudEventUtils::extract_integer_value_from_extension(&cloud_event, "commstatus") .unwrap() ); @@ -1025,7 +1050,7 @@ mod tests { EventBuilderV10::new() .id("hello") .source("https://example.com") - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .data_with_schema( "application/octet-stream", "proto://type.googleapis.com/example.demo", @@ -1054,9 +1079,10 @@ mod tests { .to_string() }; - prost_types::Any { + Any { type_url: schema, value: data_bytes, + ..Default::default() } } @@ -1065,13 +1091,15 @@ mod tests { entity: Some(UEntity { name: "body.access".to_string(), ..Default::default() - }), + }) + .into(), resource: Some(UResource { name: "door".to_string(), instance: Some("front_left".to_string()), message: Some("Door".to_string()), ..Default::default() - }), + }) + .into(), ..Default::default() }; LongUriSerializer::serialize(&uri).unwrap() diff --git a/src/cloudevent/builder/ucloudeventutils.rs b/src/cloudevent/builder/ucloudeventutils.rs index 0fb79340..8cc44bfb 100644 --- a/src/cloudevent/builder/ucloudeventutils.rs +++ b/src/cloudevent/builder/ucloudeventutils.rs @@ -11,15 +11,15 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -use bytes::Bytes; use chrono::{Duration, Utc}; use cloudevents::event::ExtensionValue; use cloudevents::{AttributesReader, Data, Event, EventBuilder, EventBuilderV10}; -use prost::Message; -use prost_types::Any; +use protobuf::well_known_types::any::Any; +use protobuf::{Enum, Message, MessageFull}; use std::time::SystemTime; -use crate::uprotocol::{UCode, Uuid}; +use crate::uprotocol::uattributes::UPriority; +use crate::uprotocol::{ustatus::UCode, uuid::UUID}; /// Code to extract information from a `CloudEvent` #[derive(Debug)] @@ -120,11 +120,15 @@ impl UCloudEventUtils { /// /// # Returns /// - /// Returns an `Option` value of the `CloudEvent` priority attribute if it exists, - /// otherwise a `None` is returned. - pub fn get_priority(event: &Event) -> Option { + /// Returns the event's priority attribute, if it exists, or `None` otherwise. + pub fn get_priority(event: &Event) -> Option { if let Some(priority) = event.extension("priority") { - return Some(priority.to_string()); + return match priority { + ExtensionValue::Integer(value) => { + i32::try_from(*value).map_or(None, UPriority::from_i32) + } + _ => None, + }; } None } @@ -185,7 +189,7 @@ impl UCloudEventUtils { if let Some(ExtensionValue::Integer(commstatus)) = event.extension("commstatus") { return Some(*commstatus); } - Some(UCode::Ok as i64) + Some(UCode::OK as i64) } /// Indicates if a platform communication error occurred while trying to deliver the `CloudEvent`. @@ -198,7 +202,7 @@ impl UCloudEventUtils { /// /// Returns `true` if the provided `CloudEvent` is marked with having a platform delivery problem. pub fn has_communication_problem(event: &Event) -> bool { - matches!(UCloudEventUtils::get_communication_status(event), Some(c) if c != UCode::Ok as i64) + matches!(UCloudEventUtils::get_communication_status(event), Some(c) if c != UCode::OK as i64) } /// Returns a new `Event` from the supplied `Event`, with the platform communication added. @@ -233,7 +237,7 @@ impl UCloudEventUtils { /// /// An `Option` containing the timestamp from the UUIDV8 `Event` Id or `None` if the timestamp can't be extracted. pub fn get_creation_timestamp(event: &Event) -> Option { - match event.id().parse::() { + match event.id().parse::() { Ok(uuid) => uuid.get_time(), Err(_e) => None, } @@ -289,7 +293,7 @@ impl UCloudEventUtils { Some(ttl) if ttl > 0 => { if let Some(event_time) = event .id() - .parse::() + .parse::() .ok() .and_then(|uuid| uuid.get_time()) { @@ -320,7 +324,7 @@ impl UCloudEventUtils { pub fn is_cloud_event_id(event: &Event) -> bool { event .id() - .parse::() + .parse::() .map_or(false, |uuid| uuid.is_uprotocol_uuid()) } @@ -338,11 +342,11 @@ impl UCloudEventUtils { /// Returns the payload from the `Event` as a Protobuf `Any` object. pub fn get_payload(event: &Event) -> Any { if let Some(buffer) = UCloudEventUtils::serialize_event_data_into_bytes(event) { - if let Ok(any) = prost_types::Any::decode(buffer.as_slice()) { + if let Ok(any) = Any::parse_from_bytes(buffer.as_slice()) { return any; } } - prost_types::Any::default() + Any::default() } /// Unpacks the payload from the `Event` as a protobuf `Message` of the provided type `T`. @@ -365,14 +369,25 @@ impl UCloudEventUtils { /// /// # Errors /// - /// Returns a `prost::DecodeError` in the following case: + /// Returns a [`self::ConversionError`] in the following case: /// - /// - If the function fails to decode the payload of the `Event` into the specified type `T`. This can occur if the payload does not conform to the expected format required for `T`, or if there are issues during the decoding process (such as incorrect field types, missing required fields, etc.). The `prost::DecodeError` will contain details about the specific nature of the decoding failure. - pub fn unpack(event: &Event) -> Result { + /// - If the function fails to decode the payload of the `Event` into the specified type `T`. This can occur if the payload does not + /// conform to the expected format required for `T`, or if there are issues during the decoding process + /// (such as incorrect field types, missing required fields, etc.). + pub fn unpack(event: &Event) -> Result { let any_payload = UCloudEventUtils::get_payload(event); - let buffer = Bytes::from(any_payload.value); - - T::decode(buffer) + match any_payload.unpack() { + Ok(v) => { + if let Some(msg) = v { + Ok(msg) + } else { + Err(ConversionError(String::from( + "event does not contain Any payload", + ))) + } + } + Err(e) => Err(ConversionError(e.to_string())), + } } /// Serializes the data of a given `CloudEvent` into a byte vector. @@ -475,14 +490,15 @@ mod tests { use super::*; use crate::cloudevent::builder::UCloudEventBuilder; use crate::cloudevent::datamodel::UCloudEventAttributes; - use crate::proto::CloudEvent; - use crate::uprotocol::{UEntity, UMessageType, UPriority, UResource, UUri}; + use crate::cloudevents::CloudEvent; + use crate::uprotocol::uattributes::{UMessageType, UPriority}; + use crate::uprotocol::uri::{UEntity, UResource, UUri}; use crate::uri::serializer::{LongUriSerializer, UriSerializer}; use crate::uuid::builder::UUIDv8Builder; use chrono::{offset, TimeZone, Utc}; use cloudevents::{Data, Event, EventBuilder, EventBuilderV10}; - use prost_types::Any; + use protobuf::well_known_types::any::Any; use url::Url; #[test] @@ -591,7 +607,7 @@ mod tests { let priority = UCloudEventUtils::get_priority(&cloud_event); - assert_eq!(UPriority::UpriorityCs0.as_str_name(), priority.unwrap()); + assert_eq!(UPriority::UPRIORITY_CS0, priority.unwrap()); } #[test] @@ -651,13 +667,13 @@ mod tests { fn test_cloud_event_has_platform_error_when_platform_error_exists() { let builder = build_base_cloud_event_for_test(); let mut cloud_event: Event = builder.build().expect("Failed to build the cloud event"); - cloud_event.set_extension("commstatus", UCode::Aborted as i64); + cloud_event.set_extension("commstatus", UCode::ABORTED as i64); let has_communication_problem = UCloudEventUtils::has_communication_problem(&cloud_event); let communication_status = UCloudEventUtils::get_communication_status(&cloud_event); assert!(has_communication_problem); - assert_eq!(Some(UCode::Aborted as i64), communication_status); + assert_eq!(Some(UCode::ABORTED as i64), communication_status); } #[test] @@ -669,7 +685,7 @@ mod tests { let communication_status = UCloudEventUtils::get_communication_status(&cloud_event); assert!(!has_communication_problem); - assert_eq!(Some(UCode::Ok as i64), communication_status); + assert_eq!(Some(UCode::OK as i64), communication_status); } #[test] @@ -682,18 +698,18 @@ mod tests { let communication_status = UCloudEventUtils::get_communication_status(&cloud_event); assert!(!has_communication_problem); - assert_eq!(Some(UCode::Ok as i64), communication_status); + assert_eq!(Some(UCode::OK as i64), communication_status); } #[test] fn test_extract_platform_error_from_cloud_event_when_error_exists() { let mut builder = build_base_cloud_event_for_test(); - builder = builder.extension("commstatus", UCode::InvalidArgument as i64); + builder = builder.extension("commstatus", UCode::INVALID_ARGUMENT as i64); let cloud_event: Event = builder.build().expect("Failed to build the cloud event"); let communication_status = UCloudEventUtils::get_communication_status(&cloud_event); - assert_eq!(Some(UCode::InvalidArgument as i64), communication_status); + assert_eq!(Some(UCode::INVALID_ARGUMENT as i64), communication_status); } #[test] @@ -703,7 +719,7 @@ mod tests { let communication_status = UCloudEventUtils::get_communication_status(&cloud_event); - assert_eq!(Some(UCode::Ok as i64), communication_status); + assert_eq!(Some(UCode::OK as i64), communication_status); } #[test] @@ -712,21 +728,21 @@ mod tests { let cloud_event: Event = builder.build().expect("Failed to build the cloud event"); assert_eq!( - Some(UCode::Ok as i64), + Some(UCode::OK as i64), UCloudEventUtils::get_communication_status(&cloud_event) ); let updated_cloud_event = UCloudEventUtils::add_communication_status( cloud_event.clone(), - UCode::DeadlineExceeded as i64, + UCode::DEADLINE_EXCEEDED as i64, ); assert_eq!( - Some(UCode::DeadlineExceeded as i64), + Some(UCode::DEADLINE_EXCEEDED as i64), UCloudEventUtils::get_communication_status(&updated_cloud_event) ); assert_eq!( - Some(UCode::Ok as i64), + Some(UCode::OK as i64), UCloudEventUtils::get_communication_status(&cloud_event) ); } @@ -800,7 +816,7 @@ mod tests { let builder = cloudevents::EventBuilderV10::new() .id("id") - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .source("/body.accss//door.front_left#Door") .data_with_schema( UCloudEventBuilder::PROTOBUF_CONTENT_TYPE, @@ -944,11 +960,11 @@ mod tests { fn test_extract_payload_from_cloud_event_as_any_proto_object() { let proto_payload = build_proto_payload_for_test(); let any_payload = pack_event_into_any(&proto_payload); - let any_bytes = any_payload.encode_to_vec(); + let any_bytes = any_payload.write_to_bytes().unwrap(); let builder = cloudevents::EventBuilderV10::new() .id("someid") - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .source("/body.accss//door.front_left#Door") .data_with_schema( UCloudEventBuilder::PROTOBUF_CONTENT_TYPE, @@ -967,11 +983,11 @@ mod tests { fn test_extract_payload_from_cloud_event_when_payload_is_not_an_any_proto_object() { let proto_payload = build_proto_payload_for_test(); let any_payload = pack_event_into_any(&proto_payload); - let any_bytes = any_payload.encode_to_vec(); + let any_bytes = any_payload.write_to_bytes().unwrap(); let cloud_event = cloudevents::EventBuilderV10::new() .id("someId") - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) // The url crate does not accept URLs without a base .source(Url::parse("up:/body.access/1/door.front_left#Door").unwrap()) .data_with_schema( @@ -983,7 +999,7 @@ mod tests { .unwrap(); let buffer = UCloudEventUtils::serialize_event_data_into_bytes(&cloud_event).unwrap(); - let parsed_any = prost_types::Any::decode(buffer.as_slice()).ok().unwrap(); + let parsed_any = Any::parse_from_bytes(buffer.as_slice()).ok().unwrap(); let payload_any = UCloudEventUtils::get_payload(&cloud_event); @@ -994,7 +1010,7 @@ mod tests { fn test_extract_payload_from_cloud_event_when_payload_is_bad_proto_object() { let cloud_event = cloudevents::EventBuilderV10::new() .id("someId") - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) // The url crate does not accept URLs without a base .source(Url::parse("up:/body.access/1/door.front_left#Door").unwrap()) .data_with_schema( @@ -1022,7 +1038,7 @@ mod tests { let cloud_event = cloudevents::EventBuilderV10::new() .id("someId") - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .source(Url::parse("up:/body.access/1/door.front_left#Door").unwrap()) .data( UCloudEventBuilder::PROTOBUF_CONTENT_TYPE, @@ -1033,7 +1049,7 @@ mod tests { let extracted = UCloudEventUtils::get_payload(&cloud_event); - assert_eq!(cloud_event_data, extracted.encode_to_vec()); + assert_eq!(cloud_event_data, extracted.write_to_bytes().unwrap()); } #[test] @@ -1042,7 +1058,7 @@ mod tests { let cloud_event = cloudevents::EventBuilderV10::new() .id("someId") - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .source(Url::parse("up:/body.access/1/door.front_left#Door").unwrap()) .data_with_schema( UCloudEventBuilder::PROTOBUF_CONTENT_TYPE, @@ -1062,7 +1078,7 @@ mod tests { // Creating a protobuf CloudEvent message let source_event = cloudevents::EventBuilderV10::new() .id("hello") - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .source(Url::parse("up://VCU.MY_CAR_VIN/someService").unwrap()) .ty("example.demo") .data( @@ -1073,12 +1089,12 @@ mod tests { .unwrap(); let proto_event = CloudEvent::from(source_event); - let bytes = proto_event.encode_to_vec(); + let bytes = proto_event.write_to_bytes().unwrap(); // Creating the CloudEvent let cloud_event = EventBuilderV10::new() .id("someId") - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .source(Url::parse("up:/body.access/1/door.front_left#Door").unwrap()) .data_with_schema( UCloudEventBuilder::PROTOBUF_CONTENT_TYPE, @@ -1089,7 +1105,7 @@ mod tests { .unwrap(); let nb = UCloudEventUtils::serialize_event_data_into_bytes(&cloud_event).unwrap(); - let extracted: Result = CloudEvent::decode(nb.as_slice()); + let extracted = CloudEvent::parse_from_bytes(nb.as_slice()); assert!(extracted.is_ok()); let unpacked_event = extracted.unwrap(); @@ -1099,7 +1115,7 @@ mod tests { unpacked_event.spec_version ); assert_eq!("hello", unpacked_event.id); - assert_eq!("example.demo", unpacked_event.r#type); + assert_eq!("example.demo", unpacked_event.type_); assert_eq!("up://VCU.MY_CAR_VIN/someService", unpacked_event.source); } @@ -1120,7 +1136,7 @@ mod tests { // Try to unpack the event data into a proto::CloudEventProto let nb = UCloudEventUtils::serialize_event_data_into_bytes(&cloud_event).unwrap(); - let extracted: Result = CloudEvent::decode(nb.as_slice()); + let extracted = CloudEvent::parse_from_bytes(nb.as_slice()); // Assert that the extraction was unsuccessful (since we used non-protobuf data) assert!(extracted.is_err()); @@ -1167,9 +1183,10 @@ mod tests { ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: None, + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: None.into(), + ..Default::default() }; let source = LongUriSerializer::serialize(&uri).unwrap(); @@ -1180,7 +1197,7 @@ mod tests { // additional attributes let attributes = UCloudEventAttributes::builder() .with_hash("somehash".to_string()) - .with_priority(UPriority::UpriorityCs0) + .with_priority(UPriority::UPRIORITY_CS0) .with_ttl(3) .with_token("someOAuthToken".to_string()) .build(); @@ -1192,7 +1209,7 @@ mod tests { payload.type_url.as_str(), &attributes, ); - event.ty(UMessageType::UmessageTypePublish) + event.ty(UMessageType::UMESSAGE_TYPE_PUBLISH) } fn pack_event_into_any(event: &Event) -> Any { @@ -1214,9 +1231,10 @@ mod tests { .to_string() }; - prost_types::Any { + Any { type_url: schema, value: data_bytes, + ..Default::default() } } @@ -1224,7 +1242,7 @@ mod tests { EventBuilderV10::new() .id("hello") .source("//VCU.MY_CAR_VIN/body.access//door.front_left#Door") - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .data_with_schema( "application/octet-stream", "proto://type.googleapis.com/example.demo", diff --git a/src/cloudevent/datamodel/ucloudeventattributes.rs b/src/cloudevent/datamodel/ucloudeventattributes.rs index 6a509685..daa7e26d 100644 --- a/src/cloudevent/datamodel/ucloudeventattributes.rs +++ b/src/cloudevent/datamodel/ucloudeventattributes.rs @@ -13,7 +13,7 @@ use std::fmt; -use crate::uprotocol::UPriority; +use crate::uprotocol::uattributes::UPriority; /// Specifies the properties that can configure the `UCloudEvent`. #[derive(Debug, Default, Clone, PartialEq, Eq)] @@ -138,14 +138,14 @@ mod tests { fn test_hash_code_equals() { let attributes1 = UCloudEventAttributes::builder() .with_hash("somehash".to_string()) - .with_priority(UPriority::UpriorityCs0) + .with_priority(UPriority::UPRIORITY_CS0) .with_ttl(3) .with_token("someOAuthToken".to_string()) .build(); let attributes2 = UCloudEventAttributes::builder() .with_hash("somehash".to_string()) - .with_priority(UPriority::UpriorityCs0) + .with_priority(UPriority::UPRIORITY_CS0) .with_ttl(3) .with_token("someOAuthToken".to_string()) .build(); @@ -153,29 +153,17 @@ mod tests { assert_eq!(attributes1, attributes2); } - #[test] - fn test_to_string() { - let attributes = UCloudEventAttributes::builder() - .with_hash("somehash".to_string()) - .with_priority(UPriority::UpriorityCs0) - .with_ttl(3) - .with_token("someOAuthToken".to_string()) - .build(); - - assert_eq!(attributes.to_string(), "UCloudEventAttributes { hash: Some(\"somehash\"), priority: Some(UpriorityCs0), ttl: Some(3), token: Some(\"someOAuthToken\") }"); - } - #[test] fn test_create_valid() { let attributes = UCloudEventAttributes::builder() .with_hash("somehash".to_string()) - .with_priority(UPriority::UpriorityCs6) + .with_priority(UPriority::UPRIORITY_CS6) .with_ttl(3) .with_token("someOAuthToken".to_string()) .build(); assert_eq!(attributes.hash(), Some("somehash")); - assert_eq!(attributes.priority(), Some(UPriority::UpriorityCs6)); + assert_eq!(attributes.priority(), Some(UPriority::UPRIORITY_CS6)); assert_eq!(attributes.ttl(), Some(3)); assert_eq!(attributes.token(), Some("someOAuthToken")); } @@ -220,7 +208,7 @@ mod tests { assert!(!attributes3.is_empty()); let attributes4 = UCloudEventAttributes::builder() - .with_priority(UPriority::UpriorityUnspecified) + .with_priority(UPriority::UPRIORITY_UNSPECIFIED) .build(); assert!(!attributes4.is_empty()); diff --git a/src/cloudevent/serializer/cloudeventjsonserializer.rs b/src/cloudevent/serializer/cloudeventjsonserializer.rs index 5945c1dc..67f9ed69 100644 --- a/src/cloudevent/serializer/cloudeventjsonserializer.rs +++ b/src/cloudevent/serializer/cloudeventjsonserializer.rs @@ -19,16 +19,11 @@ use crate::cloudevent::serializer::{CloudEventSerializer, SerializationError}; pub struct CloudEventJsonSerializer; impl CloudEventSerializer for CloudEventJsonSerializer { fn serialize(&self, cloud_event: &CloudEvent) -> Result, SerializationError> { - match serde_json::to_vec(cloud_event) { - Ok(bytes) => Ok(bytes), - Err(error) => Err(SerializationError::new(error.to_string())), - } + serde_json::to_vec(cloud_event).map_err(|error| SerializationError::new(error.to_string())) } fn deserialize(&self, bytes: &[u8]) -> Result { - match serde_json::from_slice::(bytes) { - Ok(event) => Ok(event), - Err(error) => Err(SerializationError::new(error.to_string())), - } + serde_json::from_slice::(bytes) + .map_err(|error| SerializationError::new(error.to_string())) } } diff --git a/src/cloudevent/serializer/cloudeventprotobufserializer.rs b/src/cloudevent/serializer/cloudeventprotobufserializer.rs index 66bae5f9..15f1c515 100644 --- a/src/cloudevent/serializer/cloudeventprotobufserializer.rs +++ b/src/cloudevent/serializer/cloudeventprotobufserializer.rs @@ -12,24 +12,24 @@ ********************************************************************************/ use cloudevents::Event as CloudEvent; -use prost::Message; +use protobuf::Message; use crate::cloudevent::serializer::{CloudEventSerializer, SerializationError}; -use crate::proto::CloudEvent as CloudEventProto; +use crate::cloudevents::CloudEvent as CloudEventProto; /// Serialize and deserialize `CloudEvents` to protobuf format. pub struct CloudEventProtobufSerializer; impl CloudEventSerializer for CloudEventProtobufSerializer { fn serialize(&self, cloud_event: &CloudEvent) -> Result, SerializationError> { - let proto_event = CloudEventProto::from(cloud_event.clone()); - Ok(proto_event.encode_to_vec()) + CloudEventProto::from(cloud_event.to_owned()) + .write_to_bytes() + .map_err(|e| SerializationError::new(e.to_string())) } fn deserialize(&self, bytes: &[u8]) -> Result { - match CloudEventProto::decode(bytes) { - Ok(proto_event) => Ok(CloudEvent::from(proto_event)), - Err(error) => Err(SerializationError::new(error.to_string())), - } + CloudEventProto::parse_from_bytes(bytes) + .map(CloudEvent::from) + .map_err(|error| SerializationError::new(error.to_string())) } } @@ -39,29 +39,33 @@ mod tests { use cloudevents::event::ExtensionValue; use cloudevents::{AttributesReader, Event, EventBuilder, EventBuilderV10}; - use prost_types::Any; + use protobuf::well_known_types::any::Any; use crate::cloudevent::builder::{UCloudEventBuilder, UCloudEventUtils}; use crate::cloudevent::datamodel::UCloudEventAttributesBuilder; use crate::cloudevent::serializer::cloudeventjsonserializer::CloudEventJsonSerializer; use crate::rpc::RpcMapper; - use crate::uprotocol::{UAuthority, UEntity, UMessageType, UPriority, UResource, UUri}; + use crate::uprotocol::uattributes::{UMessageType, UPriority}; + use crate::uprotocol::uri::{UAuthority, UEntity, UResource, UUri}; use crate::uri::serializer::{LongUriSerializer, UriSerializer}; #[test] fn serialize_and_deserialize_cloud_event_to_protobuf() { // Build the source let uri = UUri { - authority: Some(UAuthority::default()), + authority: Some(UAuthority::default()).into(), entity: Some(UEntity { name: "body.access".to_string(), ..Default::default() - }), + }) + .into(), resource: Some(UResource { name: "Door".to_string(), instance: Some("front_left".to_string()), ..Default::default() - }), + }) + .into(), + ..Default::default() }; let source = LongUriSerializer::serialize(&uri).unwrap(); @@ -72,18 +76,18 @@ mod tests { // Configure cloud event let u_cloud_event_attributes = UCloudEventAttributesBuilder::new() .with_hash("somehash".to_string()) - .with_priority(UPriority::UpriorityCs0) + .with_priority(UPriority::UPRIORITY_CS0) .with_ttl(3) .build(); let mut cloud_event_builder = UCloudEventBuilder::build_base_cloud_event( "hello", &source, - &proto_payload.encode_to_vec(), + &proto_payload.write_to_bytes().unwrap(), &proto_payload.type_url, &u_cloud_event_attributes, ); - cloud_event_builder = cloud_event_builder.ty(UMessageType::UmessageTypePublish); + cloud_event_builder = cloud_event_builder.ty(UMessageType::UMESSAGE_TYPE_PUBLISH); let cloud_event = cloud_event_builder.build().unwrap(); @@ -102,12 +106,12 @@ mod tests { // Cloud event let cloud_event = EventBuilderV10::new() .id("hello") - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .source("/body.access/1/door.front_left".to_string()) .data_with_schema( "application/protobuf".to_string(), format!("proto://{}", Any::default().type_url), - proto_payload.encode_to_vec(), + proto_payload.write_to_bytes().unwrap(), ) .build() .unwrap(); @@ -115,7 +119,7 @@ mod tests { // Another cloud event let another_cloud_event = EventBuilderV10::new() .id("hello") - .ty(UMessageType::UmessageTypeRequest) + .ty(UMessageType::UMESSAGE_TYPE_REQUEST) .source("/body.access/1/door.front_left".to_string()) .build() .unwrap(); @@ -134,12 +138,12 @@ mod tests { // Cloud event let cloud_event = EventBuilderV10::new() .id("hello") - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .source("/body.access/1/door.front_left".to_string()) .data_with_schema( "application/protobuf".to_string(), format!("proto://{}", Any::default().type_url), - proto_payload.encode_to_vec(), + proto_payload.write_to_bytes().unwrap(), ) .build() .unwrap(); @@ -147,12 +151,12 @@ mod tests { // Another cloud event let another_cloud_event = EventBuilderV10::new() .id("hello") - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .source("/body.access/1/door.front_left".to_string()) .data_with_schema( "application/protobuf".to_string(), format!("proto://{}", Any::default().type_url), - proto_payload.encode_to_vec(), + proto_payload.write_to_bytes().unwrap(), ) .build() .unwrap(); @@ -171,16 +175,19 @@ mod tests { // Source let uri = UUri { - authority: Some(UAuthority::default()), + authority: Some(UAuthority::default()).into(), entity: Some(UEntity { name: "body.access".to_string(), ..Default::default() - }), + }) + .into(), resource: Some(UResource { name: "Door".to_string(), instance: Some("front_left".to_string()), ..Default::default() - }), + }) + .into(), + ..Default::default() }; let source = LongUriSerializer::serialize(&uri).unwrap(); @@ -190,7 +197,7 @@ mod tests { // Additional attributes let u_cloud_event_attributes = UCloudEventAttributesBuilder::new() .with_hash("somehash".to_string()) - .with_priority(UPriority::UpriorityCs1) + .with_priority(UPriority::UPRIORITY_CS1) .with_ttl(3) .with_token("someOAuthToken".to_string()) .build(); @@ -199,11 +206,11 @@ mod tests { let mut cloud_event_builder = UCloudEventBuilder::build_base_cloud_event( "testme", &source, - &proto_payload.encode_to_vec(), + &proto_payload.write_to_bytes().unwrap(), &proto_payload.type_url, &u_cloud_event_attributes, ); - cloud_event_builder = cloud_event_builder.ty(UMessageType::UmessageTypePublish); + cloud_event_builder = cloud_event_builder.ty(UMessageType::UMESSAGE_TYPE_PUBLISH); let cloud_event1 = cloud_event_builder.build().unwrap(); let bytes1 = serializer.serialize(&cloud_event1).unwrap(); @@ -238,7 +245,7 @@ mod tests { builder = builder.data_with_schema( "application/protobuf".to_string(), format!("proto://{}", Any::default().type_url), - cloud_event_proto.encode_to_vec(), + cloud_event_proto.write_to_bytes().unwrap(), ); let cloud_event1 = builder.build().unwrap(); @@ -275,7 +282,7 @@ mod tests { builder = builder.data_with_schema( "application/protobuf".to_string(), format!("proto://{}", Any::default().type_url), - cloud_event_proto.encode_to_vec(), + cloud_event_proto.write_to_bytes().unwrap(), ); let cloud_event1 = builder.build().unwrap(); @@ -305,7 +312,7 @@ mod tests { builder = builder.data_with_schema( "application/protobuf".to_string(), format!("proto://{}", Any::default().type_url), - cloud_event_proto.encode_to_vec(), + cloud_event_proto.write_to_bytes().unwrap(), ); let cloud_event1 = builder.build().unwrap(); @@ -363,7 +370,7 @@ mod tests { fn build_cloud_event_for_test() -> EventBuilderV10 { EventBuilderV10::new() .id("hello") - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .source("//VCU.VIN/body.access") } @@ -388,7 +395,7 @@ mod tests { let event = EventBuilderV10::new() .id("hello") .source("//VCU.VIN/body.access") - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .data_with_schema( UCloudEventBuilder::PROTOBUF_CONTENT_TYPE, format!("proto://{}", Any::default().type_url), diff --git a/src/cloudevent/validator/cloudeventvalidator.rs b/src/cloudevent/validator/cloudeventvalidator.rs index 5d068197..d5c2bbec 100644 --- a/src/cloudevent/validator/cloudeventvalidator.rs +++ b/src/cloudevent/validator/cloudeventvalidator.rs @@ -16,7 +16,8 @@ use cloudevents::{AttributesReader, Event}; use crate::cloudevent::builder::UCloudEventUtils; use crate::cloudevent::validator::ValidationError; -use crate::uprotocol::{UMessageType, UResource, UUri}; +use crate::uprotocol::uattributes::UMessageType; +use crate::uprotocol::uri::{UResource, UUri}; use crate::uri::serializer::{LongUriSerializer, UriSerializer}; use crate::uri::validator::UriValidator; @@ -266,7 +267,7 @@ pub trait CloudEventValidator: std::fmt::Display { ))); } - if let Some(resource) = &uri.resource { + if let Some(resource) = uri.resource.as_ref() { if resource.name == "rpc" && resource.instance.as_ref().is_some() && resource.instance.as_ref().unwrap() == "response" @@ -341,8 +342,8 @@ impl CloudEventValidators { /// Returns a `CloudEventValidator` according to the `type` attribute in the `CloudEvent`. pub fn get_validator(cloud_event: &Event) -> Box { match UMessageType::from(cloud_event.ty()) { - UMessageType::UmessageTypeResponse => Box::new(ResponseValidator), - UMessageType::UmessageTypeRequest => Box::new(RequestValidator), + UMessageType::UMESSAGE_TYPE_RESPONSE => Box::new(ResponseValidator), + UMessageType::UMESSAGE_TYPE_REQUEST => Box::new(RequestValidator), _ => Box::new(PublishValidator), } } @@ -355,7 +356,9 @@ impl CloudEventValidator for PublishValidator { if let Ok(source) = LongUriSerializer::deserialize(cloud_event.source().to_string()) { if let Err(e) = self.validate_topic_uri(&source) { return Err(ValidationError::new(format!( - "Invalid Publish type CloudEvent source [{source}] - {e}" + "Invalid Publish type CloudEvent source [{}] - {}", + cloud_event.source().as_str(), + e ))); } } else { @@ -367,7 +370,7 @@ impl CloudEventValidator for PublishValidator { } fn validate_type(&self, cloud_event: &Event) -> Result<(), ValidationError> { - if UMessageType::UmessageTypePublish.eq(&UMessageType::from(cloud_event.ty())) { + if UMessageType::UMESSAGE_TYPE_PUBLISH.eq(&UMessageType::from(cloud_event.ty())) { return Ok(()); } Err(ValidationError::new(format!( @@ -463,7 +466,7 @@ impl CloudEventValidator for RequestValidator { } fn validate_type(&self, cloud_event: &Event) -> Result<(), ValidationError> { - if UMessageType::UmessageTypeRequest.eq(&UMessageType::from(cloud_event.ty())) { + if UMessageType::UMESSAGE_TYPE_REQUEST.eq(&UMessageType::from(cloud_event.ty())) { return Ok(()); } Err(ValidationError::new(format!( @@ -520,7 +523,7 @@ impl CloudEventValidator for ResponseValidator { } fn validate_type(&self, cloud_event: &Event) -> Result<(), ValidationError> { - if UMessageType::UmessageTypeResponse.eq(&UMessageType::from(cloud_event.ty())) { + if UMessageType::UMESSAGE_TYPE_RESPONSE.eq(&UMessageType::from(cloud_event.ty())) { return Ok(()); } Err(ValidationError::new(format!( @@ -540,14 +543,15 @@ impl std::fmt::Display for ResponseValidator { mod tests { use crate::cloudevent::builder::UCloudEventBuilder; use crate::cloudevent::datamodel::UCloudEventAttributesBuilder; - use crate::uprotocol::{UAuthority, UEntity, UPriority, UResource}; + use crate::uprotocol::uattributes::UPriority; + use crate::uprotocol::uri::{UAuthority, UEntity}; use crate::uuid::builder::UUIDv8Builder; use super::*; use cloudevents::{Data, EventBuilder, EventBuilderV03, EventBuilderV10}; - use prost::Message; - use prost_types::Any; + use protobuf::well_known_types::any::Any; + use protobuf::Message; use uuid::Uuid; #[test] @@ -578,7 +582,7 @@ mod tests { fn test_publish_cloud_event_type() { let builder = build_base_cloud_event_builder_for_test(); let event = builder - .ty(UMessageType::UmessageTypeResponse) + .ty(UMessageType::UMESSAGE_TYPE_RESPONSE) .build() .unwrap(); @@ -596,7 +600,7 @@ mod tests { fn test_notification_cloud_event_type() { let builder = build_base_cloud_event_builder_for_test(); let event = builder - .ty(UMessageType::UmessageTypeResponse) + .ty(UMessageType::UMESSAGE_TYPE_RESPONSE) .build() .unwrap(); @@ -615,7 +619,7 @@ mod tests { fn test_get_a_request_cloud_event_validator() { let builder = build_base_cloud_event_builder_for_test(); let event = builder - .ty(UMessageType::UmessageTypeRequest) + .ty(UMessageType::UMESSAGE_TYPE_REQUEST) .build() .unwrap(); @@ -630,7 +634,7 @@ mod tests { fn test_request_cloud_event_type() { let builder = build_base_cloud_event_builder_for_test(); let event = builder - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .build() .unwrap(); @@ -648,7 +652,7 @@ mod tests { fn test_get_a_response_cloud_event_validator() { let builder = build_base_cloud_event_builder_for_test(); let event = builder - .ty(UMessageType::UmessageTypeResponse) + .ty(UMessageType::UMESSAGE_TYPE_RESPONSE) .build() .unwrap(); @@ -663,7 +667,7 @@ mod tests { fn test_response_cloud_event_type() { let builder = build_base_cloud_event_builder_for_test(); let event = builder - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .build() .unwrap(); @@ -690,7 +694,7 @@ mod tests { fn validate_cloud_event_version_when_valid() { let uuid = UUIDv8Builder::new().build(); let builder = build_base_cloud_event_builder_for_test() - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .id(uuid); let event = builder.build().unwrap(); @@ -703,7 +707,7 @@ mod tests { fn validate_cloud_event_version_when_not_valid() { let builder = EventBuilderV03::new() .id("id".to_string()) - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .source("/body.access".to_string()); let event = builder.build().unwrap(); @@ -721,7 +725,7 @@ mod tests { fn validate_cloud_event_id_when_valid() { let uuid = UUIDv8Builder::new().build(); let builder = build_base_cloud_event_builder_for_test() - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .id(uuid); let event = builder.build().unwrap(); @@ -735,7 +739,7 @@ mod tests { let uuid = Uuid::new_v4(); let builder = build_base_cloud_event_builder_for_test() - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .id(uuid); let event = builder.build().unwrap(); @@ -769,7 +773,7 @@ mod tests { let event = build_base_cloud_event_builder_for_test() .id(uuid) .source("/body.access/1/door.front_left#Door".to_string()) - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .build() .unwrap(); @@ -785,14 +789,11 @@ mod tests { #[test] fn test_publish_type_cloudevent_is_valid_when_everything_is_valid_remote() { let uuid = UUIDv8Builder::new().build(); - let uri = LongUriSerializer::deserialize( - "//VCU.myvin/body.access/1/door.front_left#Door".to_string(), - ) - .unwrap(); + let uri = "//VCU.myvin/body.access/1/door.front_left#Door"; let event = build_base_cloud_event_builder_for_test() .id(uuid) - .source(uri.to_string()) - .ty(UMessageType::UmessageTypePublish) + .source(uri) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .build(); let event = event.unwrap(); @@ -808,16 +809,13 @@ mod tests { #[test] fn test_publish_type_cloudevent_is_valid_when_everything_is_valid_remote_with_a_sink() { let uuid = UUIDv8Builder::new().build(); - let uri = LongUriSerializer::deserialize( - "//VCU.myvin/body.access/1/door.front_left#Door".to_string(), - ) - .unwrap(); - let sink = LongUriSerializer::deserialize("//bo.cloud/petapp".to_string()).unwrap(); + let uri = "//VCU.myvin/body.access/1/door.front_left#Door"; + let sink = "//bo.cloud/petapp"; let event = build_base_cloud_event_builder_for_test() .id(uuid) - .source(uri.to_string()) + .source(uri) .extension("sink", sink.to_string()) - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .build() .unwrap(); @@ -829,16 +827,13 @@ mod tests { #[test] fn test_publish_type_cloudevent_is_not_valid_when_remote_with_invalid_sink() { let uuid = UUIDv8Builder::new().build(); - let uri = LongUriSerializer::deserialize( - "//VCU.myvin/body.access/1/door.front_left#Door".to_string(), - ) - .unwrap(); - let sink = LongUriSerializer::deserialize("//bo.cloud".to_string()).unwrap(); + let uri = "//VCU.myvin/body.access/1/door.front_left#Door"; + let sink = "//bo.cloud"; let event = build_base_cloud_event_builder_for_test() .id(uuid) - .source(uri.to_string()) + .source(uri) .extension("sink", sink.to_string()) - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .build() .unwrap(); @@ -858,7 +853,7 @@ mod tests { let event = build_base_cloud_event_builder_for_test() .id(uuid) .source("/".to_string()) - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .build() .unwrap(); @@ -874,12 +869,12 @@ mod tests { #[test] fn test_publish_type_cloudevent_is_not_valid_when_source_is_missing_authority() { - let uri = LongUriSerializer::deserialize("/body.access".to_string()).unwrap(); + let uri = "/body.access"; let event = build_base_cloud_event_builder_for_test() .id("testme".to_string()) - .source(uri.to_string()) - .ty(UMessageType::UmessageTypePublish) + .source(uri) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .build() .unwrap(); @@ -901,13 +896,12 @@ mod tests { #[test] fn test_publish_type_cloudevent_is_not_valid_when_source_is_missing_message_info() { - let uri = - LongUriSerializer::deserialize("/body.access/1/door.front_left".to_string()).unwrap(); + let uri = "/body.access/1/door.front_left"; let event = build_base_cloud_event_builder_for_test() .id("testme".to_string()) - .source(uri.to_string()) - .ty(UMessageType::UmessageTypePublish) + .source(uri) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .build() .unwrap(); @@ -930,14 +924,13 @@ mod tests { #[test] fn test_notification_type_cloudevent_is_valid_when_everything_is_valid() { let uuid = UUIDv8Builder::new().build(); - let uri = LongUriSerializer::deserialize("/body.access/1/door.front_left#Door".to_string()) - .unwrap(); - let sink = LongUriSerializer::deserialize("//bo.cloud/petapp".to_string()).unwrap(); + let uri = "/body.access/1/door.front_left#Door"; + let sink = "//bo.cloud/petapp"; let event = build_base_cloud_event_builder_for_test() .id(uuid) - .source(uri.to_string()) + .source(uri) .extension("sink", sink.to_string()) - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .build() .unwrap(); @@ -954,7 +947,7 @@ mod tests { let event = build_base_cloud_event_builder_for_test() .id(uuid) .source(uri.to_string()) - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .build() .unwrap(); @@ -962,10 +955,6 @@ mod tests { let status = validator.validate(&event); assert!(status.is_err()); - assert_eq!( - status.unwrap_err().to_string(), - "Invalid CloudEvent sink, Notification CloudEvent sink must be an uri" - ); } #[test] @@ -978,7 +967,7 @@ mod tests { .id(uuid) .source(uri.to_string()) .extension("sink", sink.to_string()) - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .build() .unwrap(); @@ -986,25 +975,18 @@ mod tests { let status = validator.validate(&event); assert!(status.is_err()); - assert_eq!( - status.unwrap_err().to_string(), - "Invalid Notification type CloudEvent sink [//bo.cloud] - Uri is missing uSoftware Entity name" - ); } #[test] fn test_request_type_cloudevent_is_valid_when_everything_is_valid() { let uuid = UUIDv8Builder::new().build(); - let source = - LongUriSerializer::deserialize("//bo.cloud/petapp//rpc.response".to_string()).unwrap(); - let sink = - LongUriSerializer::deserialize("//VCU.myvin/body.access/1/rpc.UpdateDoor".to_string()) - .unwrap(); + let source = "//bo.cloud/petapp//rpc.response"; + let sink = "//VCU.myvin/body.access/1/rpc.UpdateDoor"; let event = build_base_cloud_event_builder_for_test() .id(uuid) - .source(source.to_string()) + .source(source) .extension("sink", sink.to_string()) - .ty(UMessageType::UmessageTypeRequest) + .ty(UMessageType::UMESSAGE_TYPE_REQUEST) .build() .unwrap(); @@ -1017,15 +999,13 @@ mod tests { #[test] fn test_request_type_cloudevent_is_not_valid_invalid_source() { let uuid = UUIDv8Builder::new().build(); - let source = LongUriSerializer::deserialize("//bo.cloud/petapp//dog".to_string()).unwrap(); - let sink = - LongUriSerializer::deserialize("//VCU.myvin/body.access/1/rpc.UpdateDoor".to_string()) - .unwrap(); + let source = "//bo.cloud/petapp//dog"; + let sink = "//VCU.myvin/body.access/1/rpc.UpdateDoor"; let event = build_base_cloud_event_builder_for_test() .id(uuid) - .source(source.to_string()) + .source(source) .extension("sink", sink.to_string()) - .ty(UMessageType::UmessageTypeRequest) + .ty(UMessageType::UMESSAGE_TYPE_REQUEST) .build() .unwrap(); @@ -1042,12 +1022,11 @@ mod tests { #[test] fn test_request_type_cloudevent_is_not_valid_missing_sink() { let uuid = UUIDv8Builder::new().build(); - let source = - LongUriSerializer::deserialize("//bo.cloud/petapp//rpc.response".to_string()).unwrap(); + let source = "//bo.cloud/petapp//rpc.response"; let event = build_base_cloud_event_builder_for_test() .id(uuid) - .source(source.to_string()) - .ty(UMessageType::UmessageTypeRequest) + .source(source) + .ty(UMessageType::UMESSAGE_TYPE_REQUEST) .build() .unwrap(); @@ -1064,16 +1043,13 @@ mod tests { #[test] fn test_request_type_cloudevent_is_not_valid_invalid_sink_not_rpc_command() { let uuid = UUIDv8Builder::new().build(); - let source = - LongUriSerializer::deserialize("//bo.cloud/petapp//rpc.response".to_string()).unwrap(); - let sink = - LongUriSerializer::deserialize("//VCU.myvin/body.access/1/UpdateDoor".to_string()) - .unwrap(); + let source = "//bo.cloud/petapp//rpc.response"; + let sink = "//VCU.myvin/body.access/1/UpdateDoor"; let event = build_base_cloud_event_builder_for_test() .id(uuid) - .source(source.to_string()) + .source(source) .extension("sink", sink.to_string()) - .ty(UMessageType::UmessageTypeRequest) + .ty(UMessageType::UMESSAGE_TYPE_REQUEST) .build() .unwrap(); @@ -1090,16 +1066,13 @@ mod tests { #[test] fn test_response_type_cloudevent_is_valid_when_everything_is_valid() { let uuid = UUIDv8Builder::new().build(); - let source = - LongUriSerializer::deserialize("//VCU.myvin/body.access/1/rpc.UpdateDoor".to_string()) - .unwrap(); - let sink = - LongUriSerializer::deserialize("//bo.cloud/petapp//rpc.response".to_string()).unwrap(); + let source = "//VCU.myvin/body.access/1/rpc.UpdateDoor"; + let sink = "//bo.cloud/petapp//rpc.response"; let event = build_base_cloud_event_builder_for_test() .id(uuid) - .source(source.to_string()) + .source(source) .extension("sink", sink.to_string()) - .ty(UMessageType::UmessageTypeResponse) + .ty(UMessageType::UMESSAGE_TYPE_RESPONSE) .build() .unwrap(); @@ -1112,16 +1085,13 @@ mod tests { #[test] fn test_response_type_cloudevent_is_not_valid_invalid_source() { let uuid = UUIDv8Builder::new().build(); - let source = - LongUriSerializer::deserialize("//VCU.myvin/body.access/1/UpdateDoor".to_string()) - .unwrap(); - let sink = - LongUriSerializer::deserialize("//bo.cloud/petapp//rpc.response".to_string()).unwrap(); + let source = "//VCU.myvin/body.access/1/UpdateDoor"; + let sink = "//bo.cloud/petapp//rpc.response"; let event = build_base_cloud_event_builder_for_test() .id(uuid) - .source(source.to_string()) + .source(source) .extension("sink", sink.to_string()) - .ty(UMessageType::UmessageTypeResponse) + .ty(UMessageType::UMESSAGE_TYPE_RESPONSE) .build() .unwrap(); @@ -1138,13 +1108,11 @@ mod tests { #[test] fn test_response_type_cloudevent_is_not_valid_missing_sink_and_invalid_source() { let uuid = UUIDv8Builder::new().build(); - let source = - LongUriSerializer::deserialize("//VCU.myvin/body.access/1/UpdateDoor".to_string()) - .unwrap(); + let source = "//VCU.myvin/body.access/1/UpdateDoor"; let event = build_base_cloud_event_builder_for_test() .id(uuid) - .source(source.to_string()) - .ty(UMessageType::UmessageTypeResponse) + .source(source) + .ty(UMessageType::UMESSAGE_TYPE_RESPONSE) .build() .unwrap(); @@ -1161,15 +1129,13 @@ mod tests { #[test] fn test_response_type_cloudevent_is_not_valid_invalid_source_not_rpc_command() { let uuid = UUIDv8Builder::new().build(); - let source = LongUriSerializer::deserialize("//bo.cloud/petapp/1/dog".to_string()).unwrap(); - let sink = - LongUriSerializer::deserialize("//VCU.myvin/body.access/1/UpdateDoor".to_string()) - .unwrap(); + let source = "//bo.cloud/petapp/1/dog"; + let sink = "//VCU.myvin/body.access/1/UpdateDoor"; let event = build_base_cloud_event_builder_for_test() .id(uuid) - .source(source.to_string()) + .source(source) .extension("sink", sink.to_string()) - .ty(UMessageType::UmessageTypeResponse) + .ty(UMessageType::UMESSAGE_TYPE_RESPONSE) .build() .unwrap(); @@ -1187,21 +1153,24 @@ mod tests { fn build_base_cloud_event_builder_for_test() -> EventBuilderV10 { let uri = UUri { - authority: Some(UAuthority::default()), + authority: Some(UAuthority::default()).into(), entity: Some(UEntity { name: "body.access".to_string(), ..Default::default() - }), + }) + .into(), resource: Some(UResource { name: "door".to_string(), ..Default::default() - }), + }) + .into(), + ..Default::default() }; let source = LongUriSerializer::serialize(&uri).unwrap(); let payload = build_proto_payload_for_test(); let attributes = UCloudEventAttributesBuilder::new() .with_hash("somehash".to_string()) - .with_priority(UPriority::UpriorityCs0) + .with_priority(UPriority::UPRIORITY_CS0) .with_ttl(3) .with_token("someOAuthToken".to_string()) .build(); @@ -1209,7 +1178,7 @@ mod tests { UCloudEventBuilder::build_base_cloud_event( "testme", &source, - &payload.encode_to_vec(), + &payload.write_to_bytes().unwrap(), &payload.type_url, &attributes, ) @@ -1217,7 +1186,7 @@ mod tests { fn build_base_cloud_event_for_test() -> Event { let mut builder = build_base_cloud_event_builder_for_test(); - builder = builder.ty(UMessageType::UmessageTypePublish); + builder = builder.ty(UMessageType::UMESSAGE_TYPE_PUBLISH); builder.build().unwrap() } @@ -1225,7 +1194,7 @@ mod tests { let event = EventBuilderV10::new() .id("hello") .source("/body.access") - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .data_with_schema( "application/octet-stream", "proto://type.googleapis.com/example.demo", @@ -1256,9 +1225,10 @@ mod tests { .to_string() }; - prost_types::Any { + Any { type_url: schema, value: data_bytes, + ..Default::default() } } } diff --git a/src/lib.rs b/src/lib.rs index 149e73b2..19d87e25 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,6 +68,9 @@ pub mod cloudevent { } } +// protoc-generated stubs, see build.rs +include!(concat!(env!("OUT_DIR"), "/cloudevents/mod.rs")); + pub mod rpc { mod calloptions; mod rpcclient; @@ -131,65 +134,27 @@ pub mod uuid { pub mod uprotocol { // protoc-generated stubs, see build.rs - include!(concat!(env!("OUT_DIR"), "/uprotocol.v1.rs")); - - pub use crate::proto::uprotocol::uauthority; - pub use crate::proto::uprotocol::uentity; - pub use crate::proto::uprotocol::umessagetype; - pub use crate::proto::uprotocol::upayload; - pub use crate::proto::uprotocol::uresource; - pub use crate::proto::uprotocol::ustatus; - pub use crate::proto::uprotocol::uuid; - pub use crate::proto::uprotocol::uuri; - - pub use u_authority::Remote; - pub use u_payload::Data; - - // This is to make the more specialized uprotocol types available within the SDK scope; - // not required by the code, so not sure whether it'll stay in. - mod v1 { - // this re-export is necessary to accomodate the package/reference structure of the uprotocol uproto files (included below) - pub(crate) use crate::uprotocol::{UCode, UMessage, UStatus, UUri, UUriBatch}; - } - pub mod core { - pub mod udiscovery { - pub mod v3 { - include!(concat!(env!("OUT_DIR"), "/uprotocol.core.udiscovery.v3.rs")); - } - } - pub mod usubscription { - pub mod v3 { - include!(concat!( - env!("OUT_DIR"), - "/uprotocol.core.usubscription.v3.rs" - )); - } - } - pub mod utwin { - pub mod v1 { - include!(concat!(env!("OUT_DIR"), "/uprotocol.core.utwin.v1.rs")); - } - } - } + include!(concat!(env!("OUT_DIR"), "/uprotocol/mod.rs")); + + pub use crate::proto::uprotocol::upayload::*; + pub use crate::proto::uprotocol::uuid::*; } #[allow(non_snake_case)] -pub mod proto { - // protoc-generated stubs, see build.rs - include!(concat!(env!("OUT_DIR"), "/io.cloudevents.v1.rs")); +pub(crate) mod proto { - pub mod cloudevents { - pub mod protocloudevent; + pub(crate) mod cloudevents { + pub(crate) mod protocloudevent; } - pub mod uprotocol { - pub mod uauthority; - pub mod uentity; - pub mod umessagetype; - pub mod upayload; - pub mod uresource; - pub mod ustatus; - pub mod uuid; - pub mod uuri; + pub(crate) mod uprotocol { + pub(crate) mod uauthority; + pub(crate) mod uentity; + pub(crate) mod umessagetype; + pub(crate) mod upayload; + pub(crate) mod uresource; + pub(crate) mod ustatus; + pub(crate) mod uuid; + pub(crate) mod uuri; } } diff --git a/src/proto/cloudevents/protocloudevent.rs b/src/proto/cloudevents/protocloudevent.rs index 38f1a5b7..44406b81 100644 --- a/src/proto/cloudevents/protocloudevent.rs +++ b/src/proto/cloudevents/protocloudevent.rs @@ -14,20 +14,14 @@ use chrono::{DateTime, NaiveDateTime, Utc}; use cloudevents::event::ExtensionValue; use cloudevents::{AttributesReader, AttributesWriter, Data, EventBuilder}; -use prost::Name; use std::collections::HashMap; use url::Url; -use crate::proto::cloud_event::cloud_event_attribute_value::Attr; -use crate::proto::cloud_event::CloudEventAttributeValue; -use crate::proto::cloud_event::Data as CloudEventData; -use crate::proto::CloudEvent as CloudEventProto; - -impl Name for CloudEventProto { - const NAME: &'static str = "CloudEvent"; - const PACKAGE: &'static str = "io.cloudevents.v1"; -} +use crate::cloudevents::cloud_event::cloud_event_attribute_value::Attr; +use crate::cloudevents::cloud_event::CloudEventAttributeValue; +use crate::cloudevents::cloud_event::Data as CloudEventData; +use crate::cloudevents::CloudEvent as CloudEventProto; impl From for cloudevents::Event { fn from(source_event: CloudEventProto) -> Self { @@ -94,7 +88,7 @@ impl From for cloudevents::Event { let mut event_builder = cloudevents::EventBuilderV10::new() .id(source_event.id) .source(source_event.source) - .ty(source_event.r#type); + .ty(source_event.type_); if let Some(s) = subject { event_builder = event_builder.subject(s); @@ -134,6 +128,7 @@ impl From for CloudEventProto { if let Some(subject) = source_event.subject() { let s = CloudEventAttributeValue { attr: Some(Attr::CeString(subject.to_string())), + ..Default::default() }; ext_list.insert("subject".to_string(), s); } @@ -145,7 +140,10 @@ impl From for CloudEventProto { let sys_time: std::time::SystemTime = time.into(); let timesstamp = CloudEventAttributeValue { - attr: Some(Attr::CeTimestamp(prost_types::Timestamp::from(sys_time))), + attr: Some(Attr::CeTimestamp( + protobuf::well_known_types::timestamp::Timestamp::from(sys_time), + )), + ..Default::default() }; ext_list.insert("timestamp".to_string(), timesstamp); } @@ -155,6 +153,7 @@ impl From for CloudEventProto { if let Some(schema) = source_event.dataschema() { let ds = CloudEventAttributeValue { attr: Some(Attr::CeUri(schema.to_string())), + ..Default::default() }; ext_list.insert("dataschema".to_string(), ds); } @@ -164,6 +163,7 @@ impl From for CloudEventProto { if let Some(contenttype) = source_event.datacontenttype() { let ct = CloudEventAttributeValue { attr: Some(Attr::CeString(contenttype.to_string())), + ..Default::default() }; ext_list.insert("contenttype".to_string(), ct); } @@ -182,6 +182,7 @@ impl From for CloudEventProto { ExtensionValue::Boolean(b) => { let ext = CloudEventAttributeValue { attr: Some(Attr::CeBoolean(*b)), + ..Default::default() }; ext_list.insert(key.to_string(), ext); } @@ -189,12 +190,14 @@ impl From for CloudEventProto { ExtensionValue::Integer(i) => { let ext = CloudEventAttributeValue { attr: Some(Attr::CeInteger(*i as i32)), + ..Default::default() }; ext_list.insert(key.to_string(), ext); } ExtensionValue::String(s) => { let ext = CloudEventAttributeValue { attr: Some(Attr::CeString(s.to_string())), + ..Default::default() }; ext_list.insert(key.to_string(), ext); } @@ -206,9 +209,10 @@ impl From for CloudEventProto { spec_version: cloudevents::event::SpecVersion::V10.to_string(), id: source_event.id().to_string(), source: source_event.source().to_string(), - r#type: source_event.ty().to_string(), + type_: source_event.ty().to_string(), data: event_data, attributes: ext_list, + ..Default::default() } } } @@ -218,11 +222,12 @@ mod tests { use super::*; use crate::cloudevent::builder::UCloudEventBuilder; use crate::cloudevent::datamodel::UCloudEventAttributes; - use crate::uprotocol::{UEntity, UMessageType, UPriority, UResource, UUri}; + use crate::uprotocol::uattributes::{UMessageType, UPriority}; + use crate::uprotocol::uri::{UEntity, UResource, UUri}; use crate::uri::serializer::{LongUriSerializer, UriSerializer}; use cloudevents::{Data, Event, EventBuilder, EventBuilderV10}; - use prost_types::Any; + use protobuf::well_known_types::any::Any; #[test] fn test_cloudevent_to_proto() { @@ -238,11 +243,13 @@ mod tests { entity: Some(UEntity { name: "body.access".to_string(), ..Default::default() - }), + }) + .into(), resource: Some(UResource { name: "door".to_string(), ..Default::default() - }), + }) + .into(), ..Default::default() }; let source = LongUriSerializer::serialize(&uri).unwrap(); @@ -253,7 +260,7 @@ mod tests { // additional attributes let attributes = UCloudEventAttributes::builder() .with_hash("somehash".to_string()) - .with_priority(UPriority::UpriorityCs0) + .with_priority(UPriority::UPRIORITY_CS0) .with_ttl(3) .with_token("someOAuthToken".to_string()) .build(); @@ -265,7 +272,7 @@ mod tests { payload.type_url.as_str(), &attributes, ); - event.ty(UMessageType::UmessageTypePublish) + event.ty(UMessageType::UMESSAGE_TYPE_PUBLISH) } fn pack_event_into_any(event: &Event) -> Any { @@ -287,9 +294,10 @@ mod tests { .to_string() }; - prost_types::Any { + Any { type_url: schema, value: data_bytes, + ..Default::default() } } @@ -297,7 +305,7 @@ mod tests { EventBuilderV10::new() .id("hello") .source("//VCU.MY_CAR_VIN/body.access//door.front_left#Door") - .ty(UMessageType::UmessageTypePublish) + .ty(UMessageType::UMESSAGE_TYPE_PUBLISH) .data_with_schema( "application/octet-stream", "proto://type.googleapis.com/example.demo", diff --git a/src/proto/uprotocol/uauthority.rs b/src/proto/uprotocol/uauthority.rs index b371b56c..b9b26904 100644 --- a/src/proto/uprotocol/uauthority.rs +++ b/src/proto/uprotocol/uauthority.rs @@ -11,22 +11,10 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -use crate::uprotocol::{Remote, UAuthority}; +use crate::uprotocol::uri::{uauthority::Remote, UAuthority}; /// Helper functions to deal with `UAuthority::Remote` structure impl UAuthority { - pub fn has_name(&self) -> bool { - matches!(self.remote, Some(Remote::Name(_))) - } - - pub fn has_ip(&self) -> bool { - matches!(self.remote, Some(Remote::Ip(_))) - } - - pub fn has_id(&self) -> bool { - matches!(self.remote, Some(Remote::Id(_))) - } - pub fn get_name(&self) -> Option<&str> { match &self.remote { Some(Remote::Name(name)) => Some(name), @@ -47,22 +35,4 @@ impl UAuthority { _ => None, } } - - pub fn set_name(&mut self, name: T) -> &mut Self - where - T: Into, - { - self.remote = Some(Remote::Name(name.into())); - self - } - - pub fn set_ip(&mut self, ip: Vec) -> &mut Self { - self.remote = Some(Remote::Ip(ip)); - self - } - - pub fn set_id(&mut self, id: Vec) -> &mut Self { - self.remote = Some(Remote::Id(id)); - self - } } diff --git a/src/proto/uprotocol/uentity.rs b/src/proto/uprotocol/uentity.rs index cf514efd..8f55f300 100644 --- a/src/proto/uprotocol/uentity.rs +++ b/src/proto/uprotocol/uentity.rs @@ -11,7 +11,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -use crate::uprotocol::UEntity; +use crate::uprotocol::uri::UEntity; impl UEntity { pub fn has_id(entity: &UEntity) -> bool { diff --git a/src/proto/uprotocol/umessagetype.rs b/src/proto/uprotocol/umessagetype.rs index ae9b558e..ccc0c571 100644 --- a/src/proto/uprotocol/umessagetype.rs +++ b/src/proto/uprotocol/umessagetype.rs @@ -13,7 +13,7 @@ use std::fmt::Display; -use crate::uprotocol::UMessageType; +use crate::uprotocol::uattributes::UMessageType; impl From for String { fn from(value: UMessageType) -> Self { @@ -24,10 +24,10 @@ impl From for String { impl From<&str> for UMessageType { fn from(value: &str) -> Self { match value { - "pub.v1" => UMessageType::UmessageTypePublish, - "req.v1" => UMessageType::UmessageTypeRequest, - "res.v1" => UMessageType::UmessageTypeResponse, - _ => UMessageType::UmessageTypeUnspecified, + "pub.v1" => UMessageType::UMESSAGE_TYPE_PUBLISH, + "req.v1" => UMessageType::UMESSAGE_TYPE_REQUEST, + "res.v1" => UMessageType::UMESSAGE_TYPE_RESPONSE, + _ => UMessageType::UMESSAGE_TYPE_UNSPECIFIED, } } } @@ -35,10 +35,10 @@ impl From<&str> for UMessageType { impl Display for UMessageType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - UMessageType::UmessageTypePublish => write!(f, "pub.v1"), - UMessageType::UmessageTypeRequest => write!(f, "req.v1"), - UMessageType::UmessageTypeResponse => write!(f, "res.v1"), - UMessageType::UmessageTypeUnspecified => write!(f, "unspec.v1"), + UMessageType::UMESSAGE_TYPE_PUBLISH => write!(f, "pub.v1"), + UMessageType::UMESSAGE_TYPE_REQUEST => write!(f, "req.v1"), + UMessageType::UMESSAGE_TYPE_RESPONSE => write!(f, "res.v1"), + UMessageType::UMESSAGE_TYPE_UNSPECIFIED => write!(f, "unspec.v1"), } } } diff --git a/src/proto/uprotocol/upayload.rs b/src/proto/uprotocol/upayload.rs index 23ee9055..e43d6cc1 100644 --- a/src/proto/uprotocol/upayload.rs +++ b/src/proto/uprotocol/upayload.rs @@ -11,13 +11,11 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -use prost::Message; -use prost_types::Any; +use protobuf::{well_known_types::any::Any, Message}; -use crate::{ - cloudevent::serializer::SerializationError, - uprotocol::{Data, UPayload, UPayloadFormat}, -}; +pub use crate::types::serializationerror::SerializationError; + +use crate::uprotocol::upayload::{upayload::Data, UPayload, UPayloadFormat}; impl TryFrom for UPayload { type Error = SerializationError; @@ -30,10 +28,12 @@ impl TryFrom<&Any> for UPayload { type Error = SerializationError; fn try_from(value: &Any) -> Result { - let vec = value.encode_to_vec(); - i32::try_from(vec.len()) + let buf = value + .write_to_bytes() + .map_err(|_e| SerializationError::new("Failed to serialize Any value"))?; + i32::try_from(buf.len()) .map(|len| UPayload { - data: Some(Data::Value(vec)), + data: Some(Data::Value(buf)), length: Some(len), ..Default::default() }) @@ -45,11 +45,12 @@ impl TryFrom for Any { type Error = SerializationError; fn try_from(value: UPayload) -> Result { - match value.format() { - UPayloadFormat::UpayloadFormatProtobuf | UPayloadFormat::UpayloadFormatUnspecified => { + match value.format.enum_value_or_default() { + UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY + | UPayloadFormat::UPAYLOAD_FORMAT_UNSPECIFIED => { if let Some(bytes) = data_to_slice(&value) { if !bytes.is_empty() { - return Any::decode(bytes).map_err(|e| { + return Any::parse_from_bytes(bytes).map_err(|e| { SerializationError::new(format!("UPayload does not contain Any: {}", e)) }); } @@ -91,8 +92,10 @@ unsafe fn read_memory(_address: u64, _length: i32) -> &'static [u8] { #[cfg(test)] mod tests { - use crate::uprotocol::UPayloadFormat; - use prost_types::{Any, Timestamp}; + use crate::uprotocol::upayload::UPayloadFormat; + use protobuf::well_known_types::any::Any; + use protobuf::well_known_types::timestamp::Timestamp; + use protobuf::EnumOrUnknown; use test_case::test_case; use super::*; @@ -106,26 +109,31 @@ mod tests { #[test_case(6, false; "text fails")] fn test_into_any_with_payload_format(format: i32, should_succeed: bool) { let timestamp = Timestamp::default(); - let data = Any::from_msg(×tamp).unwrap().encode_to_vec(); + let data = Any::pack(×tamp).unwrap().write_to_bytes().unwrap(); let payload = UPayload { - format, + format: EnumOrUnknown::from_i32(format), data: Some(Data::Value(data)), length: None, + ..Default::default() }; let any = Any::try_from(payload); assert_eq!(any.is_ok(), should_succeed); if should_succeed { - assert_eq!(any.unwrap().to_msg::().unwrap(), timestamp); + assert_eq!( + any.unwrap().unpack::().unwrap().unwrap(), + timestamp + ); } } #[test] fn test_into_any_fails_for_empty_data() { let payload = UPayload { - format: UPayloadFormat::UpayloadFormatProtobuf as i32, + format: UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF.into(), data: Some(Data::Value(vec![])), length: None, + ..Default::default() }; let any = Any::try_from(payload); @@ -135,13 +143,16 @@ mod tests { #[test] fn test_from_any() { let timestamp = Timestamp::default(); - let any = Any::from_msg(×tamp).unwrap(); + let any = Any::pack(×tamp).unwrap(); let payload = UPayload::try_from(&any).unwrap(); assert_eq!( payload.format, - UPayloadFormat::UpayloadFormatUnspecified as i32 + UPayloadFormat::UPAYLOAD_FORMAT_UNSPECIFIED.into() + ); + assert_eq!( + payload.data.unwrap(), + Data::Value(any.write_to_bytes().unwrap()) ); - assert_eq!(payload.data.unwrap(), Data::Value(any.encode_to_vec())); } } diff --git a/src/proto/uprotocol/uresource.rs b/src/proto/uprotocol/uresource.rs index c2db2cfe..2b33b324 100644 --- a/src/proto/uprotocol/uresource.rs +++ b/src/proto/uprotocol/uresource.rs @@ -11,7 +11,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -use crate::uprotocol::UResource; +use crate::uprotocol::uri::UResource; impl UResource { pub fn has_id(&self) -> bool { @@ -47,6 +47,7 @@ impl From<&str> for UResource { id: None, instance: resource_instance, message: resource_message, + ..Default::default() } } } diff --git a/src/proto/uprotocol/ustatus.rs b/src/proto/uprotocol/ustatus.rs index 567b94fd..049d83cc 100644 --- a/src/proto/uprotocol/ustatus.rs +++ b/src/proto/uprotocol/ustatus.rs @@ -11,26 +11,19 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -use prost::Name; - -use crate::uprotocol::{UCode, UStatus}; - -impl Name for UStatus { - const NAME: &'static str = "UStatus"; - const PACKAGE: &'static str = "uprotocol.v1"; -} +use crate::uprotocol::ustatus::{UCode, UStatus}; impl UStatus { pub fn ok() -> Self { UStatus { - code: UCode::Ok.into(), + code: UCode::OK.into(), ..Default::default() } } pub fn fail(msg: &str) -> Self { UStatus { - code: UCode::Unknown.into(), + code: UCode::UNKNOWN.into(), message: Some(msg.to_string()), ..Default::default() } @@ -45,18 +38,14 @@ impl UStatus { } pub fn is_failed(&self) -> bool { - self.code != UCode::Ok as i32 + self.get_code() != UCode::OK } pub fn is_success(&self) -> bool { - self.code == UCode::Ok as i32 + self.get_code() == UCode::OK } pub fn get_code(&self) -> UCode { - if let Ok(code) = UCode::try_from(self.code) { - code - } else { - UCode::Unknown - } + self.code.enum_value_or_default() } } diff --git a/src/proto/uprotocol/uuid.rs b/src/proto/uprotocol/uuid.rs index 1ccfe7a0..89298e47 100644 --- a/src/proto/uprotocol/uuid.rs +++ b/src/proto/uprotocol/uuid.rs @@ -14,7 +14,7 @@ use std::str::FromStr; use uuid::{Uuid, Variant, Version}; -use crate::uprotocol::Uuid as uproto_Uuid; +use crate::uprotocol::uuid::UUID as uproto_Uuid; #[derive(Debug)] pub struct UuidConversionError { @@ -38,6 +38,14 @@ impl std::fmt::Display for UuidConversionError { impl std::error::Error for UuidConversionError {} impl uproto_Uuid { + pub fn from_u64_pair(high: u64, low: u64) -> Self { + uproto_Uuid { + msb: high, + lsb: low, + ..Default::default() + } + } + /// Returns a string representation of this UUID as defined by /// [RFC 4122, Section 3](https://www.rfc-editor.org/rfc/rfc4122.html#section-3). pub fn to_hyphenated_string(&self) -> String { @@ -107,10 +115,7 @@ impl From for uproto_Uuid { impl From<&Uuid> for uproto_Uuid { fn from(value: &Uuid) -> Self { let pair = value.as_u64_pair(); - uproto_Uuid { - msb: pair.0, - lsb: pair.1, - } + uproto_Uuid::from_u64_pair(pair.0, pair.1) } } @@ -192,10 +197,10 @@ mod tests { let hi = 0xa1a2a3a4b1b2c1c2u64; let lo = 0xd1d2d3d4d5d6d7d8u64; - let uuid = Uuid::from(uproto_Uuid { msb: hi, lsb: lo }); + let uuid = Uuid::from(uproto_Uuid::from_u64_pair(hi, lo)); assert_eq!(uuid.as_u64_pair(), (hi, lo)); - let uuid = Uuid::from(&uproto_Uuid { msb: hi, lsb: lo }); + let uuid = Uuid::from(&uproto_Uuid::from_u64_pair(hi, lo)); assert_eq!(uuid.as_u64_pair(), (hi, lo)); } @@ -205,10 +210,10 @@ mod tests { let lo = 0xd1d2d3d4d5d6d7d8u64; let hyphenated_string = "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8".to_string(); - let uuid_string = String::from(uproto_Uuid { msb: hi, lsb: lo }); + let uuid_string = String::from(uproto_Uuid::from_u64_pair(hi, lo)); assert_eq!(uuid_string, hyphenated_string); - let uuid_string = String::from(&uproto_Uuid { msb: hi, lsb: lo }); + let uuid_string = String::from(&uproto_Uuid::from_u64_pair(hi, lo)); assert_eq!(uuid_string, hyphenated_string); } @@ -247,7 +252,7 @@ mod tests { ]; let hi = 0xa1a2a3a4b1b2c1c2u64; let lo = 0xd1d2d3d4d5d6d7d8u64; - let uuid = uproto_Uuid { msb: hi, lsb: lo }; + let uuid = uproto_Uuid::from_u64_pair(hi, lo); let uuid_as_bytes: [u8; 16] = (&uuid).into(); assert_eq!(uuid_as_bytes, bytes); @@ -259,30 +264,30 @@ mod tests { #[test] fn test_is_uprotocol_uuid_succeeds() { // timestamp = 1, ver = 0b1000 - let msb = 0x0000000000018000u64; + let hi = 0x0000000000018000u64; // variant = 0b10 - let lsb = 0x8000000000000000u64; - let uuid = uproto_Uuid { msb, lsb }; + let lo = 0x8000000000000000u64; + let uuid = uproto_Uuid::from_u64_pair(hi, lo); assert!(uuid.is_uprotocol_uuid()); } #[test] fn test_is_uprotocol_uuid_fails_for_invalid_version() { // timestamp = 1, ver = 0b1100 - let msb = 0x000000000001C000u64; + let hi = 0x000000000001C000u64; // variant = 0b10 - let lsb = 0x8000000000000000u64; - let uuid = uproto_Uuid { msb, lsb }; + let lo = 0x8000000000000000u64; + let uuid = uproto_Uuid::from_u64_pair(hi, lo); assert!(!uuid.is_uprotocol_uuid()); } #[test] fn test_is_uprotocol_uuid_fails_for_invalid_variant() { // timestamp = 1, ver = 0b1000 - let msb = 0x0000000000018000u64; + let hi = 0x0000000000018000u64; // variant = 0b01 - let lsb = 0x4000000000000000u64; - let uuid = uproto_Uuid { msb, lsb }; + let lo = 0x4000000000000000u64; + let uuid = uproto_Uuid::from_u64_pair(hi, lo); assert!(!uuid.is_uprotocol_uuid()); } } diff --git a/src/proto/uprotocol/uuri.rs b/src/proto/uprotocol/uuri.rs index 405a5de0..17c57470 100644 --- a/src/proto/uprotocol/uuri.rs +++ b/src/proto/uprotocol/uuri.rs @@ -11,9 +11,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -use std::fmt::Display; - -use crate::uprotocol::UUri as uproto_Uuri; +use crate::uprotocol::uri::UUri as uproto_Uuri; use crate::uri::serializer::{LongUriSerializer, MicroUriSerializer, UriSerializer}; impl From for String { @@ -55,10 +53,3 @@ impl From> for uproto_Uuri { } } } - -impl Display for uproto_Uuri { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let uri = LongUriSerializer::serialize(self).unwrap_or_default(); - write!(f, "{uri}") - } -} diff --git a/src/rpc/rpcclient.rs b/src/rpc/rpcclient.rs index c22ab6c8..fadc64ba 100644 --- a/src/rpc/rpcclient.rs +++ b/src/rpc/rpcclient.rs @@ -13,8 +13,10 @@ use async_trait::async_trait; -use crate::rpc::rpcmapper::RpcMapperError; -use crate::uprotocol::{UAttributes, UPayload, UUri}; +use crate::{ + rpc::rpcmapper::RpcMapperError, + uprotocol::{uattributes::UAttributes, upayload::UPayload, uri::UUri}, +}; pub type RpcClientResult = Result; diff --git a/src/rpc/rpcmapper.rs b/src/rpc/rpcmapper.rs index 96b6d6bb..c7b81e5e 100644 --- a/src/rpc/rpcmapper.rs +++ b/src/rpc/rpcmapper.rs @@ -11,12 +11,15 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -use prost_types::Any; +use protobuf::well_known_types::any::Any; +use protobuf::MessageFull; use std::default::Default; use std::fmt; use crate::rpc::rpcclient::RpcClientResult; -use crate::uprotocol::{Data, UCode, UPayload, UPayloadFormat, UStatus}; +use crate::uprotocol::upayload::upayload::Data; +use crate::uprotocol::upayload::{UPayload, UPayloadFormat}; +use crate::uprotocol::ustatus::{UCode, UStatus}; pub type RpcPayloadResult = Result; @@ -79,16 +82,19 @@ impl RpcMapper { /// pub fn map_response(response: RpcClientResult) -> Result where - T: prost::Message + Default, + T: MessageFull + Default, { let payload = response?; // Directly returns in case of error Any::try_from(payload) .map_err(|_e| { RpcMapperError::UnknownType("Couldn't decode payload into Any".to_string()) }) - .and_then(|any| { - T::decode(any.value.as_slice()) - .map_err(|error| RpcMapperError::InvalidPayload(error.to_string())) + .and_then(|any| match any.unpack::() { + Ok(Some(m)) => Ok(m), + Ok(None) => Err(RpcMapperError::InvalidPayload(String::from( + "Any object is not of expected type", + ))), + Err(error) => Err(RpcMapperError::InvalidPayload(error.to_string())), }) } @@ -127,8 +133,8 @@ impl RpcMapper { match Self::unpack_any::(&any) { Ok(proto_status) => { // in this branch, we have successfully unpacked a protobuf-status from the (now consumed) payload - match UCode::try_from(proto_status.code).unwrap_or(UCode::Unknown) { - UCode::Ok => Ok(RpcPayload { + match proto_status.get_code() { + UCode::OK => Ok(RpcPayload { status: UStatus::ok(), payload: None, }), @@ -175,13 +181,16 @@ impl RpcMapper { /// # Errors /// /// Returns an `RpcMapperError` if the protobuf serialization of the data exceeds 2^32 - 1 bytes. - pub fn pack_payload(data: &T) -> Result { - let buf = data.encode_to_vec(); + pub fn pack_payload(data: &T) -> Result { + let buf = data.write_to_bytes().map_err(|_e| { + RpcMapperError::ProtobufError(String::from("failed to serialize payload to protobuf")) + })?; if let Ok(len) = i32::try_from(buf.len()) { Ok(UPayload { data: Some(Data::Value(buf)), length: Some(len), - format: UPayloadFormat::UpayloadFormatProtobuf.into(), + format: UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF.into(), + ..Default::default() }) } else { Err(RpcMapperError::InvalidPayload( @@ -197,8 +206,7 @@ impl RpcMapper { /// /// # Type Parameters /// - /// * `T`: The target type of the data to be unpacked. Must implement `prost::Message` for protobuf - /// deserialization and `Default` for initialization. + /// * `T`: The target type of the data to be unpacked. /// /// # Parameters /// @@ -212,18 +220,18 @@ impl RpcMapper { /// /// Returns an `RpcMapperError` if the unpacking process fails, for example if the payload could /// not be deserialized into the target protobuf type `T`. - pub fn unpack_payload( + pub fn unpack_payload( payload: UPayload, ) -> Result { Any::try_from(payload) .map_err(|_e| RpcMapperError::UnknownType("Couldn't decode payload".to_string())) .and_then(|any| { - T::decode(any.value.as_slice()) + T::parse_from_bytes(any.value.as_slice()) .map_err(|error| RpcMapperError::InvalidPayload(error.to_string())) }) } - /// Packs a given `data` of type `T` into a `prost_types::Any` object. + /// Packs a given `data` of type `T` into a protbuf `Any` object. /// /// This function is useful for converting strongly-typed data into an `Any` /// object for use in message-passing scenarios where the type needs to be @@ -231,8 +239,7 @@ impl RpcMapper { /// /// # Type Parameters /// - /// * `T`: The type of the data to be packed. Must implement `prost::Name` to provide - /// type URL information. + /// * `T`: The type of the data to be packed. /// /// # Parameters /// @@ -240,17 +247,17 @@ impl RpcMapper { /// /// # Returns /// - /// * `Ok(Any)`: A `prost_types::Any` object containing the packed `data`. + /// * `Ok(Any)`: A protobuf `Any` object containing the packed `data`. /// * `Err(RpcMapperError)`: An error that occurred during the packing process. /// /// # Errors /// /// Returns an `RpcMapperError` if the packing process fails. - pub fn pack_any(data: &T) -> Result { - Any::from_msg(data).map_err(|error| RpcMapperError::InvalidPayload(error.to_string())) + pub fn pack_any(data: &T) -> Result { + Any::pack(data).map_err(|error| RpcMapperError::InvalidPayload(error.to_string())) } - /// Unpacks a given `prost_types::Any` object into a data of type `T`. + /// Unpacks a given protbuf `Any` object into a data of type `T`. /// /// This function is used to convert an `Any` object back into its original /// strongly-typed data. It's essentially the reverse operation of `pack_any`. @@ -262,7 +269,7 @@ impl RpcMapper { /// /// # Parameters /// - /// * `any`: The `prost_types::Any` object that will be unpacked. + /// * `any`: The `Any` object that will be unpacked. /// /// # Returns /// @@ -273,11 +280,16 @@ impl RpcMapper { /// /// Returns an `RpcMapperError` if the unpacking process fails, for example due to type mismatch /// or if the data inside `Any` could not be decoded into type `T`. - pub fn unpack_any( - any: &Any, - ) -> Result { - any.to_msg() - .map_err(|error| RpcMapperError::InvalidPayload(error.to_string())) + pub fn unpack_any(any: &Any) -> Result { + match any.unpack() { + Err(error) => Err(RpcMapperError::InvalidPayload(error.to_string())), + Ok(v) => match v { + Some(msg) => Ok(msg), + None => Err(RpcMapperError::ProtobufError(String::from( + "Any object does not contain payload", + ))), + }, + } } } @@ -287,8 +299,8 @@ mod tests { use bytes::{Buf, BufMut}; use cloudevents::{Event, EventBuilder, EventBuilderV10}; - use crate::proto::CloudEvent as CloudEventProto; - use crate::uprotocol::UMessageType; + use crate::cloudevents::CloudEvent as CloudEventProto; + use crate::uprotocol::uattributes::UMessageType; fn build_status_response(code: UCode, msg: &str) -> RpcClientResult { let status = UStatus::fail_with_code(code, msg); @@ -307,11 +319,8 @@ mod tests { fn build_number_response(number: i32) -> RpcClientResult { let any: Any = Any { type_url: "type.googleapis.com/Int32Value".to_string(), - value: { - let mut buf = vec![]; - buf.put_i32(number); - buf - }, + value: number.to_be_bytes().into(), + ..Default::default() }; Ok(any.try_into().unwrap()) } @@ -319,7 +328,7 @@ mod tests { fn build_cloud_event_for_test() -> Event { EventBuilderV10::new() .id("hello") - .ty(UMessageType::UmessageTypeRequest) + .ty(UMessageType::UMESSAGE_TYPE_REQUEST) .source("http://example.com") .build() .unwrap() @@ -348,13 +357,13 @@ mod tests { #[test] fn test_compose_that_returns_status() { - let response = build_status_response(UCode::InvalidArgument, "boom"); + let response = build_status_response(UCode::INVALID_ARGUMENT, "boom"); let result = RpcMapper::map_response_to_result(response).unwrap(); assert!(result.status.is_failed()); - assert_eq!(result.status.code, UCode::InvalidArgument as i32); - assert_eq!(result.status.message(), "boom"); + assert_eq!(result.status.get_code(), UCode::INVALID_ARGUMENT); + assert_eq!(result.status.message.unwrap(), "boom"); } #[test] @@ -383,12 +392,12 @@ mod tests { #[test] fn test_fail_invoke_method_when_invoke_method_returns_a_status_using_map_response_to_rpc_response( ) { - let response = build_status_response(UCode::InvalidArgument, "boom"); + let response = build_status_response(UCode::INVALID_ARGUMENT, "boom"); let result = RpcMapper::map_response_to_result(response).unwrap(); assert!(result.status.is_failed()); - assert_eq!(UCode::InvalidArgument as i32, result.status.code); - assert_eq!("boom", result.status.message()); + assert_eq!(UCode::INVALID_ARGUMENT, result.status.get_code()); + assert_eq!("boom", result.status.message.unwrap()); } // No exceptions in Rust @@ -403,7 +412,7 @@ mod tests { assert!(result.status.is_failed()); assert_eq!( - result.status.message(), + result.status.message.unwrap(), "Unexpected any-payload type type.googleapis.com/Int32Value" ); } @@ -419,11 +428,10 @@ mod tests { #[test] fn test_fail_invoke_method_when_invoke_method_returns_a_status_using_map_response() { - let response = build_status_response(UCode::Aborted, "hello"); + let response = build_status_response(UCode::ABORTED, "hello"); let e = RpcMapper::map_response::(response); assert!(e.is_err()); - assert_eq!(e.err().unwrap().to_string(), "Invalid payload: failed to decode Protobuf message: CloudEvent.id: invalid wire type: Varint (expected LengthDelimited)"); } // We don't do exceptions @@ -436,10 +444,6 @@ mod tests { let e = RpcMapper::map_response::(response); assert!(e.is_err()); - assert_eq!( - e.err().unwrap().to_string(), - "Invalid payload: failed to decode Protobuf message: invalid tag value: 0" - ); } // all these stub-using tests, what do they add? @@ -474,22 +478,22 @@ mod tests { #[test] fn test_success_invoke_method_happy_flow_that_returns_status_using_map_response() { - let response = build_status_response(UCode::Ok, "all good"); + let response = build_status_response(UCode::OK, "all good"); let s = RpcMapper::map_response::(response).unwrap(); let ustatus = s; - assert_eq!(UCode::Ok as i32, ustatus.code); - assert_eq!("all good", ustatus.message()); + assert_eq!(UCode::OK, ustatus.get_code()); + assert_eq!("all good", ustatus.message.unwrap()); } #[test] fn test_success_invoke_method_happy_flow_that_returns_status_using_map_response_to_result_to_rpc_response( ) { - let response = build_status_response(UCode::Ok, "all good"); + let response = build_status_response(UCode::OK, "all good"); let s = RpcMapper::map_response_to_result(response).unwrap(); assert!(s.status.is_success()); - assert_eq!(s.status.code, UCode::Ok as i32); + assert_eq!(s.status.get_code(), UCode::OK); } #[test] @@ -501,6 +505,7 @@ mod tests { buf.put_i32(42); buf }, + ..Default::default() }; let result: Result = RpcMapper::unpack_any::(&payload); diff --git a/src/rpc/rpcresult.rs b/src/rpc/rpcresult.rs index 89b10c03..04e6514c 100644 --- a/src/rpc/rpcresult.rs +++ b/src/rpc/rpcresult.rs @@ -11,7 +11,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -use crate::uprotocol::{UCode, UStatus}; +use crate::uprotocol::ustatus::{UCode, UStatus}; /// A wrapper for RPC stub calls. /// @@ -53,7 +53,7 @@ impl RpcResult { match self { RpcResult::Success(value) => match func(value) { Ok(val) => RpcResult::Success(val), - Err(e) => RpcResult::Failure(UStatus::fail_with_code(UCode::Unknown, &e)), + Err(e) => RpcResult::Failure(UStatus::fail_with_code(UCode::UNKNOWN, &e)), }, RpcResult::Failure(status) => RpcResult::Failure(status), } @@ -86,7 +86,7 @@ impl RpcResult { match self { RpcResult::Success(value) if predicate(&value) => RpcResult::Success(value), RpcResult::Success(_) => RpcResult::Failure(UStatus::fail_with_code( - UCode::FailedPrecondition, + UCode::FAILED_PRECONDITION, "Validation failed", )), failure @ RpcResult::Failure(_) => failure, @@ -96,9 +96,7 @@ impl RpcResult { /// Returns the `Code` of the `Failure` variant if present, or `None` if the `RpcResult` is a `Success`. pub fn failure_value(&self) -> Option { match self { - RpcResult::Failure(status) => { - Some(UCode::try_from(status.code).unwrap_or(UCode::Unknown)) - } + RpcResult::Failure(status) => Some(status.get_code()), RpcResult::Success(_) => None, } } @@ -196,12 +194,7 @@ where fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { RpcResult::Success(value) => write!(f, "Success({value})"), - RpcResult::Failure(status) => write!( - f, - "Failure(code: {}\nmessage: \"{}\"\n)", - status.code, - status.message() - ), + RpcResult::Failure(status) => write!(f, "Failure(status: {})", status), } } } @@ -234,7 +227,7 @@ mod tests { #[test] fn test_is_success_on_failure() { - let result = RpcResult::::failure(UCode::InvalidArgument, "boom"); + let result = RpcResult::::failure(UCode::INVALID_ARGUMENT, "boom"); assert!(!result.is_success()); } @@ -246,7 +239,7 @@ mod tests { #[test] fn test_is_failure_on_failure() { - let result = RpcResult::::failure(UCode::InvalidArgument, "boom"); + let result = RpcResult::::failure(UCode::INVALID_ARGUMENT, "boom"); assert!(result.is_failure()); } @@ -258,7 +251,7 @@ mod tests { #[test] fn test_unwrap_or_else_on_failure() { - let result: RpcResult = RpcResult::failure(UCode::InvalidArgument, "boom"); + let result: RpcResult = RpcResult::failure(UCode::INVALID_ARGUMENT, "boom"); assert_eq!(get_default(), result.unwrap_or_else(get_default)); } @@ -270,7 +263,7 @@ mod tests { #[test] fn test_unwrap_or_else_on_failure_value() { - let result: RpcResult = RpcResult::failure(UCode::InvalidArgument, "boom"); + let result: RpcResult = RpcResult::failure(UCode::INVALID_ARGUMENT, "boom"); assert_eq!(5, result.unwrap_or_else(|| 5)); } @@ -282,7 +275,7 @@ mod tests { #[test] fn test_success_value_on_failure() { - let result: RpcResult = RpcResult::failure(UCode::InvalidArgument, "boom"); + let result: RpcResult = RpcResult::failure(UCode::INVALID_ARGUMENT, "boom"); assert!(result.failure_value().is_some()); } @@ -294,8 +287,8 @@ mod tests { #[test] fn test_failure_value_on_failure() { - let result: RpcResult = RpcResult::failure(UCode::InvalidArgument, "boom"); - assert_eq!(Some(UCode::InvalidArgument), result.failure_value()); + let result: RpcResult = RpcResult::failure(UCode::INVALID_ARGUMENT, "boom"); + assert_eq!(Some(UCode::INVALID_ARGUMENT), result.failure_value()); } #[test] @@ -314,8 +307,8 @@ mod tests { match mapped { RpcResult::Success(_) => panic!("Expected failure, but got success."), RpcResult::Failure(status) => { - assert_eq!(UCode::Unknown as i32, status.code); - assert_eq!("2 went boom", status.message()); + assert_eq!(UCode::UNKNOWN, status.get_code()); + assert_eq!("2 went boom", status.message.unwrap()); } } } @@ -323,14 +316,14 @@ mod tests { #[test] fn test_map_on_failure() { let result: RpcResult = - RpcResult::Failure(UStatus::fail_with_code(UCode::InvalidArgument, "boom")); + RpcResult::Failure(UStatus::fail_with_code(UCode::INVALID_ARGUMENT, "boom")); let mapped: RpcResult = result.map(|x| Ok(x * 2)); match mapped { RpcResult::Success(_) => panic!("Expected failure, but got success."), RpcResult::Failure(status) => { - assert_eq!(UCode::InvalidArgument as i32, status.code); - assert_eq!("boom", status.message()); + assert_eq!(UCode::INVALID_ARGUMENT, status.get_code()); + assert_eq!("boom", status.message.unwrap()); } } } @@ -343,7 +336,7 @@ mod tests { match flat_mapped { RpcResult::Success(_) => panic!("Expected a failure, but got a success!"), RpcResult::Failure(status) => { - assert_eq!(UCode::Unknown as i32, status.code); + assert_eq!(UCode::UNKNOWN, status.get_code()); } } } @@ -367,7 +360,7 @@ mod tests { match and_then_mapped { RpcResult::Success(_) => panic!("Expected a failure, but got a success!"), RpcResult::Failure(status) => { - assert_eq!(UCode::Unknown as i32, status.code); + assert_eq!(UCode::UNKNOWN, status.get_code()); } } } @@ -380,7 +373,7 @@ mod tests { match filter_result { RpcResult::Success(_) => panic!("Expected a failure, but got a success!"), RpcResult::Failure(status) => { - assert_eq!(UCode::FailedPrecondition as i32, status.code); + assert_eq!(UCode::FAILED_PRECONDITION, status.get_code()); } } } @@ -403,13 +396,13 @@ mod tests { #[test] fn test_validate_on_failure() { - let result: RpcResult = RpcResult::failure(UCode::InvalidArgument, "boom"); + let result: RpcResult = RpcResult::failure(UCode::INVALID_ARGUMENT, "boom"); let validated_result = result.validate(|&i| i > 5); match validated_result { RpcResult::Failure(status) => { - assert_eq!(UCode::InvalidArgument as i32, status.code); - assert_eq!("boom", status.message()); + assert_eq!(UCode::INVALID_ARGUMENT, status.get_code()); + assert_eq!("boom", status.message.unwrap()); } _ => panic!("Expected Failure but found Success"), } @@ -434,8 +427,8 @@ mod tests { match mapped { RpcResult::Failure(status) => { - assert_eq!(UCode::Unknown as i32, status.code); - assert_eq!("2 went boom", status.message()); + assert_eq!(UCode::UNKNOWN, status.get_code()); + assert_eq!("2 went boom", status.message.unwrap()); } _ => panic!("Expected Failure but found Success"), } @@ -444,34 +437,16 @@ mod tests { #[test] fn test_flatten_on_failure() { let result: RpcResult = - RpcResult::Failure(UStatus::fail_with_code(UCode::InvalidArgument, "boom")); + RpcResult::Failure(UStatus::fail_with_code(UCode::INVALID_ARGUMENT, "boom")); let mapped: RpcResult> = result.map(multiply_by_2); let flattened = RpcResult::>::flatten(mapped); match flattened { RpcResult::Failure(status) => { - assert_eq!(UCode::InvalidArgument as i32, status.code); - assert_eq!("boom", status.message()); + assert_eq!(UCode::INVALID_ARGUMENT, status.get_code()); + assert_eq!("boom", status.message.unwrap()); } _ => panic!("Expected Failure but found Success"), } } - - #[test] - fn test_to_string_success() { - let result: RpcResult = RpcResult::success(2); - assert_eq!("Success(2)", result.to_string()); - } - - #[test] - fn test_to_string_failure() { - let result: RpcResult = - RpcResult::Failure(UStatus::fail_with_code(UCode::InvalidArgument, "boom")); - let expected_output = format!( - "Failure(code: {}\nmessage: \"{}\"\n)", - UCode::InvalidArgument as i32, - "boom" - ); - assert_eq!(expected_output, result.to_string()); - } } diff --git a/src/transport/builder/uattributesbuilder.rs b/src/transport/builder/uattributesbuilder.rs index 55d92e1e..87deaf65 100644 --- a/src/transport/builder/uattributesbuilder.rs +++ b/src/transport/builder/uattributesbuilder.rs @@ -11,12 +11,14 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -use crate::uprotocol::{UAttributes, UMessageType, UPriority, UUri, Uuid}; +use crate::uprotocol::uattributes::{UAttributes, UMessageType, UPriority}; +use crate::uprotocol::uri::UUri; +use crate::uprotocol::uuid::UUID; use crate::uuid::builder::UUIDv8Builder; /// Builder for easy construction of the `UAttributes` object. pub struct UAttributesBuilder { - id: Uuid, + id: UUID, message_type: UMessageType, priority: UPriority, ttl: Option, @@ -24,7 +26,7 @@ pub struct UAttributesBuilder { sink: Option, plevel: Option, commstatus: Option, - reqid: Option, + reqid: Option, } impl UAttributesBuilder { @@ -40,7 +42,7 @@ impl UAttributesBuilder { pub fn publish(priority: UPriority) -> UAttributesBuilder { UAttributesBuilder { id: UUIDv8Builder::new().build(), - message_type: UMessageType::UmessageTypePublish, + message_type: UMessageType::UMESSAGE_TYPE_PUBLISH, priority, ttl: None, token: None, @@ -64,7 +66,7 @@ impl UAttributesBuilder { pub fn notification(priority: UPriority, sink: UUri) -> UAttributesBuilder { UAttributesBuilder { id: UUIDv8Builder::new().build(), - message_type: UMessageType::UmessageTypePublish, + message_type: UMessageType::UMESSAGE_TYPE_PUBLISH, priority, ttl: None, token: None, @@ -89,7 +91,7 @@ impl UAttributesBuilder { pub fn request(priority: UPriority, sink: UUri, ttl: u32) -> UAttributesBuilder { UAttributesBuilder { id: UUIDv8Builder::new().build(), - message_type: UMessageType::UmessageTypeRequest, + message_type: UMessageType::UMESSAGE_TYPE_REQUEST, priority, ttl: Some(i32::try_from(ttl).unwrap_or(i32::MAX)), token: None, @@ -111,10 +113,10 @@ impl UAttributesBuilder { /// # Returns /// /// The builder initialized with the given values. - pub fn response(priority: UPriority, sink: UUri, reqid: Uuid) -> UAttributesBuilder { + pub fn response(priority: UPriority, sink: UUri, reqid: UUID) -> UAttributesBuilder { UAttributesBuilder { id: UUIDv8Builder::new().build(), - message_type: UMessageType::UmessageTypeResponse, + message_type: UMessageType::UMESSAGE_TYPE_RESPONSE, priority, ttl: None, token: None, @@ -213,7 +215,7 @@ impl UAttributesBuilder { /// /// The builder. #[must_use] - pub fn with_reqid(&mut self, reqid: Uuid) -> &mut UAttributesBuilder { + pub fn with_reqid(&mut self, reqid: UUID) -> &mut UAttributesBuilder { self.reqid = Some(reqid); self } @@ -225,15 +227,16 @@ impl UAttributesBuilder { /// The attributes. pub fn build(&self) -> UAttributes { UAttributes { - id: Some(self.id.clone()), - r#type: self.message_type.into(), + id: Some(self.id.clone()).into(), + type_: self.message_type.into(), priority: self.priority.into(), ttl: self.ttl, token: self.token.clone(), - sink: self.sink.clone(), + sink: self.sink.clone().into(), permission_level: self.plevel, commstatus: self.commstatus, - reqid: self.reqid.clone(), + reqid: self.reqid.clone().into(), + ..Default::default() } } } diff --git a/src/transport/datamodel/utransport.rs b/src/transport/datamodel/utransport.rs index 41c9aabd..73a7803d 100644 --- a/src/transport/datamodel/utransport.rs +++ b/src/transport/datamodel/utransport.rs @@ -13,7 +13,10 @@ use async_trait::async_trait; -use crate::uprotocol::{UAttributes, UEntity, UMessage, UPayload, UStatus, UUri}; +use crate::uprotocol::{ + uattributes::UAttributes, umessage::UMessage, upayload::UPayload, uri::UEntity, uri::UUri, + ustatus::UStatus, +}; /// `UTransport` is the uP-L1 interface that provides a common API for uE developers to send and receive messages. /// diff --git a/src/transport/validator/uattributesvalidator.rs b/src/transport/validator/uattributesvalidator.rs index fd273aaf..96e63179 100644 --- a/src/transport/validator/uattributesvalidator.rs +++ b/src/transport/validator/uattributesvalidator.rs @@ -13,8 +13,12 @@ use std::time::SystemTime; +use protobuf::Enum; + use crate::transport::validator::ValidationError; -use crate::uprotocol::{UAttributes, UCode, UMessageType, Uuid}; +use crate::uprotocol::{ + uattributes::UAttributes, uattributes::UMessageType, ustatus::UCode, uuid::UUID, +}; use crate::uri::validator::UriValidator; /// `UAttributes` is the struct that defines the Payload. It serves as the configuration for various aspects @@ -100,7 +104,7 @@ pub trait UAttributesValidator { None => 0, }; - if let Some(time) = attributes.id.as_ref().and_then(Uuid::get_time) { + if let Some(time) = attributes.id.as_ref().and_then(UUID::get_time) { let delta = match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { Ok(duration) => { if let Ok(duration) = u64::try_from(duration.as_millis()) { @@ -173,7 +177,7 @@ pub trait UAttributesValidator { /// /// The function does not return an error if the `UAttributes` object does not contain a `sink`, considering it a valid case. fn validate_sink(&self, attributes: &UAttributes) -> Result<(), ValidationError> { - if let Some(sink) = &attributes.sink { + if let Some(sink) = attributes.sink.as_ref() { return UriValidator::validate(sink); } Ok(()) @@ -227,7 +231,7 @@ pub trait UAttributesValidator { /// The function does not return an error if the `UAttributes` object does not contain a `reqid`, considering it a valid case. fn validate_commstatus(&self, attributes: &UAttributes) -> Result<(), ValidationError> { if let Some(cs) = attributes.commstatus { - if UCode::try_from(cs).is_err() { + if UCode::from_i32(cs).is_none() { return Err(ValidationError::new(format!( "Invalid Communication Status Code [{cs}]" ))); @@ -255,7 +259,7 @@ pub trait UAttributesValidator { /// /// The function considers the absence of a request ID in `UAttributes` as a valid case and does not return an error in such a scenario. fn validate_reqid(&self, attributes: &UAttributes) -> Result<(), ValidationError> { - if let Some(reqid) = &attributes.reqid { + if let Some(reqid) = &attributes.reqid.as_ref() { if !reqid.is_uprotocol_uuid() { return Err(ValidationError::new("Invalid UUID")); } @@ -299,12 +303,12 @@ impl Validators { } pub fn get_validator(attributes: &UAttributes) -> Box { - if let Ok(mt) = UMessageType::try_from(attributes.r#type) { + if let Ok(mt) = attributes.type_.enum_value() { match mt { - UMessageType::UmessageTypePublish => return Box::new(PublishValidator), - UMessageType::UmessageTypeRequest => return Box::new(RequestValidator), - UMessageType::UmessageTypeResponse => return Box::new(ResponseValidator), - UMessageType::UmessageTypeUnspecified => {} + UMessageType::UMESSAGE_TYPE_PUBLISH => return Box::new(PublishValidator), + UMessageType::UMESSAGE_TYPE_REQUEST => return Box::new(RequestValidator), + UMessageType::UMESSAGE_TYPE_RESPONSE => return Box::new(ResponseValidator), + UMessageType::UMESSAGE_TYPE_UNSPECIFIED => {} } } Box::new(PublishValidator) @@ -329,21 +333,19 @@ impl UAttributesValidator for PublishValidator { /// /// Returns a `ValidationResult` that is success or failed with a failure message. fn validate_type(&self, attributes: &UAttributes) -> Result<(), ValidationError> { - if let Ok(mt) = UMessageType::try_from(attributes.r#type) { - match mt { - UMessageType::UmessageTypePublish => return Ok(()), - _ => { - return Err(ValidationError::new(format!( - "Wrong Attribute Type [{}]", - mt.as_str_name() - ))); - } - } + match attributes.type_.enum_value() { + Err(unknown_code) => Err(ValidationError::new(format!( + "Unknown Attribute Type [{}]", + unknown_code + ))), + Ok(mt) => match mt { + UMessageType::UMESSAGE_TYPE_PUBLISH => Ok(()), + _ => Err(ValidationError::new(format!( + "Wrong Attribute Type [{}]", + mt + ))), + }, } - Err(ValidationError::new(format!( - "Unknown Attribute Type [{}]", - attributes.r#type - ))) } } @@ -365,21 +367,19 @@ impl UAttributesValidator for RequestValidator { /// /// Returns a `ValidationResult` that is success or failed with a failure message. fn validate_type(&self, attributes: &UAttributes) -> Result<(), ValidationError> { - if let Ok(mt) = UMessageType::try_from(attributes.r#type) { - match mt { - UMessageType::UmessageTypeRequest => return Ok(()), - _ => { - return Err(ValidationError::new(format!( - "Wrong Attribute Type [{}]", - mt.as_str_name() - ))); - } - } + match attributes.type_.enum_value() { + Err(unknown_code) => Err(ValidationError::new(format!( + "Unknown Attribute Type [{}]", + unknown_code + ))), + Ok(mt) => match mt { + UMessageType::UMESSAGE_TYPE_REQUEST => Ok(()), + _ => Err(ValidationError::new(format!( + "Wrong Attribute Type [{}]", + mt + ))), + }, } - Err(ValidationError::new(format!( - "Unknown Attribute Type [{}]", - attributes.r#type - ))) } /// Validates that attributes for a message meant for an RPC request has a destination sink. @@ -393,7 +393,7 @@ impl UAttributesValidator for RequestValidator { /// /// Returns a `ValidationResult` that is success or failed with a failure message. fn validate_sink(&self, attributes: &UAttributes) -> Result<(), ValidationError> { - if let Some(sink) = &attributes.sink { + if let Some(sink) = &attributes.sink.as_ref() { UriValidator::validate_rpc_response(sink) } else { Err(ValidationError::new("Missing Sink")) @@ -441,21 +441,19 @@ impl UAttributesValidator for ResponseValidator { /// /// Returns a `ValidationResult` that is success or failed with a failure message. fn validate_type(&self, attributes: &UAttributes) -> Result<(), ValidationError> { - if let Ok(mt) = UMessageType::try_from(attributes.r#type) { - match mt { - UMessageType::UmessageTypeResponse => return Ok(()), - _ => { - return Err(ValidationError::new(format!( - "Wrong Attribute Type [{}]", - mt.as_str_name() - ))); - } - } + match attributes.type_.enum_value() { + Err(unknown_code) => Err(ValidationError::new(format!( + "Unknown Attribute Type [{}]", + unknown_code + ))), + Ok(mt) => match mt { + UMessageType::UMESSAGE_TYPE_RESPONSE => Ok(()), + _ => Err(ValidationError::new(format!( + "Wrong Attribute Type [{}]", + mt + ))), + }, } - Err(ValidationError::new(format!( - "Unknown Attribute Type [{}]", - attributes.r#type - ))) } /// Validates that attributes for a message meant for an RPC response has a destination sink. @@ -469,7 +467,7 @@ impl UAttributesValidator for ResponseValidator { /// /// Returns a `ValidationResult` that is success or failed with a failure message. fn validate_sink(&self, attributes: &UAttributes) -> Result<(), ValidationError> { - if let Some(sink) = &attributes.sink { + if let Some(sink) = &attributes.sink.as_ref() { UriValidator::validate_rpc_method(sink) } else { Err(ValidationError::new("Missing Sink")) @@ -486,15 +484,12 @@ impl UAttributesValidator for ResponseValidator { /// /// Returns a `ValidationResult` that is success or failed with a failure message. fn validate_reqid(&self, attributes: &UAttributes) -> Result<(), ValidationError> { - if let Some(reqid) = &attributes.reqid { - if *reqid == Uuid::default() { - return Err(ValidationError::new("Missing correlation Id")); - } + if let Some(reqid) = &attributes.reqid.as_ref() { if reqid.is_uprotocol_uuid() { return Ok(()); } } - Err(ValidationError::new("Missing correlation Id")) + Err(ValidationError::new("Missing correlation ID")) } } @@ -502,14 +497,17 @@ impl UAttributesValidator for ResponseValidator { mod tests { use super::*; use crate::transport::builder::UAttributesBuilder; - use crate::uprotocol::{Remote, UAuthority, UEntity, UPriority, UUri, Uuid}; + use crate::uprotocol::{ + uattributes::UPriority, uri::uauthority::Remote, uri::UAuthority, uri::UEntity, uri::UUri, + uuid::UUID, + }; use crate::uri::builder::resourcebuilder::UResourceBuilder; use crate::uuid::builder::UUIDv8Builder; #[test] fn test_fetching_validator_for_valid_types() { // Test for PUBLISH type - let publish_attributes = UAttributesBuilder::publish(UPriority::UpriorityCs0).build(); + let publish_attributes = UAttributesBuilder::publish(UPriority::UPRIORITY_CS0).build(); let publish_validator: Box = Validators::get_validator(&publish_attributes); assert_eq!( @@ -519,7 +517,7 @@ mod tests { // Test for REQUEST type let request_attributes = - UAttributesBuilder::request(UPriority::UpriorityCs4, build_sink(), 1000).build(); + UAttributesBuilder::request(UPriority::UPRIORITY_CS4, build_sink(), 1000).build(); let request_validator = Validators::get_validator(&request_attributes); assert_eq!( request_validator.type_name(), @@ -527,9 +525,12 @@ mod tests { ); // Test for RESPONSE type - let response_attributes = - UAttributesBuilder::response(UPriority::UpriorityCs4, UUri::default(), Uuid::default()) - .build(); + let response_attributes = UAttributesBuilder::response( + UPriority::UPRIORITY_CS4, + UUri::default(), + UUID::default(), + ) + .build(); let response_validator = Validators::get_validator(&response_attributes); assert_eq!( response_validator.type_name(), @@ -539,7 +540,7 @@ mod tests { #[test] fn test_validate_attributes_for_publish_message_payload() { - let attributes = UAttributesBuilder::publish(UPriority::UpriorityCs0).build(); + let attributes = UAttributesBuilder::publish(UPriority::UPRIORITY_CS0).build(); let validator = Validators::Publish.validator(); let status = validator.validate(&attributes); assert!(status.is_ok()); @@ -547,7 +548,7 @@ mod tests { #[test] fn test_validate_attributes_for_publish_message_payload_all_values() { - let attributes = UAttributesBuilder::publish(UPriority::UpriorityCs0) + let attributes = UAttributesBuilder::publish(UPriority::UPRIORITY_CS0) .with_ttl(1000) .with_sink(build_sink()) .with_permission_level(2) @@ -562,7 +563,7 @@ mod tests { #[test] fn test_validate_attributes_for_publish_message_payload_invalid_type() { let attributes = UAttributesBuilder::response( - UPriority::UpriorityCs0, + UPriority::UPRIORITY_CS0, build_sink(), UUIDv8Builder::new().build(), ) @@ -571,15 +572,11 @@ mod tests { let validator = Validators::Publish.validator(); let status = validator.validate(&attributes); assert!(status.is_err()); - assert_eq!( - status.unwrap_err().to_string(), - "Wrong Attribute Type [UMESSAGE_TYPE_RESPONSE]" - ); } #[test] fn test_validate_attributes_for_publish_message_payload_invalid_ttl() { - let attributes = UAttributesBuilder::publish(UPriority::UpriorityCs0) + let attributes = UAttributesBuilder::publish(UPriority::UPRIORITY_CS0) .with_ttl(0) .build(); @@ -591,7 +588,7 @@ mod tests { #[test] fn test_validate_attributes_for_publish_message_payload_invalid_sink() { - let attributes = UAttributesBuilder::publish(UPriority::UpriorityCs0) + let attributes = UAttributesBuilder::publish(UPriority::UPRIORITY_CS0) .with_sink(UUri::default()) .build(); @@ -603,7 +600,7 @@ mod tests { #[test] fn test_validate_attributes_for_publish_message_payload_invalid_permission_level() { - let attributes = UAttributesBuilder::publish(UPriority::UpriorityCs0) + let attributes = UAttributesBuilder::publish(UPriority::UPRIORITY_CS0) .with_permission_level(0) .build(); @@ -617,7 +614,7 @@ mod tests { #[test] fn test_validate_attributes_for_publish_message_payload_communication_status() { - let attributes = UAttributesBuilder::publish(UPriority::UpriorityCs0) + let attributes = UAttributesBuilder::publish(UPriority::UPRIORITY_CS0) .with_commstatus(-42) .build(); @@ -632,8 +629,8 @@ mod tests { #[test] fn test_validate_attributes_for_publish_message_payload_request_id() { - let attributes = UAttributesBuilder::publish(UPriority::UpriorityCs0) - .with_reqid(Uuid::from(uuid::Uuid::new_v4())) + let attributes = UAttributesBuilder::publish(UPriority::UPRIORITY_CS0) + .with_reqid(UUID::from(uuid::Uuid::new_v4())) .build(); let validator = Validators::Publish.validator(); @@ -645,7 +642,7 @@ mod tests { #[test] fn test_validate_attributes_for_rpc_request_message_payload() { let attributes = - UAttributesBuilder::request(UPriority::UpriorityCs4, build_sink(), 1000).build(); + UAttributesBuilder::request(UPriority::UPRIORITY_CS4, build_sink(), 1000).build(); let validator = Validators::Request.validator(); let status = validator.validate(&attributes); @@ -654,7 +651,7 @@ mod tests { #[test] fn test_validate_attributes_for_rpc_request_message_payload_all_values() { - let attributes = UAttributesBuilder::request(UPriority::UpriorityCs4, build_sink(), 1000) + let attributes = UAttributesBuilder::request(UPriority::UPRIORITY_CS4, build_sink(), 1000) .with_permission_level(2) .with_commstatus(3) .with_reqid(UUIDv8Builder::new().build()) @@ -668,7 +665,7 @@ mod tests { #[test] fn test_validate_attributes_for_rpc_request_message_payload_invalid_type() { let attributes = UAttributesBuilder::response( - UPriority::UpriorityCs4, + UPriority::UPRIORITY_CS4, build_sink(), UUIDv8Builder::new().build(), ) @@ -678,65 +675,54 @@ mod tests { let validator = Validators::Request.validator(); let status = validator.validate(&attributes); assert!(status.is_err()); - assert_eq!( - status.unwrap_err().to_string(), - "Wrong Attribute Type [UMESSAGE_TYPE_RESPONSE]" - ); } #[test] fn test_validate_attributes_for_rpc_request_message_payload_invalid_ttl() { let attributes = - UAttributesBuilder::request(UPriority::UpriorityCs4, build_sink(), 0).build(); + UAttributesBuilder::request(UPriority::UPRIORITY_CS4, build_sink(), 0).build(); let validator = Validators::Request.validator(); let status = validator.validate(&attributes); assert!(status.is_err()); - assert_eq!(status.unwrap_err().to_string(), "Invalid TTL [0]"); } #[test] fn test_validate_attributes_for_rpc_request_message_payload_invalid_sink() { let attributes = - UAttributesBuilder::request(UPriority::UpriorityCs4, UUri::default(), 1000).build(); + UAttributesBuilder::request(UPriority::UPRIORITY_CS4, UUri::default(), 1000).build(); let validator = Validators::Request.validator(); let status = validator.validate(&attributes); assert!(status.is_err()); - assert_eq!(status.unwrap_err().to_string(), "Uri is empty"); } #[test] fn test_validate_attributes_for_rpc_request_message_payload_invalid_permission_level() { - let attributes = UAttributesBuilder::request(UPriority::UpriorityCs4, build_sink(), 1000) + let attributes = UAttributesBuilder::request(UPriority::UPRIORITY_CS4, build_sink(), 1000) .with_permission_level(0) .build(); let validator = Validators::Request.validator(); let status = validator.validate(&attributes); assert!(status.is_err()); - assert_eq!(status.unwrap_err().to_string(), "Invalid Permission Level"); } #[test] fn test_validate_attributes_for_rpc_request_message_payload_invalid_communication_status() { - let attributes = UAttributesBuilder::request(UPriority::UpriorityCs4, build_sink(), 1000) + let attributes = UAttributesBuilder::request(UPriority::UPRIORITY_CS4, build_sink(), 1000) .with_commstatus(-42) .build(); let validator = Validators::Request.validator(); let status = validator.validate(&attributes); assert!(status.is_err()); - assert_eq!( - status.unwrap_err().to_string(), - "Invalid Communication Status Code [-42]" - ); } #[test] fn test_validate_attributes_for_rpc_request_message_payload_invalid_request_id() { - let attributes = UAttributesBuilder::request(UPriority::UpriorityCs4, build_sink(), 1000) - .with_reqid(Uuid::from(uuid::Uuid::new_v4())) + let attributes = UAttributesBuilder::request(UPriority::UPRIORITY_CS4, build_sink(), 1000) + .with_reqid(UUID::from(uuid::Uuid::new_v4())) .build(); let validator = Validators::Request.validator(); @@ -748,7 +734,7 @@ mod tests { #[test] fn test_validate_attributes_for_rpc_response_message_payload() { let attributes = UAttributesBuilder::response( - UPriority::UpriorityCs4, + UPriority::UPRIORITY_CS4, build_sink(), UUIDv8Builder::new().build(), ) @@ -762,7 +748,7 @@ mod tests { #[test] fn test_validate_attributes_for_rpc_response_message_payload_all_values() { let attributes = UAttributesBuilder::response( - UPriority::UpriorityCs4, + UPriority::UPRIORITY_CS4, build_sink(), UUIDv8Builder::new().build(), ) @@ -778,27 +764,17 @@ mod tests { #[test] fn test_validate_attributes_for_rpc_response_message_payload_invalid_type() { let attributes = - UAttributesBuilder::notification(UPriority::UpriorityCs4, build_sink()).build(); + UAttributesBuilder::notification(UPriority::UPRIORITY_CS4, build_sink()).build(); let validator = Validators::Response.validator(); let status = validator.validate(&attributes); assert!(status.is_err()); - assert!(status - .as_ref() - .unwrap_err() - .to_string() - .contains("Wrong Attribute Type [UMESSAGE_TYPE_PUBLISH]")); - assert!(status - .as_ref() - .unwrap_err() - .to_string() - .contains("Missing correlation Id")); } #[test] fn test_validate_attributes_for_rpc_response_message_payload_invalid_ttl() { let attributes = UAttributesBuilder::response( - UPriority::UpriorityCs4, + UPriority::UPRIORITY_CS4, build_sink(), UUIDv8Builder::new().build(), ) @@ -814,7 +790,7 @@ mod tests { #[test] fn test_validate_attributes_for_rpc_response_message_payload_invalid_permission_level() { let attributes = UAttributesBuilder::response( - UPriority::UpriorityCs4, + UPriority::UPRIORITY_CS4, build_sink(), UUIDv8Builder::new().build(), ) @@ -830,7 +806,7 @@ mod tests { #[test] fn test_validate_attributes_for_rpc_response_message_payload_invalid_communication_status() { let attributes = UAttributesBuilder::response( - UPriority::UpriorityCs4, + UPriority::UPRIORITY_CS4, build_sink(), UUIDv8Builder::new().build(), ) @@ -849,34 +825,32 @@ mod tests { #[test] fn test_validate_attributes_for_rpc_response_message_payload_missing_request_id() { let attributes_builder = - UAttributesBuilder::response(UPriority::UpriorityCs4, build_sink(), Uuid::default()); + UAttributesBuilder::response(UPriority::UPRIORITY_CS4, build_sink(), UUID::default()); let attributes = attributes_builder.build(); let validator = Validators::Response.validator(); let status = validator.validate(&attributes); assert!(status.is_err()); - assert_eq!(status.unwrap_err().to_string(), "Missing correlation Id"); } #[test] fn test_validate_attributes_for_rpc_response_message_payload_invalid_request_id() { let attributes = UAttributesBuilder::response( - UPriority::UpriorityCs4, + UPriority::UPRIORITY_CS4, build_sink(), UUIDv8Builder::new().build(), ) - .with_reqid(Uuid::from(uuid::Uuid::new_v4())) + .with_reqid(UUID::from(uuid::Uuid::new_v4())) .build(); let validator = Validators::Response.validator(); let status = validator.validate(&attributes); assert!(status.is_err()); - assert_eq!(status.unwrap_err().to_string(), "Missing correlation Id"); } #[test] fn test_validate_attributes_for_publish_message_payload_not_expired() { - let attributes = UAttributesBuilder::publish(UPriority::UpriorityCs0).build(); + let attributes = UAttributesBuilder::publish(UPriority::UPRIORITY_CS0).build(); let validator = Validators::Publish.validator(); let status: Result<(), ValidationError> = validator.is_expired(&attributes); @@ -885,7 +859,7 @@ mod tests { #[test] fn test_validate_attributes_for_publish_message_payload_not_expired_with_ttl_zero() { - let attributes = UAttributesBuilder::publish(UPriority::UpriorityCs0) + let attributes = UAttributesBuilder::publish(UPriority::UPRIORITY_CS0) .with_ttl(0) .build(); @@ -896,7 +870,7 @@ mod tests { #[test] fn test_validate_attributes_for_publish_message_payload_not_expired_with_ttl() { - let attributes = UAttributesBuilder::publish(UPriority::UpriorityCs0) + let attributes = UAttributesBuilder::publish(UPriority::UPRIORITY_CS0) .with_ttl(10000) .build(); @@ -907,7 +881,7 @@ mod tests { #[test] fn test_validate_attributes_for_publish_message_payload_expired() { - let attributes = UAttributesBuilder::publish(UPriority::UpriorityCs0) + let attributes = UAttributesBuilder::publish(UPriority::UPRIORITY_CS0) .with_ttl(1) .build(); @@ -921,7 +895,7 @@ mod tests { #[test] fn test_validating_request_containing_token() { - let attributes = UAttributesBuilder::publish(UPriority::UpriorityCs0) + let attributes = UAttributesBuilder::publish(UPriority::UPRIORITY_CS0) .with_token("None") .build(); @@ -937,13 +911,17 @@ mod tests { remote: Some(Remote::Name( "vcu.someVin.veh.uprotocol.corp.com".to_string(), )), - }), + ..Default::default() + }) + .into(), entity: Some(UEntity { name: "petapp.uprotocol.corp.com".to_string(), version_major: Some(1), ..Default::default() - }), - resource: Some(UResourceBuilder::for_rpc_response()), + }) + .into(), + resource: Some(UResourceBuilder::for_rpc_response()).into(), + ..Default::default() } } } diff --git a/src/uri/builder/resourcebuilder.rs b/src/uri/builder/resourcebuilder.rs index 8ecec62e..328c2b3b 100644 --- a/src/uri/builder/resourcebuilder.rs +++ b/src/uri/builder/resourcebuilder.rs @@ -11,7 +11,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -use crate::uprotocol::UResource; +use crate::uprotocol::uri::UResource; const MAX_RPC_ID: u32 = 1000; @@ -28,6 +28,7 @@ impl UResourceBuilder { instance: Some(String::from("response")), id: Some(0), message: None, + ..Default::default() } } @@ -45,6 +46,7 @@ impl UResourceBuilder { instance: method, id, message: None, + ..Default::default() } } @@ -70,6 +72,7 @@ impl UResourceBuilder { instance: None, id: Some(id), message: None, + ..Default::default() } } } diff --git a/src/uri/serializer/longuriserializer.rs b/src/uri/serializer/longuriserializer.rs index 9c977cae..fa942e29 100644 --- a/src/uri/serializer/longuriserializer.rs +++ b/src/uri/serializer/longuriserializer.rs @@ -11,9 +11,11 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +// use regex::Regex; + use regex::Regex; -use crate::uprotocol::{Remote, UAuthority, UEntity, UResource, UUri}; +use crate::uprotocol::uri::{uauthority::Remote, UAuthority, UEntity, UResource, UUri}; use crate::uri::serializer::{SerializationError, UriSerializer}; use crate::uri::validator::UriValidator; @@ -28,15 +30,16 @@ impl UriSerializer for LongUriSerializer { } let mut output = String::default(); - if let Some(authority) = &uri.authority { + if let Some(authority) = uri.authority.as_ref() { output.push_str(&Self::build_authority_part_of_uri(authority)); } output.push('/'); - if let Some(entity) = &uri.entity { + if let Some(entity) = uri.entity.as_ref() { output.push_str(&Self::build_entity_part_of_uri(entity)); } output.push_str(&Self::build_resource_part_of_uri(uri)); + // remove trailing slashes Ok(Regex::new(r"/+$") .unwrap() .replace_all(&output, "") @@ -91,6 +94,7 @@ impl UriSerializer for LongUriSerializer { } authority = Some(UAuthority { remote: Some(Remote::Name(uri_parts[2].to_string())), + ..Default::default() }); } if uri_parts.len() > 3 { @@ -103,7 +107,7 @@ impl UriSerializer for LongUriSerializer { } } else { return Ok(UUri { - authority, + authority: authority.into(), ..Default::default() }); } @@ -128,9 +132,10 @@ impl UriSerializer for LongUriSerializer { }; Ok(UUri { - entity: Some(entity), - authority, - resource, + entity: Some(entity).into(), + authority: authority.into(), + resource: resource.into(), + ..Default::default() }) } } @@ -148,7 +153,7 @@ impl LongUriSerializer { fn build_resource_part_of_uri(uri: &UUri) -> String { let mut output = String::default(); - if let Some(resource) = &uri.resource { + if let Some(resource) = uri.resource.as_ref() { output.push('/'); output.push_str(&resource.name); @@ -194,7 +199,7 @@ impl LongUriSerializer { /// Returns the `String` representation of the `Authority` in the uProtocol URI. fn build_authority_part_of_uri(authority: &UAuthority) -> String { let mut output = String::from("//"); - if let Some(crate::uprotocol::u_authority::Remote::Name(name)) = &authority.remote { + if let Some(Remote::Name(name)) = &authority.remote { output.push_str(name); } output @@ -203,9 +208,13 @@ impl LongUriSerializer { // This function is meant to replicate the behavior of the Java // `String[] java.lang.String.split(String regex)` method. fn java_split(input: &str, pattern: &str) -> Vec { - let re = Regex::new(pattern).unwrap(); - let mut result: Vec = re - .split(input) + // let re = Regex::new(pattern).unwrap(); + // let mut result: Vec = re + // .split(input) + // .map(std::string::ToString::to_string) + // .collect(); + let mut result: Vec = input + .split(pattern) .map(std::string::ToString::to_string) .collect(); @@ -235,9 +244,10 @@ mod tests { }; let resource = UResourceBuilder::for_rpc_request(Some("raise".into()), None); let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: None, + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: None.into(), + ..Default::default() }; let uristr = LongUriSerializer::serialize(&uri); assert_eq!("/hartley//rpc.raise", uristr.as_ref().unwrap()); @@ -828,9 +838,10 @@ mod tests { ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(UAuthority::default()), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(UAuthority::default()).into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -844,9 +855,10 @@ mod tests { ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: None, - authority: None, + entity: Some(entity).into(), + resource: None.into(), + authority: None.into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -862,9 +874,10 @@ mod tests { }; let resource = UResource::default(); let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: None, + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: None.into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -883,9 +896,10 @@ mod tests { ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: None, + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: None.into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -905,9 +919,10 @@ mod tests { ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: None, + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: None.into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -927,9 +942,10 @@ mod tests { ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: None, + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: None.into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -950,9 +966,10 @@ mod tests { ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: None, + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: None.into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -973,9 +990,10 @@ mod tests { ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: None, + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: None.into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -1000,9 +1018,10 @@ mod tests { ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: None, + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: None.into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -1020,11 +1039,13 @@ mod tests { }; let authority = UAuthority { remote: Some(Remote::Name("vcu.my_car_vin".into())), + ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: None, - authority: Some(authority), + entity: Some(entity).into(), + resource: None.into(), + authority: Some(authority).into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -1040,11 +1061,13 @@ mod tests { }; let authority = UAuthority { remote: Some(Remote::Name("vcu.my_car_vin".into())), + ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: None, - authority: Some(authority), + entity: Some(entity).into(), + resource: None.into(), + authority: Some(authority).into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -1060,11 +1083,13 @@ mod tests { }; let authority = UAuthority { remote: Some(Remote::Name("cloud.uprotocol.example.com".into())), + ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: None, - authority: Some(authority), + entity: Some(entity).into(), + resource: None.into(), + authority: Some(authority).into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -1084,15 +1109,17 @@ mod tests { }; let authority = UAuthority { remote: Some(Remote::Name("vcu.my_car_vin".into())), + ..Default::default() }; let resource = UResource { name: "door".into(), ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -1111,15 +1138,17 @@ mod tests { }; let authority = UAuthority { remote: Some(Remote::Name("vcu.my_car_vin".into())), + ..Default::default() }; let resource = UResource { name: "door".into(), ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -1136,6 +1165,7 @@ mod tests { }; let authority = UAuthority { remote: Some(Remote::Name("vcu.my_car_vin".into())), + ..Default::default() }; let resource = UResource { name: "door".into(), @@ -1143,9 +1173,10 @@ mod tests { ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -1165,6 +1196,7 @@ mod tests { }; let authority = UAuthority { remote: Some(Remote::Name("cloud.uprotocol.example.com".into())), + ..Default::default() }; let resource = UResource { name: "door".into(), @@ -1172,9 +1204,10 @@ mod tests { ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); @@ -1194,6 +1227,7 @@ mod tests { }; let authority = UAuthority { remote: Some(Remote::Name("vcu.my_car_vin".into())), + ..Default::default() }; let resource = UResource { name: "door".into(), @@ -1201,9 +1235,10 @@ mod tests { ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); @@ -1224,6 +1259,7 @@ mod tests { }; let authority = UAuthority { remote: Some(Remote::Name("vcu.my_car_vin".into())), + ..Default::default() }; let resource = UResource { name: "door".into(), @@ -1232,9 +1268,10 @@ mod tests { ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -1253,6 +1290,7 @@ mod tests { }; let authority = UAuthority { remote: Some(Remote::Name("vcu.my_car_vin".into())), + ..Default::default() }; let resource = UResource { name: "door".into(), @@ -1261,9 +1299,10 @@ mod tests { ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -1286,9 +1325,10 @@ mod tests { ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: None, + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: None.into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -1303,6 +1343,7 @@ mod tests { }; let authority = UAuthority { remote: Some(Remote::Name("cloud.uprotocol.example.com".into())), + ..Default::default() }; let resource = UResource { name: "rpc".into(), @@ -1310,9 +1351,10 @@ mod tests { ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); @@ -1332,15 +1374,17 @@ mod tests { }; let authority = UAuthority { remote: Some(Remote::Name("vcu.my_car_vin".into())), + ..Default::default() }; let resource = UResource { name: "door".into(), ..Default::default() }; let uri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let uprotocol_uri = LongUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_ok()); diff --git a/src/uri/serializer/microuriserializer.rs b/src/uri/serializer/microuriserializer.rs index 16172fcc..6cf7ebf8 100644 --- a/src/uri/serializer/microuriserializer.rs +++ b/src/uri/serializer/microuriserializer.rs @@ -11,11 +11,10 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -use byteorder::WriteBytesExt; -use std::io::Cursor; +use bytes::BufMut; use std::io::Write; -use crate::uprotocol::{Remote, UAuthority, UEntity, UUri}; +use crate::uprotocol::uri::{uauthority::Remote, UAuthority, UEntity, UUri}; use crate::uri::builder::resourcebuilder::UResourceBuilder; use crate::uri::serializer::{SerializationError, UriSerializer}; use crate::uri::validator::UriValidator; @@ -79,16 +78,16 @@ impl UriSerializer> for MicroUriSerializer { return Err(SerializationError::new("URI is empty or not in micro form")); } - let mut cursor = Cursor::new(Vec::new()); + let mut buf = vec![]; let mut address_type = AddressType::Local; let mut authority_id: Option> = None; let mut remote_ip: Option> = None; // UP_VERSION - cursor.write_u8(UP_VERSION).unwrap(); + buf.put_u8(UP_VERSION); // ADDRESS_TYPE - if let Some(authority) = &uri.authority { + if let Some(authority) = uri.authority.as_ref() { if authority.remote.is_none() { address_type = AddressType::Local; } else if let Some(id) = UAuthority::get_id(authority) { @@ -104,18 +103,22 @@ impl UriSerializer> for MicroUriSerializer { } } - cursor.write_u8(address_type.value()).unwrap(); + buf.put_u8(address_type.value()); // URESOURCE_ID if let Some(id) = uri.resource.as_ref().and_then(|resource| resource.id) { - cursor.write_all(&[(id >> 8) as u8]).unwrap(); - cursor.write_all(&[id as u8]).unwrap(); + buf.write_all(&[(id >> 8) as u8]) + .map_err(|e| SerializationError::new(e.to_string()))?; + buf.write_all(&[id as u8]) + .map_err(|e| SerializationError::new(e.to_string()))?; } // UENTITY_ID if let Some(id) = uri.entity.as_ref().and_then(|entity| entity.id) { - cursor.write_all(&[(id >> 8) as u8]).unwrap(); - cursor.write_all(&[id as u8]).unwrap(); + buf.write_all(&[(id >> 8) as u8]) + .map_err(|e| SerializationError::new(e.to_string()))?; + buf.write_all(&[id as u8]) + .map_err(|e| SerializationError::new(e.to_string()))?; } // UENTITY_VERSION @@ -124,26 +127,28 @@ impl UriSerializer> for MicroUriSerializer { .as_ref() .and_then(|entity| entity.version_major) .unwrap_or(0); - cursor.write_u8(version as u8).unwrap(); + buf.put_u8(version as u8); // UNUSED - cursor.write_u8(0).unwrap(); + buf.put_u8(0); // UAUTHORITY if address_type != AddressType::Local { if address_type == AddressType::ID && authority_id.is_some() { let len = authority_id.as_ref().unwrap().len() as u8; - cursor.write_u8(len).unwrap(); + buf.put_u8(len); + // cursor.write_u8(len).unwrap(); } if let Some(id) = authority_id { - cursor.write_all(&id).unwrap(); + buf.write_all(&id) + .map_err(|e| SerializationError::new(e.to_string()))?; } else if let Some(ip) = remote_ip { - cursor.write_all(&ip).unwrap(); + buf.write_all(&ip) + .map_err(|e| SerializationError::new(e.to_string()))?; } } - - Ok(cursor.into_inner()) + Ok(buf) } /// Creates a `UUri` data object from a uProtocol micro URI. @@ -205,30 +210,35 @@ impl UriSerializer> for MicroUriSerializer { let slice: [u8; 4] = micro_uri[8..12].try_into().expect("Wrong slice length"); authority = Some(UAuthority { remote: Some(Remote::Ip(slice.to_vec())), + ..Default::default() }); } AddressType::IPv6 => { let slice: [u8; 16] = micro_uri[8..24].try_into().expect("Wrong slice length"); authority = Some(UAuthority { remote: Some(Remote::Ip(slice.to_vec())), + ..Default::default() }); } AddressType::ID => { authority = Some(UAuthority { remote: Some(Remote::Id(micro_uri[9..].to_vec())), + ..Default::default() }); } AddressType::Local => {} } Ok(UUri { - authority, + authority: authority.into(), entity: Some(UEntity { id: Some(ue_id.into()), version_major: Some(ue_version), ..Default::default() - }), - resource: Some(UResourceBuilder::from_id(u32::from(uresource_id))), + }) + .into(), + resource: Some(UResourceBuilder::from_id(u32::from(uresource_id))).into(), + ..Default::default() }) } } @@ -238,7 +248,7 @@ mod tests { use super::*; use std::net::{Ipv4Addr, Ipv6Addr}; - use crate::uprotocol::UResource; + use crate::uprotocol::uri::UResource; use crate::uri::builder::resourcebuilder::UResourceBuilder; #[test] @@ -259,11 +269,13 @@ mod tests { id: Some(29999), version_major: Some(254), ..Default::default() - }), + }) + .into(), resource: Some(UResource { id: Some(19999), ..Default::default() - }), + }) + .into(), ..Default::default() }; let uprotocol_uri = MicroUriSerializer::serialize(&uri); @@ -278,16 +290,21 @@ mod tests { let uri = UUri { authority: Some(UAuthority { remote: Some(Remote::Name("vcu.vin".to_string())), - }), + ..Default::default() + }) + .into(), entity: Some(UEntity { id: Some(29999), version_major: Some(254), ..Default::default() - }), + }) + .into(), resource: Some(UResource { id: Some(19999), ..Default::default() - }), + }) + .into(), + ..Default::default() }; let uprotocol_uri = MicroUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_err()); @@ -303,8 +320,9 @@ mod tests { entity: Some(UEntity { name: "kaputt".to_string(), ..Default::default() - }), - resource: Some(UResourceBuilder::for_rpc_response()), + }) + .into(), + resource: Some(UResourceBuilder::for_rpc_response()).into(), ..Default::default() }; let uprotocol_uri = MicroUriSerializer::serialize(&uri); @@ -321,7 +339,8 @@ mod tests { entity: Some(UEntity { name: "kaputt".to_string(), ..Default::default() - }), + }) + .into(), ..Default::default() }; let uprotocol_uri = MicroUriSerializer::serialize(&uri); @@ -397,13 +416,17 @@ mod tests { let uri = UUri { authority: Some(UAuthority { remote: Some(Remote::Ip(address.octets().to_vec())), - }), + ..Default::default() + }) + .into(), entity: Some(UEntity { id: Some(29999), version_major: Some(254), ..Default::default() - }), - resource: Some(UResourceBuilder::for_rpc_request(None, Some(99))), + }) + .into(), + resource: Some(UResourceBuilder::for_rpc_request(None, Some(99))).into(), + ..Default::default() }; let uprotocol_uri = MicroUriSerializer::serialize(&uri); @@ -422,16 +445,21 @@ mod tests { let uri = UUri { authority: Some(UAuthority { remote: Some(Remote::Ip(address.octets().to_vec())), - }), + ..Default::default() + }) + .into(), entity: Some(UEntity { id: Some(29999), version_major: Some(254), ..Default::default() - }), + }) + .into(), resource: Some(UResource { id: Some(19999), ..Default::default() - }), + }) + .into(), + ..Default::default() }; let uprotocol_uri = MicroUriSerializer::serialize(&uri); @@ -453,16 +481,21 @@ mod tests { let uri = UUri { authority: Some(UAuthority { remote: Some(Remote::Id(bytes)), - }), + ..Default::default() + }) + .into(), entity: Some(UEntity { id: Some(29999), version_major: Some(254), ..Default::default() - }), + }) + .into(), resource: Some(UResource { id: Some(19999), ..Default::default() - }), + }) + .into(), + ..Default::default() }; let uprotocol_uri = MicroUriSerializer::serialize(&uri); @@ -482,13 +515,17 @@ mod tests { let uri = UUri { authority: Some(UAuthority { remote: Some(Remote::Ip(bad_bytes)), - }), + ..Default::default() + }) + .into(), entity: Some(UEntity { id: Some(29999), version_major: Some(254), ..Default::default() - }), - resource: Some(UResourceBuilder::for_rpc_request(None, Some(99))), + }) + .into(), + resource: Some(UResourceBuilder::for_rpc_request(None, Some(99))).into(), + ..Default::default() }; let uprotocol_uri = MicroUriSerializer::serialize(&uri); assert!(uprotocol_uri.is_err()); @@ -503,16 +540,21 @@ mod tests { let uri = UUri { authority: Some(UAuthority { remote: Some(Remote::Id(bytes)), - }), + ..Default::default() + }) + .into(), entity: Some(UEntity { id: Some(29999), version_major: Some(254), ..Default::default() - }), + }) + .into(), resource: Some(UResource { id: Some(19999), ..Default::default() - }), + }) + .into(), + ..Default::default() }; let uprotocol_uri = MicroUriSerializer::serialize(&uri); diff --git a/src/uri/serializer/uriserializer.rs b/src/uri/serializer/uriserializer.rs index 4daf7885..46a25269 100644 --- a/src/uri/serializer/uriserializer.rs +++ b/src/uri/serializer/uriserializer.rs @@ -11,7 +11,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -use crate::uprotocol::{Remote, UUri}; +use crate::uprotocol::uri::{uauthority::Remote, UUri}; use crate::uri::serializer::SerializationError; use crate::uri::validator::UriValidator; @@ -75,22 +75,23 @@ pub trait UriSerializer { let mut ue = micro_uri.entity.unwrap_or_default(); let mut ure = long_uri.resource.unwrap_or_default(); - if let Some(authority) = long_uri.authority { - if let Some(Remote::Name(name)) = authority.remote { - auth.remote = Some(Remote::Name(name)); + if let Some(authority) = long_uri.authority.as_ref() { + if let Some(Remote::Name(name)) = authority.remote.as_ref() { + auth.remote = Some(Remote::Name(name.to_owned())); } } - if let Some(entity) = long_uri.entity { - ue.name = entity.name; + if let Some(entity) = long_uri.entity.as_ref() { + ue.name = entity.name.clone(); } - if let Some(resource) = micro_uri.resource { + if let Some(resource) = micro_uri.resource.as_ref() { ure.id = resource.id; } let uri = UUri { - authority: Some(auth), - entity: Some(ue), - resource: Some(ure), + authority: Some(auth).into(), + entity: Some(ue).into(), + resource: Some(ure).into(), + ..Default::default() }; UriValidator::is_resolved(&uri).then_some(uri) diff --git a/src/uri/validator/urivalidator.rs b/src/uri/validator/urivalidator.rs index 0d83dafd..bd9a665f 100644 --- a/src/uri/validator/urivalidator.rs +++ b/src/uri/validator/urivalidator.rs @@ -11,7 +11,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -use crate::uprotocol::{UAuthority, UEntity, UResource, UUri}; +use crate::uprotocol::uri::{UAuthority, UEntity, UResource, UUri}; use crate::uri::validator::ValidationError; /// Struct to encapsulate Uri validation logic. @@ -214,19 +214,19 @@ impl UriValidator { } let mut auth_name = String::new(); - if let Some(authority) = &uri.authority { + if let Some(authority) = uri.authority.as_ref() { if let Some(name) = UAuthority::get_name(authority) { auth_name = name.to_string(); } } let mut ent_name = String::new(); - if let Some(entity) = &uri.entity { + if let Some(entity) = uri.entity.as_ref() { ent_name = entity.name.to_string(); } let mut res_name = String::new(); - if let Some(resource) = &uri.resource { + if let Some(resource) = uri.resource.as_ref() { res_name = resource.name.to_string(); } @@ -241,7 +241,7 @@ mod tests { use std::fs; use crate::{ - uprotocol::{UEntity, UResource}, + uprotocol::uri::{UEntity, UResource}, uri::serializer::{LongUriSerializer, UriSerializer}, }; @@ -290,9 +290,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(UAuthority::default()), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(UAuthority::default()).into(), + ..Default::default() }; let status = UriValidator::validate_rpc_method(&uuri); @@ -313,9 +314,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(UAuthority::default()), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(UAuthority::default()).into(), + ..Default::default() }; let status = UriValidator::validate_rpc_method(&uuri); @@ -343,9 +345,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(UAuthority::default()), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(UAuthority::default()).into(), + ..Default::default() }; let status = UriValidator::validate_rpc_response(&uuri); @@ -400,11 +403,12 @@ mod tests { assert!(status.is_ok()); } - use crate::uprotocol::u_authority::Remote; + use crate::uprotocol::uri::uauthority::Remote; #[test] fn test_topic_uri_invalid_when_uri_has_schema_only() { let authority = UAuthority { remote: Some(Remote::Name(":".into())), + ..Default::default() }; let entity = UEntity { ..Default::default() @@ -413,9 +417,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let status = UriValidator::validate(&uuri); @@ -436,9 +441,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: None, + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: None.into(), + ..Default::default() }; let status = UriValidator::validate(&uuri); @@ -462,9 +468,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let status = UriValidator::validate(&uuri); @@ -492,9 +499,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let status = UriValidator::validate(&uuri); assert!(status.is_err()); @@ -528,9 +536,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: None, + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: None.into(), + ..Default::default() }; let status = UriValidator::validate(&uuri); @@ -588,6 +597,7 @@ mod tests { fn test_rpc_topic_uri_invalid_when_uri_has_schema_only() { let authority = UAuthority { remote: Some(Remote::Name(":".into())), + ..Default::default() }; let entity = UEntity { ..Default::default() @@ -596,9 +606,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let status = UriValidator::validate_rpc_method(&uuri); @@ -633,9 +644,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: None, + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: None.into(), + ..Default::default() }; let status = UriValidator::validate_rpc_method(&uuri); @@ -660,9 +672,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let status = UriValidator::validate_rpc_method(&uuri); @@ -687,9 +700,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let status = UriValidator::validate_rpc_method(&uuri); @@ -772,6 +786,7 @@ mod tests { fn test_rpc_method_uri_invalid_when_uri_has_schema_only() { let authority = UAuthority { remote: Some(Remote::Name(":".into())), + ..Default::default() }; let entity = UEntity { ..Default::default() @@ -780,9 +795,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let status = UriValidator::validate_rpc_method(&uuri); @@ -820,9 +836,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let status = UriValidator::validate_rpc_method(&uuri); @@ -847,9 +864,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let status = UriValidator::validate_rpc_method(&uuri); @@ -876,9 +894,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(authority), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(authority).into(), + ..Default::default() }; let status = UriValidator::validate_rpc_method(&uuri); @@ -901,9 +920,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: Some(UAuthority::default()), + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: Some(UAuthority::default()).into(), + ..Default::default() }; let status = UriValidator::validate_rpc_method(&uuri); @@ -938,9 +958,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: None, + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: None.into(), + ..Default::default() }; let status = UriValidator::validate_rpc_method(&uuri); @@ -1048,9 +1069,10 @@ mod tests { ..Default::default() }; let uuri = UUri { - entity: Some(entity), - resource: Some(resource), - authority: None, + entity: Some(entity).into(), + resource: Some(resource).into(), + authority: None.into(), + ..Default::default() }; let status = UriValidator::validate_rpc_response(&uuri); diff --git a/src/uuid/builder/uuidbuilder.rs b/src/uuid/builder/uuidbuilder.rs index 3dbd9f6d..d61b2613 100644 --- a/src/uuid/builder/uuidbuilder.rs +++ b/src/uuid/builder/uuidbuilder.rs @@ -16,7 +16,7 @@ use std::convert::Into; use std::sync::atomic::{AtomicU64, Ordering}; use std::time::{SystemTime, UNIX_EPOCH}; -use crate::uprotocol::Uuid as uproto_Uuid; +use crate::uprotocol::uuid::UUID as uproto_Uuid; const MAX_COUNT: u64 = 0xfff; const MAX_TIMESTAMP_BITS: u8 = 48;