summaryrefslogtreecommitdiffstats
path: root/third_party/rust/bincode/src/config.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/bincode/src/config.rs')
-rw-r--r--third_party/rust/bincode/src/config.rs364
1 files changed, 364 insertions, 0 deletions
diff --git a/third_party/rust/bincode/src/config.rs b/third_party/rust/bincode/src/config.rs
new file mode 100644
index 0000000000..885dbc7f09
--- /dev/null
+++ b/third_party/rust/bincode/src/config.rs
@@ -0,0 +1,364 @@
+use super::internal::{Bounded, Infinite, SizeLimit};
+use byteorder::{BigEndian, ByteOrder, LittleEndian, NativeEndian};
+use de::read::BincodeRead;
+use error::Result;
+use serde;
+use std::io::{Read, Write};
+use std::marker::PhantomData;
+use {DeserializerAcceptor, SerializerAcceptor};
+
+use self::EndianOption::*;
+use self::LimitOption::*;
+
+struct DefaultOptions(Infinite);
+
+pub(crate) trait Options {
+ type Limit: SizeLimit + 'static;
+ type Endian: ByteOrder + 'static;
+
+ fn limit(&mut self) -> &mut Self::Limit;
+}
+
+pub(crate) trait OptionsExt: Options + Sized {
+ fn with_no_limit(self) -> WithOtherLimit<Self, Infinite> {
+ WithOtherLimit::new(self, Infinite)
+ }
+
+ fn with_limit(self, limit: u64) -> WithOtherLimit<Self, Bounded> {
+ WithOtherLimit::new(self, Bounded(limit))
+ }
+
+ fn with_little_endian(self) -> WithOtherEndian<Self, LittleEndian> {
+ WithOtherEndian::new(self)
+ }
+
+ fn with_big_endian(self) -> WithOtherEndian<Self, BigEndian> {
+ WithOtherEndian::new(self)
+ }
+
+ fn with_native_endian(self) -> WithOtherEndian<Self, NativeEndian> {
+ WithOtherEndian::new(self)
+ }
+}
+
+impl<'a, O: Options> Options for &'a mut O {
+ type Limit = O::Limit;
+ type Endian = O::Endian;
+
+ #[inline(always)]
+ fn limit(&mut self) -> &mut Self::Limit {
+ (*self).limit()
+ }
+}
+
+impl<T: Options> OptionsExt for T {}
+
+impl DefaultOptions {
+ fn new() -> DefaultOptions {
+ DefaultOptions(Infinite)
+ }
+}
+
+impl Options for DefaultOptions {
+ type Limit = Infinite;
+ type Endian = LittleEndian;
+
+ #[inline(always)]
+ fn limit(&mut self) -> &mut Infinite {
+ &mut self.0
+ }
+}
+
+#[derive(Clone, Copy)]
+enum LimitOption {
+ Unlimited,
+ Limited(u64),
+}
+
+#[derive(Clone, Copy)]
+enum EndianOption {
+ Big,
+ Little,
+ Native,
+}
+
+/// A configuration builder whose options Bincode will use
+/// while serializing and deserializing.
+///
+/// ### Options
+/// Endianness: The endianness with which multi-byte integers will be read/written. *default: little endian*
+/// Limit: The maximum number of bytes that will be read/written in a bincode serialize/deserialize. *default: unlimited*
+///
+/// ### Byte Limit Details
+/// The purpose of byte-limiting is to prevent Denial-Of-Service attacks whereby malicious attackers get bincode
+/// deserialization to crash your process by allocating too much memory or keeping a connection open for too long.
+///
+/// When a byte limit is set, bincode will return `Err` on any deserialization that goes over the limit, or any
+/// serialization that goes over the limit.
+#[derive(Clone)]
+pub struct Config {
+ limit: LimitOption,
+ endian: EndianOption,
+}
+
+pub(crate) struct WithOtherLimit<O: Options, L: SizeLimit> {
+ _options: O,
+ pub(crate) new_limit: L,
+}
+
+pub(crate) struct WithOtherEndian<O: Options, E: ByteOrder> {
+ options: O,
+ _endian: PhantomData<E>,
+}
+
+impl<O: Options, L: SizeLimit> WithOtherLimit<O, L> {
+ #[inline(always)]
+ pub(crate) fn new(options: O, limit: L) -> WithOtherLimit<O, L> {
+ WithOtherLimit {
+ _options: options,
+ new_limit: limit,
+ }
+ }
+}
+
+impl<O: Options, E: ByteOrder> WithOtherEndian<O, E> {
+ #[inline(always)]
+ pub(crate) fn new(options: O) -> WithOtherEndian<O, E> {
+ WithOtherEndian {
+ options: options,
+ _endian: PhantomData,
+ }
+ }
+}
+
+impl<O: Options, E: ByteOrder + 'static> Options for WithOtherEndian<O, E> {
+ type Limit = O::Limit;
+ type Endian = E;
+
+ #[inline(always)]
+ fn limit(&mut self) -> &mut O::Limit {
+ self.options.limit()
+ }
+}
+
+impl<O: Options, L: SizeLimit + 'static> Options for WithOtherLimit<O, L> {
+ type Limit = L;
+ type Endian = O::Endian;
+
+ fn limit(&mut self) -> &mut L {
+ &mut self.new_limit
+ }
+}
+
+macro_rules! config_map {
+ ($self:expr, $opts:ident => $call:expr) => {
+ match ($self.limit, $self.endian) {
+ (Unlimited, Little) => {
+ let $opts = DefaultOptions::new().with_no_limit().with_little_endian();
+ $call
+ }
+ (Unlimited, Big) => {
+ let $opts = DefaultOptions::new().with_no_limit().with_big_endian();
+ $call
+ }
+ (Unlimited, Native) => {
+ let $opts = DefaultOptions::new().with_no_limit().with_native_endian();
+ $call
+ }
+
+ (Limited(l), Little) => {
+ let $opts = DefaultOptions::new().with_limit(l).with_little_endian();
+ $call
+ }
+ (Limited(l), Big) => {
+ let $opts = DefaultOptions::new().with_limit(l).with_big_endian();
+ $call
+ }
+ (Limited(l), Native) => {
+ let $opts = DefaultOptions::new().with_limit(l).with_native_endian();
+ $call
+ }
+ }
+ };
+}
+
+impl Config {
+ #[inline(always)]
+ pub(crate) fn new() -> Config {
+ Config {
+ limit: LimitOption::Unlimited,
+ endian: EndianOption::Little,
+ }
+ }
+
+ /// Sets the byte limit to be unlimited.
+ /// This is the default.
+ #[inline(always)]
+ pub fn no_limit(&mut self) -> &mut Self {
+ self.limit = LimitOption::Unlimited;
+ self
+ }
+
+ /// Sets the byte limit to `limit`.
+ #[inline(always)]
+ pub fn limit(&mut self, limit: u64) -> &mut Self {
+ self.limit = LimitOption::Limited(limit);
+ self
+ }
+
+ /// Sets the endianness to little-endian
+ /// This is the default.
+ #[inline(always)]
+ pub fn little_endian(&mut self) -> &mut Self {
+ self.endian = EndianOption::Little;
+ self
+ }
+
+ /// Sets the endianness to big-endian
+ #[inline(always)]
+ pub fn big_endian(&mut self) -> &mut Self {
+ self.endian = EndianOption::Big;
+ self
+ }
+
+ /// Sets the endianness to the the machine-native endianness
+ #[inline(always)]
+ pub fn native_endian(&mut self) -> &mut Self {
+ self.endian = EndianOption::Native;
+ self
+ }
+
+ /// Serializes a serializable object into a `Vec` of bytes using this configuration
+ #[inline(always)]
+ pub fn serialize<T: ?Sized + serde::Serialize>(&self, t: &T) -> Result<Vec<u8>> {
+ config_map!(self, opts => ::internal::serialize(t, opts))
+ }
+
+ /// Returns the size that an object would be if serialized using Bincode with this configuration
+ #[inline(always)]
+ pub fn serialized_size<T: ?Sized + serde::Serialize>(&self, t: &T) -> Result<u64> {
+ config_map!(self, opts => ::internal::serialized_size(t, opts))
+ }
+
+ /// Serializes an object directly into a `Writer` using this configuration
+ ///
+ /// If the serialization would take more bytes than allowed by the size limit, an error
+ /// is returned and *no bytes* will be written into the `Writer`
+ #[inline(always)]
+ pub fn serialize_into<W: Write, T: ?Sized + serde::Serialize>(
+ &self,
+ w: W,
+ t: &T,
+ ) -> Result<()> {
+ config_map!(self, opts => ::internal::serialize_into(w, t, opts))
+ }
+
+ /// Deserializes a slice of bytes into an instance of `T` using this configuration
+ #[inline(always)]
+ pub fn deserialize<'a, T: serde::Deserialize<'a>>(&self, bytes: &'a [u8]) -> Result<T> {
+ config_map!(self, opts => ::internal::deserialize(bytes, opts))
+ }
+
+ /// TODO: document
+ #[doc(hidden)]
+ #[inline(always)]
+ pub fn deserialize_in_place<'a, R, T>(&self, reader: R, place: &mut T) -> Result<()>
+ where
+ R: BincodeRead<'a>,
+ T: serde::de::Deserialize<'a>,
+ {
+ config_map!(self, opts => ::internal::deserialize_in_place(reader, opts, place))
+ }
+
+ /// Deserializes a slice of bytes with state `seed` using this configuration.
+ #[inline(always)]
+ pub fn deserialize_seed<'a, T: serde::de::DeserializeSeed<'a>>(
+ &self,
+ seed: T,
+ bytes: &'a [u8],
+ ) -> Result<T::Value> {
+ config_map!(self, opts => ::internal::deserialize_seed(seed, bytes, opts))
+ }
+
+ /// Deserializes an object directly from a `Read`er using this configuration
+ ///
+ /// If this returns an `Error`, `reader` may be in an invalid state.
+ #[inline(always)]
+ pub fn deserialize_from<R: Read, T: serde::de::DeserializeOwned>(
+ &self,
+ reader: R,
+ ) -> Result<T> {
+ config_map!(self, opts => ::internal::deserialize_from(reader, opts))
+ }
+
+ /// Deserializes an object directly from a `Read`er with state `seed` using this configuration
+ ///
+ /// If this returns an `Error`, `reader` may be in an invalid state.
+ #[inline(always)]
+ pub fn deserialize_from_seed<'a, R: Read, T: serde::de::DeserializeSeed<'a>>(
+ &self,
+ seed: T,
+ reader: R,
+ ) -> Result<T::Value> {
+ config_map!(self, opts => ::internal::deserialize_from_seed(seed, reader, opts))
+ }
+
+ /// Deserializes an object from a custom `BincodeRead`er using the default configuration.
+ /// It is highly recommended to use `deserialize_from` unless you need to implement
+ /// `BincodeRead` for performance reasons.
+ ///
+ /// If this returns an `Error`, `reader` may be in an invalid state.
+ #[inline(always)]
+ pub fn deserialize_from_custom<'a, R: BincodeRead<'a>, T: serde::de::DeserializeOwned>(
+ &self,
+ reader: R,
+ ) -> Result<T> {
+ config_map!(self, opts => ::internal::deserialize_from_custom(reader, opts))
+ }
+
+ /// Deserializes an object from a custom `BincodeRead`er with state `seed` using the default
+ /// configuration. It is highly recommended to use `deserialize_from` unless you need to
+ /// implement `BincodeRead` for performance reasons.
+ ///
+ /// If this returns an `Error`, `reader` may be in an invalid state.
+ #[inline(always)]
+ pub fn deserialize_from_custom_seed<
+ 'a,
+ R: BincodeRead<'a>,
+ T: serde::de::DeserializeSeed<'a>,
+ >(
+ &self,
+ seed: T,
+ reader: R,
+ ) -> Result<T::Value> {
+ config_map!(self, opts => ::internal::deserialize_from_custom_seed(seed, reader, opts))
+ }
+
+ /// Executes the acceptor with a serde::Deserializer instance.
+ /// NOT A PART OF THE STABLE PUBLIC API
+ #[doc(hidden)]
+ pub fn with_deserializer<'a, A, R>(&self, reader: R, acceptor: A) -> A::Output
+ where
+ A: DeserializerAcceptor<'a>,
+ R: BincodeRead<'a>,
+ {
+ config_map!(self, opts => {
+ let mut deserializer = ::de::Deserializer::new(reader, opts);
+ acceptor.accept(&mut deserializer)
+ })
+ }
+
+ /// Executes the acceptor with a serde::Serializer instance.
+ /// NOT A PART OF THE STABLE PUBLIC API
+ #[doc(hidden)]
+ pub fn with_serializer<A, W>(&self, writer: W, acceptor: A) -> A::Output
+ where
+ A: SerializerAcceptor,
+ W: Write,
+ {
+ config_map!(self, opts => {
+ let mut serializer = ::ser::Serializer::new(writer, opts);
+ acceptor.accept(&mut serializer)
+ })
+ }
+}