use std::any::Any;
use std::any::TypeId;
use std::fmt;
use std::io::Write;
use crate::coded_output_stream::with::WithCodedOutputStream;
use crate::error::ProtobufError;
use crate::reflect::MessageDescriptor;
use crate::reflect::ReflectEqMode;
use crate::wire_format::check_message_size;
use crate::CodedInputStream;
use crate::CodedOutputStream;
use crate::MessageFull;
use crate::SpecialFields;
use crate::UnknownFields;
pub trait MessageDyn: Any + fmt::Debug + fmt::Display + Send + Sync + 'static {
fn descriptor_dyn(&self) -> MessageDescriptor;
fn merge_from_dyn(&mut self, is: &mut CodedInputStream) -> crate::Result<()>;
fn write_to_with_cached_sizes_dyn(&self, os: &mut CodedOutputStream) -> crate::Result<()>;
fn compute_size_dyn(&self) -> u64;
fn is_initialized_dyn(&self) -> bool;
fn special_fields_dyn(&self) -> &SpecialFields;
fn mut_special_fields_dyn(&mut self) -> &mut SpecialFields;
}
impl<M: MessageFull> MessageDyn for M {
fn descriptor_dyn(&self) -> MessageDescriptor {
M::descriptor()
}
fn merge_from_dyn(&mut self, is: &mut CodedInputStream) -> crate::Result<()> {
self.merge_from(is)
}
fn write_to_with_cached_sizes_dyn(&self, os: &mut CodedOutputStream) -> crate::Result<()> {
self.write_to_with_cached_sizes(os)
}
fn compute_size_dyn(&self) -> u64 {
self.compute_size()
}
fn is_initialized_dyn(&self) -> bool {
self.is_initialized()
}
fn special_fields_dyn(&self) -> &SpecialFields {
self.special_fields()
}
fn mut_special_fields_dyn(&mut self) -> &mut SpecialFields {
self.mut_special_fields()
}
}
impl dyn MessageDyn {
pub fn check_initialized_dyn(&self) -> crate::Result<()> {
if !self.is_initialized_dyn() {
Err(
ProtobufError::MessageNotInitialized(self.descriptor_dyn().name().to_owned())
.into(),
)
} else {
Ok(())
}
}
pub fn write_to_writer_dyn(&self, w: &mut dyn Write) -> crate::Result<()> {
w.with_coded_output_stream(|os| self.write_to_dyn(os))
}
pub fn write_to_vec_dyn(&self, v: &mut Vec<u8>) -> crate::Result<()> {
v.with_coded_output_stream(|os| self.write_to_dyn(os))
}
pub fn write_to_dyn(&self, os: &mut CodedOutputStream) -> crate::Result<()> {
self.check_initialized_dyn()?;
let size = self.compute_size_dyn();
let size = check_message_size(size)?;
os.reserve_additional(size, self.descriptor_dyn().name())?;
self.write_to_with_cached_sizes_dyn(os)?;
Ok(())
}
pub fn write_length_delimited_to_vec_dyn(&self, vec: &mut Vec<u8>) -> crate::Result<()> {
let mut os = CodedOutputStream::vec(vec);
self.write_length_delimited_to_dyn(&mut os)?;
os.flush()?;
Ok(())
}
pub fn merge_from_bytes_dyn(&mut self, bytes: &[u8]) -> crate::Result<()> {
let mut is = CodedInputStream::from_bytes(bytes);
self.merge_from_dyn(&mut is)
}
pub fn write_to_bytes_dyn(&self) -> crate::Result<Vec<u8>> {
self.check_initialized_dyn()?;
let size = self.compute_size_dyn();
let size = check_message_size(size)?;
let mut v = Vec::new();
let mut os = CodedOutputStream::vec(&mut v);
os.reserve_additional(size, self.descriptor_dyn().name())?;
self.write_to_with_cached_sizes_dyn(&mut os)?;
os.flush()?;
drop(os);
Ok(v)
}
pub fn write_length_delimited_to_dyn(&self, os: &mut CodedOutputStream) -> crate::Result<()> {
let size = self.compute_size_dyn();
let size = check_message_size(size)?;
os.reserve_additional_for_length_delimited(size, self.descriptor_dyn().name())?;
os.write_raw_varint32(size)?;
let pos = os.total_bytes_written();
self.write_to_with_cached_sizes_dyn(os)?;
assert_eq!(os.total_bytes_written() - pos, size as u64);
Ok(())
}
pub fn write_length_delimited_to_writer_dyn(&self, w: &mut dyn Write) -> crate::Result<()> {
w.with_coded_output_stream(|os| self.write_length_delimited_to_dyn(os))
}
pub fn write_length_delimited_to_bytes_dyn(&self) -> crate::Result<Vec<u8>> {
let mut v = Vec::new();
v.with_coded_output_stream(|os| self.write_length_delimited_to_dyn(os))?;
Ok(v)
}
pub fn unknown_fields_dyn(&self) -> &UnknownFields {
self.special_fields_dyn().unknown_fields()
}
pub fn mut_unknown_fields_dyn(&mut self) -> &mut UnknownFields {
self.mut_special_fields_dyn().mut_unknown_fields()
}
pub fn downcast_box<T: Any>(
self: Box<dyn MessageDyn>,
) -> std::result::Result<Box<T>, Box<dyn MessageDyn>> {
if Any::type_id(&*self) == TypeId::of::<T>() {
unsafe {
let raw: *mut dyn MessageDyn = Box::into_raw(self);
Ok(Box::from_raw(raw as *mut T))
}
} else {
Err(self)
}
}
pub fn downcast_ref<'a, M: MessageFull + 'a>(&'a self) -> Option<&'a M> {
if Any::type_id(&*self) == TypeId::of::<M>() {
unsafe { Some(&*(self as *const dyn MessageDyn as *const M)) }
} else {
None
}
}
pub fn downcast_mut<'a, M: MessageFull + 'a>(&'a mut self) -> Option<&'a mut M> {
if Any::type_id(&*self) == TypeId::of::<M>() {
unsafe { Some(&mut *(self as *mut dyn MessageDyn as *mut M)) }
} else {
None
}
}
pub fn clone_box(&self) -> Box<dyn MessageDyn> {
self.descriptor_dyn().clone_message(self)
}
pub fn reflect_eq_dyn(&self, other: &dyn MessageDyn, mode: &ReflectEqMode) -> bool {
MessageDescriptor::reflect_eq_maybe_unrelated(self, other, mode)
}
}
impl Clone for Box<dyn MessageDyn> {
fn clone(&self) -> Self {
(*self).clone_box()
}
}
impl PartialEq for Box<dyn MessageDyn> {
fn eq(&self, other: &Box<dyn MessageDyn>) -> bool {
MessageDescriptor::reflect_eq_maybe_unrelated(&**self, &**other, &ReflectEqMode::default())
}
}
#[cfg(test)]
mod test {
use crate::descriptor::FileDescriptorProto;
use crate::MessageDyn;
#[test]
fn downcast_ref() {
let m = FileDescriptorProto::new();
let d = &m as &dyn MessageDyn;
let c: &FileDescriptorProto = d.downcast_ref().unwrap();
assert_eq!(
c as *const FileDescriptorProto,
&m as *const FileDescriptorProto
);
}
#[test]
fn downcast_mut() {
let mut m = FileDescriptorProto::new();
let d = &mut m as &mut dyn MessageDyn;
let c: &mut FileDescriptorProto = d.downcast_mut().unwrap();
assert_eq!(
c as *const FileDescriptorProto,
&m as *const FileDescriptorProto
);
}
#[test]
fn downcast_box() {
let m = FileDescriptorProto::new();
let d: Box<dyn MessageDyn> = Box::new(m);
let mut _c: Box<FileDescriptorProto> = d.downcast_box().unwrap();
}
}