<commit_before>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use serde::{ser, Serialize};

use error::Error;
use token::Token;

/// A `Serializer` that ensures that a value serializes to a given list of tokens.
#[derive(Debug)]
pub struct Serializer<'a> {
    tokens: &'a [Token],
}

impl<'a> Serializer<'a> {
    /// Creates the serializer.
    pub fn new(tokens: &'a [Token]) -> Self {
        Serializer { tokens: tokens }
    }

    /// Pulls the next token off of the serializer, ignoring it.
    fn next_token(&mut self) -> Option<Token> {
        if let Some((&first, rest)) = self.tokens.split_first() {
            self.tokens = rest;
            Some(first)
        } else {
            None
        }
    }

    pub fn remaining(&self) -> usize {
        self.tokens.len()
    }
}

macro_rules! assert_next_token {
    ($ser:expr, $expected:ident) => {
        assert_next_token!($ser, stringify!($expected), Token::$expected, true);
    };
    ($ser:expr, $expected:ident($v:expr)) => {
        assert_next_token!(
            $ser,
            format_args!("{}({:?})", stringify!($expected), $v),
            Token::$expected(v),
            v == $v
        );
    };
    ($ser:expr, $expected:ident { $($k:ident),* }) => {
        let compare = ($($k,)*);
        let field_format = || {
            use std::fmt::Write;
            let mut buffer = String::new();
            $(
                write!(&mut buffer, "{}: {:?}, ", stringify!($k), $k).unwrap();
            )*
            buffer
        };
        assert_next_token!(
            $ser,
            format_args!("{} {{ {}}}", stringify!($expected), field_format()),
            Token::$expected { $($k),* },
            ($($k,)*) == compare
        );
    };
    ($ser:expr, $expected:expr, $pat:pat, $guard:expr) => {
        match $ser.next_token() {
            Some($pat) if $guard => {}
            Some(other) => {
                panic!("expected Token::{} but serialized as {}",
                       $expected, other);
            }
            None => {
                panic!("expected Token::{} after end of serialized tokens",
                       $expected);
            }
        }
    };
}

impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    type SerializeSeq = Self;
    type SerializeTuple = Self;
    type SerializeTupleStruct = Self;
    type SerializeTupleVariant = Variant<'s, 'a>;
    type SerializeMap = Self;
    type SerializeStruct = Self;
    type SerializeStructVariant = Variant<'s, 'a>;

    fn serialize_bool(self, v: bool) -> Result<(), Error> {
        assert_next_token!(self, Bool(v));
        Ok(())
    }

    fn serialize_i8(self, v: i8) -> Result<(), Error> {
        assert_next_token!(self, I8(v));
        Ok(())
    }

    fn serialize_i16(self, v: i16) -> Result<(), Error> {
        assert_next_token!(self, I16(v));
        Ok(())
    }

    fn serialize_i32(self, v: i32) -> Result<(), Error> {
        assert_next_token!(self, I32(v));
        Ok(())
    }

    fn serialize_i64(self, v: i64) -> Result<(), Error> {
        assert_next_token!(self, I64(v));
        Ok(())
    }

    fn serialize_u8(self, v: u8) -> Result<(), Error> {
        assert_next_token!(self, U8(v));
        Ok(())
    }

    fn serialize_u16(self, v: u16) -> Result<(), Error> {
        assert_next_token!(self, U16(v));
        Ok(())
    }

    fn serialize_u32(self, v: u32) -> Result<(), Error> {
        assert_next_token!(self, U32(v));
        Ok(())
    }

    fn serialize_u64(self, v: u64) -> Result<(), Error> {
        assert_next_token!(self, U64(v));
        Ok(())
    }

    fn serialize_f32(self, v: f32) -> Result<(), Error> {
        assert_next_token!(self, F32(v));
        Ok(())
    }

    fn serialize_f64(self, v: f64) -> Result<(), Error> {
        assert_next_token!(self, F64(v));
        Ok(())
    }

    fn serialize_char(self, v: char) -> Result<(), Error> {
        assert_next_token!(self, Char(v));
        Ok(())
    }

    fn serialize_str(self, v: &str) -> Result<(), Error> {
        match self.tokens.first() {
            Some(&Token::BorrowedStr(_)) => assert_next_token!(self, BorrowedStr(v)),
            Some(&Token::String(_)) => assert_next_token!(self, String(v)),
            _ => assert_next_token!(self, Str(v)),
        }
        Ok(())
    }

    fn serialize_bytes(self, v: &[u8]) -> Result<(), Self::Error> {
        match self.tokens.first() {
            Some(&Token::BorrowedBytes(_)) => assert_next_token!(self, BorrowedBytes(v)),
            Some(&Token::ByteBuf(_)) => assert_next_token!(self, ByteBuf(v)),
            _ => assert_next_token!(self, Bytes(v)),
        }
        Ok(())
    }

    fn serialize_unit(self) -> Result<(), Error> {
        assert_next_token!(self, Unit);
        Ok(())
    }

    fn serialize_unit_struct(self, name: &'static str) -> Result<(), Error> {
        assert_next_token!(self, UnitStruct { name });
        Ok(())
    }

    fn serialize_unit_variant(
        self,
        name: &'static str,
        _variant_index: u32,
        variant: &'static str,
    ) -> Result<(), Error> {
        if self.tokens.first() == Some(&Token::Enum { name: name }) {
            self.next_token();
            assert_next_token!(self, Str(variant));
            assert_next_token!(self, Unit);
        } else {
            assert_next_token!(self, UnitVariant { name, variant });
        }
        Ok(())
    }

    fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        assert_next_token!(self, NewtypeStruct { name });
        value.serialize(self)
    }

    fn serialize_newtype_variant<T: ?Sized>(
        self,
        name: &'static str,
        _variant_index: u32,
        variant: &'static str,
        value: &T,
    ) -> Result<(), Error>
    where
        T: Serialize,
    {
        if self.tokens.first() == Some(&Token::Enum { name: name }) {
            self.next_token();
            assert_next_token!(self, Str(variant));
        } else {
            assert_next_token!(self, NewtypeVariant { name, variant });
        }
        value.serialize(self)
    }

    fn serialize_none(self) -> Result<(), Error> {
        assert_next_token!(self, None);
        Ok(())
    }

    fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        assert_next_token!(self, Some);
        value.serialize(self)
    }

    fn serialize_seq(self, len: Option<usize>) -> Result<Self, Error> {
        assert_next_token!(self, Seq { len });
        Ok(self)
    }

    fn serialize_tuple(self, len: usize) -> Result<Self, Error> {
        assert_next_token!(self, Tuple { len });
        Ok(self)
    }

    fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
        assert_next_token!(self, TupleStruct { name, len });
        Ok(self)
    }

    fn serialize_tuple_variant(
        self,
        name: &'static str,
        _variant_index: u32,
        variant: &'static str,
        len: usize,
    ) -> Result<Self::SerializeTupleVariant, Error> {
        if self.tokens.first() == Some(&Token::Enum { name: name }) {
            self.next_token();
            assert_next_token!(self, Str(variant));
            let len = Some(len);
            assert_next_token!(self, Seq { len });
            Ok(Variant {
                ser: self,
                end: Token::SeqEnd,
            })
        } else {
            assert_next_token!(self, TupleVariant { name, variant, len });
            Ok(Variant {
                ser: self,
                end: Token::TupleVariantEnd,
            })
        }
    }

    fn serialize_map(self, len: Option<usize>) -> Result<Self, Error> {
        assert_next_token!(self, Map { len });
        Ok(self)
    }

    fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
        assert_next_token!(self, Struct { name, len });
        Ok(self)
    }

    fn serialize_struct_variant(
        self,
        name: &'static str,
        _variant_index: u32,
        variant: &'static str,
        len: usize,
    ) -> Result<Self::SerializeStructVariant, Error> {
        if self.tokens.first() == Some(&Token::Enum { name: name }) {
            self.next_token();
            assert_next_token!(self, Str(variant));
            let len = Some(len);
            assert_next_token!(self, Map { len });
            Ok(Variant {
                ser: self,
                end: Token::MapEnd,
            })
        } else {
            assert_next_token!(self, StructVariant { name, variant, len });
            Ok(Variant {
                ser: self,
                end: Token::StructVariantEnd,
            })
        }
    }

    fn is_human_readable(&self) -> bool {
        panic!(
            "Types which have different human-readable and compact representations \
             must explicitly mark their test cases with `serde_test::Configure`"
        );
    }
}

pub struct Variant<'s, 'a: 's> {
    ser: &'s mut Serializer<'a>,
    end: Token,
}

