313 lines
9.7 KiB
Rust
313 lines
9.7 KiB
Rust
use std::any::Any;
|
|
use std::any::TypeId;
|
|
use std::fmt;
|
|
use std::io::Read;
|
|
use std::io::Write;
|
|
|
|
#[cfg(feature = "bytes")]
|
|
use bytes::Bytes;
|
|
|
|
use crate::clear::Clear;
|
|
use crate::coded_input_stream::CodedInputStream;
|
|
use crate::coded_input_stream::WithCodedInputStream;
|
|
use crate::coded_output_stream::with_coded_output_stream_to_bytes;
|
|
use crate::coded_output_stream::CodedOutputStream;
|
|
use crate::coded_output_stream::WithCodedOutputStream;
|
|
use crate::error::ProtobufError;
|
|
use crate::error::ProtobufResult;
|
|
use crate::reflect::MessageDescriptor;
|
|
use crate::unknown::UnknownFields;
|
|
|
|
/// Trait implemented for all generated structs for protobuf messages.
|
|
///
|
|
/// Also, generated messages implement `Clone + Default + PartialEq`
|
|
pub trait Message: fmt::Debug + Clear + Any + Send + Sync {
|
|
/// Message descriptor for this message, used for reflection.
|
|
fn descriptor(&self) -> &'static MessageDescriptor;
|
|
|
|
/// True iff all required fields are initialized.
|
|
/// Always returns `true` for protobuf 3.
|
|
fn is_initialized(&self) -> bool;
|
|
|
|
/// Update this message object with fields read from given stream.
|
|
fn merge_from(&mut self, is: &mut CodedInputStream) -> ProtobufResult<()>;
|
|
|
|
/// Parse message from stream.
|
|
fn parse_from(is: &mut CodedInputStream) -> ProtobufResult<Self>
|
|
where
|
|
Self: Sized,
|
|
{
|
|
let mut r: Self = Message::new();
|
|
r.merge_from(is)?;
|
|
r.check_initialized()?;
|
|
Ok(r)
|
|
}
|
|
|
|
/// Write message to the stream.
|
|
///
|
|
/// Sizes of this messages and nested messages must be cached
|
|
/// by calling `compute_size` prior to this call.
|
|
fn write_to_with_cached_sizes(&self, os: &mut CodedOutputStream) -> ProtobufResult<()>;
|
|
|
|
/// Compute and cache size of this message and all nested messages
|
|
fn compute_size(&self) -> u32;
|
|
|
|
/// Get size previously computed by `compute_size`.
|
|
fn get_cached_size(&self) -> u32;
|
|
|
|
/// Write the message to the stream.
|
|
///
|
|
/// Results in error if message is not fully initialized.
|
|
fn write_to(&self, os: &mut CodedOutputStream) -> ProtobufResult<()> {
|
|
self.check_initialized()?;
|
|
|
|
// cache sizes
|
|
self.compute_size();
|
|
// TODO: reserve additional
|
|
self.write_to_with_cached_sizes(os)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Write the message to the stream prepending the message with message length
|
|
/// encoded as varint.
|
|
fn write_length_delimited_to(&self, os: &mut CodedOutputStream) -> ProtobufResult<()> {
|
|
let size = self.compute_size();
|
|
os.write_raw_varint32(size)?;
|
|
self.write_to_with_cached_sizes(os)?;
|
|
|
|
// TODO: assert we've written same number of bytes as computed
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Write the message to the vec, prepend the message with message length
|
|
/// encoded as varint.
|
|
fn write_length_delimited_to_vec(&self, vec: &mut Vec<u8>) -> ProtobufResult<()> {
|
|
let mut os = CodedOutputStream::vec(vec);
|
|
self.write_length_delimited_to(&mut os)?;
|
|
os.flush()?;
|
|
Ok(())
|
|
}
|
|
|
|
/// Update this message object with fields read from given stream.
|
|
fn merge_from_bytes(&mut self, bytes: &[u8]) -> ProtobufResult<()> {
|
|
let mut is = CodedInputStream::from_bytes(bytes);
|
|
self.merge_from(&mut is)
|
|
}
|
|
|
|
/// Parse message from reader.
|
|
/// Parse stops on EOF or when error encountered.
|
|
fn parse_from_reader(reader: &mut dyn Read) -> ProtobufResult<Self>
|
|
where
|
|
Self: Sized,
|
|
{
|
|
let mut is = CodedInputStream::new(reader);
|
|
let r = Message::parse_from(&mut is)?;
|
|
is.check_eof()?;
|
|
Ok(r)
|
|
}
|
|
|
|
/// Parse message from byte array.
|
|
fn parse_from_bytes(bytes: &[u8]) -> ProtobufResult<Self>
|
|
where
|
|
Self: Sized,
|
|
{
|
|
let mut is = CodedInputStream::from_bytes(bytes);
|
|
let r = Message::parse_from(&mut is)?;
|
|
is.check_eof()?;
|
|
Ok(r)
|
|
}
|
|
|
|
/// Parse message from `Bytes` object.
|
|
/// Resulting message may share references to the passed bytes object.
|
|
#[cfg(feature = "bytes")]
|
|
fn parse_from_carllerche_bytes(bytes: &Bytes) -> ProtobufResult<Self>
|
|
where
|
|
Self: Sized,
|
|
{
|
|
let mut is = CodedInputStream::from_carllerche_bytes(bytes);
|
|
let r = Self::parse_from(&mut is)?;
|
|
is.check_eof()?;
|
|
Ok(r)
|
|
}
|
|
|
|
/// Check if all required fields of this object are initialized.
|
|
fn check_initialized(&self) -> ProtobufResult<()> {
|
|
if !self.is_initialized() {
|
|
Err(ProtobufError::message_not_initialized(
|
|
self.descriptor().name(),
|
|
))
|
|
} else {
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
/// Write the message to the writer.
|
|
fn write_to_writer(&self, w: &mut dyn Write) -> ProtobufResult<()> {
|
|
w.with_coded_output_stream(|os| self.write_to(os))
|
|
}
|
|
|
|
/// Write the message to bytes vec.
|
|
fn write_to_vec(&self, v: &mut Vec<u8>) -> ProtobufResult<()> {
|
|
v.with_coded_output_stream(|os| self.write_to(os))
|
|
}
|
|
|
|
/// Write the message to bytes vec.
|
|
fn write_to_bytes(&self) -> ProtobufResult<Vec<u8>> {
|
|
self.check_initialized()?;
|
|
|
|
let size = self.compute_size() as usize;
|
|
let mut v = Vec::with_capacity(size);
|
|
// skip zerofill
|
|
unsafe {
|
|
v.set_len(size);
|
|
}
|
|
{
|
|
let mut os = CodedOutputStream::bytes(&mut v);
|
|
self.write_to_with_cached_sizes(&mut os)?;
|
|
os.check_eof();
|
|
}
|
|
Ok(v)
|
|
}
|
|
|
|
/// Write the message to the writer, prepend the message with message length
|
|
/// encoded as varint.
|
|
fn write_length_delimited_to_writer(&self, w: &mut dyn Write) -> ProtobufResult<()> {
|
|
w.with_coded_output_stream(|os| self.write_length_delimited_to(os))
|
|
}
|
|
|
|
/// Write the message to the bytes vec, prepend the message with message length
|
|
/// encoded as varint.
|
|
fn write_length_delimited_to_bytes(&self) -> ProtobufResult<Vec<u8>> {
|
|
with_coded_output_stream_to_bytes(|os| self.write_length_delimited_to(os))
|
|
}
|
|
|
|
/// Get a reference to unknown fields.
|
|
fn get_unknown_fields<'s>(&'s self) -> &'s UnknownFields;
|
|
/// Get a mutable reference to unknown fields.
|
|
fn mut_unknown_fields<'s>(&'s mut self) -> &'s mut UnknownFields;
|
|
|
|
/// Get type id for downcasting.
|
|
fn type_id(&self) -> TypeId {
|
|
TypeId::of::<Self>()
|
|
}
|
|
|
|
/// View self as `Any`.
|
|
fn as_any(&self) -> &dyn Any;
|
|
|
|
/// View self as mutable `Any`.
|
|
fn as_any_mut(&mut self) -> &mut dyn Any {
|
|
panic!()
|
|
}
|
|
|
|
/// Convert boxed self to boxed `Any`.
|
|
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
|
panic!()
|
|
}
|
|
|
|
// Rust does not allow implementation of trait for trait:
|
|
// impl<M : Message> fmt::Debug for M {
|
|
// ...
|
|
// }
|
|
|
|
/// Create an empty message object.
|
|
///
|
|
///
|
|
/// ```
|
|
/// # use protobuf::Message;
|
|
/// # fn foo<MyMessage: Message>() {
|
|
/// let m = MyMessage::new();
|
|
/// # }
|
|
/// ```
|
|
fn new() -> Self
|
|
where
|
|
Self: Sized;
|
|
|
|
/// Get message descriptor for message type.
|
|
///
|
|
/// ```
|
|
/// # use protobuf::Message;
|
|
/// # fn foo<MyMessage: Message>() {
|
|
/// let descriptor = MyMessage::descriptor_static();
|
|
/// assert_eq!("MyMessage", descriptor.name());
|
|
/// # }
|
|
/// ```
|
|
fn descriptor_static() -> &'static MessageDescriptor
|
|
where
|
|
Self: Sized,
|
|
{
|
|
panic!(
|
|
"descriptor_static is not implemented for message, \
|
|
LITE_RUNTIME must be used"
|
|
);
|
|
}
|
|
|
|
/// Return a pointer to default immutable message with static lifetime.
|
|
///
|
|
/// ```
|
|
/// # use protobuf::Message;
|
|
/// # fn foo<MyMessage: Message>() {
|
|
/// let m: &MyMessage = MyMessage::default_instance();
|
|
/// # }
|
|
/// ```
|
|
fn default_instance() -> &'static Self
|
|
where
|
|
Self: Sized;
|
|
}
|
|
|
|
pub fn message_down_cast<'a, M: Message + 'a>(m: &'a dyn Message) -> &'a M {
|
|
m.as_any().downcast_ref::<M>().unwrap()
|
|
}
|
|
|
|
/// Parse message from reader.
|
|
/// Parse stops on EOF or when error encountered.
|
|
#[deprecated(since = "2.19", note = "Use Message::parse_from_reader instead")]
|
|
pub fn parse_from_reader<M: Message>(reader: &mut dyn Read) -> ProtobufResult<M> {
|
|
M::parse_from_reader(reader)
|
|
}
|
|
|
|
/// Parse message from byte array.
|
|
#[deprecated(since = "2.19", note = "Use Message::parse_from_bytes instead")]
|
|
pub fn parse_from_bytes<M: Message>(bytes: &[u8]) -> ProtobufResult<M> {
|
|
M::parse_from_bytes(bytes)
|
|
}
|
|
|
|
/// Parse message from `Bytes` object.
|
|
/// Resulting message may share references to the passed bytes object.
|
|
#[cfg(feature = "bytes")]
|
|
#[deprecated(
|
|
since = "2.19",
|
|
note = "Use Message::parse_from_carllerche_bytes instead"
|
|
)]
|
|
pub fn parse_from_carllerche_bytes<M: Message>(bytes: &Bytes) -> ProtobufResult<M> {
|
|
M::parse_from_carllerche_bytes(bytes)
|
|
}
|
|
|
|
/// Parse length-delimited message from stream.
|
|
///
|
|
/// Read varint length first, and read messages of that length then.
|
|
///
|
|
/// This function is deprecated and will be removed in the next major release.
|
|
#[deprecated]
|
|
pub fn parse_length_delimited_from<M: Message>(is: &mut CodedInputStream) -> ProtobufResult<M> {
|
|
is.read_message::<M>()
|
|
}
|
|
|
|
/// Parse length-delimited message from `Read`.
|
|
///
|
|
/// This function is deprecated and will be removed in the next major release.
|
|
#[deprecated]
|
|
pub fn parse_length_delimited_from_reader<M: Message>(r: &mut dyn Read) -> ProtobufResult<M> {
|
|
// TODO: wrong: we may read length first, and then read exact number of bytes needed
|
|
r.with_coded_input_stream(|is| is.read_message::<M>())
|
|
}
|
|
|
|
/// Parse length-delimited message from bytes.
|
|
///
|
|
/// This function is deprecated and will be removed in the next major release.
|
|
#[deprecated]
|
|
pub fn parse_length_delimited_from_bytes<M: Message>(bytes: &[u8]) -> ProtobufResult<M> {
|
|
bytes.with_coded_input_stream(|is| is.read_message::<M>())
|
|
}
|