use crate::*;
pub trait ProxiedOneof: From<Self::Proxy> + Into<Self::Proxy> {
type Proxy: OneofProxy<Oneof = Self> + From<Self> + Into<Self>;
#[inline]
fn into_proxy(self) -> Self::Proxy {
self.into()
}
}
pub trait OneofProxy: From<Self::Oneof> + Into<Self::Oneof> {
type Oneof: ProtoOneof + From<Self> + Into<Self>;
#[inline]
fn into_oneof(self) -> Self::Oneof {
self.into()
}
}
pub trait ProtoOneof {
#[doc(hidden)]
const TAGS: &[i32];
fn proto_schema() -> Oneof;
#[doc(hidden)]
fn __check_tags(
message_name: &str,
oneof_name: &str,
found_tags: &mut [i32],
) -> Result<(), String> {
use similar_asserts::SimpleDiff;
let expected = Self::TAGS;
found_tags.sort_unstable();
if expected != found_tags {
let exp_str = format!("{expected:#?}");
let found_str = format!("{found_tags:#?}");
let diff = SimpleDiff::from_str(&exp_str, &found_str, "expected", "found");
let error = format!(
"Found tags mismatch for oneof {oneof_name} in message {message_name}:\n{diff}"
);
return Err(error);
}
Ok(())
}
}
pub trait ValidatedOneof: ProtoValidation + Clone {
#[inline]
fn validate(&self) -> Result<(), ValidationErrors> {
if !Self::HAS_DEFAULT_VALIDATOR {
return Ok(());
}
let mut ctx = ValidationCtx::default();
let _ = self.validate_with_ctx(&mut ctx);
if ctx.violations.is_empty() {
Ok(())
} else {
Err(ctx.violations)
}
}
#[inline]
fn is_valid(&self) -> bool {
if Self::HAS_DEFAULT_VALIDATOR {
self.validate().is_ok()
} else {
true
}
}
#[inline]
fn validated(self) -> Result<Self, ValidationErrors> {
if !Self::HAS_DEFAULT_VALIDATOR {
return Ok(self);
}
match self.validate() {
Ok(()) => Ok(self),
Err(e) => Err(e),
}
}
fn validate_with_ctx(&self, ctx: &mut ValidationCtx) -> ValidationResult;
}
#[derive(Debug, Default, Clone, PartialEq, Builder)]
#[non_exhaustive]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Oneof {
pub name: FixedStr,
pub fields: Vec<Field>,
pub options: Vec<ProtoOption>,
pub validators: Vec<ValidatorSchema>,
}
impl Oneof {
#[must_use]
pub(crate) const fn has_options(&self) -> bool {
!self.options.is_empty() || !self.validators.is_empty()
}
pub fn options_with_validators(&self) -> impl Iterator<Item = &options::ProtoOption> {
self.options
.iter()
.chain(self.validators.iter().map(|v| &v.schema))
}
#[doc(hidden)]
#[must_use]
#[inline]
pub fn with_name(mut self, name: impl Into<FixedStr>) -> Self {
self.name = name.into();
self
}
#[doc(hidden)]
#[must_use]
#[inline]
pub fn with_validators(mut self, mut validators: Vec<ValidatorSchema>) -> Self {
self.validators.append(&mut validators);
self
}
#[doc(hidden)]
#[must_use]
#[inline]
pub fn with_options(mut self, mut options: Vec<ProtoOption>) -> Self {
self.options.append(&mut options);
self
}
}