impl<'s, 'a> ser::SerializeSeq for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_next_token!(self, SeqEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeTuple for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_next_token!(self, TupleEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeTupleStruct for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_next_token!(self, TupleStructEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeTupleVariant for Variant<'s, 'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        value.serialize(&mut *self.ser)
    }

    fn end(self) -> Result<(), Error> {
        match self.end {
            Token::TupleVariantEnd => assert_next_token!(self.ser, TupleVariantEnd),
            Token::SeqEnd => assert_next_token!(self.ser, SeqEnd),
            _ => unreachable!(),
        }
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeMap for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
    where
        T: Serialize,
    {
        key.serialize(&mut **self)
    }

    fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
    where
        T: Serialize,
    {
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Self::Error> {
        assert_next_token!(self, MapEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(
        &mut self,
        key: &'static str,
        value: &T,
    ) -> Result<(), Self::Error>
    where
        T: Serialize,
    {
        try!(key.serialize(&mut **self));
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Self::Error> {
        assert_next_token!(self, StructEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeStructVariant for Variant<'s, 'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(
        &mut self,
        key: &'static str,
        value: &T,
    ) -> Result<(), Self::Error>
    where
        T: Serialize,
    {
        try!(key.serialize(&mut *self.ser));
        value.serialize(&mut *self.ser)
    }

    fn end(self) -> Result<(), Self::Error> {
        match self.end {
            Token::StructVariantEnd => assert_next_token!(self.ser, StructVariantEnd),
            Token::MapEnd => assert_next_token!(self.ser, MapEnd),
            _ => unreachable!(),
        }
        Ok(())
    }
}
<commit_msg>Fix clippy lint about literal in format string<commit_after>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use serde::{ser, Serialize};

use error::Error;
use token::Token;

/// A `Serializer` that ensures that a value serializes to a given list of tokens.
#[derive(Debug)]
pub struct Serializer<'a> {
    tokens: &'a [Token],
}

impl<'a> Serializer<'a> {
    /// Creates the serializer.
    pub fn new(tokens: &'a [Token]) -> Self {
        Serializer { tokens: tokens }
    }

    /// Pulls the next token off of the serializer, ignoring it.
    fn next_token(&mut self) -> Option<Token> {
        if let Some((&first, rest)) = self.tokens.split_first() {
            self.tokens = rest;
            Some(first)
        } else {
            None
        }
    }

    pub fn remaining(&self) -> usize {
        self.tokens.len()
    }
}

macro_rules! assert_next_token {
    ($ser:expr, $expected:ident) => {
        assert_next_token!($ser, stringify!($expected), Token::$expected, true);
    };
    ($ser:expr, $expected:ident($v:expr)) => {
        assert_next_token!(
            $ser,
            format_args!(concat!(stringify!($expected), "({:?})"), $v),
            Token::$expected(v),
            v == $v
        );
    };
    ($ser:expr, $expected:ident { $($k:ident),* }) => {
        let compare = ($($k,)*);
        let field_format = || {
            use std::fmt::Write;
            let mut buffer = String::new();
            $(
                write!(&mut buffer, concat!(stringify!($k), ": {:?}, "), $k).unwrap();
            )*
            buffer
        };
        assert_next_token!(
            $ser,
            format_args!(concat!(stringify!($expected), " {{ {}}}"), field_format()),
            Token::$expected { $($k),* },
            ($($k,)*) == compare
        );
    };
    ($ser:expr, $expected:expr, $pat:pat, $guard:expr) => {
        match $ser.next_token() {
            Some($pat) if $guard => {}
            Some(other) => {
                panic!("expected Token::{} but serialized as {}",
                       $expected, other);
            }
            None => {
                panic!("expected Token::{} after end of serialized tokens",
                       $expected);
            }
        }
    };
}

impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    type SerializeSeq = Self;
    type SerializeTuple = Self;
    type SerializeTupleStruct = Self;
    type SerializeTupleVariant = Variant<'s, 'a>;
    type SerializeMap = Self;
    type SerializeStruct = Self;
    type SerializeStructVariant = Variant<'s, 'a>;

    fn serialize_bool(self, v: bool) -> Result<(), Error> {
        assert_next_token!(self, Bool(v));
        Ok(())
    }

    fn serialize_i8(self, v: i8) -> Result<(), Error> {
        assert_next_token!(self, I8(v));
        Ok(())
    }

    fn serialize_i16(self, v: i16) -> Result<(), Error> {
        assert_next_token!(self, I16(v));
        Ok(())
    }

    fn serialize_i32(self, v: i32) -> Result<(), Error> {
        assert_next_token!(self, I32(v));
        Ok(())
    }

    fn serialize_i64(self, v: i64) -> Result<(), Error> {
        assert_next_token!(self, I64(v));
        Ok(())
    }

    fn serialize_u8(self, v: u8) -> Result<(), Error> {
        assert_next_token!(self, U8(v));
        Ok(())
    }

    fn serialize_u16(self, v: u16) -> Result<(), Error> {
        assert_next_token!(self, U16(v));
        Ok(())
    }

    fn serialize_u32(self, v: u32) -> Result<(), Error> {
        assert_next_token!(self, U32(v));
        Ok(())
    }

    fn serialize_u64(self, v: u64) -> Result<(), Error> {
        assert_next_token!(self, U64(v));
        Ok(())
    }

    fn serialize_f32(self, v: f32) -> Result<(), Error> {
        assert_next_token!(self, F32(v));
        Ok(())
    }

    fn serialize_f64(self, v: f64) -> Result<(), Error> {
        assert_next_token!(self, F64(v));
        Ok(())
    }

    fn serialize_char(self, v: char) -> Result<(), Error> {
        assert_next_token!(self, Char(v));
        Ok(())
    }

    fn serialize_str(self, v: &str) -> Result<(), Error> {
        match self.tokens.first() {
            Some(&Token::BorrowedStr(_)) => assert_next_token!(self, BorrowedStr(v)),
            Some(&Token::String(_)) => assert_next_token!(self, String(v)),
            _ => assert_next_token!(self, Str(v)),
        }
        Ok(())
    }

    fn serialize_bytes(self, v: &[u8]) -> Result<(), Self::Error> {
        match self.tokens.first() {
            Some(&Token::BorrowedBytes(_)) => assert_next_token!(self, BorrowedBytes(v)),
            Some(&Token::ByteBuf(_)) => assert_next_token!(self, ByteBuf(v)),
            _ => assert_next_token!(self, Bytes(v)),
        }
        Ok(())
    }

    fn serialize_unit(self) -> Result<(), Error> {
        assert_next_token!(self, Unit);
        Ok(())
    }

    fn serialize_unit_struct(self, name: &'static str) -> Result<(), Error> {
        assert_next_token!(self, UnitStruct { name });
        Ok(())
    }

    fn serialize_unit_variant(
        self,
        name: &'static str,
        _variant_index: u32,
        variant: &'static str,
    ) -> Result<(), Error> {
        if self.tokens.first() == Some(&Token::Enum { name: name }) {
            self.next_token();
            assert_next_token!(self, Str(variant));
            assert_next_token!(self, Unit);
        } else {
            assert_next_token!(self, UnitVariant { name, variant });
        }
        Ok(())
    }

    fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        assert_next_token!(self, NewtypeStruct { name });
        value.serialize(self)
    }

    fn serialize_newtype_variant<T: ?Sized>(
        self,
        name: &'static str,
        _variant_index: u32,
        variant: &'static str,
        value: &T,
    ) -> Result<(), Error>
    where
        T: Serialize,
    {
        if self.tokens.first() == Some(&Token::Enum { name: name }) {
            self.next_token();
            assert_next_token!(self, Str(variant));
        } else {
            assert_next_token!(self, NewtypeVariant { name, variant });
        }
        value.serialize(self)
    }

    fn serialize_none(self) -> Result<(), Error> {
        assert_next_token!(self, None);
        Ok(())
    }

    fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        assert_next_token!(self, Some);
        value.serialize(self)
    }

    fn serialize_seq(self, len: Option<usize>) -> Result<Self, Error> {
        assert_next_token!(self, Seq { len });
        Ok(self)
    }

    fn serialize_tuple(self, len: usize) -> Result<Self, Error> {
        assert_next_token!(self, Tuple { len });
        Ok(self)
    }

    fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
        assert_next_token!(self, TupleStruct { name, len });
        Ok(self)
    }

    fn serialize_tuple_variant(
        self,
        name: &'static str,
        _variant_index: u32,
        variant: &'static str,
        len: usize,
    ) -> Result<Self::SerializeTupleVariant, Error> {
        if self.tokens.first() == Some(&Token::Enum { name: name }) {
            self.next_token();
            assert_next_token!(self, Str(variant));
            let len = Some(len);
            assert_next_token!(self, Seq { len });
            Ok(Variant {
                ser: self,
                end: Token::SeqEnd,
            })
        } else {
            assert_next_token!(self, TupleVariant { name, variant, len });
            Ok(Variant {
                ser: self,
                end: Token::TupleVariantEnd,
            })
        }
    }

    fn serialize_map(self, len: Option<usize>) -> Result<Self, Error> {
        assert_next_token!(self, Map { len });
        Ok(self)
    }

    fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
        assert_next_token!(self, Struct { name, len });
        Ok(self)
    }

    fn serialize_struct_variant(
        self,
        name: &'static str,
        _variant_index: u32,
        variant: &'static str,
        len: usize,
    ) -> Result<Self::SerializeStructVariant, Error> {
        if self.tokens.first() == Some(&Token::Enum { name: name }) {
            self.next_token();
            assert_next_token!(self, Str(variant));
            let len = Some(len);
            assert_next_token!(self, Map { len });
            Ok(Variant {
                ser: self,
                end: Token::MapEnd,
            })
        } else {
            assert_next_token!(self, StructVariant { name, variant, len });
            Ok(Variant {
                ser: self,
                end: Token::StructVariantEnd,
            })
        }
    }

    fn is_human_readable(&self) -> bool {
        panic!(
            "Types which have different human-readable and compact representations \
             must explicitly mark their test cases with `serde_test::Configure`"
        );
    }
}

pub struct Variant<'s, 'a: 's> {
    ser: &'s mut Serializer<'a>,
    end: Token,
}

impl<'s, 'a> ser::SerializeSeq for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_next_token!(self, SeqEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeTuple for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_next_token!(self, TupleEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeTupleStruct for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_next_token!(self, TupleStructEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeTupleVariant for Variant<'s, 'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        value.serialize(&mut *self.ser)
    }

    fn end(self) -> Result<(), Error> {
        match self.end {
            Token::TupleVariantEnd => assert_next_token!(self.ser, TupleVariantEnd),
            Token::SeqEnd => assert_next_token!(self.ser, SeqEnd),
            _ => unreachable!(),
        }
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeMap for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
    where
        T: Serialize,
    {
        key.serialize(&mut **self)
    }

    fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
    where
        T: Serialize,
    {
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Self::Error> {
        assert_next_token!(self, MapEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(
        &mut self,
        key: &'static str,
        value: &T,
    ) -> Result<(), Self::Error>
    where
        T: Serialize,
    {
        try!(key.serialize(&mut **self));
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Self::Error> {
        assert_next_token!(self, StructEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeStructVariant for Variant<'s, 'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(
        &mut self,
        key: &'static str,
        value: &T,
    ) -> Result<(), Self::Error>
    where
        T: Serialize,
    {
        try!(key.serialize(&mut *self.ser));
        value.serialize(&mut *self.ser)
    }

    fn end(self) -> Result<(), Self::Error> {
        match self.end {
            Token::StructVariantEnd => assert_next_token!(self.ser, StructVariantEnd),
            Token::MapEnd => assert_next_token!(self.ser, MapEnd),
            _ => unreachable!(),
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::io::{self, Write};
use std::ops::Deref;

use byteorder::{BigEndian, WriteBytesExt};

pub const DHT_EXT: (usize, u8) = (7, 1);
pub const EXT_PROTO: (usize, u8) = (5, 0x10);
pub const UT_META_ID: u8 = 9;
pub const UT_PEX_ID: u8 = 11;

pub trait Bitfield: Clone + From<Vec<u8>> {
    fn bytes(&self) -> usize;
    fn byte_at(&self, pos: usize) -> u8;
}

pub trait Buffer: Clone + Deref<Target = [u8]> {}

pub enum Message<BF: Bitfield, Buf: Clone + Deref<Target = [u8]>> {
    // TODO: Consider moving this to the heap,
    // reduces the enum size from 48 bytes to 24,
    // memcpy of Message's ends up taking ~4% of
    // CPU time, could be worth reducing as such.
    Handshake {
        rsv: [u8; 8],
        hash: [u8; 20],
        id: [u8; 20],
    },
    KeepAlive,
    Choke,
    Unchoke,
    Interested,
    Uninterested,
    Have(u32),
    Bitfield(BF),
    Request {
        index: u32,
        begin: u32,
        length: u32,
    },
    Piece {
        index: u32,
        begin: u32,
        length: u32,
        data: Buf,
    },
    Cancel {
        index: u32,
        begin: u32,
        length: u32,
    },
    Port(u16),
    Extension {
        id: u8,
        payload: Vec<u8>,
    },
}

impl<BF: Bitfield, Buf: Buffer> fmt::Debug for Message<BF, Buf> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Message::Handshake { rsv, .. } => {
                write!(f, "Message::Handshake {{ extensions: {:?} }}", &rsv[..])
            }
            Message::KeepAlive => write!(f, "Message::KeepAlive"),
            Message::Choke => write!(f, "Message::Choke"),
            Message::Unchoke => write!(f, "Message::Unchoke"),
            Message::Interested => write!(f, "Message::Interested"),
            Message::Uninterested => write!(f, "Message::Uninterested"),
            Message::Have(p) => write!(f, "Message::Have({})", p),
            Message::Bitfield(_) => write!(f, "Message::Bitfield"),
            Message::Request {
                index,
                begin,
                length,
            } => write!(
                f,
                "Message::Request {{ idx: {}, begin: {}, len: {} }}",
                index, begin, length
            ),
            Message::Piece { index, begin, .. } => {
                write!(f, "Message::Piece {{ idx: {}, begin: {} }}", index, begin)
            }
            Message::Cancel {
                index,
                begin,
                length,
            } => write!(
                f,
                "Message::Cancel {{ idx: {}, begin: {}, len: {} }}",
                index, begin, length
            ),
            Message::Port(port) => write!(f, "Message::Port({:?})", port),
            Message::Extension { id, .. } => write!(f, "Message::Extension {{ id: {} }}", id),
        }
    }
}

impl<BF: Bitfield, Buf: Buffer> Clone for Message<BF, Buf> {
    fn clone(&self) -> Self {
        match *self {
            Message::Handshake { rsv, hash, id } => Message::Handshake { rsv, hash, id },
            Message::KeepAlive => Message::KeepAlive,
            Message::Choke => Message::Choke,
            Message::Unchoke => Message::Unchoke,
            Message::Interested => Message::Interested,
            Message::Uninterested => Message::Uninterested,
            Message::Have(p) => Message::Have(p),
            Message::Bitfield(ref b) => Message::Bitfield(b.clone()),
            Message::Request {
                index,
                begin,
                length,
            } => Message::Request {
                index,
                begin,
                length,
            },
            Message::Piece {
                index,
                begin,
                length,
                ref data,
            } => {
                if cfg!(test) {
                    Message::Piece {
                        index,
                        begin,
                        length,
                        data: data.clone(),
                    }
                } else {
                    unreachable!("pieces should not be cloned outside of testing");
                }
            }
            Message::Cancel {
                index,
                begin,
                length,
            } => Message::Cancel {
                index,
                begin,
                length,
            },
            Message::Port(port) => Message::Port(port),
            Message::Extension { id, ref payload } => Message::Extension {
                id,
                payload: payload.clone(),
            },
        }
    }
}

impl<BF: Bitfield, Buf: Buffer> PartialEq for Message<BF, Buf> {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (
                &Message::Handshake { rsv, hash, id },
                &Message::Handshake {
                    rsv: rsv_,
                    hash: hash_,
                    id: id_,
                },
            ) => rsv == rsv_ && hash == hash_ && id == id_,
            (&Message::KeepAlive, &Message::KeepAlive)
            | (&Message::Choke, &Message::Choke)
            | (&Message::Unchoke, &Message::Unchoke)
            | (&Message::Interested, &Message::Interested)
            | (&Message::Uninterested, &Message::Uninterested) => true,
            (&Message::Have(p), &Message::Have(p_)) => p == p_,
            (&Message::Port(p), &Message::Port(p_)) => p == p_,
            (
                &Message::Request {
                    index,
                    begin,
                    length,
                },
                &Message::Request {
                    index: i,
                    begin: b,
                    length: l,
                },
            )
            | (
                &Message::Piece {
                    index,
                    begin,
                    length,
                    ..
                },
                &Message::Piece {
                    index: i,
                    begin: b,
                    length: l,
                    ..
                },
            )
            | (
                &Message::Cancel {
                    index,
                    begin,
                    length,
                },
                &Message::Cancel {
                    index: i,
                    begin: b,
                    length: l,
                },
            ) => index == i && begin == b && length == l,
            (
                &Message::Extension { id, ref payload },
                &Message::Extension {
                    id: i,
                    payload: ref p,
                },
            ) => id == i && payload == p,
            _ => false,
        }
    }
}

impl<BF: Bitfield, Buf: Buffer> Message<BF, Buf> {
    pub fn handshake(peer_id: &[u8; 20], hash: &[u8; 20]) -> Self {
        let mut rsv = [0u8; 8];
        rsv[DHT_EXT.0] |= DHT_EXT.1;
        rsv[EXT_PROTO.0] |= EXT_PROTO.1;
        Message::Handshake {
            rsv,
            hash: *hash,
            id: *peer_id,
        }
    }

    pub fn request(idx: u32, offset: u32, len: u32) -> Self {
        Message::Request {
            index: idx,
            begin: offset,
            length: len,
        }
    }

    pub fn piece(index: u32, begin: u32, length: u32, data: Buf) -> Self {
        Message::Piece {
            index,
            begin,
            data,
            length,
        }
    }

    pub fn get_handshake_data(&self) -> ([u8; 20], [u8; 20], [u8; 8]) {
        match *self {
            Message::Handshake { hash, id, rsv } => (hash, id, rsv),
            _ => unreachable!(),
        }
    }

    pub fn is_special(&self) -> bool {
        match *self {
            Message::Handshake { .. } | Message::Bitfield(_) | Message::Extension { .. } => true,
            _ => false,
        }
    }

    pub fn len(&self) -> usize {
        match *self {
            Message::Handshake { .. } => 68,
            Message::KeepAlive => 4,
            Message::Choke | Message::Unchoke | Message::Interested | Message::Uninterested => 5,
            Message::Port(_) => 7,
            Message::Have(_) => 9,
            Message::Bitfield(ref pf) => 5 + pf.bytes(),
            Message::Request { .. } | Message::Cancel { .. } => 17,
            Message::Piece { ref data, .. } => 13 + data.len(),
            Message::Extension { ref payload, .. } => 6 + payload.len(),
        }
    }

    pub fn encode(&self, mut buf: &mut [u8]) -> io::Result<()> {
        match *self {
            Message::Handshake { rsv, hash, id } => {
                if id.len() != 20 {
                    return Err(io::Error::new(
                        io::ErrorKind::InvalidData,
                        "Invalid Peer ID",
                    ));
                }
                buf.write_u8(19)?;
                buf.write_all("BitTorrent protocol".as_ref())?;
                buf.write_all(&rsv)?;
                buf.write_all(&hash)?;
                buf.write_all(&id)?;
            }
            Message::KeepAlive => {
                buf.write_u32::<BigEndian>(0)?;
            }
            Message::Choke => {
                buf.write_u32::<BigEndian>(1)?;
                buf.write_u8(0)?;
            }
            Message::Unchoke => {
                buf.write_u32::<BigEndian>(1)?;
                buf.write_u8(1)?;
            }
            Message::Interested => {
                buf.write_u32::<BigEndian>(1)?;
                buf.write_u8(2)?;
            }
            Message::Uninterested => {
                buf.write_u32::<BigEndian>(1)?;
                buf.write_u8(3)?;
            }
            Message::Port(p) => {
                buf.write_u32::<BigEndian>(3)?;
                buf.write_u8(0x09)?;
                buf.write_u16::<BigEndian>(p)?;
            }
            Message::Have(piece) => {
                buf.write_u32::<BigEndian>(5)?;
                buf.write_u8(4)?;
                buf.write_u32::<BigEndian>(piece)?;
            }
            Message::Bitfield(ref pf) => {
                buf.write_u32::<BigEndian>(1 + pf.bytes() as u32)?;
                buf.write_u8(5)?;
                for i in 0..pf.bytes() {
                    buf.write_u8(pf.byte_at(i))?;
                }
            }
            Message::Request {
                index,
                begin,
                length,
            } => {
                buf.write_u32::<BigEndian>(13)?;
                buf.write_u8(6)?;
                buf.write_u32::<BigEndian>(index)?;
                buf.write_u32::<BigEndian>(begin)?;
                buf.write_u32::<BigEndian>(length)?;
            }
            Message::Piece {
                index,
                begin,
                length,
                ..
            } => {
                buf.write_u32::<BigEndian>(9 + length)?;
                buf.write_u8(7)?;
                buf.write_u32::<BigEndian>(index)?;
                buf.write_u32::<BigEndian>(begin)?;
            }
            Message::Cancel {
                index,
                begin,
                length,
            } => {
                buf.write_u32::<BigEndian>(13)?;
                buf.write_u8(8)?;
                buf.write_u32::<BigEndian>(index)?;
                buf.write_u32::<BigEndian>(begin)?;
                buf.write_u32::<BigEndian>(length)?;
            }
            Message::Extension { id, ref payload } => {
                buf.write_u32::<BigEndian>(2 + payload.len() as u32)?;
                buf.write_u8(20)?;
                buf.write_u8(id)?;
                buf.write_all(payload)?;
            }
        };
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}
<commit_msg>Remove test specific clone gate<commit_after>use std::fmt;
use std::io::{self, Write};
use std::ops::Deref;

use byteorder::{BigEndian, WriteBytesExt};

pub const DHT_EXT: (usize, u8) = (7, 1);
pub const EXT_PROTO: (usize, u8) = (5, 0x10);
pub const UT_META_ID: u8 = 9;
pub const UT_PEX_ID: u8 = 11;

pub trait Bitfield: Clone + From<Vec<u8>> {
    fn bytes(&self) -> usize;
    fn byte_at(&self, pos: usize) -> u8;
}

pub trait Buffer: Clone + Deref<Target = [u8]> {}

pub enum Message<BF: Bitfield, Buf: Clone + Deref<Target = [u8]>> {
    // TODO: Consider moving this to the heap,
    // reduces the enum size from 48 bytes to 24,
    // memcpy of Message's ends up taking ~4% of
    // CPU time, could be worth reducing as such.
    Handshake {
        rsv: [u8; 8],
        hash: [u8; 20],
        id: [u8; 20],
    },
    KeepAlive,
    Choke,
    Unchoke,
    Interested,
    Uninterested,
    Have(u32),
    Bitfield(BF),
    Request {
        index: u32,
        begin: u32,
        length: u32,
    },
    Piece {
        index: u32,
        begin: u32,
        length: u32,
        data: Buf,
    },
    Cancel {
        index: u32,
        begin: u32,
        length: u32,
    },
    Port(u16),
    Extension {
        id: u8,
        payload: Vec<u8>,
    },
}

impl<BF: Bitfield, Buf: Buffer> fmt::Debug for Message<BF, Buf> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Message::Handshake { rsv, .. } => {
                write!(f, "Message::Handshake {{ extensions: {:?} }}", &rsv[..])
            }
            Message::KeepAlive => write!(f, "Message::KeepAlive"),
            Message::Choke => write!(f, "Message::Choke"),
            Message::Unchoke => write!(f, "Message::Unchoke"),
            Message::Interested => write!(f, "Message::Interested"),
            Message::Uninterested => write!(f, "Message::Uninterested"),
            Message::Have(p) => write!(f, "Message::Have({})", p),
            Message::Bitfield(_) => write!(f, "Message::Bitfield"),
            Message::Request {
                index,
                begin,
                length,
            } => write!(
                f,
                "Message::Request {{ idx: {}, begin: {}, len: {} }}",
                index, begin, length
            ),
            Message::Piece { index, begin, .. } => {
                write!(f, "Message::Piece {{ idx: {}, begin: {} }}", index, begin)
            }
            Message::Cancel {
                index,
                begin,
                length,
            } => write!(
                f,
                "Message::Cancel {{ idx: {}, begin: {}, len: {} }}",
                index, begin, length
            ),
            Message::Port(port) => write!(f, "Message::Port({:?})", port),
            Message::Extension { id, .. } => write!(f, "Message::Extension {{ id: {} }}", id),
        }
    }
}

impl<BF: Bitfield, Buf: Buffer> Clone for Message<BF, Buf> {
    fn clone(&self) -> Self {
        match *self {
            Message::Handshake { rsv, hash, id } => Message::Handshake { rsv, hash, id },
            Message::KeepAlive => Message::KeepAlive,
            Message::Choke => Message::Choke,
            Message::Unchoke => Message::Unchoke,
            Message::Interested => Message::Interested,
            Message::Uninterested => Message::Uninterested,
            Message::Have(p) => Message::Have(p),
            Message::Bitfield(ref b) => Message::Bitfield(b.clone()),
            Message::Request {
                index,
                begin,
                length,
            } => Message::Request {
                index,
                begin,
                length,
            },
            Message::Piece {
                index,
                begin,
                length,
                ref data,
            } => {
                Message::Piece {
                    index,
                    begin,
                    length,
                    data: data.clone(),
                }
            }
            Message::Cancel {
                index,
                begin,
                length,
            } => Message::Cancel {
                index,
                begin,
                length,
            },
            Message::Port(port) => Message::Port(port),
            Message::Extension { id, ref payload } => Message::Extension {
                id,
                payload: payload.clone(),
            },
        }
    }
}

impl<BF: Bitfield, Buf: Buffer> PartialEq for Message<BF, Buf> {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (
                &Message::Handshake { rsv, hash, id },
                &Message::Handshake {
                    rsv: rsv_,
                    hash: hash_,
                    id: id_,
                },
            ) => rsv == rsv_ && hash == hash_ && id == id_,
            (&Message::KeepAlive, &Message::KeepAlive)
            | (&Message::Choke, &Message::Choke)
            | (&Message::Unchoke, &Message::Unchoke)
            | (&Message::Interested, &Message::Interested)
            | (&Message::Uninterested, &Message::Uninterested) => true,
            (&Message::Have(p), &Message::Have(p_)) => p == p_,
            (&Message::Port(p), &Message::Port(p_)) => p == p_,
            (
                &Message::Request {
                    index,
                    begin,
                    length,
                },
                &Message::Request {
                    index: i,
                    begin: b,
                    length: l,
                },
            )
            | (
                &Message::Piece {
                    index,
                    begin,
                    length,
                    ..
                },
                &Message::Piece {
                    index: i,
                    begin: b,
                    length: l,
                    ..
                },
            )
            | (
                &Message::Cancel {
                    index,
                    begin,
                    length,
                },
                &Message::Cancel {
                    index: i,
                    begin: b,
                    length: l,
                },
            ) => index == i && begin == b && length == l,
            (
                &Message::Extension { id, ref payload },
                &Message::Extension {
                    id: i,
                    payload: ref p,
                },
            ) => id == i && payload == p,
            _ => false,
        }
    }
}

impl<BF: Bitfield, Buf: Buffer> Message<BF, Buf> {
    pub fn handshake(peer_id: &[u8; 20], hash: &[u8; 20]) -> Self {
        let mut rsv = [0u8; 8];
        rsv[DHT_EXT.0] |= DHT_EXT.1;
        rsv[EXT_PROTO.0] |= EXT_PROTO.1;
        Message::Handshake {
            rsv,
            hash: *hash,
            id: *peer_id,
        }
    }

    pub fn request(idx: u32, offset: u32, len: u32) -> Self {
        Message::Request {
            index: idx,
            begin: offset,
            length: len,
        }
    }

    pub fn piece(index: u32, begin: u32, length: u32, data: Buf) -> Self {
        Message::Piece {
            index,
            begin,
            data,
            length,
        }
    }

    pub fn get_handshake_data(&self) -> ([u8; 20], [u8; 20], [u8; 8]) {
        match *self {
            Message::Handshake { hash, id, rsv } => (hash, id, rsv),
            _ => unreachable!(),
        }
    }

    pub fn is_special(&self) -> bool {
        match *self {
            Message::Handshake { .. } | Message::Bitfield(_) | Message::Extension { .. } => true,
            _ => false,
        }
    }

    pub fn len(&self) -> usize {
        match *self {
            Message::Handshake { .. } => 68,
            Message::KeepAlive => 4,
            Message::Choke | Message::Unchoke | Message::Interested | Message::Uninterested => 5,
            Message::Port(_) => 7,
            Message::Have(_) => 9,
            Message::Bitfield(ref pf) => 5 + pf.bytes(),
            Message::Request { .. } | Message::Cancel { .. } => 17,
            Message::Piece { ref data, .. } => 13 + data.len(),
            Message::Extension { ref payload, .. } => 6 + payload.len(),
        }
    }

    pub fn encode(&self, mut buf: &mut [u8]) -> io::Result<()> {
        match *self {
            Message::Handshake { rsv, hash, id } => {
                if id.len() != 20 {
                    return Err(io::Error::new(
                        io::ErrorKind::InvalidData,
                        "Invalid Peer ID",
                    ));
                }
                buf.write_u8(19)?;
                buf.write_all("BitTorrent protocol".as_ref())?;
                buf.write_all(&rsv)?;
                buf.write_all(&hash)?;
                buf.write_all(&id)?;
            }
            Message::KeepAlive => {
                buf.write_u32::<BigEndian>(0)?;
            }
            Message::Choke => {
                buf.write_u32::<BigEndian>(1)?;
                buf.write_u8(0)?;
            }
            Message::Unchoke => {
                buf.write_u32::<BigEndian>(1)?;
                buf.write_u8(1)?;
            }
            Message::Interested => {
                buf.write_u32::<BigEndian>(1)?;
                buf.write_u8(2)?;
            }
            Message::Uninterested => {
                buf.write_u32::<BigEndian>(1)?;
                buf.write_u8(3)?;
            }
            Message::Port(p) => {
                buf.write_u32::<BigEndian>(3)?;
                buf.write_u8(0x09)?;
                buf.write_u16::<BigEndian>(p)?;
            }
            Message::Have(piece) => {
                buf.write_u32::<BigEndian>(5)?;
                buf.write_u8(4)?;
                buf.write_u32::<BigEndian>(piece)?;
            }
            Message::Bitfield(ref pf) => {
                buf.write_u32::<BigEndian>(1 + pf.bytes() as u32)?;
                buf.write_u8(5)?;
                for i in 0..pf.bytes() {
                    buf.write_u8(pf.byte_at(i))?;
                }
            }
            Message::Request {
                index,
                begin,
                length,
            } => {
                buf.write_u32::<BigEndian>(13)?;
                buf.write_u8(6)?;
                buf.write_u32::<BigEndian>(index)?;
                buf.write_u32::<BigEndian>(begin)?;
                buf.write_u32::<BigEndian>(length)?;
            }
            Message::Piece {
                index,
                begin,
                length,
                ..
            } => {
                buf.write_u32::<BigEndian>(9 + length)?;
                buf.write_u8(7)?;
                buf.write_u32::<BigEndian>(index)?;
                buf.write_u32::<BigEndian>(begin)?;
            }
            Message::Cancel {
                index,
                begin,
                length,
            } => {
                buf.write_u32::<BigEndian>(13)?;
                buf.write_u8(8)?;
                buf.write_u32::<BigEndian>(index)?;
                buf.write_u32::<BigEndian>(begin)?;
                buf.write_u32::<BigEndian>(length)?;
            }
            Message::Extension { id, ref payload } => {
                buf.write_u32::<BigEndian>(2 + payload.len() as u32)?;
                buf.write_u8(20)?;
                buf.write_u8(id)?;
                buf.write_all(payload)?;
            }
        };
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}
<|endoftext|>


<commit_before>use std::io::Timer;
use std::io::timer;
use std::iter;

static INTERVAL: u64 = 1000;

fn main() {
    // Create a timer object
    let mut timer = Timer::new().unwrap();

    // Create a one-shot notification
    // (superfluous type annotation)
    let oneshot: Receiver<()> = timer.oneshot(INTERVAL);

    println!("Wait {} ms...", INTERVAL);

    // Block the task until notification arrives
    oneshot.recv();

    println!("Done");

    println!("Sleep for {} ms...", INTERVAL);

    // This is equivalent to `timer.oneshot(INTERVAL).recv()`
    timer::sleep(INTERVAL);

    println!("Done");

    // The same timer can be used to generate periodic notifications
    // (superfluous type annotation)
    let metronome: Receiver<()> = timer.periodic(INTERVAL);

    println!("Countdown");
    for i in iter::range_step(5u, 0, -1) {
        // This loop will run once every second
        metronome.recv();

        println!("{}", i);
    }
    metronome.recv();
    println!("Ignition!");
}
<commit_msg>fix timer range_step<commit_after>use std::io::Timer;
use std::io::timer;
use std::iter;

static INTERVAL: u64 = 1000;

fn main() {
    // Create a timer object
    let mut timer = Timer::new().unwrap();

    // Create a one-shot notification
    // (superfluous type annotation)
    let oneshot: Receiver<()> = timer.oneshot(INTERVAL);

    println!("Wait {} ms...", INTERVAL);

    // Block the task until notification arrives
    oneshot.recv();

    println!("Done");

    println!("Sleep for {} ms...", INTERVAL);

    // This is equivalent to `timer.oneshot(INTERVAL).recv()`
    timer::sleep(INTERVAL);

    println!("Done");

    // The same timer can be used to generate periodic notifications
    // (superfluous type annotation)
    let metronome: Receiver<()> = timer.periodic(INTERVAL);

    println!("Countdown");
    for i in iter::range_step(5i, 0, -1) {
        // This loop will run once every second
        metronome.recv();

        println!("{}", i);
    }
    metronome.recv();
    println!("Ignition!");
}
<|endoftext|>


<commit_before>use gdk_pixbuf::{PixbufLoader, PixbufLoaderExt};
use gio;
use glib::translate::*;
use std::cell::RefCell;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::rc::Rc;

use allowed_url::{AllowedUrl, Fragment};
use error::LoadingError;
use handle::LoadOptions;
use io;
use node::{NodeType, RsvgNode};
use properties::ComputedValues;
use structure::{IntrinsicDimensions, NodeSvg};
use surface_utils::shared_surface::SharedImageSurface;
use xml::XmlState;
use xml2_load::xml_state_load_from_possibly_compressed_stream;

/// A loaded SVG file and its derived data
///
/// This contains the tree of nodes (SVG elements), the mapping
/// of id to node, and the CSS styles defined for this SVG.
pub struct Svg {
    tree: RsvgNode,

    ids: HashMap<String, RsvgNode>,

    // These require interior mutability because we load the extern
    // resources all over the place.  Eventually we'll be able to do this
    // once, at loading time, and keep this immutable.
    externs: RefCell<Resources>,
    images: RefCell<Images>,

    // Once we do not need to load externs, we can drop this as well
    load_options: LoadOptions,
}

impl Svg {
    pub fn new(tree: RsvgNode, ids: HashMap<String, RsvgNode>, load_options: LoadOptions) -> Svg {
        let values = ComputedValues::default();
        tree.cascade(&values);

        Svg {
            tree,
            ids,
            externs: RefCell::new(Resources::new()),
            images: RefCell::new(Images::new()),
            load_options,
        }
    }

    pub fn load_from_stream(
        load_options: &LoadOptions,
        stream: &gio::InputStream,
        cancellable: Option<&gio::Cancellable>,
    ) -> Result<Svg, LoadingError> {
        let load_flags = load_options.flags;
        let mut xml = XmlState::new(load_options);

        xml_state_load_from_possibly_compressed_stream(&mut xml, load_flags, stream, cancellable)?;

        xml.steal_result()
    }

    pub fn root(&self) -> RsvgNode {
        self.tree.clone()
    }

    pub fn lookup(&self, fragment: &Fragment) -> Result<RsvgNode, LoadingError> {
        if fragment.uri().is_some() {
            self.externs
                .borrow_mut()
                .lookup(&self.load_options, fragment)
        } else {
            self.lookup_node_by_id(fragment.fragment())
                .ok_or(LoadingError::BadUrl)
        }
    }

    pub fn lookup_node_by_id(&self, id: &str) -> Option<RsvgNode> {
        self.ids.get(id).map(|n| (*n).clone())
    }

    pub fn lookup_image(&self, href: &str) -> Result<SharedImageSurface, LoadingError> {
        self.images.borrow_mut().lookup(&self.load_options, href)
    }

    pub fn get_intrinsic_dimensions(&self) -> IntrinsicDimensions {
        let root = self.root();

        assert!(root.get_type() == NodeType::Svg);

        root.with_impl(|svg: &NodeSvg| svg.get_intrinsic_dimensions())
    }
}

struct Resources {
    resources: HashMap<AllowedUrl, Result<Rc<Svg>, LoadingError>>,
}

impl Resources {
    pub fn new() -> Resources {
        Resources {
            resources: Default::default(),
        }
    }

    pub fn lookup(
        &mut self,
        load_options: &LoadOptions,
        fragment: &Fragment,
    ) -> Result<RsvgNode, LoadingError> {
        if let Some(ref href) = fragment.uri() {
            self.get_extern_svg(load_options, href).and_then(|svg| {
                svg.lookup_node_by_id(fragment.fragment())
                    .ok_or(LoadingError::BadUrl)
            })
        } else {
            unreachable!();
        }
    }

    fn get_extern_svg(
        &mut self,
        load_options: &LoadOptions,
        href: &str,
    ) -> Result<Rc<Svg>, LoadingError> {
        let aurl = AllowedUrl::from_href(href, load_options.base_url.as_ref())
            .map_err(|_| LoadingError::BadUrl)?;

        match self.resources.entry(aurl) {
            Entry::Occupied(e) => e.get().clone(),
            Entry::Vacant(e) => {
                let svg = load_svg(load_options, e.key()).map(|s| Rc::new(s));
                let res = e.insert(svg);
                res.clone()
            }
        }
    }
}

struct Images {
    images: HashMap<AllowedUrl, Result<SharedImageSurface, LoadingError>>,
}

impl Images {
    pub fn new() -> Images {
        Images {
            images: Default::default(),
        }
    }

    pub fn lookup(
        &mut self,
        load_options: &LoadOptions,
        href: &str,
    ) -> Result<SharedImageSurface, LoadingError> {
        let aurl = AllowedUrl::from_href(href, load_options.base_url.as_ref())
            .map_err(|_| LoadingError::BadUrl)?;

        match self.images.entry(aurl) {
            Entry::Occupied(e) => e.get().clone(),
            Entry::Vacant(e) => {
                let surface = load_image(load_options, e.key());
                let res = e.insert(surface);
                res.clone()
            }
        }
    }
}

fn load_svg(load_options: &LoadOptions, aurl: &AllowedUrl) -> Result<Svg, LoadingError> {
    // FIXME: pass a cancellable to these
    io::acquire_stream(aurl, None).and_then(|stream| {
        Svg::load_from_stream(&load_options.copy_with_base_url(aurl), &stream, None)
    })
}

fn load_image(
    load_options: &LoadOptions,
    aurl: &AllowedUrl,
) -> Result<SharedImageSurface, LoadingError> {
    let data = io::acquire_data(&aurl, None)?;

    if data.data.len() == 0 {
        return Err(LoadingError::EmptyData);
    }

    let loader = if let Some(ref content_type) = data.content_type {
        PixbufLoader::new_with_mime_type(content_type)?
    } else {
        PixbufLoader::new()
    };

    loader.write(&data.data)?;
    loader.close()?;

    let pixbuf = loader.get_pixbuf().ok_or(LoadingError::Unknown)?;

    let surface = SharedImageSurface::from_pixbuf(&pixbuf)?;

    if load_options.flags.keep_image_data {
        if let Some(mime_type) = data.content_type {
            let data_ptr = ToGlibContainerFromSlice::to_glib_full_from_slice(&data.data);

            extern "C" {
                fn cairo_surface_set_mime_data(
                    surface: *mut cairo_sys::cairo_surface_t,
                    mime_type: *const libc::c_char,
                    data: *mut libc::c_char,
                    length: libc::c_ulong,
                    destroy: cairo_sys::cairo_destroy_func_t,
                    closure: *mut libc::c_void,
                ) -> cairo_sys::cairo_status_t;
            }

            unsafe {
                let status = cairo_surface_set_mime_data(
                    surface.to_glib_none().0,
                    mime_type.to_glib_none().0,
                    data_ptr as *mut _,
                    data.data.len() as libc::c_ulong,
                    Some(glib_sys::g_free),
                    data_ptr as *mut _,
                );

                if status != cairo_sys::STATUS_SUCCESS {
                    return Err(LoadingError::Cairo(status.into()));
                }
            }
        }
    }

    Ok(surface)
}
<commit_msg>svg.rs: Destructure the BinaryData from io::acquire_data()<commit_after>use gdk_pixbuf::{PixbufLoader, PixbufLoaderExt};
use gio;
use glib::translate::*;
use std::cell::RefCell;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::rc::Rc;

use allowed_url::{AllowedUrl, Fragment};
use error::LoadingError;
use handle::LoadOptions;
use io::{self, BinaryData};
use node::{NodeType, RsvgNode};
use properties::ComputedValues;
use structure::{IntrinsicDimensions, NodeSvg};
use surface_utils::shared_surface::SharedImageSurface;
use xml::XmlState;
use xml2_load::xml_state_load_from_possibly_compressed_stream;

/// A loaded SVG file and its derived data
///
/// This contains the tree of nodes (SVG elements), the mapping
/// of id to node, and the CSS styles defined for this SVG.
pub struct Svg {
    tree: RsvgNode,

    ids: HashMap<String, RsvgNode>,

    // These require interior mutability because we load the extern
    // resources all over the place.  Eventually we'll be able to do this
    // once, at loading time, and keep this immutable.
    externs: RefCell<Resources>,
    images: RefCell<Images>,

    // Once we do not need to load externs, we can drop this as well
    load_options: LoadOptions,
}

impl Svg {
    pub fn new(tree: RsvgNode, ids: HashMap<String, RsvgNode>, load_options: LoadOptions) -> Svg {
        let values = ComputedValues::default();
        tree.cascade(&values);

        Svg {
            tree,
            ids,
            externs: RefCell::new(Resources::new()),
            images: RefCell::new(Images::new()),
            load_options,
        }
    }

    pub fn load_from_stream(
        load_options: &LoadOptions,
        stream: &gio::InputStream,
        cancellable: Option<&gio::Cancellable>,
    ) -> Result<Svg, LoadingError> {
        let load_flags = load_options.flags;
        let mut xml = XmlState::new(load_options);

        xml_state_load_from_possibly_compressed_stream(&mut xml, load_flags, stream, cancellable)?;

        xml.steal_result()
    }

    pub fn root(&self) -> RsvgNode {
        self.tree.clone()
    }

    pub fn lookup(&self, fragment: &Fragment) -> Result<RsvgNode, LoadingError> {
        if fragment.uri().is_some() {
            self.externs
                .borrow_mut()
                .lookup(&self.load_options, fragment)
        } else {
            self.lookup_node_by_id(fragment.fragment())
                .ok_or(LoadingError::BadUrl)
        }
    }

    pub fn lookup_node_by_id(&self, id: &str) -> Option<RsvgNode> {
        self.ids.get(id).map(|n| (*n).clone())
    }

    pub fn lookup_image(&self, href: &str) -> Result<SharedImageSurface, LoadingError> {
        self.images.borrow_mut().lookup(&self.load_options, href)
    }

    pub fn get_intrinsic_dimensions(&self) -> IntrinsicDimensions {
        let root = self.root();

        assert!(root.get_type() == NodeType::Svg);

        root.with_impl(|svg: &NodeSvg| svg.get_intrinsic_dimensions())
    }
}

struct Resources {
    resources: HashMap<AllowedUrl, Result<Rc<Svg>, LoadingError>>,
}

impl Resources {
    pub fn new() -> Resources {
        Resources {
            resources: Default::default(),
        }
    }

    pub fn lookup(
        &mut self,
        load_options: &LoadOptions,
        fragment: &Fragment,
    ) -> Result<RsvgNode, LoadingError> {
        if let Some(ref href) = fragment.uri() {
            self.get_extern_svg(load_options, href).and_then(|svg| {
                svg.lookup_node_by_id(fragment.fragment())
                    .ok_or(LoadingError::BadUrl)
            })
        } else {
            unreachable!();
        }
    }

    fn get_extern_svg(
        &mut self,
        load_options: &LoadOptions,
        href: &str,
    ) -> Result<Rc<Svg>, LoadingError> {
        let aurl = AllowedUrl::from_href(href, load_options.base_url.as_ref())
            .map_err(|_| LoadingError::BadUrl)?;

        match self.resources.entry(aurl) {
            Entry::Occupied(e) => e.get().clone(),
            Entry::Vacant(e) => {
                let svg = load_svg(load_options, e.key()).map(|s| Rc::new(s));
                let res = e.insert(svg);
                res.clone()
            }
        }
    }
}

struct Images {
    images: HashMap<AllowedUrl, Result<SharedImageSurface, LoadingError>>,
}

impl Images {
    pub fn new() -> Images {
        Images {
            images: Default::default(),
        }
    }

    pub fn lookup(
        &mut self,
        load_options: &LoadOptions,
        href: &str,
    ) -> Result<SharedImageSurface, LoadingError> {
        let aurl = AllowedUrl::from_href(href, load_options.base_url.as_ref())
            .map_err(|_| LoadingError::BadUrl)?;

        match self.images.entry(aurl) {
            Entry::Occupied(e) => e.get().clone(),
            Entry::Vacant(e) => {
                let surface = load_image(load_options, e.key());
                let res = e.insert(surface);
                res.clone()
            }
        }
    }
}

fn load_svg(load_options: &LoadOptions, aurl: &AllowedUrl) -> Result<Svg, LoadingError> {
    // FIXME: pass a cancellable to these
    io::acquire_stream(aurl, None).and_then(|stream| {
        Svg::load_from_stream(&load_options.copy_with_base_url(aurl), &stream, None)
    })
}

fn load_image(
    load_options: &LoadOptions,
    aurl: &AllowedUrl,
) -> Result<SharedImageSurface, LoadingError> {
    let BinaryData {
        data: bytes,
        content_type,
    } = io::acquire_data(&aurl, None)?;

    if bytes.len() == 0 {
        return Err(LoadingError::EmptyData);
    }

    let loader = if let Some(ref content_type) = content_type {
        PixbufLoader::new_with_mime_type(content_type)?
    } else {
        PixbufLoader::new()
    };

    loader.write(&bytes)?;
    loader.close()?;

    let pixbuf = loader.get_pixbuf().ok_or(LoadingError::Unknown)?;

    let surface = SharedImageSurface::from_pixbuf(&pixbuf)?;

    if load_options.flags.keep_image_data {
        if let Some(mime_type) = content_type {
            let data_ptr = ToGlibContainerFromSlice::to_glib_full_from_slice(&bytes);

            extern "C" {
                fn cairo_surface_set_mime_data(
                    surface: *mut cairo_sys::cairo_surface_t,
                    mime_type: *const libc::c_char,
                    data: *mut libc::c_char,
                    length: libc::c_ulong,
                    destroy: cairo_sys::cairo_destroy_func_t,
                    closure: *mut libc::c_void,
                ) -> cairo_sys::cairo_status_t;
            }

            unsafe {
                let status = cairo_surface_set_mime_data(
                    surface.to_glib_none().0,
                    mime_type.to_glib_none().0,
                    data_ptr as *mut _,
                    bytes.len() as libc::c_ulong,
                    Some(glib_sys::g_free),
                    data_ptr as *mut _,
                );

                if status != cairo_sys::STATUS_SUCCESS {
                    return Err(LoadingError::Cairo(status.into()));
                }
            }
        }
    }

    Ok(surface)
}
<|endoftext|>


<commit_before>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::collections::HashSet;

use syn::{self, visit};
use syn::punctuated::{Punctuated, Pair};

use internals::ast::{Data, Container};
use internals::attr;

use proc_macro2::Span;

// Remove the default from every type parameter because in the generated impls
// they look like associated types: "error: associated type bindings are not
// allowed here".
pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
    syn::Generics {
        params: generics
            .params
            .iter()
            .map(|param| match *param {
                syn::GenericParam::Type(ref param) => {
                    syn::GenericParam::Type(syn::TypeParam {
                        eq_token: None,
                        default: None,
                        ..param.clone()
                    })
                }
                _ => param.clone(),
            })
            .collect(),
        ..generics.clone()
    }
}

pub fn with_where_predicates(
    generics: &syn::Generics,
    predicates: &[syn::WherePredicate],
) -> syn::Generics {
    let mut generics = generics.clone();
    generics.make_where_clause()
        .predicates
        .extend(predicates.into_iter().cloned());
    generics
}

pub fn with_where_predicates_from_fields<F, W>(
    cont: &Container,
    generics: &syn::Generics,
    trait_bound: &syn::Path,
    from_field: F,
    gen_bound_where: W,
) -> syn::Generics
where
    F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
    W: Fn(&attr::Field) -> bool,
{
    let type_params = generics.type_params()
        .map(|param| param.ident)
        .collect::<HashSet<_>>();

    let predicates_from_associated_types = cont.data
        .all_fields()
        .filter(|field| gen_bound_where(&field.attrs))
        .filter_map(|field| {
            if let syn::Type::Path(ref ty) = *field.ty {
                if let Some(Pair::Punctuated(ref t, _)) = ty.path.segments.first() {
                    if type_params.contains(&t.ident) {
                        return Some(parse_quote!(#ty: #trait_bound));
                    }
                }
            }
            None::<syn::WherePredicate>
        });

    let predicates_from_field_attrs = cont.data
        .all_fields()
        .flat_map(|field| from_field(&field.attrs))
        .flat_map(|predicates| predicates.to_vec());

    let mut generics = generics.clone();
    {
        let predicates = &mut generics.make_where_clause().predicates;
        predicates.extend(predicates_from_associated_types);
        predicates.extend(predicates_from_field_attrs);
    }
    generics
}

// Puts the given bound on any generic type parameters that are used in fields
// for which filter returns true.
//
// For example, the following struct needs the bound `A: Serialize, B: Serialize`.
//
//     struct S<'b, A, B: 'b, C> {
//         a: A,
//         b: Option<&'b B>
//         #[serde(skip_serializing)]
//         c: C,
//     }
pub fn with_bound<F>(
    cont: &Container,
    generics: &syn::Generics,
    filter: F,
    bound: &syn::Path,
) -> syn::Generics
where
    F: Fn(&attr::Field, Option<&attr::Variant>) -> bool,
{
    struct FindTyParams {
        // Set of all generic type parameters on the current struct (A, B, C in
        // the example). Initialized up front.
        all_ty_params: HashSet<syn::Ident>,
        // Set of generic type parameters used in fields for which filter
        // returns true (A and B in the example). Filled in as the visitor sees
        // them.
        relevant_ty_params: HashSet<syn::Ident>,
    }
    impl<'ast> visit::Visit<'ast> for FindTyParams {
        fn visit_path(&mut self, path: &syn::Path) {
            if let Some(seg) = path.segments.last() {
                if seg.into_value().ident == "PhantomData" {
                    // Hardcoded exception, because PhantomData<T> implements
                    // Serialize and Deserialize whether or not T implements it.
                    return;
                }
            }
            if path.leading_colon.is_none() && path.segments.len() == 1 {
                let id = path.segments[0].ident;
                if self.all_ty_params.contains(&id) {
                    self.relevant_ty_params.insert(id);
                }
            }
            visit::visit_path(self, path);
        }

        // Type parameter should not be considered used by a macro path.
        //
        //     struct TypeMacro<T> {
        //         mac: T!(),
        //         marker: PhantomData<T>,
        //     }
        fn visit_macro(&mut self, _mac: &syn::Macro) {}
    }

    let all_ty_params = generics.type_params()
        .map(|param| param.ident)
        .collect();

    let mut visitor = FindTyParams {
        all_ty_params: all_ty_params,
        relevant_ty_params: HashSet::new(),
    };
    match cont.data {
        Data::Enum(ref variants) => for variant in variants.iter() {
            let relevant_fields = variant
                .fields
                .iter()
                .filter(|field| filter(&field.attrs, Some(&variant.attrs)));
            for field in relevant_fields {
                visit::visit_type(&mut visitor, field.ty);
            }
        },
        Data::Struct(_, ref fields) => {
            for field in fields.iter().filter(|field| filter(&field.attrs, None)) {
                visit::visit_type(&mut visitor, field.ty);
            }
        }
    }

    let new_predicates = generics.type_params()
        .map(|param| param.ident)
        .filter(|id| visitor.relevant_ty_params.contains(id))
        .map(|id| {
            syn::WherePredicate::Type(syn::PredicateType {
                lifetimes: None,
                // the type parameter that is being bounded e.g. T
                bounded_ty: syn::Type::Path(syn::TypePath {
                    qself: None,
                    path: id.into(),
                }),
                colon_token: Default::default(),
                // the bound e.g. Serialize
                bounds: vec![
                    syn::TypeParamBound::Trait(syn::TraitBound {
                        paren_token: None,
                        modifier: syn::TraitBoundModifier::None,
                        lifetimes: None,
                        path: bound.clone(),
                    }),
                ].into_iter().collect(),
            })
        });

    let mut generics = generics.clone();
    generics.make_where_clause()
        .predicates
        .extend(new_predicates);
    generics
}

pub fn with_self_bound(
    cont: &Container,
    generics: &syn::Generics,
    bound: &syn::Path,
) -> syn::Generics {
    let mut generics = generics.clone();
    generics.make_where_clause()
        .predicates
        .push(syn::WherePredicate::Type(syn::PredicateType {
            lifetimes: None,
            // the type that is being bounded e.g. MyStruct<'a, T>
            bounded_ty: type_of_item(cont),
            colon_token: Default::default(),
            // the bound e.g. Default
            bounds: vec![
                syn::TypeParamBound::Trait(syn::TraitBound {
                    paren_token: None,
                    modifier: syn::TraitBoundModifier::None,
                    lifetimes: None,
                    path: bound.clone(),
                }),
            ].into_iter().collect(),
        }));
    generics
}

pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics {
    let bound = syn::Lifetime::new(lifetime, Span::call_site());
    let def = syn::LifetimeDef {
        attrs: Vec::new(),
        lifetime: bound,
        colon_token: None,
        bounds: Punctuated::new(),
    };

    let params = Some(syn::GenericParam::Lifetime(def))
        .into_iter()
        .chain(generics.params
            .iter()
            .cloned()
            .map(|mut param| {
                match param {
                    syn::GenericParam::Lifetime(ref mut param) => {
                        param.bounds.push(bound);
                    }
                    syn::GenericParam::Type(ref mut param) => {
                        param.bounds.push(syn::TypeParamBound::Lifetime(bound));
                    }
                    syn::GenericParam::Const(_) => {}
                }
                param
            }))
        .collect();

    syn::Generics {
        params: params,
        ..generics.clone()
    }
}

fn type_of_item(cont: &Container) -> syn::Type {
    syn::Type::Path(syn::TypePath {
        qself: None,
        path: syn::Path {
            leading_colon: None,
            segments: vec![
                syn::PathSegment {
                    ident: cont.ident,
                    arguments: syn::PathArguments::AngleBracketed(
                        syn::AngleBracketedGenericArguments {
                            colon2_token: None,
                            lt_token: Default::default(),
                            args: cont.generics
                                .params
                                .iter()
                                .map(|param| match *param {
                                    syn::GenericParam::Type(ref param) => {
                                        syn::GenericArgument::Type(syn::Type::Path(syn::TypePath {
                                            qself: None,
                                            path: param.ident.into(),
                                        }))
                                    }
                                    syn::GenericParam::Lifetime(ref param) => {
                                        syn::GenericArgument::Lifetime(param.lifetime)
                                    }
                                    syn::GenericParam::Const(_) => {
                                        panic!("Serde does not support const generics yet");
                                    }
                                })
                                .collect(),
                            gt_token: Default::default(),
                        },
                    ),
                },
            ].into_iter().collect(),
        },
    })
}
<commit_msg>Name type_params consistently with Syn<commit_after>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::collections::HashSet;

use syn::{self, visit};
use syn::punctuated::{Punctuated, Pair};

use internals::ast::{Data, Container};
use internals::attr;

use proc_macro2::Span;

// Remove the default from every type parameter because in the generated impls
// they look like associated types: "error: associated type bindings are not
// allowed here".
pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
    syn::Generics {
        params: generics
            .params
            .iter()
            .map(|param| match *param {
                syn::GenericParam::Type(ref param) => {
                    syn::GenericParam::Type(syn::TypeParam {
                        eq_token: None,
                        default: None,
                        ..param.clone()
                    })
                }
                _ => param.clone(),
            })
            .collect(),
        ..generics.clone()
    }
}

pub fn with_where_predicates(
    generics: &syn::Generics,
    predicates: &[syn::WherePredicate],
) -> syn::Generics {
    let mut generics = generics.clone();
    generics.make_where_clause()
        .predicates
        .extend(predicates.into_iter().cloned());
    generics
}

pub fn with_where_predicates_from_fields<F, W>(
    cont: &Container,
    generics: &syn::Generics,
    trait_bound: &syn::Path,
    from_field: F,
    gen_bound_where: W,
) -> syn::Generics
where
    F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
    W: Fn(&attr::Field) -> bool,
{
    let type_params = generics.type_params()
        .map(|param| param.ident)
        .collect::<HashSet<_>>();

    let predicates_from_associated_types = cont.data
        .all_fields()
        .filter(|field| gen_bound_where(&field.attrs))
        .filter_map(|field| {
            if let syn::Type::Path(ref ty) = *field.ty {
                if let Some(Pair::Punctuated(ref t, _)) = ty.path.segments.first() {
                    if type_params.contains(&t.ident) {
                        return Some(parse_quote!(#ty: #trait_bound));
                    }
                }
            }
            None::<syn::WherePredicate>
        });

    let predicates_from_field_attrs = cont.data
        .all_fields()
        .flat_map(|field| from_field(&field.attrs))
        .flat_map(|predicates| predicates.to_vec());

    let mut generics = generics.clone();
    {
        let predicates = &mut generics.make_where_clause().predicates;
        predicates.extend(predicates_from_associated_types);
        predicates.extend(predicates_from_field_attrs);
    }
    generics
}

// Puts the given bound on any generic type parameters that are used in fields
// for which filter returns true.
//
// For example, the following struct needs the bound `A: Serialize, B: Serialize`.
//
//     struct S<'b, A, B: 'b, C> {
//         a: A,
//         b: Option<&'b B>
//         #[serde(skip_serializing)]
//         c: C,
//     }
pub fn with_bound<F>(
    cont: &Container,
    generics: &syn::Generics,
    filter: F,
    bound: &syn::Path,
) -> syn::Generics
where
    F: Fn(&attr::Field, Option<&attr::Variant>) -> bool,
{
    struct FindTyParams {
        // Set of all generic type parameters on the current struct (A, B, C in
        // the example). Initialized up front.
        all_type_params: HashSet<syn::Ident>,
        // Set of generic type parameters used in fields for which filter
        // returns true (A and B in the example). Filled in as the visitor sees
        // them.
        relevant_type_params: HashSet<syn::Ident>,
    }
    impl<'ast> visit::Visit<'ast> for FindTyParams {
        fn visit_path(&mut self, path: &syn::Path) {
            if let Some(seg) = path.segments.last() {
                if seg.into_value().ident == "PhantomData" {
                    // Hardcoded exception, because PhantomData<T> implements
                    // Serialize and Deserialize whether or not T implements it.
                    return;
                }
            }
            if path.leading_colon.is_none() && path.segments.len() == 1 {
                let id = path.segments[0].ident;
                if self.all_type_params.contains(&id) {
                    self.relevant_type_params.insert(id);
                }
            }
            visit::visit_path(self, path);
        }

        // Type parameter should not be considered used by a macro path.
        //
        //     struct TypeMacro<T> {
        //         mac: T!(),
        //         marker: PhantomData<T>,
        //     }
        fn visit_macro(&mut self, _mac: &syn::Macro) {}
    }

    let all_type_params = generics.type_params()
        .map(|param| param.ident)
        .collect();

    let mut visitor = FindTyParams {
        all_type_params: all_type_params,
        relevant_type_params: HashSet::new(),
    };
    match cont.data {
        Data::Enum(ref variants) => for variant in variants.iter() {
            let relevant_fields = variant
                .fields
                .iter()
                .filter(|field| filter(&field.attrs, Some(&variant.attrs)));
            for field in relevant_fields {
                visit::visit_type(&mut visitor, field.ty);
            }
        },
        Data::Struct(_, ref fields) => {
            for field in fields.iter().filter(|field| filter(&field.attrs, None)) {
                visit::visit_type(&mut visitor, field.ty);
            }
        }
    }

    let new_predicates = generics.type_params()
        .map(|param| param.ident)
        .filter(|id| visitor.relevant_type_params.contains(id))
        .map(|id| {
            syn::WherePredicate::Type(syn::PredicateType {
                lifetimes: None,
                // the type parameter that is being bounded e.g. T
                bounded_ty: syn::Type::Path(syn::TypePath {
                    qself: None,
                    path: id.into(),
                }),
                colon_token: Default::default(),
                // the bound e.g. Serialize
                bounds: vec![
                    syn::TypeParamBound::Trait(syn::TraitBound {
                        paren_token: None,
                        modifier: syn::TraitBoundModifier::None,
                        lifetimes: None,
                        path: bound.clone(),
                    }),
                ].into_iter().collect(),
            })
        });

    let mut generics = generics.clone();
    generics.make_where_clause()
        .predicates
        .extend(new_predicates);
    generics
}

pub fn with_self_bound(
    cont: &Container,
    generics: &syn::Generics,
    bound: &syn::Path,
) -> syn::Generics {
    let mut generics = generics.clone();
    generics.make_where_clause()
        .predicates
        .push(syn::WherePredicate::Type(syn::PredicateType {
            lifetimes: None,
            // the type that is being bounded e.g. MyStruct<'a, T>
            bounded_ty: type_of_item(cont),
            colon_token: Default::default(),
            // the bound e.g. Default
            bounds: vec![
                syn::TypeParamBound::Trait(syn::TraitBound {
                    paren_token: None,
                    modifier: syn::TraitBoundModifier::None,
                    lifetimes: None,
                    path: bound.clone(),
                }),
            ].into_iter().collect(),
        }));
    generics
}

pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics {
    let bound = syn::Lifetime::new(lifetime, Span::call_site());
    let def = syn::LifetimeDef {
        attrs: Vec::new(),
        lifetime: bound,
        colon_token: None,
        bounds: Punctuated::new(),
    };

    let params = Some(syn::GenericParam::Lifetime(def))
        .into_iter()
        .chain(generics.params
            .iter()
            .cloned()
            .map(|mut param| {
                match param {
                    syn::GenericParam::Lifetime(ref mut param) => {
                        param.bounds.push(bound);
                    }
                    syn::GenericParam::Type(ref mut param) => {
                        param.bounds.push(syn::TypeParamBound::Lifetime(bound));
                    }
                    syn::GenericParam::Const(_) => {}
                }
                param
            }))
        .collect();

    syn::Generics {
        params: params,
        ..generics.clone()
    }
}

fn type_of_item(cont: &Container) -> syn::Type {
    syn::Type::Path(syn::TypePath {
        qself: None,
        path: syn::Path {
            leading_colon: None,
            segments: vec![
                syn::PathSegment {
                    ident: cont.ident,
                    arguments: syn::PathArguments::AngleBracketed(
                        syn::AngleBracketedGenericArguments {
                            colon2_token: None,
                            lt_token: Default::default(),
                            args: cont.generics
                                .params
                                .iter()
                                .map(|param| match *param {
                                    syn::GenericParam::Type(ref param) => {
                                        syn::GenericArgument::Type(syn::Type::Path(syn::TypePath {
                                            qself: None,
                                            path: param.ident.into(),
                                        }))
                                    }
                                    syn::GenericParam::Lifetime(ref param) => {
                                        syn::GenericArgument::Lifetime(param.lifetime)
                                    }
                                    syn::GenericParam::Const(_) => {
                                        panic!("Serde does not support const generics yet");
                                    }
                                })
                                .collect(),
                            gt_token: Default::default(),
                        },
                    ),
                },
            ].into_iter().collect(),
        },
    })
}
<|endoftext|>