diff --git a/build.rs b/build.rs index e44a24c..b72e9fd 100644 --- a/build.rs +++ b/build.rs @@ -3,7 +3,7 @@ use std::path::Path; fn init_proto() -> Result<(), Box> { // Define the path to the output directory within the `src` folder - let out_dir = Path::new("proto"); + let out_dir = Path::new("src/protos"); std::fs::create_dir_all(out_dir)?; let descriptor_set_path = format!( @@ -12,10 +12,10 @@ fn init_proto() -> Result<(), Box> { ); let files = &[ - "proto/ratings_features_app.proto", - "proto/ratings_features_chart.proto", - "proto/ratings_features_user.proto", - "proto/ratings_features_common.proto", + "protos/ratings_features_app.proto", + "protos/ratings_features_chart.proto", + "protos/ratings_features_user.proto", + "protos/ratings_features_common.proto", ]; tonic_build::configure() @@ -28,7 +28,7 @@ fn init_proto() -> Result<(), Box> { "Category", r#"#[strum(serialize_all = "kebab_case", ascii_case_insensitive)]"#, ) - .compile(files, &["proto"])?; + .compile(files, &["protos"])?; Ok(()) } diff --git a/proto/ratings_features_app.proto b/protos/ratings_features_app.proto similarity index 100% rename from proto/ratings_features_app.proto rename to protos/ratings_features_app.proto diff --git a/proto/ratings_features_chart.proto b/protos/ratings_features_chart.proto similarity index 100% rename from proto/ratings_features_chart.proto rename to protos/ratings_features_chart.proto diff --git a/proto/ratings_features_common.proto b/protos/ratings_features_common.proto similarity index 100% rename from proto/ratings_features_common.proto rename to protos/ratings_features_common.proto diff --git a/proto/ratings_features_user.proto b/protos/ratings_features_user.proto similarity index 100% rename from proto/ratings_features_user.proto rename to protos/ratings_features_user.proto diff --git a/src/features/pb.rs b/src/features/pb.rs index d20971e..e794f70 100644 --- a/src/features/pb.rs +++ b/src/features/pb.rs @@ -7,23 +7,23 @@ pub mod app { //! Contains protobufs relating to the app features - include!("../../proto/ratings.features.app.rs"); + include!("../protos/ratings.features.app.rs"); } pub mod common { //! Contains common protobufs - include!("../../proto/ratings.features.common.rs"); + include!("../protos/ratings.features.common.rs"); } pub mod user { //! Contains user protobufs - include!("../../proto/ratings.features.user.rs"); + include!("../protos/ratings.features.user.rs"); } pub mod chart { //! Contains chart protobufs - include!("../../proto/ratings.features.chart.rs"); + include!("../protos/ratings.features.chart.rs"); } diff --git a/src/protos/ratings.features.app.rs b/src/protos/ratings.features.app.rs new file mode 100644 index 0000000..f8df299 --- /dev/null +++ b/src/protos/ratings.features.app.rs @@ -0,0 +1,304 @@ +// This file is @generated by prost-build. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetRatingRequest { + #[prost(string, tag = "1")] + pub snap_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetRatingResponse { + #[prost(message, optional, tag = "1")] + pub rating: ::core::option::Option, +} +/// Generated client implementations. +pub mod app_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct AppClient { + inner: tonic::client::Grpc, + } + impl AppClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl AppClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> AppClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + AppClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + pub async fn get_rating( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/ratings.features.app.App/GetRating", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("ratings.features.app.App", "GetRating")); + self.inner.unary(req, path, codec).await + } + } +} +/// Generated server implementations. +pub mod app_server { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with AppServer. + #[async_trait] + pub trait App: Send + Sync + 'static { + async fn get_rating( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + } + #[derive(Debug)] + pub struct AppServer { + inner: _Inner, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + struct _Inner(Arc); + impl AppServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + let inner = _Inner(inner); + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> for AppServer + where + T: App, + B: Body + Send + 'static, + B::Error: Into + Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + let inner = self.inner.clone(); + match req.uri().path() { + "/ratings.features.app.App/GetRating" => { + #[allow(non_camel_case_types)] + struct GetRatingSvc(pub Arc); + impl tonic::server::UnaryService + for GetRatingSvc { + type Response = super::GetRatingResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_rating(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetRatingSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } + } + } + } + impl Clone for AppServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + impl Clone for _Inner { + fn clone(&self) -> Self { + Self(Arc::clone(&self.0)) + } + } + impl std::fmt::Debug for _Inner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } + } + impl tonic::server::NamedService for AppServer { + const NAME: &'static str = "ratings.features.app.App"; + } +} diff --git a/src/protos/ratings.features.chart.rs b/src/protos/ratings.features.chart.rs new file mode 100644 index 0000000..1fab135 --- /dev/null +++ b/src/protos/ratings.features.chart.rs @@ -0,0 +1,432 @@ +// This file is @generated by prost-build. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetChartRequest { + #[prost(enumeration = "Timeframe", tag = "1")] + pub timeframe: i32, + #[prost(enumeration = "Category", optional, tag = "2")] + pub category: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetChartResponse { + #[prost(enumeration = "Timeframe", tag = "1")] + pub timeframe: i32, + #[prost(message, repeated, tag = "2")] + pub ordered_chart_data: ::prost::alloc::vec::Vec, + #[prost(enumeration = "Category", optional, tag = "3")] + pub category: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ChartData { + #[prost(float, tag = "1")] + pub raw_rating: f32, + #[prost(message, optional, tag = "2")] + pub rating: ::core::option::Option, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum Timeframe { + Unspecified = 0, + Week = 1, + Month = 2, +} +impl Timeframe { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Timeframe::Unspecified => "TIMEFRAME_UNSPECIFIED", + Timeframe::Week => "TIMEFRAME_WEEK", + Timeframe::Month => "TIMEFRAME_MONTH", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "TIMEFRAME_UNSPECIFIED" => Some(Self::Unspecified), + "TIMEFRAME_WEEK" => Some(Self::Week), + "TIMEFRAME_MONTH" => Some(Self::Month), + _ => None, + } + } +} +/// The categories that can be selected, these +/// are taken directly from `curl -sS -X GET --unix-socket /run/snapd.socket " +/// On 2024-02-03, it may need to be kept in sync. +#[derive(sqlx::Type, strum::EnumString)] +#[strum(serialize_all = "kebab_case", ascii_case_insensitive)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum Category { + ArtAndDesign = 0, + BookAndReference = 1, + Development = 2, + DevicesAndIot = 3, + Education = 4, + Entertainment = 5, + Featured = 6, + Finance = 7, + Games = 8, + HealthAndFitness = 9, + MusicAndAudio = 10, + NewsAndWeather = 11, + Personalisation = 12, + PhotoAndVideo = 13, + Productivity = 14, + Science = 15, + Security = 16, + ServerAndCloud = 17, + Social = 18, + Utilities = 19, +} +impl Category { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Category::ArtAndDesign => "ART_AND_DESIGN", + Category::BookAndReference => "BOOK_AND_REFERENCE", + Category::Development => "DEVELOPMENT", + Category::DevicesAndIot => "DEVICES_AND_IOT", + Category::Education => "EDUCATION", + Category::Entertainment => "ENTERTAINMENT", + Category::Featured => "FEATURED", + Category::Finance => "FINANCE", + Category::Games => "GAMES", + Category::HealthAndFitness => "HEALTH_AND_FITNESS", + Category::MusicAndAudio => "MUSIC_AND_AUDIO", + Category::NewsAndWeather => "NEWS_AND_WEATHER", + Category::Personalisation => "PERSONALISATION", + Category::PhotoAndVideo => "PHOTO_AND_VIDEO", + Category::Productivity => "PRODUCTIVITY", + Category::Science => "SCIENCE", + Category::Security => "SECURITY", + Category::ServerAndCloud => "SERVER_AND_CLOUD", + Category::Social => "SOCIAL", + Category::Utilities => "UTILITIES", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "ART_AND_DESIGN" => Some(Self::ArtAndDesign), + "BOOK_AND_REFERENCE" => Some(Self::BookAndReference), + "DEVELOPMENT" => Some(Self::Development), + "DEVICES_AND_IOT" => Some(Self::DevicesAndIot), + "EDUCATION" => Some(Self::Education), + "ENTERTAINMENT" => Some(Self::Entertainment), + "FEATURED" => Some(Self::Featured), + "FINANCE" => Some(Self::Finance), + "GAMES" => Some(Self::Games), + "HEALTH_AND_FITNESS" => Some(Self::HealthAndFitness), + "MUSIC_AND_AUDIO" => Some(Self::MusicAndAudio), + "NEWS_AND_WEATHER" => Some(Self::NewsAndWeather), + "PERSONALISATION" => Some(Self::Personalisation), + "PHOTO_AND_VIDEO" => Some(Self::PhotoAndVideo), + "PRODUCTIVITY" => Some(Self::Productivity), + "SCIENCE" => Some(Self::Science), + "SECURITY" => Some(Self::Security), + "SERVER_AND_CLOUD" => Some(Self::ServerAndCloud), + "SOCIAL" => Some(Self::Social), + "UTILITIES" => Some(Self::Utilities), + _ => None, + } + } +} +/// Generated client implementations. +pub mod chart_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct ChartClient { + inner: tonic::client::Grpc, + } + impl ChartClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl ChartClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> ChartClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + ChartClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + pub async fn get_chart( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/ratings.features.chart.Chart/GetChart", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("ratings.features.chart.Chart", "GetChart")); + self.inner.unary(req, path, codec).await + } + } +} +/// Generated server implementations. +pub mod chart_server { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with ChartServer. + #[async_trait] + pub trait Chart: Send + Sync + 'static { + async fn get_chart( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + } + #[derive(Debug)] + pub struct ChartServer { + inner: _Inner, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + struct _Inner(Arc); + impl ChartServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + let inner = _Inner(inner); + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> for ChartServer + where + T: Chart, + B: Body + Send + 'static, + B::Error: Into + Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + let inner = self.inner.clone(); + match req.uri().path() { + "/ratings.features.chart.Chart/GetChart" => { + #[allow(non_camel_case_types)] + struct GetChartSvc(pub Arc); + impl tonic::server::UnaryService + for GetChartSvc { + type Response = super::GetChartResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_chart(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetChartSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } + } + } + } + impl Clone for ChartServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + impl Clone for _Inner { + fn clone(&self) -> Self { + Self(Arc::clone(&self.0)) + } + } + impl std::fmt::Debug for _Inner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } + } + impl tonic::server::NamedService for ChartServer { + const NAME: &'static str = "ratings.features.chart.Chart"; + } +} diff --git a/src/protos/ratings.features.common.rs b/src/protos/ratings.features.common.rs new file mode 100644 index 0000000..9e9f6a9 --- /dev/null +++ b/src/protos/ratings.features.common.rs @@ -0,0 +1,49 @@ +// This file is @generated by prost-build. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Rating { + #[prost(string, tag = "1")] + pub snap_id: ::prost::alloc::string::String, + #[prost(uint64, tag = "2")] + pub total_votes: u64, + #[prost(enumeration = "RatingsBand", tag = "3")] + pub ratings_band: i32, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum RatingsBand { + VeryGood = 0, + Good = 1, + Neutral = 2, + Poor = 3, + VeryPoor = 4, + InsufficientVotes = 5, +} +impl RatingsBand { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + RatingsBand::VeryGood => "VERY_GOOD", + RatingsBand::Good => "GOOD", + RatingsBand::Neutral => "NEUTRAL", + RatingsBand::Poor => "POOR", + RatingsBand::VeryPoor => "VERY_POOR", + RatingsBand::InsufficientVotes => "INSUFFICIENT_VOTES", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "VERY_GOOD" => Some(Self::VeryGood), + "GOOD" => Some(Self::Good), + "NEUTRAL" => Some(Self::Neutral), + "POOR" => Some(Self::Poor), + "VERY_POOR" => Some(Self::VeryPoor), + "INSUFFICIENT_VOTES" => Some(Self::InsufficientVotes), + _ => None, + } + } +} diff --git a/src/protos/ratings.features.user.rs b/src/protos/ratings.features.user.rs new file mode 100644 index 0000000..8b234b1 --- /dev/null +++ b/src/protos/ratings.features.user.rs @@ -0,0 +1,639 @@ +// This file is @generated by prost-build. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AuthenticateRequest { + /// sha256(\[$user:$machineId\]) + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AuthenticateResponse { + #[prost(string, tag = "1")] + pub token: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ListMyVotesRequest { + #[prost(string, tag = "1")] + pub snap_id_filter: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ListMyVotesResponse { + #[prost(message, repeated, tag = "1")] + pub votes: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetSnapVotesRequest { + #[prost(string, tag = "1")] + pub snap_id: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetSnapVotesResponse { + #[prost(message, repeated, tag = "1")] + pub votes: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Vote { + #[prost(string, tag = "1")] + pub snap_id: ::prost::alloc::string::String, + #[prost(int32, tag = "2")] + pub snap_revision: i32, + #[prost(bool, tag = "3")] + pub vote_up: bool, + #[prost(message, optional, tag = "4")] + pub timestamp: ::core::option::Option<::prost_types::Timestamp>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct VoteRequest { + #[prost(string, tag = "1")] + pub snap_id: ::prost::alloc::string::String, + #[prost(int32, tag = "2")] + pub snap_revision: i32, + #[prost(bool, tag = "3")] + pub vote_up: bool, +} +/// Generated client implementations. +pub mod user_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct UserClient { + inner: tonic::client::Grpc, + } + impl UserClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl UserClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> UserClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + UserClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + pub async fn authenticate( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/ratings.features.user.User/Authenticate", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("ratings.features.user.User", "Authenticate")); + self.inner.unary(req, path, codec).await + } + pub async fn delete( + &mut self, + request: impl tonic::IntoRequest<()>, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/ratings.features.user.User/Delete", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("ratings.features.user.User", "Delete")); + self.inner.unary(req, path, codec).await + } + pub async fn vote( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/ratings.features.user.User/Vote", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("ratings.features.user.User", "Vote")); + self.inner.unary(req, path, codec).await + } + pub async fn list_my_votes( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/ratings.features.user.User/ListMyVotes", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("ratings.features.user.User", "ListMyVotes")); + self.inner.unary(req, path, codec).await + } + pub async fn get_snap_votes( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/ratings.features.user.User/GetSnapVotes", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("ratings.features.user.User", "GetSnapVotes")); + self.inner.unary(req, path, codec).await + } + } +} +/// Generated server implementations. +pub mod user_server { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with UserServer. + #[async_trait] + pub trait User: Send + Sync + 'static { + async fn authenticate( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn delete( + &self, + request: tonic::Request<()>, + ) -> std::result::Result, tonic::Status>; + async fn vote( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + async fn list_my_votes( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + async fn get_snap_votes( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; + } + #[derive(Debug)] + pub struct UserServer { + inner: _Inner, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + struct _Inner(Arc); + impl UserServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + let inner = _Inner(inner); + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> for UserServer + where + T: User, + B: Body + Send + 'static, + B::Error: Into + Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + let inner = self.inner.clone(); + match req.uri().path() { + "/ratings.features.user.User/Authenticate" => { + #[allow(non_camel_case_types)] + struct AuthenticateSvc(pub Arc); + impl tonic::server::UnaryService + for AuthenticateSvc { + type Response = super::AuthenticateResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::authenticate(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = AuthenticateSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/ratings.features.user.User/Delete" => { + #[allow(non_camel_case_types)] + struct DeleteSvc(pub Arc); + impl tonic::server::UnaryService<()> for DeleteSvc { + type Response = (); + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call(&mut self, request: tonic::Request<()>) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::delete(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = DeleteSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/ratings.features.user.User/Vote" => { + #[allow(non_camel_case_types)] + struct VoteSvc(pub Arc); + impl tonic::server::UnaryService + for VoteSvc { + type Response = (); + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::vote(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = VoteSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/ratings.features.user.User/ListMyVotes" => { + #[allow(non_camel_case_types)] + struct ListMyVotesSvc(pub Arc); + impl tonic::server::UnaryService + for ListMyVotesSvc { + type Response = super::ListMyVotesResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::list_my_votes(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = ListMyVotesSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/ratings.features.user.User/GetSnapVotes" => { + #[allow(non_camel_case_types)] + struct GetSnapVotesSvc(pub Arc); + impl tonic::server::UnaryService + for GetSnapVotesSvc { + type Response = super::GetSnapVotesResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_snap_votes(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = GetSnapVotesSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } + } + } + } + impl Clone for UserServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + impl Clone for _Inner { + fn clone(&self) -> Self { + Self(Arc::clone(&self.0)) + } + } + impl std::fmt::Debug for _Inner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } + } + impl tonic::server::NamedService for UserServer { + const NAME: &'static str = "ratings.features.user.User"; + } +}