#[cfg(feature = "reflection")]
use tonic_reflection::server::{ServerReflection, ServerReflectionServer};
#[derive(Debug, Clone)]
pub struct ReflectionConfig {
pub enabled: bool,
pub file_descriptor_sets: Vec<&'static [u8]>,
}
impl Default for ReflectionConfig {
fn default() -> Self {
Self {
enabled: true,
file_descriptor_sets: Vec::new(),
}
}
}
impl ReflectionConfig {
pub fn new() -> Self {
Self::default()
}
pub fn enabled(mut self, enabled: bool) -> Self {
self.enabled = enabled;
self
}
pub fn add_file_descriptor_set(mut self, fds: &'static [u8]) -> Self {
self.file_descriptor_sets.push(fds);
self
}
}
#[cfg(feature = "reflection")]
pub struct ReflectionService {
config: ReflectionConfig,
}
#[cfg(feature = "reflection")]
impl ReflectionService {
pub fn new(file_descriptor_sets: &[&'static [u8]]) -> Self {
Self {
config: ReflectionConfig {
enabled: true,
file_descriptor_sets: file_descriptor_sets.to_vec(),
},
}
}
pub fn with_config(config: ReflectionConfig) -> Self {
Self { config }
}
pub fn build_server(
&self,
) -> Option<ServerReflectionServer<impl ServerReflection>> {
if !self.config.enabled || self.config.file_descriptor_sets.is_empty() {
return None;
}
let mut builder = tonic_reflection::server::Builder::configure();
for fds in &self.config.file_descriptor_sets {
builder = builder.register_encoded_file_descriptor_set(fds);
}
builder.build_v1().ok()
}
pub fn build_server_v1alpha(
&self,
) -> Option<tonic_reflection::server::v1alpha::ServerReflectionServer<impl tonic_reflection::server::v1alpha::ServerReflection>> {
if !self.config.enabled || self.config.file_descriptor_sets.is_empty() {
return None;
}
let mut builder = tonic_reflection::server::Builder::configure();
for fds in &self.config.file_descriptor_sets {
builder = builder.register_encoded_file_descriptor_set(fds);
}
builder.build_v1alpha().ok()
}
}
#[cfg(feature = "reflection")]
impl std::fmt::Debug for ReflectionService {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ReflectionService")
.field("enabled", &self.config.enabled)
.field(
"file_descriptor_count",
&self.config.file_descriptor_sets.len(),
)
.finish()
}
}
#[cfg(not(feature = "reflection"))]
pub struct ReflectionService {
_private: (),
}
#[cfg(not(feature = "reflection"))]
impl ReflectionService {
pub fn new(_file_descriptor_sets: &[&'static [u8]]) -> Self {
Self { _private: () }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn reflection_config_defaults() {
let config = ReflectionConfig::default();
assert!(config.enabled);
assert!(config.file_descriptor_sets.is_empty());
}
#[test]
fn reflection_config_builder() {
let config = ReflectionConfig::new()
.enabled(false);
assert!(!config.enabled);
}
#[cfg(feature = "reflection")]
#[test]
fn reflection_service_disabled_returns_none() {
let service = ReflectionService::with_config(
ReflectionConfig::new().enabled(false),
);
assert!(service.build_server().is_none());
}
#[cfg(feature = "reflection")]
#[test]
fn reflection_service_empty_fds_returns_none() {
let service = ReflectionService::new(&[]);
assert!(service.build_server().is_none());
}
}