#[cfg(test)]
mod test;
#[cfg(feature = "introspection")]
use crate::introspection::{ir, Introspectable, LexicalId, References};
use crate::tags::{self, PrimaryTag, Tag};
use crate::{
convert_value, Deserialize, DeserializeError, DeserializePrimary, Deserializer,
ProtocolVersion, Serialize, SerializeError, SerializePrimary, Serializer, Value,
ValueConversionError, ValueKind,
};
use bytes::BytesMut;
use std::borrow::{Borrow, Cow};
use std::cmp::Ordering;
use std::ops::Deref;
use std::{fmt, mem};
const MSG_HEADER_LEN: usize = 9;
#[derive(Clone, Eq)]
pub struct SerializedValue {
buf: BytesMut,
}
impl SerializedValue {
pub fn empty() -> Self {
Self {
buf: BytesMut::new(),
}
}
pub fn serialize_as<T: Tag>(value: impl Serialize<T>) -> Result<Self, SerializeError> {
let mut this = Self::new();
let serializer = Serializer::new(&mut this.buf, 0)?;
value.serialize(serializer)?;
Ok(this)
}
pub fn serialize(value: impl SerializePrimary) -> Result<Self, SerializeError> {
Self::serialize_as(value)
}
pub fn take(&mut self) -> Self {
mem::take(self)
}
pub fn convert(
&mut self,
from: Option<ProtocolVersion>,
to: ProtocolVersion,
) -> Result<(), ValueConversionError> {
convert_value::convert_mut(self, from, to)
}
pub(crate) fn new() -> Self {
Self {
buf: BytesMut::zeroed(MSG_HEADER_LEN),
}
}
pub(crate) fn from_bytes_mut(buf: BytesMut) -> Self {
debug_assert!(buf.len() > MSG_HEADER_LEN);
Self { buf }
}
pub(crate) fn into_bytes_mut(self) -> BytesMut {
self.buf
}
}
impl Default for SerializedValue {
fn default() -> Self {
Self::empty()
}
}
impl Deref for SerializedValue {
type Target = SerializedValueSlice;
fn deref(&self) -> &SerializedValueSlice {
SerializedValueSlice::new(&self.buf[MSG_HEADER_LEN..])
}
}
impl fmt::Debug for SerializedValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("SerializedValue")
.field("buf", &&*self.buf)
.finish()
}
}
impl AsRef<SerializedValueSlice> for SerializedValue {
fn as_ref(&self) -> &SerializedValueSlice {
self
}
}
impl Borrow<SerializedValueSlice> for SerializedValue {
fn borrow(&self) -> &SerializedValueSlice {
self
}
}
impl AsRef<[u8]> for SerializedValue {
fn as_ref(&self) -> &[u8] {
self
}
}
impl PartialEq for SerializedValue {
fn eq(&self, other: &Self) -> bool {
***self == ***other
}
}
impl PartialEq<SerializedValueSlice> for SerializedValue {
fn eq(&self, other: &SerializedValueSlice) -> bool {
***self == **other
}
}
impl PartialEq<[u8]> for SerializedValue {
fn eq(&self, other: &[u8]) -> bool {
***self == *other
}
}
impl PartialEq<SerializedValue> for [u8] {
fn eq(&self, other: &SerializedValue) -> bool {
*self == ***other
}
}
impl PartialOrd for SerializedValue {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for SerializedValue {
fn cmp(&self, other: &Self) -> Ordering {
(***self).cmp(&***other)
}
}
impl PartialOrd<SerializedValueSlice> for SerializedValue {
fn partial_cmp(&self, other: &SerializedValueSlice) -> Option<Ordering> {
(***self).partial_cmp(&**other)
}
}
impl PartialOrd<[u8]> for SerializedValue {
fn partial_cmp(&self, other: &[u8]) -> Option<Ordering> {
(***self).partial_cmp(other)
}
}
impl PartialOrd<SerializedValue> for [u8] {
fn partial_cmp(&self, other: &SerializedValue) -> Option<Ordering> {
(*self).partial_cmp(&***other)
}
}
impl PrimaryTag for SerializedValue {
type Tag = tags::Value;
}
impl Serialize<tags::Value> for SerializedValue {
fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
serializer.serialize(&self)
}
}
impl Serialize<tags::Value> for &SerializedValue {
fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
serializer.serialize(&**self)
}
}
impl Deserialize<tags::Value> for SerializedValue {
fn deserialize(deserializer: Deserializer) -> Result<Self, DeserializeError> {
deserializer
.split_off_serialized_value()
.map(SerializedValueSlice::to_owned)
}
}
#[cfg(feature = "introspection")]
impl Introspectable for SerializedValue {
fn layout() -> ir::LayoutIr {
ir::BuiltInTypeIr::Value.into()
}
fn lexical_id() -> LexicalId {
LexicalId::VALUE
}
fn add_references(_references: &mut References) {}
}
#[cfg(feature = "fuzzing")]
impl<'a> arbitrary::Arbitrary<'a> for SerializedValue {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let len = u.arbitrary_len::<u8>()?.max(1);
let bytes = u.bytes(len)?;
let mut buf = BytesMut::with_capacity(MSG_HEADER_LEN + len);
buf.resize(MSG_HEADER_LEN, 0);
buf.extend_from_slice(bytes);
Ok(Self::from_bytes_mut(buf))
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct SerializedValueSlice([u8]);
impl SerializedValueSlice {
pub(crate) fn new<T: AsRef<[u8]> + ?Sized>(buf: &T) -> &Self {
let self_ptr = buf.as_ref() as *const [u8] as *const Self;
unsafe { &*self_ptr }
}
pub fn kind(&self) -> Result<ValueKind, DeserializeError> {
let mut buf = &self.0;
let deserializer = Deserializer::new(&mut buf, 0)?;
deserializer.peek_value_kind()
}
pub fn deserialize_as<T: Tag, U: Deserialize<T>>(&self) -> Result<U, DeserializeError> {
let mut buf = &self.0;
let deserializer = Deserializer::new(&mut buf, 0)?;
let res = U::deserialize(deserializer);
if res.is_ok() && !buf.is_empty() {
return Err(DeserializeError::TrailingData);
}
res
}
pub fn deserialize<T: DeserializePrimary>(&self) -> Result<T, DeserializeError> {
self.deserialize_as()
}
pub fn deserialize_as_value(&self) -> Result<Value, DeserializeError> {
self.deserialize()
}
pub fn convert(
&self,
from: Option<ProtocolVersion>,
to: ProtocolVersion,
) -> Result<Cow<'_, Self>, ValueConversionError> {
convert_value::convert(self, from, to)
}
}
impl Deref for SerializedValueSlice {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.0
}
}
impl AsRef<[u8]> for SerializedValueSlice {
fn as_ref(&self) -> &[u8] {
self
}
}
impl ToOwned for SerializedValueSlice {
type Owned = SerializedValue;
fn to_owned(&self) -> SerializedValue {
let mut buf = BytesMut::with_capacity(MSG_HEADER_LEN + self.len());
buf.resize(MSG_HEADER_LEN, 0);
buf.extend_from_slice(self);
SerializedValue::from_bytes_mut(buf)
}
}
impl PartialEq<SerializedValue> for SerializedValueSlice {
fn eq(&self, other: &SerializedValue) -> bool {
**self == ***other
}
}
impl PartialEq<[u8]> for SerializedValueSlice {
fn eq(&self, other: &[u8]) -> bool {
**self == *other
}
}
impl PartialEq<SerializedValueSlice> for [u8] {
fn eq(&self, other: &SerializedValueSlice) -> bool {
*self == **other
}
}
impl PartialOrd<SerializedValue> for SerializedValueSlice {
fn partial_cmp(&self, other: &SerializedValue) -> Option<Ordering> {
(**self).partial_cmp(&***other)
}
}
impl PartialOrd<[u8]> for SerializedValueSlice {
fn partial_cmp(&self, other: &[u8]) -> Option<Ordering> {
(**self).partial_cmp(other)
}
}
impl PartialOrd<SerializedValueSlice> for [u8] {
fn partial_cmp(&self, other: &SerializedValueSlice) -> Option<Ordering> {
(*self).partial_cmp(&**other)
}
}
impl PrimaryTag for &SerializedValueSlice {
type Tag = tags::Value;
}
impl Serialize<tags::Value> for &SerializedValueSlice {
fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
serializer.copy_from_serialized_value(self)
}
}
#[cfg(feature = "introspection")]
impl Introspectable for SerializedValueSlice {
fn layout() -> ir::LayoutIr {
ir::BuiltInTypeIr::Value.into()
}
fn lexical_id() -> LexicalId {
LexicalId::VALUE
}
fn add_references(_references: &mut References) {}
}