From b2cd41976af7f56f82ee557f99783dd8dcfe409d Mon Sep 17 00:00:00 2001 From: Paul Flynn Date: Thu, 3 Oct 2024 18:18:48 -0400 Subject: [PATCH] Redis and Flatbuffers Integration for Event Handling (#10) --- .gitignore | 1 + Cargo.toml | 5 +- README.md | 26 +- src/bin/main.rs | 249 +++++- src/bin/schemas/event_generated.rs | 1176 ++++++++++++++++++++++++++++ src/bin/schemas/mod.rs | 1 + 6 files changed, 1422 insertions(+), 36 deletions(-) create mode 100644 src/bin/schemas/event_generated.rs create mode 100644 src/bin/schemas/mod.rs diff --git a/.gitignore b/.gitignore index a0a0cf4..835b388 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ Cargo.lock /etc/contracts/ev/ /etc/contracts/simple_abac/.idea/ /apple-app-site-association.json +/dump.rdb diff --git a/Cargo.toml b/Cargo.toml index 51332ab..e39e5b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,8 @@ [package] name = "arkavo-rs" -version = "0.7.0" +version = "0.9.0" edition = "2021" +rust-version = "1.80.0" [lib] name = "nanotdf" @@ -42,6 +43,8 @@ ink = "5.0.0" jsonwebtoken = "9.3.0" async-nats = "0.36.0" serde_json = "1.0.128" +redis = { version = "0.27.2", features = ["tokio-comp"] } +flatbuffers = "24.3.25" [dev-dependencies] criterion = "0.5.1" diff --git a/README.md b/README.md index 560d1aa..cd775ec 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,16 @@ Implementation of KAS from [OpenTDF specification](https://github.com/opentdf/sp - Rust (latest stable version) - `cargo` package manager - NATS +- Redis ```bash -brew install nats-server +brew install nats-server redis flatbuffers +``` + +### Compile Flatbuffers (optional) + +```shell +flatc --binary --rust idl/event.fbs ``` ### Installation @@ -35,6 +42,13 @@ brew install nats-server cargo build ``` + Release build + + ```shell + export RUSTFLAGS="-C target-cpu=native" + cargo build --release + ``` + ### Running the Server 1. Ensure you have a valid EC private key in PEM format named `recipient_private_key.pem`. @@ -42,7 +56,7 @@ brew install nats-server ```shell openssl ecparam -genkey -name prime256v1 -noout -out recipient_private_key.pem ``` - + Validate ```shell openssl ec -in recipient_private_key.pem -text -noout @@ -75,6 +89,7 @@ The server can be configured using environment variables. If not set, default va | TLS_CERT_PATH | Path to the TLS certificate file | ./fullchain.pem | | TLS_KEY_PATH | Path to the TLS private key file | ./privkey.pem | | KAS_KEY_PATH | Path to the KAS private key file | ./recipient_private_key.pem | +| REDIS_URL | URL for Redis connection | redis://localhost:6379 | All file paths are relative to the current working directory where the server is run. @@ -84,6 +99,7 @@ export TLS_CERT_PATH=/path/to/fullchain.pem export TLS_KEY_PATH=/path/to/privkey.pem export KAS_KEY_PATH=/path/to/recipient_private_key.pem export NATS_URL=nats://localhost:4222 +export REDIS_URL=redis://localhost:6379 export ENABLE_TIMING_LOGS=true export RUST_LOG=info ``` @@ -101,6 +117,10 @@ environment variables or secure vaults for managing sensitive information in pro nats-server ``` +```shell +redis-server +``` + #### Start backend ```shell @@ -130,4 +150,4 @@ sequenceDiagram Server ->> Server: Compute shared_secret = ECDH(server_private_key, client_public_key) Client ->> Client: Compute shared_secret = ECDH(client_private_key, server_public_key) Note over Client, Server: Both have the same shared_secret -``` +``` \ No newline at end of file diff --git a/src/bin/main.rs b/src/bin/main.rs index 59b513c..ec91129 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,13 +1,8 @@ mod contracts; - -use std::env; -use std::pin::Pin; -use std::sync::Arc; -use std::sync::RwLock; -use std::task::{Context, Poll}; -use std::time::{Duration, Instant}; +mod schemas; use crate::contracts::contract_simple_abac; +use crate::schemas::event_generated::arkavo::{Event, EventData}; use aes_gcm::aead::generic_array::GenericArray; use aes_gcm::aead::KeyInit; use aes_gcm::aead::{Aead, Key}; @@ -15,17 +10,27 @@ use aes_gcm::Aes256Gcm; use async_nats::Message as NatsMessage; use async_nats::{Client as NatsClient, PublishError}; use elliptic_curve::point::AffineCoordinates; +use flatbuffers::root; use futures_util::{SinkExt, StreamExt}; use hkdf::Hkdf; use jsonwebtoken::{decode, DecodingKey, Validation}; use log::{error, info}; use nanotdf::{BinaryParser, ProtocolEnum}; +use native_tls::{Identity, Protocol, TlsAcceptor as NativeTlsAcceptor}; use once_cell::sync::OnceCell; use p256::ecdh::EphemeralSecret; use p256::{elliptic_curve::sec1::ToEncodedPoint, PublicKey, SecretKey}; use rand_core::{OsRng, RngCore}; +use redis::AsyncCommands; +use redis::Client as RedisClient; use serde::{Deserialize, Serialize}; use sha2::Sha256; +use std::env; +use std::pin::Pin; +use std::sync::Arc; +use std::sync::RwLock; +use std::task::{Context, Poll}; +use std::time::{Duration, Instant}; use tokio::fs; use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf}; use tokio::net::TcpListener; @@ -92,7 +97,6 @@ impl NATSMessage { } } -#[derive(Debug)] struct ConnectionState { salt_lock: RwLock>>, shared_secret_lock: RwLock>>, @@ -118,6 +122,7 @@ enum MessageType { Rewrap = 0x03, RewrappedKey = 0x04, Nats = 0x05, + Event = 0x06, } impl MessageType { @@ -128,6 +133,7 @@ impl MessageType { 0x03 => Some(MessageType::Rewrap), 0x04 => Some(MessageType::RewrappedKey), 0x05 => Some(MessageType::Nats), + 0x06 => Some(MessageType::Event), _ => None, } } @@ -149,6 +155,7 @@ async fn main() -> Result<(), Box> { // Load configuration let settings = load_config()?; + let server_state = Arc::new(ServerState::new(settings.clone())?); // Load and cache the apple-app-site-association.json file let apple_app_site_association = load_apple_app_site_association().await; // Initialize KAS keys @@ -156,10 +163,10 @@ async fn main() -> Result<(), Box> { // Set up TLS if not disabled let tls_acceptor = if settings.tls_enabled { - Some(TlsAcceptor::from(load_tls_config( + Some(load_tls_config( &settings.tls_cert_path, &settings.tls_key_path, - )?)) + )?) } else { None }; @@ -194,7 +201,7 @@ async fn main() -> Result<(), Box> { // Accept connections while let Ok((stream, _)) = listener.accept().await { let tls_acceptor_clone = tls_acceptor.clone(); - let settings_clone = settings.clone(); + let server_state_clone = server_state.clone(); let nats_connection_clone = nats_connection.clone(); let apple_app_site_association_clone = apple_app_site_association.clone(); @@ -214,7 +221,7 @@ async fn main() -> Result<(), Box> { handle_connection( stream, - &settings_clone, + server_state_clone, nats_connection_clone, apple_app_site_association_clone, ) @@ -228,21 +235,27 @@ async fn main() -> Result<(), Box> { fn load_tls_config( cert_path: &str, key_path: &str, -) -> Result> { +) -> Result> { let cert = std::fs::read(cert_path)?; let key = std::fs::read(key_path)?; - let identity = native_tls::Identity::from_pkcs8(&cert, &key)?; - let acceptor = native_tls::TlsAcceptor::new(identity)?; - + let identity = Identity::from_pkcs8(&cert, &key)?; + // Create native_tls TlsAcceptor with custom options + let mut builder = NativeTlsAcceptor::builder(identity); + // Set minimum TLS version to TLS 1.2 + builder.min_protocol_version(Some(Protocol::Tlsv12)); + // Build the native_tls acceptor + let native_acceptor = builder + .build() + .map_err(|e| format!("Failed to build TLS acceptor: {}", e))?; + // Convert to tokio_native_tls acceptor + let acceptor = TlsAcceptor::from(native_acceptor); Ok(acceptor) } async fn handle_websocket( - mut ws_stream: tokio_tungstenite::WebSocketStream< - impl tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin, - >, - settings: &ServerSettings, + mut ws_stream: tokio_tungstenite::WebSocketStream, + server_state: Arc, nats_connection: Arc, ) { let (outgoing_tx, mut outgoing_rx) = mpsc::unbounded_channel(); @@ -251,7 +264,7 @@ async fn handle_websocket( // Set up NATS subscription for this connection let nats_task = tokio::spawn(handle_nats_subscription( nats_connection.clone(), - settings.nats_subject.clone(), + server_state.settings.nats_subject.clone(), connection_state.clone(), )); // Handle incoming WebSocket messages @@ -281,7 +294,7 @@ async fn handle_websocket( println!("Invalid JWT: {}", e); } } - } else if let Some(response) = handle_binary_message(&connection_state, msg.into_data(), settings, nats_connection.clone()).await { + } else if let Some(response) = handle_binary_message(&connection_state, &server_state, msg.into_data(), nats_connection.clone()).await { if ws_stream.send(response).await.is_err() { eprintln!("Failed to send response through WebSocket"); break; @@ -314,7 +327,7 @@ async fn handle_websocket( async fn handle_connection( stream: impl AsyncRead + AsyncWrite + Unpin, - settings: &ServerSettings, + server_state: Arc, nats_connection: Arc, apple_app_site_association: Arc>, ) { @@ -353,7 +366,7 @@ async fn handle_connection( rewindable_stream.rewind(); match tokio_tungstenite::accept_async(rewindable_stream).await { Ok(ws_stream) => { - handle_websocket(ws_stream, settings, nats_connection).await; + handle_websocket(ws_stream, server_state, nats_connection).await; } Err(e) => { eprintln!("Failed to accept websocket: {}", e); @@ -379,8 +392,8 @@ fn verify_token(token: &str) -> Result { async fn handle_binary_message( connection_state: &Arc, + server_state: &Arc, data: Vec, - settings: &ServerSettings, nats_connection: Arc, ) -> Option { if data.is_empty() { @@ -393,13 +406,22 @@ async fn handle_binary_message( match message_type { Some(MessageType::PublicKey) => handle_public_key(connection_state, payload).await, // incoming Some(MessageType::KasPublicKey) => handle_kas_public_key(payload).await, // outgoing - Some(MessageType::Rewrap) => handle_rewrap(connection_state, payload, settings).await, // incoming - Some(MessageType::RewrappedKey) => None, // outgoing + Some(MessageType::Rewrap) => { + handle_rewrap(connection_state, payload, &server_state.settings).await + } // incoming + Some(MessageType::RewrappedKey) => None, // outgoing Some(MessageType::Nats) => { - handle_nats_publish(connection_state, payload, settings, nats_connection).await + handle_nats_publish( + connection_state, + payload, + &server_state.settings, + nats_connection, + ) + .await } // internal + Some(MessageType::Event) => handle_event(server_state, payload).await, // embedded None => { - println!("Unknown message type: {:?}", message_type); + // println!("Unknown message type: {:?}", message_type); None } } @@ -581,15 +603,15 @@ async fn handle_public_key( } // println!("Client Public Key payload: {}", hex::encode(payload.as_ref())); if payload.len() != 33 { - println!("Client Public Key wrong size"); - println!("Client Public Key length: {}", payload.len()); + error!("Client Public Key wrong size"); + error!("Client Public Key length: {}", payload.len()); return None; } // Deserialize the public key sent by the client let client_public_key = match PublicKey::from_sec1_bytes(payload) { Ok(key) => key, Err(e) => { - println!("Error deserializing client public key: {:?}", e); + error!("Error deserializing client public key: {:?}", e); return None; } }; @@ -682,6 +704,143 @@ async fn handle_nats_message( Ok(()) } +async fn handle_event(server_state: &Arc, payload: &[u8]) -> Option { + let start_time = Instant::now(); + let mut event_data: Option> = None; + if let Ok(event) = root::(payload) { + println!("Event Action: {:?}", event.action()); + println!("Event Timestamp: {:?}", event.timestamp()); + println!("Event Status: {:?}", event.status()); + println!("Event Data Type: {:?}", event.data_type()); + // redis connection + let mut redis_conn = match server_state + .redis_client + .get_multiplexed_async_connection() + .await + { + Ok(conn) => conn, + Err(e) => { + error!("Failed to connect to Redis: {}", e); + return None; + } + }; + // Deserialize the event data based on its type + match event.data_type() { + EventData::UserEvent => { + if let Some(user_event) = event.data_as_user_event() { + println!("User Event:"); + println!(" Source Type: {:?}", user_event.source_type()); + println!(" Target Type: {:?}", user_event.target_type()); + println!(" Source ID: {:?}", user_event.source_id()); + println!(" Target ID: {:?}", user_event.target_id()); + let target_id = user_event.target_id().unwrap(); + // Retrieve the event object from Redis + event_data = match redis_conn.get::<_, Vec>(target_id.bytes()).await { + Ok(data) => { + println!("redis target_id: {:?}", target_id); + println!("redis data size: {} bytes", data.len()); + if data.is_empty() { + error!("Retrieved data from Redis has size 0"); + return None; + } + Some(data) + } + Err(e) => { + error!("Failed to retrieve event from Redis: {}", e); + return None; + } + }; + } + } + EventData::CacheEvent => { + if let Some(cache_event) = event.data_as_cache_event() { + println!("Cache Event:"); + println!(" Target ID: {:?}", cache_event.target_id()); + println!(" Target Payload: {:?}", cache_event.target_payload()); + println!( + " Target Payload Size: {:?}", + cache_event.target_payload()?.bytes().len() + ); + println!(" TTL: {:?}", cache_event.ttl()); + println!(" One Time Access: {:?}", cache_event.one_time_access()); + // Cache the object in Redis with specified TTL + let ttl = cache_event.ttl(); + if ttl > 0 { + if let (Some(target_id), Some(target_payload)) = + (cache_event.target_id(), cache_event.target_payload()) + { + let target_id_bytes = target_id.bytes(); + let target_payload_bytes = target_payload.bytes(); + redis_conn + .set_ex::<_, _, String>( + target_id_bytes, + target_payload_bytes, + ttl as u64, + ) + .await + .map_err(|e| { + error!("Failed to cache data in Redis: {}", e); + }) + .ok()?; + } else { + error!("target_id or target_payload was None while caching with TTL"); + return None; + } + } else if let (Some(target_id), Some(target_payload)) = + (cache_event.target_id(), cache_event.target_payload()) + { + let target_id_bytes = target_id.bytes(); + let target_payload_bytes = target_payload.bytes(); + redis_conn + .set::<_, _, String>(target_id_bytes, target_payload_bytes) + .await + .map_err(|e| { + error!("Failed to cache data in Redis: {}", e); + }) + .ok()?; + } else { + error!("target_id or target_payload was None while caching without TTL"); + } + event_data = Some(cache_event.target_payload().unwrap().bytes().to_vec()); + } + } + EventData::NONE => { + println!("No event data"); + } + _ => { + println!("Unknown event data type: {:?}", event.data_type()); + } + } + } else { + error!("Failed to parse Event from payload"); + return None; + } + let response_data = match event_data { + Some(data) => { + let mut response = Vec::new(); + response.push(MessageType::Event as u8); + response.extend_from_slice(&data); + response + } + None => { + error!("Event not found in Redis"); + let mut response = Vec::new(); + response.push(MessageType::Event as u8); + response.extend_from_slice(b"Event not found"); + response + } + }; + + let total_time = start_time.elapsed(); + log_timing( + &server_state.settings, + "Total time for handle_event", + total_time, + ); + + Some(Message::Binary(response_data)) +} + fn init_kas_keys(key_path: &str) -> Result<(), Box> { let pem_content = std::fs::read_to_string(key_path)?; let ec_pem_contents = pem_content.as_bytes(); @@ -740,6 +899,30 @@ fn custom_ecdh( Ok(shared_secret) } +struct ServerState { + settings: ServerSettings, + redis_client: RedisClient, +} + +impl ServerState { + fn new(settings: ServerSettings) -> Result { + info!("Attempting to connect to Redis at {}", settings.redis_url); + match RedisClient::open(settings.redis_url.clone()) { + Ok(client) => { + info!("Successfully connected to Redis server"); + Ok(ServerState { + settings, + redis_client: client, + }) + } + Err(e) => { + error!("Failed to connect to Redis server: {}", e); + Err(e) + } + } + } +} + #[derive(Debug, Deserialize, Clone)] struct ServerSettings { port: u16, @@ -750,6 +933,7 @@ struct ServerSettings { enable_timing_logs: bool, nats_url: String, nats_subject: String, + redis_url: String, } fn log_timing(settings: &ServerSettings, message: &str, duration: std::time::Duration) { @@ -792,6 +976,7 @@ fn load_config() -> Result> { .unwrap_or(false), nats_url: env::var("NATS_URL").unwrap_or_else(|_| "nats://localhost:4222".to_string()), nats_subject: env::var("NATS_SUBJECT").unwrap_or_else(|_| "nanotdf.messages".to_string()), + redis_url: env::var("REDIS_URL").unwrap_or_else(|_| "redis://localhost:6379".to_string()), }) } diff --git a/src/bin/schemas/event_generated.rs b/src/bin/schemas/event_generated.rs new file mode 100644 index 0000000..0f98049 --- /dev/null +++ b/src/bin/schemas/event_generated.rs @@ -0,0 +1,1176 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// @generated + +extern crate flatbuffers; + +#[allow(unused_imports, dead_code)] +pub mod arkavo { + extern crate flatbuffers; + use self::flatbuffers::Follow; + + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MIN_ACTION: i8 = 0; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MAX_ACTION: i8 = 8; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + #[allow(non_camel_case_types)] + pub const ENUM_VALUES_ACTION: [Action; 9] = [ + Action::unused, + Action::join, + Action::apply, + Action::approve, + Action::leave, + Action::cache, + Action::store, + Action::share, + Action::invite, + ]; + + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] + #[repr(transparent)] + pub struct Action(pub i8); + #[allow(non_upper_case_globals)] + impl Action { + pub const unused: Self = Self(0); + pub const join: Self = Self(1); + pub const apply: Self = Self(2); + pub const approve: Self = Self(3); + pub const leave: Self = Self(4); + pub const cache: Self = Self(5); + pub const store: Self = Self(6); + pub const share: Self = Self(7); + pub const invite: Self = Self(8); + + pub const ENUM_MIN: i8 = 0; + pub const ENUM_MAX: i8 = 8; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::unused, + Self::join, + Self::apply, + Self::approve, + Self::leave, + Self::cache, + Self::store, + Self::share, + Self::invite, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::unused => Some("unused"), + Self::join => Some("join"), + Self::apply => Some("apply"), + Self::approve => Some("approve"), + Self::leave => Some("leave"), + Self::cache => Some("cache"), + Self::store => Some("store"), + Self::share => Some("share"), + Self::invite => Some("invite"), + _ => None, + } + } + } + impl core::fmt::Debug for Action { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } + } + impl<'a> flatbuffers::Follow<'a> for Action { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); + Self(b) + } + } + + impl flatbuffers::Push for Action { + type Output = Action; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); + } + } + + impl flatbuffers::EndianScalar for Action { + type Scalar = i8; + #[inline] + fn to_little_endian(self) -> i8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: i8) -> Self { + let b = i8::from_le(v); + Self(b) + } + } + + impl flatbuffers::Verifiable for Action { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, + pos: usize, + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + i8::run_verifier(v, pos) + } + } + + impl flatbuffers::SimpleToVerifyInSlice for Action {} + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MIN_ACTION_STATUS: i8 = 0; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MAX_ACTION_STATUS: i8 = 4; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + #[allow(non_camel_case_types)] + pub const ENUM_VALUES_ACTION_STATUS: [ActionStatus; 5] = [ + ActionStatus::unused, + ActionStatus::preparing, + ActionStatus::fulfilling, + ActionStatus::fulfilled, + ActionStatus::failed, + ]; + + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] + #[repr(transparent)] + pub struct ActionStatus(pub i8); + #[allow(non_upper_case_globals)] + impl ActionStatus { + pub const unused: Self = Self(0); + pub const preparing: Self = Self(1); + pub const fulfilling: Self = Self(2); + pub const fulfilled: Self = Self(3); + pub const failed: Self = Self(4); + + pub const ENUM_MIN: i8 = 0; + pub const ENUM_MAX: i8 = 4; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::unused, + Self::preparing, + Self::fulfilling, + Self::fulfilled, + Self::failed, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::unused => Some("unused"), + Self::preparing => Some("preparing"), + Self::fulfilling => Some("fulfilling"), + Self::fulfilled => Some("fulfilled"), + Self::failed => Some("failed"), + _ => None, + } + } + } + impl core::fmt::Debug for ActionStatus { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } + } + impl<'a> flatbuffers::Follow<'a> for ActionStatus { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); + Self(b) + } + } + + impl flatbuffers::Push for ActionStatus { + type Output = ActionStatus; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); + } + } + + impl flatbuffers::EndianScalar for ActionStatus { + type Scalar = i8; + #[inline] + fn to_little_endian(self) -> i8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: i8) -> Self { + let b = i8::from_le(v); + Self(b) + } + } + + impl flatbuffers::Verifiable for ActionStatus { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, + pos: usize, + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + i8::run_verifier(v, pos) + } + } + + impl flatbuffers::SimpleToVerifyInSlice for ActionStatus {} + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MIN_ENTITY_TYPE: i8 = 0; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MAX_ENTITY_TYPE: i8 = 2; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + #[allow(non_camel_case_types)] + pub const ENUM_VALUES_ENTITY_TYPE: [EntityType; 3] = [ + EntityType::unused, + EntityType::stream_profile, + EntityType::account_profile, + ]; + + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] + #[repr(transparent)] + pub struct EntityType(pub i8); + #[allow(non_upper_case_globals)] + impl EntityType { + pub const unused: Self = Self(0); + pub const stream_profile: Self = Self(1); + pub const account_profile: Self = Self(2); + + pub const ENUM_MIN: i8 = 0; + pub const ENUM_MAX: i8 = 2; + pub const ENUM_VALUES: &'static [Self] = + &[Self::unused, Self::stream_profile, Self::account_profile]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::unused => Some("unused"), + Self::stream_profile => Some("stream_profile"), + Self::account_profile => Some("account_profile"), + _ => None, + } + } + } + impl core::fmt::Debug for EntityType { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } + } + impl<'a> flatbuffers::Follow<'a> for EntityType { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); + Self(b) + } + } + + impl flatbuffers::Push for EntityType { + type Output = EntityType; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); + } + } + + impl flatbuffers::EndianScalar for EntityType { + type Scalar = i8; + #[inline] + fn to_little_endian(self) -> i8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: i8) -> Self { + let b = i8::from_le(v); + Self(b) + } + } + + impl flatbuffers::Verifiable for EntityType { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, + pos: usize, + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + i8::run_verifier(v, pos) + } + } + + impl flatbuffers::SimpleToVerifyInSlice for EntityType {} + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MIN_EVENT_DATA: u8 = 0; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MAX_EVENT_DATA: u8 = 2; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + #[allow(non_camel_case_types)] + pub const ENUM_VALUES_EVENT_DATA: [EventData; 3] = + [EventData::NONE, EventData::UserEvent, EventData::CacheEvent]; + + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] + #[repr(transparent)] + pub struct EventData(pub u8); + #[allow(non_upper_case_globals)] + impl EventData { + pub const NONE: Self = Self(0); + pub const UserEvent: Self = Self(1); + pub const CacheEvent: Self = Self(2); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 2; + pub const ENUM_VALUES: &'static [Self] = &[Self::NONE, Self::UserEvent, Self::CacheEvent]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NONE => Some("NONE"), + Self::UserEvent => Some("UserEvent"), + Self::CacheEvent => Some("CacheEvent"), + _ => None, + } + } + } + impl core::fmt::Debug for EventData { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } + } + impl<'a> flatbuffers::Follow<'a> for EventData { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); + Self(b) + } + } + + impl flatbuffers::Push for EventData { + type Output = EventData; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); + } + } + + impl flatbuffers::EndianScalar for EventData { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } + } + + impl flatbuffers::Verifiable for EventData { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, + pos: usize, + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + u8::run_verifier(v, pos) + } + } + + impl flatbuffers::SimpleToVerifyInSlice for EventData {} + pub struct EventDataUnionTableOffset {} + + pub enum UserEventOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct UserEvent<'a> { + pub _tab: flatbuffers::Table<'a>, + } + + impl<'a> flatbuffers::Follow<'a> for UserEvent<'a> { + type Inner = UserEvent<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: flatbuffers::Table::new(buf, loc), + } + } + } + + impl<'a> UserEvent<'a> { + pub const VT_SOURCE_TYPE: flatbuffers::VOffsetT = 4; + pub const VT_TARGET_TYPE: flatbuffers::VOffsetT = 6; + pub const VT_SOURCE_ID: flatbuffers::VOffsetT = 8; + pub const VT_TARGET_ID: flatbuffers::VOffsetT = 10; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + UserEvent { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args UserEventArgs<'args>, + ) -> flatbuffers::WIPOffset> { + let mut builder = UserEventBuilder::new(_fbb); + if let Some(x) = args.target_id { + builder.add_target_id(x); + } + if let Some(x) = args.source_id { + builder.add_source_id(x); + } + builder.add_target_type(args.target_type); + builder.add_source_type(args.source_type); + builder.finish() + } + + #[inline] + pub fn source_type(&self) -> EntityType { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(UserEvent::VT_SOURCE_TYPE, Some(EntityType::unused)) + .unwrap() + } + } + #[inline] + pub fn target_type(&self) -> EntityType { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(UserEvent::VT_TARGET_TYPE, Some(EntityType::unused)) + .unwrap() + } + } + #[inline] + pub fn source_id(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::>>( + UserEvent::VT_SOURCE_ID, + None, + ) + } + } + #[inline] + pub fn target_id(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::>>( + UserEvent::VT_TARGET_ID, + None, + ) + } + } + } + + impl flatbuffers::Verifiable for UserEvent<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, + pos: usize, + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("source_type", Self::VT_SOURCE_TYPE, false)? + .visit_field::("target_type", Self::VT_TARGET_TYPE, false)? + .visit_field::>>( + "source_id", + Self::VT_SOURCE_ID, + false, + )? + .visit_field::>>( + "target_id", + Self::VT_TARGET_ID, + false, + )? + .finish(); + Ok(()) + } + } + pub struct UserEventArgs<'a> { + pub source_type: EntityType, + pub target_type: EntityType, + pub source_id: Option>>, + pub target_id: Option>>, + } + impl<'a> Default for UserEventArgs<'a> { + #[inline] + fn default() -> Self { + UserEventArgs { + source_type: EntityType::unused, + target_type: EntityType::unused, + source_id: None, + target_id: None, + } + } + } + + pub struct UserEventBuilder<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + start_: flatbuffers::WIPOffset, + } + impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> UserEventBuilder<'a, 'b, A> { + #[inline] + pub fn add_source_type(&mut self, source_type: EntityType) { + self.fbb_.push_slot::( + UserEvent::VT_SOURCE_TYPE, + source_type, + EntityType::unused, + ); + } + #[inline] + pub fn add_target_type(&mut self, target_type: EntityType) { + self.fbb_.push_slot::( + UserEvent::VT_TARGET_TYPE, + target_type, + EntityType::unused, + ); + } + #[inline] + pub fn add_source_id( + &mut self, + source_id: flatbuffers::WIPOffset>, + ) { + self.fbb_ + .push_slot_always::>(UserEvent::VT_SOURCE_ID, source_id); + } + #[inline] + pub fn add_target_id( + &mut self, + target_id: flatbuffers::WIPOffset>, + ) { + self.fbb_ + .push_slot_always::>(UserEvent::VT_TARGET_ID, target_id); + } + #[inline] + pub fn new( + _fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + ) -> UserEventBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + UserEventBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } + } + + impl core::fmt::Debug for UserEvent<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("UserEvent"); + ds.field("source_type", &self.source_type()); + ds.field("target_type", &self.target_type()); + ds.field("source_id", &self.source_id()); + ds.field("target_id", &self.target_id()); + ds.finish() + } + } + pub enum CacheEventOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct CacheEvent<'a> { + pub _tab: flatbuffers::Table<'a>, + } + + impl<'a> flatbuffers::Follow<'a> for CacheEvent<'a> { + type Inner = CacheEvent<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: flatbuffers::Table::new(buf, loc), + } + } + } + + impl<'a> CacheEvent<'a> { + pub const VT_TARGET_ID: flatbuffers::VOffsetT = 4; + pub const VT_TARGET_PAYLOAD: flatbuffers::VOffsetT = 6; + pub const VT_TTL: flatbuffers::VOffsetT = 8; + pub const VT_ONE_TIME_ACCESS: flatbuffers::VOffsetT = 10; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + CacheEvent { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args CacheEventArgs<'args>, + ) -> flatbuffers::WIPOffset> { + let mut builder = CacheEventBuilder::new(_fbb); + builder.add_ttl(args.ttl); + if let Some(x) = args.target_payload { + builder.add_target_payload(x); + } + if let Some(x) = args.target_id { + builder.add_target_id(x); + } + builder.add_one_time_access(args.one_time_access); + builder.finish() + } + + #[inline] + pub fn target_id(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::>>( + CacheEvent::VT_TARGET_ID, + None, + ) + } + } + #[inline] + pub fn target_payload(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::>>( + CacheEvent::VT_TARGET_PAYLOAD, + None, + ) + } + } + #[inline] + pub fn ttl(&self) -> u32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(CacheEvent::VT_TTL, Some(0)).unwrap() } + } + #[inline] + pub fn one_time_access(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(CacheEvent::VT_ONE_TIME_ACCESS, Some(false)) + .unwrap() + } + } + } + + impl flatbuffers::Verifiable for CacheEvent<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, + pos: usize, + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::>>( + "target_id", + Self::VT_TARGET_ID, + false, + )? + .visit_field::>>( + "target_payload", + Self::VT_TARGET_PAYLOAD, + false, + )? + .visit_field::("ttl", Self::VT_TTL, false)? + .visit_field::("one_time_access", Self::VT_ONE_TIME_ACCESS, false)? + .finish(); + Ok(()) + } + } + pub struct CacheEventArgs<'a> { + pub target_id: Option>>, + pub target_payload: Option>>, + pub ttl: u32, + pub one_time_access: bool, + } + impl<'a> Default for CacheEventArgs<'a> { + #[inline] + fn default() -> Self { + CacheEventArgs { + target_id: None, + target_payload: None, + ttl: 0, + one_time_access: false, + } + } + } + + pub struct CacheEventBuilder<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + start_: flatbuffers::WIPOffset, + } + impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> CacheEventBuilder<'a, 'b, A> { + #[inline] + pub fn add_target_id( + &mut self, + target_id: flatbuffers::WIPOffset>, + ) { + self.fbb_ + .push_slot_always::>(CacheEvent::VT_TARGET_ID, target_id); + } + #[inline] + pub fn add_target_payload( + &mut self, + target_payload: flatbuffers::WIPOffset>, + ) { + self.fbb_.push_slot_always::>( + CacheEvent::VT_TARGET_PAYLOAD, + target_payload, + ); + } + #[inline] + pub fn add_ttl(&mut self, ttl: u32) { + self.fbb_.push_slot::(CacheEvent::VT_TTL, ttl, 0); + } + #[inline] + pub fn add_one_time_access(&mut self, one_time_access: bool) { + self.fbb_ + .push_slot::(CacheEvent::VT_ONE_TIME_ACCESS, one_time_access, false); + } + #[inline] + pub fn new( + _fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + ) -> CacheEventBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + CacheEventBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } + } + + impl core::fmt::Debug for CacheEvent<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("CacheEvent"); + ds.field("target_id", &self.target_id()); + ds.field("target_payload", &self.target_payload()); + ds.field("ttl", &self.ttl()); + ds.field("one_time_access", &self.one_time_access()); + ds.finish() + } + } + pub enum EventOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct Event<'a> { + pub _tab: flatbuffers::Table<'a>, + } + + impl<'a> flatbuffers::Follow<'a> for Event<'a> { + type Inner = Event<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: flatbuffers::Table::new(buf, loc), + } + } + } + + impl<'a> Event<'a> { + pub const VT_ACTION: flatbuffers::VOffsetT = 4; + pub const VT_TIMESTAMP: flatbuffers::VOffsetT = 6; + pub const VT_STATUS: flatbuffers::VOffsetT = 8; + pub const VT_DATA_TYPE: flatbuffers::VOffsetT = 10; + pub const VT_DATA: flatbuffers::VOffsetT = 12; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + Event { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args EventArgs, + ) -> flatbuffers::WIPOffset> { + let mut builder = EventBuilder::new(_fbb); + builder.add_timestamp(args.timestamp); + if let Some(x) = args.data { + builder.add_data(x); + } + builder.add_data_type(args.data_type); + builder.add_status(args.status); + builder.add_action(args.action); + builder.finish() + } + + #[inline] + pub fn action(&self) -> Action { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(Event::VT_ACTION, Some(Action::unused)) + .unwrap() + } + } + #[inline] + pub fn timestamp(&self) -> u64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Event::VT_TIMESTAMP, Some(0)).unwrap() } + } + #[inline] + pub fn status(&self) -> ActionStatus { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(Event::VT_STATUS, Some(ActionStatus::unused)) + .unwrap() + } + } + #[inline] + pub fn data_type(&self) -> EventData { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(Event::VT_DATA_TYPE, Some(EventData::NONE)) + .unwrap() + } + } + #[inline] + pub fn data(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::>>( + Event::VT_DATA, + None, + ) + } + } + #[inline] + #[allow(non_snake_case)] + pub fn data_as_user_event(&self) -> Option> { + if self.data_type() == EventData::UserEvent { + self.data().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { UserEvent::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn data_as_cache_event(&self) -> Option> { + if self.data_type() == EventData::CacheEvent { + self.data().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { CacheEvent::init_from_table(t) } + }) + } else { + None + } + } + } + + impl flatbuffers::Verifiable for Event<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, + pos: usize, + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("action", Self::VT_ACTION, false)? + .visit_field::("timestamp", Self::VT_TIMESTAMP, false)? + .visit_field::("status", Self::VT_STATUS, false)? + .visit_union::( + "data_type", + Self::VT_DATA_TYPE, + "data", + Self::VT_DATA, + false, + |key, v, pos| match key { + EventData::UserEvent => v + .verify_union_variant::>( + "EventData::UserEvent", + pos, + ), + EventData::CacheEvent => v + .verify_union_variant::>( + "EventData::CacheEvent", + pos, + ), + _ => Ok(()), + }, + )? + .finish(); + Ok(()) + } + } + pub struct EventArgs { + pub action: Action, + pub timestamp: u64, + pub status: ActionStatus, + pub data_type: EventData, + pub data: Option>, + } + impl Default for EventArgs { + #[inline] + fn default() -> Self { + EventArgs { + action: Action::unused, + timestamp: 0, + status: ActionStatus::unused, + data_type: EventData::NONE, + data: None, + } + } + } + + pub struct EventBuilder<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + start_: flatbuffers::WIPOffset, + } + impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> EventBuilder<'a, 'b, A> { + #[inline] + pub fn add_action(&mut self, action: Action) { + self.fbb_ + .push_slot::(Event::VT_ACTION, action, Action::unused); + } + #[inline] + pub fn add_timestamp(&mut self, timestamp: u64) { + self.fbb_ + .push_slot::(Event::VT_TIMESTAMP, timestamp, 0); + } + #[inline] + pub fn add_status(&mut self, status: ActionStatus) { + self.fbb_ + .push_slot::(Event::VT_STATUS, status, ActionStatus::unused); + } + #[inline] + pub fn add_data_type(&mut self, data_type: EventData) { + self.fbb_ + .push_slot::(Event::VT_DATA_TYPE, data_type, EventData::NONE); + } + #[inline] + pub fn add_data(&mut self, data: flatbuffers::WIPOffset) { + self.fbb_ + .push_slot_always::>(Event::VT_DATA, data); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>) -> EventBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + EventBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } + } + + impl core::fmt::Debug for Event<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("Event"); + ds.field("action", &self.action()); + ds.field("timestamp", &self.timestamp()); + ds.field("status", &self.status()); + ds.field("data_type", &self.data_type()); + match self.data_type() { + EventData::UserEvent => { + if let Some(x) = self.data_as_user_event() { + ds.field("data", &x) + } else { + ds.field( + "data", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + EventData::CacheEvent => { + if let Some(x) = self.data_as_cache_event() { + ds.field("data", &x) + } else { + ds.field( + "data", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + _ => { + let x: Option<()> = None; + ds.field("data", &x) + } + }; + ds.finish() + } + } + #[inline] + /// Verifies that a buffer of bytes contains a `Event` + /// and returns it. + /// Note that verification is still experimental and may not + /// catch every error, or be maximally performant. For the + /// previous, unchecked, behavior use + /// `root_as_event_unchecked`. + pub fn root_as_event(buf: &[u8]) -> Result { + flatbuffers::root::(buf) + } + #[inline] + /// Verifies that a buffer of bytes contains a size prefixed + /// `Event` and returns it. + /// Note that verification is still experimental and may not + /// catch every error, or be maximally performant. For the + /// previous, unchecked, behavior use + /// `size_prefixed_root_as_event_unchecked`. + pub fn size_prefixed_root_as_event( + buf: &[u8], + ) -> Result { + flatbuffers::size_prefixed_root::(buf) + } + #[inline] + /// Verifies, with the given options, that a buffer of bytes + /// contains a `Event` and returns it. + /// Note that verification is still experimental and may not + /// catch every error, or be maximally performant. For the + /// previous, unchecked, behavior use + /// `root_as_event_unchecked`. + pub fn root_as_event_with_opts<'b, 'o>( + opts: &'o flatbuffers::VerifierOptions, + buf: &'b [u8], + ) -> Result, flatbuffers::InvalidFlatbuffer> { + flatbuffers::root_with_opts::>(opts, buf) + } + #[inline] + /// Verifies, with the given verifier options, that a buffer of + /// bytes contains a size prefixed `Event` and returns + /// it. Note that verification is still experimental and may not + /// catch every error, or be maximally performant. For the + /// previous, unchecked, behavior use + /// `root_as_event_unchecked`. + pub fn size_prefixed_root_as_event_with_opts<'b, 'o>( + opts: &'o flatbuffers::VerifierOptions, + buf: &'b [u8], + ) -> Result, flatbuffers::InvalidFlatbuffer> { + flatbuffers::size_prefixed_root_with_opts::>(opts, buf) + } + #[inline] + /// Assumes, without verification, that a buffer of bytes contains a Event and returns it. + /// # Safety + /// Callers must trust the given bytes do indeed contain a valid `Event`. + pub unsafe fn root_as_event_unchecked(buf: &[u8]) -> Event { + flatbuffers::root_unchecked::(buf) + } + #[inline] + /// Assumes, without verification, that a buffer of bytes contains a size prefixed Event and returns it. + /// # Safety + /// Callers must trust the given bytes do indeed contain a valid size prefixed `Event`. + pub unsafe fn size_prefixed_root_as_event_unchecked(buf: &[u8]) -> Event { + flatbuffers::size_prefixed_root_unchecked::(buf) + } + #[inline] + pub fn finish_event_buffer<'a, 'b, A: flatbuffers::Allocator + 'a>( + fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + root: flatbuffers::WIPOffset>, + ) { + fbb.finish(root, None); + } + + #[inline] + pub fn finish_size_prefixed_event_buffer<'a, 'b, A: flatbuffers::Allocator + 'a>( + fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + root: flatbuffers::WIPOffset>, + ) { + fbb.finish_size_prefixed(root, None); + } +} // pub mod Arkavo diff --git a/src/bin/schemas/mod.rs b/src/bin/schemas/mod.rs new file mode 100644 index 0000000..b748312 --- /dev/null +++ b/src/bin/schemas/mod.rs @@ -0,0 +1 @@ +pub mod event_generated;