<commit_before>//! TODO: Auto-generate

use std::io::{Cursor, Read, Write};
use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian};
use num::FromPrimitive;
use boiler_generated::ProtoMessage;
use boiler_generated::steammessages_base::CMsgProtoBufHeader;

const PROTO_MASK: u32 = 0x80000000;

enum_from_primitive! {
    #[derive(Clone, Copy, Debug, PartialEq)]
    pub enum EMsg {
        ClientLogOnResponse = 751,
		ClientVACChallenge = 753,
		ClientSetHeartbeatRate = 755,
        ChannelEncryptRequest = 1303,
    	ChannelEncryptResponse = 1304,
    	ChannelEncryptResult = 1305,
        ClientLogon = 5514,
    }
}

impl EMsg {
    pub fn parse(data: &mut Cursor<&Vec<u8>>) -> Self {
        let raw = Self::parse_to_raw(data);
        Self::from_raw(raw)
    }

    pub fn parse_to_raw(data: &mut Cursor<&Vec<u8>>) -> u32 {
        data.read_u32::<LittleEndian>().unwrap()
    }

    pub fn from_raw(raw: u32) -> Self {
        EMsg::from_u32(raw & !PROTO_MASK).unwrap()
    }
}

#[derive(Debug)]
pub struct MsgHdr {
    pub msg: EMsg,
    pub target_job_id: u64,
    pub source_job_id: u64
}

impl MsgHdr {
    pub fn parse(data: &mut Cursor<&Vec<u8>>) -> Self {
        trace!("Decoding MsgHdr type header");

        MsgHdr {
            msg: EMsg::parse(data),
            target_job_id: data.read_u64::<LittleEndian>().unwrap(),
            source_job_id: data.read_u64::<LittleEndian>().unwrap()
        }
    }

    pub fn write_to(&self, data: &mut Cursor<Vec<u8>>) {
        data.write_u32::<LittleEndian>(self.msg as u32).unwrap();
        data.write_u64::<LittleEndian>(self.target_job_id).unwrap();
        data.write_u64::<LittleEndian>(self.source_job_id).unwrap();
    }
}

#[derive(Debug)]
pub struct MsgHdrProtoBuf {
    pub msg: EMsg,
    pub proto: CMsgProtoBufHeader,
}

impl MsgHdrProtoBuf {
    pub fn parse(_data: &mut Cursor<&Vec<u8>>) -> Self {
        trace!("Decoding MsgHdrProtoBuf type header");

        // TODO: Implement, the following is from node-steam-client
        //header = Schema.MsgHdrProtoBuf.decode(data);
        //header.proto = Steam._processProto(header.proto);
        //if (!this._sessionID && header.headerLength > 0) {
        //	this._sessionID = header.proto.client_sessionid;
        //	this.steamID = header.proto.steamid;
        //}
        //sourceJobID = header.proto.jobid_source;
        //targetJobID = header.proto.jobid_target;

        unimplemented!();
    }

    pub fn write_to(&self, data: &mut Cursor<Vec<u8>>) {
        // Turn the protobuf data into bytes
        let bytes = self.proto.write_to_bytes().unwrap();

        // Flag the msg as protobuf
        let msg = self.msg as u32 | PROTO_MASK;

        // Actually write in the header data
        data.write_u32::<LittleEndian>(msg).unwrap();
        data.write_u32::<LittleEndian>(bytes.len() as u32).unwrap();
        data.write(&bytes).unwrap();
    }
}

#[derive(Debug)]
pub struct ExtendedClientMsgHdr;

impl ExtendedClientMsgHdr {
    pub fn parse(_data: &mut Cursor<&Vec<u8>>) -> Self {
        trace!("Decoding ExtendedClientMsgHdr type header");

        // TODO: Implement, the following is from node-steam-client
        //header = Schema.ExtendedClientMsgHdr.decode(data);
        //sourceJobID = header.sourceJobID;
        //targetJobID = header.targetJobID;

        unimplemented!();
    }
}

/// A header of a message to be sent to or received from a server. Can be one of three header types.
#[derive(Debug)]
pub enum MessageHeader {
    MsgHdr(MsgHdr),
    MsgHdrProtoBuf(MsgHdrProtoBuf),
    ExtendedClientMsgHdr(ExtendedClientMsgHdr)
}

impl MessageHeader {
    pub fn parse(data: &mut Cursor<&Vec<u8>>) -> Self {
        assert!(data.position() == 0, "`data` position must be 0 when parsing a header");

        // Get the event type we received
        let emsg_raw = EMsg::parse_to_raw(data);
        let emsg = EMsg::from_raw(emsg_raw);
        debug!("Parsing message for EMsg: {:?}", emsg);

        // Reset the cursor again, the header needs it to be at the start
        data.set_position(0);

        // Handle the header of the message, which can be different things
        if emsg == EMsg::ChannelEncryptRequest ||
           emsg == EMsg::ChannelEncryptResult {
            MessageHeader::MsgHdr(MsgHdr::parse(data))
        }
        else if (emsg_raw & PROTO_MASK) != 0 {
            MessageHeader::MsgHdrProtoBuf(MsgHdrProtoBuf::parse(data))
        }
        else {
            MessageHeader::ExtendedClientMsgHdr(ExtendedClientMsgHdr::parse(data))
        }
    }

    pub fn write_to(&self, data: &mut Cursor<Vec<u8>>) {
        match *self {
            MessageHeader::MsgHdr(ref h) => h.write_to(data),
            MessageHeader::MsgHdrProtoBuf(ref h) => h.write_to(data),
            MessageHeader::ExtendedClientMsgHdr(_) => unimplemented!(),
        }
    }

    /// Gets the EMsg of the inner header type.
    pub fn emsg(&self) -> EMsg {
        match *self {
            MessageHeader::MsgHdr(ref h) => h.msg,
            MessageHeader::MsgHdrProtoBuf(_) => unimplemented!(),
            MessageHeader::ExtendedClientMsgHdr(_) => unimplemented!(),
        }
    }
}

/// A message to be sent to or received from a steam server.
#[derive(Debug)]
pub struct Message {
    pub header: MessageHeader,
    pub body: Vec<u8>
}

impl Message {
    pub fn parse(data: &mut Cursor<&Vec<u8>>) -> Self {
        // Parse in the header
        let header = MessageHeader::parse(data);

        // Get the remaining data
        let mut body = Vec::new();
        data.read_to_end(&mut body).unwrap();

        // Create the actual message
        Message {
            header: header,
            body: body
        }
    }

    pub fn write_to(&self, data: &mut Cursor<Vec<u8>>) {
        self.header.write_to(data);
        data.write(&self.body).unwrap();
    }

    pub fn into_bytes(&self) -> Vec<u8> {
        let mut data_c = Cursor::new(Vec::new());
        self.write_to(&mut data_c);
        data_c.into_inner()
    }
}
<commit_msg>Implement parsing of protobuf headers<commit_after>//! TODO: Auto-generate

use std::io::{Cursor, Read, Write};
use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian};
use num::FromPrimitive;
use boiler_generated::ProtoMessage;
use boiler_generated::steammessages_base::CMsgProtoBufHeader;

const PROTO_MASK: u32 = 0x80000000;

enum_from_primitive! {
    #[derive(Clone, Copy, Debug, PartialEq)]
    pub enum EMsg {
        ClientLogOnResponse = 751,
		ClientVACChallenge = 753,
		ClientSetHeartbeatRate = 755,
        ChannelEncryptRequest = 1303,
    	ChannelEncryptResponse = 1304,
    	ChannelEncryptResult = 1305,
        ClientLogon = 5514,
    }
}

impl EMsg {
    pub fn parse(data: &mut Cursor<&Vec<u8>>) -> Self {
        let raw = Self::parse_to_raw(data);
        Self::from_raw(raw)
    }

    pub fn parse_to_raw(data: &mut Cursor<&Vec<u8>>) -> u32 {
        data.read_u32::<LittleEndian>().unwrap()
    }

    pub fn from_raw(raw: u32) -> Self {
        EMsg::from_u32(raw & !PROTO_MASK).unwrap()
    }
}

#[derive(Debug)]
pub struct MsgHdr {
    pub msg: EMsg,
    pub target_job_id: u64,
    pub source_job_id: u64
}

impl MsgHdr {
    pub fn parse(data: &mut Cursor<&Vec<u8>>) -> Self {
        trace!("Decoding MsgHdr type header");

        MsgHdr {
            msg: EMsg::parse(data),
            target_job_id: data.read_u64::<LittleEndian>().unwrap(),
            source_job_id: data.read_u64::<LittleEndian>().unwrap()
        }
    }

    pub fn write_to(&self, data: &mut Cursor<Vec<u8>>) {
        data.write_u32::<LittleEndian>(self.msg as u32).unwrap();
        data.write_u64::<LittleEndian>(self.target_job_id).unwrap();
        data.write_u64::<LittleEndian>(self.source_job_id).unwrap();
    }
}

#[derive(Debug)]
pub struct MsgHdrProtoBuf {
    pub msg: EMsg,
    pub proto: CMsgProtoBufHeader,
}

impl MsgHdrProtoBuf {
    pub fn parse(data: &mut Cursor<&Vec<u8>>) -> Self {
        trace!("Decoding MsgHdrProtoBuf type header");

        // Read in data
        let msg = EMsg::parse(data);
        let len = data.read_u32::<LittleEndian>().unwrap() as usize;
        let mut bytes = vec![0u8; len];
        data.read(&mut bytes).unwrap();

        // Convert protobuf data to the header type
        let mut proto = CMsgProtoBufHeader::new();
        proto.merge_from_bytes(&bytes).unwrap();

        MsgHdrProtoBuf {
            msg: msg,
            proto: proto
        }
    }

    pub fn write_to(&self, data: &mut Cursor<Vec<u8>>) {
        // Turn the protobuf data into bytes
        let bytes = self.proto.write_to_bytes().unwrap();

        // Flag the msg as protobuf
        let msg = self.msg as u32 | PROTO_MASK;

        // Actually write in the header data
        data.write_u32::<LittleEndian>(msg).unwrap();
        data.write_u32::<LittleEndian>(bytes.len() as u32).unwrap();
        data.write(&bytes).unwrap();
    }
}

#[derive(Debug)]
pub struct ExtendedClientMsgHdr;

impl ExtendedClientMsgHdr {
    pub fn parse(_data: &mut Cursor<&Vec<u8>>) -> Self {
        trace!("Decoding ExtendedClientMsgHdr type header");

        // TODO: Implement, the following is from node-steam-client
        //header = Schema.ExtendedClientMsgHdr.decode(data);
        //sourceJobID = header.sourceJobID;
        //targetJobID = header.targetJobID;

        unimplemented!();
    }
}

/// A header of a message to be sent to or received from a server. Can be one of three header types.
#[derive(Debug)]
pub enum MessageHeader {
    MsgHdr(MsgHdr),
    MsgHdrProtoBuf(MsgHdrProtoBuf),
    ExtendedClientMsgHdr(ExtendedClientMsgHdr)
}

impl MessageHeader {
    pub fn parse(data: &mut Cursor<&Vec<u8>>) -> Self {
        assert!(data.position() == 0, "`data` position must be 0 when parsing a header");

        // Get the event type we received
        let emsg_raw = EMsg::parse_to_raw(data);
        let emsg = EMsg::from_raw(emsg_raw);
        debug!("Parsing message for EMsg: {:?}", emsg);

        // Reset the cursor again, the header needs it to be at the start
        data.set_position(0);

        // Handle the header of the message, which can be different things
        if emsg == EMsg::ChannelEncryptRequest ||
           emsg == EMsg::ChannelEncryptResult {
            MessageHeader::MsgHdr(MsgHdr::parse(data))
        }
        else if (emsg_raw & PROTO_MASK) != 0 {
            MessageHeader::MsgHdrProtoBuf(MsgHdrProtoBuf::parse(data))
        }
        else {
            MessageHeader::ExtendedClientMsgHdr(ExtendedClientMsgHdr::parse(data))
        }
    }

    pub fn write_to(&self, data: &mut Cursor<Vec<u8>>) {
        match *self {
            MessageHeader::MsgHdr(ref h) => h.write_to(data),
            MessageHeader::MsgHdrProtoBuf(ref h) => h.write_to(data),
            MessageHeader::ExtendedClientMsgHdr(_) => unimplemented!(),
        }
    }

    /// Gets the EMsg of the inner header type.
    pub fn emsg(&self) -> EMsg {
        match *self {
            MessageHeader::MsgHdr(ref h) => h.msg,
            MessageHeader::MsgHdrProtoBuf(ref h) => h.msg,
            MessageHeader::ExtendedClientMsgHdr(_) => unimplemented!(),
        }
    }
}

/// A message to be sent to or received from a steam server.
#[derive(Debug)]
pub struct Message {
    pub header: MessageHeader,
    pub body: Vec<u8>
}

impl Message {
    pub fn parse(data: &mut Cursor<&Vec<u8>>) -> Self {
        // Parse in the header
        let header = MessageHeader::parse(data);

        // Get the remaining data
        let mut body = Vec::new();
        data.read_to_end(&mut body).unwrap();

        // Create the actual message
        Message {
            header: header,
            body: body
        }
    }

    pub fn write_to(&self, data: &mut Cursor<Vec<u8>>) {
        self.header.write_to(data);
        data.write(&self.body).unwrap();
    }

    pub fn into_bytes(&self) -> Vec<u8> {
        let mut data_c = Cursor::new(Vec::new());
        self.write_to(&mut data_c);
        data_c.into_inner()
    }
}
<|endoftext|>


<commit_before>// check-pass

// Test `Copy` bindings in the rhs of `@` patterns.

#![feature(slice_patterns)]
#![feature(bindings_after_at)]
//~^ WARN the feature `bindings_after_at` is incomplete and may cause the compiler to crash

#[derive(Copy, Clone)]
struct C;

fn mk_c() -> C { C }

#[derive(Copy, Clone)]
struct P<A, B>(A, B);

enum E<A, B> { L(A), R(B) }

fn main() {
    let a @ b @ c @ d = C;
    let a @ (b, c) = (C, mk_c());
    let a @ P(b, P(c, d)) = P(mk_c(), P(C, C));
    let a @ [b, c] = [C, C];
    let a @ [b, .., c] = [C, mk_c(), C];
    let a @ [b, mid @ .., c] = [C, mk_c(), C];
    let a @ &(b, c) = &(C, C);
    let a @ &(b, &P(c, d)) = &(mk_c(), &P(C, C));

    fn foo(a @ [b, mid @ .., c]: [C; 3]) {}

    use self::E::*;
    match L(C) {
        L(a) | R(a) => {
            let a: C = a;
            drop(a);
            drop(a);
        }
    }
    match R(&L(&mk_c())) {
        L(L(&a)) | L(R(&a)) | R(L(&a)) | R(R(&a)) => {
            let a: C = a;
            drop(a);
            drop(a);
        }
    }
}
<commit_msg>enhance borrowck-pat-by-copy-bindings-in-at<commit_after>// check-pass

// Test `Copy` bindings in the rhs of `@` patterns.

#![feature(slice_patterns)]
#![feature(bindings_after_at)]
//~^ WARN the feature `bindings_after_at` is incomplete and may cause the compiler to crash

#[derive(Copy, Clone)]
struct C;

fn mk_c() -> C { C }

#[derive(Copy, Clone)]
struct P<A, B>(A, B);

enum E<A, B> { L(A), R(B) }

fn main() {
    let a @ b @ c @ d = C;
    let a @ (b, c) = (C, mk_c());
    let a @ P(b, P(c, d)) = P(mk_c(), P(C, C));
    let a @ [b, c] = [C, C];
    let a @ [b, .., c] = [C, mk_c(), C];
    let a @ [b, mid @ .., c] = [C, mk_c(), C];
    let a @ &(b, c) = &(C, C);
    let a @ &(b, &P(c, d)) = &(mk_c(), &P(C, C));

    fn foo(a @ [b, mid @ .., c]: [C; 3]) {}

    use self::E::*;
    match L(C) {
        L(a) | R(a) => {
            let a: C = a;
            drop(a);
            drop(a);
        }
    }
    match R(&L(&mk_c())) {
        L(L(&a)) | L(R(&a)) | R(L(&a)) | R(R(&a)) => {
            let a: C = a;
            drop(a);
            drop(a);
        }
    }

    match Ok(mk_c()) {
        Ok(ref a @ b) | Err(b @ ref a) => {
            let _: &C = a;
            let _: C = b;
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::{HashMap, hash_map};
use tensor::Tensor;
use autograd::Variable;
use std::vec::IntoIter;
use std::ops::{Deref, DerefMut};
use std::marker::PhantomData;
use nn;

pub trait ModuleStruct {
    fn init_module(self) -> Self;
}
pub struct ModRefMut<'a, T: 'a + ?Sized> {
    value: *mut T,
    phantom: PhantomData<&'a T>,
}

impl<'a, T> ModRefMut<'a, T> {
    pub fn new(value: *mut T) -> Self {
        ModRefMut {
            value: value,
            phantom: PhantomData,
        }
    }
}

impl<'a, T> From<&'a mut T> for ModRefMut<'a, T> {
    fn from(value: &mut T) -> Self {
        ModRefMut::new(value as *mut T)
    }
}
impl<'a, T> From<*mut T> for ModRefMut<'a, T> {
    fn from(value: *mut T) -> Self {
        ModRefMut::new(value)
    }
}

impl<'a, T> Deref for ModRefMut<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe { &*self.value as &T }
    }
}
impl<'a, T> DerefMut for ModRefMut<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.value as &mut T }
    }
}

pub struct Module<T: Copy> {
    pub _name: String,
    pub training: bool,
    //_backend: TorchBackend,
    //	_backward_hooks:
    //	_forward_hooks:
    _buffers: HashMap<String, Tensor<T>>,
    _params: HashMap<String, *mut nn::Parameter<T>>,
    _modules: HashMap<String, *mut Module<T>>,
}
pub struct PtrIterMut<'a, T: 'a> {
    //mod_iter: linked_hash_map::IterMut<'a, &'a str, *mut T>,
    mod_iter: hash_map::IterMut<'a, String, *mut T>,
}
pub struct PtrIter<'a, T: 'a> {
    //mod_iter: linked_hash_map::IterMut<'a, &'a str, *mut T>,
    mod_iter: hash_map::Iter<'a, String, *mut T>,
}

impl<'a, T> Iterator for PtrIter<'a, T> {
    type Item = (&'a str, &'a T);
    fn next(&mut self) -> Option<Self::Item> {
        if let Some((name, t)) = self.mod_iter.next() {
            Some((name, unsafe { &**t as &T }))
        } else {
            None
        }
    }
}

impl<'a, T> Iterator for PtrIterMut<'a, T> {
    type Item = (&'a String, &'a mut T);
    fn next(&mut self) -> Option<Self::Item> {
        if let Some((name, t)) = self.mod_iter.next() {
            Some((name, unsafe { &mut **t as &mut T }))
        } else {
            None
        }
    }
}

pub struct ParamIter<T: Copy> {
    pub modules: Vec<*mut Module<T>>,
    pub mod_iter: IntoIter<*mut Module<T>>,
    pub iter: Box<Iterator<Item = *mut nn::Parameter<T>>>,
}
fn mod_accum<T: Copy>(module: &mut Module<T>, arg: &mut Vec<*mut Module<T>>) {
    arg.push((module));
}
impl<'a, T: 'static + Copy> ParamIter<T> {
    pub fn new(root: &'a mut Module<T>) -> Self {
        let mut mods = Vec::new();
        root.apply_arg(&mut mods, mod_accum);
        let mut module = unsafe { &mut *mods[0] as &mut Module<T> };
        ParamIter {
            modules: mods.clone(),
            mod_iter: mods.into_iter(),
            iter: Box::new(module._params.iter_mut().map(|(s, d)| *d)),
        }
    }
}

impl<T: Copy + 'static> Iterator for ParamIter<T> {
    type Item = ModRefMut<'static, nn::Parameter<T>>;
    fn next(&mut self) -> Option<Self::Item> {
        if let Some(t) = self.iter.next() {
            Some(ModRefMut::new(t))
        } else if let Some(modulep) = self.mod_iter.next() {
            let mut module = unsafe { &mut *modulep as &mut Module<T> };
            self.iter = Box::new(module._params.iter_mut().map(|(s, d)| *d));
            self.next()
        } else {
            None
        }
    }
}

impl<T: Copy + 'static> Clone for Box<ParamIter<T>> {
    fn clone(&self) -> Self {
        let mut new_mod_list = self.modules.clone();
        let param_iter = Box::new(unsafe { &mut *new_mod_list[0] }
                                      ._params
                                      .iter_mut()
                                      .map(|(s, d)| *d));
        Box::new(ParamIter {
                     modules: new_mod_list,
                     mod_iter: self.modules.clone().into_iter(),
                     iter: param_iter,
                 })
    }
}

impl<T: Copy> Module<T> {
    pub fn new() -> Module<T> {
        Module {
            _name: String::from(""),
            _buffers: HashMap::new(),
            _params: HashMap::new(),
            _modules: HashMap::new(),
            training: true,
        }
    }
    #[inline]
    fn as_mut_ptr(&mut self) -> *mut Module<T> {
        self as *mut Module<T>
    }
    pub fn add_module(&mut self, module: &mut ModIntf<T>) {
        let m = module.delegate();
        self._modules.insert(m._name.clone(), m.as_mut_ptr());

    }
    pub fn add_param(&mut self, name: &str, param: &mut nn::Parameter<T>) {
        let s = String::from(name);
        self._params.insert(s, param.as_mut_ptr());

    }
    pub fn modules_iter_mut(&mut self) -> PtrIterMut<Module<T>> {
        PtrIterMut { mod_iter: self._modules.iter_mut() }
    }
    pub fn modules_iter(&mut self) -> PtrIter<Module<T>> {
        PtrIter { mod_iter: self._modules.iter() }
    }
    pub fn params_iter_mut(&mut self) -> PtrIterMut<nn::Parameter<T>> {
        PtrIterMut { mod_iter: self._params.iter_mut() }
    }
    pub fn register_buffer(&mut self, name: &str, tensor: &mut Tensor<T>) {
        self._buffers.insert(String::from(name), tensor.clone());
    }
    pub fn parameters(&mut self) -> Box<Iterator<Item = ModRefMut<'static, nn::Parameter<T>>>> {
        Box::new(ParamIter::new(self))
    }
    pub fn as_ref_mut(&mut self) -> ModRefMut<'static, Module<T>> {
        ModRefMut::new(self as *mut Module<T>)
    }
    fn _apply(&mut self, callback: fn(&mut Tensor<T>)) {
        for (_, module) in self.modules_iter_mut() {
            module._apply(callback)
        }
        for (_, param) in self.params_iter_mut() {
            param.apply(callback)
            /*
			if let Some(g) = p._grad {
					callback(g.data)
			}
			*/
            /* see also _buffers */
        }
    }
    pub fn apply(&mut self, callback: fn(&mut Self)) {
        for (_, module) in self.modules_iter_mut() {
            module.apply(callback)
        }
        callback(self)
    }
    fn apply_arg<Ta>(&mut self, arg: &mut Ta, callback: fn(&mut Self, &mut Ta)) {
        for (_, module) in self.modules_iter_mut() {
            module.apply_arg(arg, callback)
        }
        callback(self, arg)
    }
    pub fn repr(&mut self) -> String {
        let mut tmpstr = format!("{} (\n", self._name);
        for (key, module) in self.modules_iter_mut() {
            let modstr = module.repr();
            let modstr = format!("  {}", modstr);
            tmpstr = format!("{} ({}): {}\n", tmpstr, key, modstr);
        }
        tmpstr = format!("{})", tmpstr);
        tmpstr
    }
    pub fn eval(&mut self) {
        self.train(false)
    }
    fn train(&mut self, mode: bool) {
        self.training = mode;
        for (_, module) in self.modules_iter_mut() {
            module.train(mode)
        }

    }
}

pub trait ModDelegate<T: Copy> {
    fn delegate(&mut self) -> &mut Module<T>;
}

pub trait ModIntf<T: Copy>: ModDelegate<T> {
    fn forward(&mut self, input: &mut Variable<T>) -> Variable<T>;
    fn f(&mut self, input: &mut Variable<T>) -> Variable<T> {
        {
            let mut m = self.delegate();
            // do pre-forward hooks
        }
        let output = self.forward(input);
        {
            let mut m = self.delegate();
            // do post-forward hooks
        }
        output
    }
    fn train(&mut self) {
        self.delegate().train(true)
    }
    fn eval(&mut self) {
        self.delegate().train(false)
    }
    fn parameters(&mut self) -> Box<Iterator<Item = ModRefMut<'static, nn::Parameter<T>>>> {
        self.delegate().parameters()
    }
}

pub trait ModIntfV<T: Copy>: ModDelegate<T> {
    fn forwardv(&mut self, input: &mut Vec<Variable<T>>) -> Vec<Variable<T>>;
    fn fv(&mut self, input: &mut Vec<Variable<T>>) -> Vec<Variable<T>> {
        {
            let mut m = self.delegate();
            // do pre-forward hooks
        }
        let output = self.forwardv(input);
        {
            let mut m = self.delegate();
            // do post-forward hooks
        }
        output
    }
}
<commit_msg>give ParamIter a friendlier interface that doesn't need T to be 'static<commit_after>use std::collections::{HashMap, hash_map};
use tensor::Tensor;
use autograd::Variable;
use std::vec::IntoIter;
use std::ops::{Deref, DerefMut};
use std::marker::PhantomData;
use nn;

pub type Parameters<T> = Box<Iterator<Item = ModRefMut<'static, nn::Parameter<T>>>>;

pub trait ModuleStruct {
    fn init_module(self) -> Self;
}
pub struct ModRefMut<'a, T: 'a + ?Sized> {
    value: *mut T,
    phantom: PhantomData<&'a T>,
}

impl<'a, T> ModRefMut<'a, T> {
    pub fn new(value: *mut T) -> Self {
        ModRefMut {
            value: value,
            phantom: PhantomData,
        }
    }
}

impl<'a, T> From<&'a mut T> for ModRefMut<'a, T> {
    fn from(value: &mut T) -> Self {
        ModRefMut::new(value as *mut T)
    }
}
impl<'a, T> From<*mut T> for ModRefMut<'a, T> {
    fn from(value: *mut T) -> Self {
        ModRefMut::new(value)
    }
}

impl<'a, T> Deref for ModRefMut<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe { &*self.value as &T }
    }
}
impl<'a, T> DerefMut for ModRefMut<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.value as &mut T }
    }
}

pub struct Module<T: Copy> {
    pub _name: String,
    pub training: bool,
    //_backend: TorchBackend,
    //	_backward_hooks:
    //	_forward_hooks:
    _buffers: HashMap<String, Tensor<T>>,
    _params: HashMap<String, *mut nn::Parameter<T>>,
    _modules: HashMap<String, *mut Module<T>>,
}
pub struct PtrIterMut<'a, T: 'a> {
    //mod_iter: linked_hash_map::IterMut<'a, &'a str, *mut T>,
    mod_iter: hash_map::IterMut<'a, String, *mut T>,
}
pub struct PtrIter<'a, T: 'a> {
    //mod_iter: linked_hash_map::IterMut<'a, &'a str, *mut T>,
    mod_iter: hash_map::Iter<'a, String, *mut T>,
}

impl<'a, T> Iterator for PtrIter<'a, T> {
    type Item = (&'a str, &'a T);
    fn next(&mut self) -> Option<Self::Item> {
        if let Some((name, t)) = self.mod_iter.next() {
            Some((name, unsafe { &**t as &T }))
        } else {
            None
        }
    }
}

impl<'a, T> Iterator for PtrIterMut<'a, T> {
    type Item = (&'a String, &'a mut T);
    fn next(&mut self) -> Option<Self::Item> {
        if let Some((name, t)) = self.mod_iter.next() {
            Some((name, unsafe { &mut **t as &mut T }))
        } else {
            None
        }
    }
}

pub struct ParamIter<'a, T: Copy + 'a> {
    pub modules: Vec<*mut Module<T>>,
    pub mod_iter: IntoIter<*mut Module<T>>,
    pub iter: Box<Iterator<Item = *mut nn::Parameter<T>>>,
    phantom: PhantomData<&'a T>,
}
fn mod_accum<T: Copy>(module: &mut Module<T>, arg: &mut Vec<*mut Module<T>>) {
    arg.push((module));
}
impl<'a, T: 'static + Copy> ParamIter<'a, T> {
    pub fn new(root: &mut Module<T>) -> Self {
        let mut mods = Vec::new();
        root.apply_arg(&mut mods, mod_accum);
        let mut module = unsafe { &mut *mods[0] as &mut Module<T> };
        ParamIter {
            modules: mods.clone(),
            mod_iter: mods.into_iter(),
            iter: Box::new(module._params.iter_mut().map(|(_, d)| *d)),
            phantom: PhantomData,
        }
    }
}

impl<'a, T: Copy + 'static> Iterator for ParamIter<'a, T> {
    type Item = ModRefMut<'a, nn::Parameter<T>>;
    fn next(&mut self) -> Option<Self::Item> {
        if let Some(t) = self.iter.next() {
            Some(ModRefMut::new(t))
        } else if let Some(modulep) = self.mod_iter.next() {
            let mut module = unsafe { &mut *modulep as &mut Module<T> };
            self.iter = Box::new(module._params.iter_mut().map(|(_, d)| *d));
            self.next()
        } else {
            None
        }
    }
}

impl<'a, T: Copy + 'static> Clone for Box<ParamIter<'a, T>> {
    fn clone(&self) -> Self {
        let mut new_mod_list = self.modules.clone();
        let param_iter = Box::new(unsafe { &mut *new_mod_list[0] }
                                      ._params
                                      .iter_mut()
                                      .map(|(_, d)| *d));
        Box::new(ParamIter {
                     modules: new_mod_list,
                     mod_iter: self.modules.clone().into_iter(),
                     iter: param_iter,
                     phantom: PhantomData,
                 })
    }
}

impl<T: Copy> Module<T> {
    pub fn new() -> Module<T> {
        Module {
            _name: String::from(""),
            _buffers: HashMap::new(),
            _params: HashMap::new(),
            _modules: HashMap::new(),
            training: true,
        }
    }
    #[inline]
    fn as_mut_ptr(&mut self) -> *mut Module<T> {
        self as *mut Module<T>
    }
    pub fn add_module(&mut self, module: &mut ModIntf<T>) {
        let m = module.delegate();
        self._modules.insert(m._name.clone(), m.as_mut_ptr());

    }
    pub fn add_param(&mut self, name: &str, param: &mut nn::Parameter<T>) {
        self._params.insert(name.into(), param.as_mut_ptr());

    }
    pub fn modules_iter_mut(&mut self) -> PtrIterMut<Module<T>> {
        PtrIterMut { mod_iter: self._modules.iter_mut() }
    }
    pub fn modules_iter(&mut self) -> PtrIter<Module<T>> {
        PtrIter { mod_iter: self._modules.iter() }
    }
    pub fn params_iter_mut(&mut self) -> PtrIterMut<nn::Parameter<T>> {
        PtrIterMut { mod_iter: self._params.iter_mut() }
    }
    pub fn register_buffer(&mut self, name: &str, tensor: &mut Tensor<T>) {
        self._buffers.insert(String::from(name), tensor.clone());
    }
    pub fn parameters(&mut self) -> Parameters<T> {
        Box::new(ParamIter::new(self))
    }
    fn _apply(&mut self, callback: fn(&mut Tensor<T>)) {
        for (_, module) in self.modules_iter_mut() {
            module._apply(callback)
        }
        for (_, param) in self.params_iter_mut() {
            param.apply(callback)
            /*
			if let Some(g) = p._grad {
					callback(g.data)
			}
			*/
            /* see also _buffers */
        }
    }
    pub fn apply(&mut self, callback: fn(&mut Self)) {
        for (_, module) in self.modules_iter_mut() {
            module.apply(callback)
        }
        callback(self)
    }
    fn apply_arg<Ta>(&mut self, arg: &mut Ta, callback: fn(&mut Self, &mut Ta)) {
        for (_, module) in self.modules_iter_mut() {
            module.apply_arg(arg, callback)
        }
        callback(self, arg)
    }
    pub fn repr(&mut self) -> String {
        let mut tmpstr = format!("{} (\n", self._name);
        for (key, module) in self.modules_iter_mut() {
            let modstr = module.repr();
            let modstr = format!("  {}", modstr);
            tmpstr = format!("{} ({}): {}\n", tmpstr, key, modstr);
        }
        tmpstr = format!("{})", tmpstr);
        tmpstr
    }
    pub fn eval(&mut self) {
        self.train(false)
    }
    fn train(&mut self, mode: bool) {
        self.training = mode;
        for (_, module) in self.modules_iter_mut() {
            module.train(mode)
        }
    }
}

pub trait ModDelegate<T: Copy> {
    fn delegate(&mut self) -> &mut Module<T>;
}

pub trait ModIntf<T: Copy>: ModDelegate<T> {
    fn forward(&mut self, input: &mut Variable<T>) -> Variable<T>;
    fn f(&mut self, input: &mut Variable<T>) -> Variable<T> {
        {
            let mut m = self.delegate();
            // do pre-forward hooks
        }
        let output = self.forward(input);
        {
            let mut m = self.delegate();
            // do post-forward hooks
        }
        output
    }
    fn train(&mut self) {
        self.delegate().train(true)
    }
    fn eval(&mut self) {
        self.delegate().train(false)
    }
    fn parameters(&mut self) -> Box<Iterator<Item = ModRefMut<'static, nn::Parameter<T>>>> {
        self.delegate().parameters()
    }
}

pub trait ModIntfV<T: Copy>: ModDelegate<T> {
    fn forwardv(&mut self, input: &mut Vec<Variable<T>>) -> Vec<Variable<T>>;
    fn fv(&mut self, input: &mut Vec<Variable<T>>) -> Vec<Variable<T>> {
        {
            let mut m = self.delegate();
            // do pre-forward hooks
        }
        let output = self.forwardv(input);
        {
            let mut m = self.delegate();
            // do post-forward hooks
        }
        output
    }
}
<|endoftext|>


<commit_before>#![feature(plugin, inclusive_range_syntax)]
#![feature(dotdot_in_tuple_patterns)]
#![plugin(clippy)]

#![allow(dead_code, no_effect, unnecessary_operation)]
#![allow(let_and_return)]
#![allow(needless_return)]
#![allow(unused_variables)]
#![allow(cyclomatic_complexity)]
#![allow(blacklisted_name)]
#![allow(collapsible_if)]
#![allow(zero_divided_by_zero, eq_op)]

fn bar<T>(_: T) {}
fn foo() -> bool { unimplemented!() }

struct Foo {
    bar: u8,
}

#[deny(if_same_then_else)]
#[deny(match_same_arms)]
fn if_same_then_else() -> Result<&'static str, ()> {
    if true {
        //~^NOTE same as this
        Foo { bar: 42 };
        0..10;
        ..;
        0..;
        ..10;
        0...10;
        foo();
    }
    else { //~ERROR this `if` has identical blocks
        Foo { bar: 42 };
        0..10;
        ..;
        0..;
        ..10;
        0...10;
        foo();
    }

    if true {
        Foo { bar: 42 };
    }
    else {
        Foo { bar: 43 };
    }

    if true {
        0..10;
    }
    else {
        0...10;
    }

    if true {
        foo();
        foo();
    }
    else {
        foo();
    }

    let _ = if true {
        //~^NOTE same as this
        foo();
        42
    }
    else { //~ERROR this `if` has identical blocks
        foo();
        42
    };

    if true {
        foo();
    }

    let _ = if true {
        //~^NOTE same as this
        42
    }
    else { //~ERROR this `if` has identical blocks
        42
    };

    if true {
        //~^NOTE same as this
        let bar = if true {
            42
        }
        else {
            43
        };

        while foo() { break; }
        bar + 1;
    }
    else { //~ERROR this `if` has identical blocks
        let bar = if true {
            42
        }
        else {
            43
        };

        while foo() { break; }
        bar + 1;
    }

    if true {
        //~^NOTE same as this
        let _ = match 42 {
            42 => 1,
            a if a > 0 => 2,
            10...15 => 3,
            _ => 4,
        };
    }
    else if false {
        foo();
    }
    else if foo() { //~ERROR this `if` has identical blocks
        let _ = match 42 {
            42 => 1,
            a if a > 0 => 2,
            10...15 => 3,
            _ => 4,
        };
    }

    if true {
        //~^NOTE same as this
        if let Some(a) = Some(42) {}
    }
    else { //~ERROR this `if` has identical blocks
        if let Some(a) = Some(42) {}
    }

    if true {
        //~^NOTE same as this
        if let (1, .., 3) = (1, 2, 3) {}
    }
    else { //~ERROR this `if` has identical blocks
        if let (1, .., 3) = (1, 2, 3) {}
    }

    if true {
        if let (1, .., 3) = (1, 2, 3) {}
    }
    else {
        if let (.., 3) = (1, 2, 3) {}
    }

    if true {
        if let (1, .., 3) = (1, 2, 3) {}
    }
    else {
        if let (.., 4) = (1, 2, 3) {}
    }

    if true {
        if let (1, .., 3) = (1, 2, 3) {}
    }
    else {
        if let (.., 1, 3) = (1, 2, 3) {}
    }

    if true {
        if let Some(a) = Some(42) {}
    }
    else {
        if let Some(a) = Some(43) {}
    }

    let _ = match 42 {
        42 => foo(),
        //~^NOTE same as this
        //~|NOTE `42 | 51`
        51 => foo(), //~ERROR this `match` has identical arm bodies
        _ => true,
    };

    let _ = match Some(42) {
        Some(_) => 24,
        //~^NOTE same as this
        //~|NOTE `Some(_) | None`
        None => 24, //~ERROR this `match` has identical arm bodies
    };

    let _ = match Some(42) {
        Some(foo) => 24,
        None => 24,
    };

    let _ = match Some(42) {
        Some(42) => 24,
        Some(a) => 24, // bindings are different
        None => 0,
    };

    let _ = match Some(42) {
        Some(a) if a > 0 => 24,
        Some(a) => 24, // one arm has a guard
        None => 0,
    };

    match (Some(42), Some(42)) {
        (Some(a), None) => bar(a),
        //~^NOTE same as this
        //~|NOTE `(Some(a), None) | (None, Some(a))`
        (None, Some(a)) => bar(a), //~ERROR this `match` has identical arm bodies
        _ => (),
    }

    match (Some(42), Some(42)) {
        (Some(a), ..) => bar(a),
        //~^NOTE same as this
        //~|NOTE `(Some(a), ..) | (.., Some(a))`
        (.., Some(a)) => bar(a), //~ERROR this `match` has identical arm bodies
        _ => (),
    }

    match (1, 2, 3) {
        (1, .., 3) => 42,
        //~^NOTE same as this
        //~|NOTE `(1, .., 3) | (.., 3)`
        (.., 3) => 42, //~ERROR this `match` has identical arm bodies
        _ => 0,
    };

    let _ = if true {
        //~^NOTE same as this
        0.0
    } else { //~ERROR this `if` has identical blocks
        0.0
    };

    let _ = if true {
        //~^NOTE same as this
        -0.0
    } else { //~ERROR this `if` has identical blocks
        -0.0
    };

    let _ = if true {
        0.0
    } else {
        -0.0
    };

    // Different NaNs
    let _ = if true {
        0.0 / 0.0
    } else {
        std::f32::NAN
    };

    // Same NaNs
    let _ = if true {
        //~^NOTE same as this
        std::f32::NAN
    } else { //~ERROR this `if` has identical blocks
        std::f32::NAN
    };

    let _ = match Some(()) {
        Some(()) => 0.0,
        None => -0.0
    };

    match (Some(42), Some("")) {
        (Some(a), None) => bar(a),
        (None, Some(a)) => bar(a), // bindings have different types
        _ => (),
    }

    if true {
        //~^NOTE same as this
        try!(Ok("foo"));
    }
    else { //~ERROR this `if` has identical blocks
        try!(Ok("foo"));
    }

    if true {
        //~^NOTE same as this
        let foo = "";
        return Ok(&foo[0..]);
    }
    else if false {
        let foo = "bar";
        return Ok(&foo[0..]);
    }
    else { //~ERROR this `if` has identical blocks
        let foo = "";
        return Ok(&foo[0..]);
    }
}

#[deny(ifs_same_cond)]
#[allow(if_same_then_else)] // all empty blocks
fn ifs_same_cond() {
    let a = 0;
    let b = false;

    if b {
        //~^NOTE same as this
    }
    else if b { //~ERROR this `if` has the same condition as a previous if
    }

    if a == 1 {
        //~^NOTE same as this
    }
    else if a == 1 { //~ERROR this `if` has the same condition as a previous if
    }

    if 2*a == 1 {
        //~^NOTE same as this
    }
    else if 2*a == 2 {
    }
    else if 2*a == 1 { //~ERROR this `if` has the same condition as a previous if
    }
    else if a == 1 {
    }

    // See #659
    if cfg!(feature = "feature1-659") {
        1
    } else if cfg!(feature = "feature2-659") {
        2
    } else {
        3
    };

    let mut v = vec![1];
    if v.pop() == None { // ok, functions
    }
    else if v.pop() == None {
    }

    if v.len() == 42 { // ok, functions
    }
    else if v.len() == 42 {
    }
}

fn main() {}
<commit_msg>Improve test coverage of `hir` comparison<commit_after>#![feature(plugin, inclusive_range_syntax)]
#![feature(dotdot_in_tuple_patterns)]
#![plugin(clippy)]

#![allow(dead_code, no_effect, unnecessary_operation)]
#![allow(let_and_return)]
#![allow(needless_return)]
#![allow(unused_variables)]
#![allow(cyclomatic_complexity)]
#![allow(blacklisted_name)]
#![allow(collapsible_if)]
#![allow(zero_divided_by_zero, eq_op)]

fn bar<T>(_: T) {}
fn foo() -> bool { unimplemented!() }

struct Foo {
    bar: u8,
}

#[deny(if_same_then_else)]
#[deny(match_same_arms)]
fn if_same_then_else() -> Result<&'static str, ()> {
    if true {
        //~^NOTE same as this
        Foo { bar: 42 };
        0..10;
        ..;
        0..;
        ..10;
        0...10;
        foo();
    }
    else { //~ERROR this `if` has identical blocks
        Foo { bar: 42 };
        0..10;
        ..;
        0..;
        ..10;
        0...10;
        foo();
    }

    if true {
        Foo { bar: 42 };
    }
    else {
        Foo { bar: 43 };
    }

    if true {
        ();
    }
    else {
        ()
    }

    if true {
        0..10;
    }
    else {
        0...10;
    }

    if true {
        foo();
        foo();
    }
    else {
        foo();
    }

    let _ = if true {
        //~^NOTE same as this
        foo();
        let mut a = 42 + [23].len() as i32;
        a += 7;
        a = -31-a;
        a
    }
    else { //~ERROR this `if` has identical blocks
        foo();
        let mut a = 42 + [23].len() as i32;
        a += 7;
        a = -31-a;
        a
    };

    if true {
        foo();
    }

    let _ = if true {
        //~^NOTE same as this
        42
    }
    else { //~ERROR this `if` has identical blocks
        42
    };

    if true {
        //~^NOTE same as this
        for _ in &[42] {
            let foo: &Option<_> = &Some::<u8>(42);
            if true {
                break;
            } else {
                continue;
            }
        }
    }
    else { //~ERROR this `if` has identical blocks
        for _ in &[42] {
            let foo: &Option<_> = &Some::<u8>(42);
            if true {
                break;
            } else {
                continue;
            }
        }
    }

    if true {
        //~^NOTE same as this
        let bar = if true {
            42
        }
        else {
            43
        };

        while foo() { break; }
        bar + 1;
    }
    else { //~ERROR this `if` has identical blocks
        let bar = if true {
            42
        }
        else {
            43
        };

        while foo() { break; }
        bar + 1;
    }

    if true {
        //~^NOTE same as this
        let _ = match 42 {
            42 => 1,
            a if a > 0 => 2,
            10...15 => 3,
            _ => 4,
        };
    }
    else if false {
        foo();
    }
    else if foo() { //~ERROR this `if` has identical blocks
        let _ = match 42 {
            42 => 1,
            a if a > 0 => 2,
            10...15 => 3,
            _ => 4,
        };
    }

    if true {
        //~^NOTE same as this
        if let Some(a) = Some(42) {}
    }
    else { //~ERROR this `if` has identical blocks
        if let Some(a) = Some(42) {}
    }

    if true {
        //~^NOTE same as this
        if let (1, .., 3) = (1, 2, 3) {}
    }
    else { //~ERROR this `if` has identical blocks
        if let (1, .., 3) = (1, 2, 3) {}
    }

    if true {
        if let (1, .., 3) = (1, 2, 3) {}
    }
    else {
        if let (.., 3) = (1, 2, 3) {}
    }

    if true {
        if let (1, .., 3) = (1, 2, 3) {}
    }
    else {
        if let (.., 4) = (1, 2, 3) {}
    }

    if true {
        if let (1, .., 3) = (1, 2, 3) {}
    }
    else {
        if let (.., 1, 3) = (1, 2, 3) {}
    }

    if true {
        if let Some(42) = None {}
    }
    else {
        if let Option::Some(42) = None {}
    }

    if true {
        if let Some(42) = None::<u8> {}
    }
    else {
        if let Some(42) = None {}
    }

    if true {
        if let Some(a) = Some(42) {}
    }
    else {
        if let Some(a) = Some(43) {}
    }

    let _ = match 42 {
        42 => foo(),
        //~^NOTE same as this
        //~|NOTE `42 | 51`
        51 => foo(), //~ERROR this `match` has identical arm bodies
        _ => true,
    };

    let _ = match Some(42) {
        Some(_) => 24,
        //~^NOTE same as this
        //~|NOTE `Some(_) | None`
        None => 24, //~ERROR this `match` has identical arm bodies
    };

    let _ = match Some(42) {
        Some(foo) => 24,
        None => 24,
    };

    let _ = match Some(42) {
        Some(42) => 24,
        Some(a) => 24, // bindings are different
        None => 0,
    };

    let _ = match Some(42) {
        Some(a) if a > 0 => 24,
        Some(a) => 24, // one arm has a guard
        None => 0,
    };

    match (Some(42), Some(42)) {
        (Some(a), None) => bar(a),
        //~^NOTE same as this
        //~|NOTE `(Some(a), None) | (None, Some(a))`
        (None, Some(a)) => bar(a), //~ERROR this `match` has identical arm bodies
        _ => (),
    }

    match (Some(42), Some(42)) {
        (Some(a), ..) => bar(a),
        //~^NOTE same as this
        //~|NOTE `(Some(a), ..) | (.., Some(a))`
        (.., Some(a)) => bar(a), //~ERROR this `match` has identical arm bodies
        _ => (),
    }

    match (1, 2, 3) {
        (1, .., 3) => 42,
        //~^NOTE same as this
        //~|NOTE `(1, .., 3) | (.., 3)`
        (.., 3) => 42, //~ERROR this `match` has identical arm bodies
        _ => 0,
    };

    let _ = if true {
        //~^NOTE same as this
        0.0
    } else { //~ERROR this `if` has identical blocks
        0.0
    };

    let _ = if true {
        //~^NOTE same as this
        -0.0
    } else { //~ERROR this `if` has identical blocks
        -0.0
    };

    let _ = if true {
        0.0
    } else {
        -0.0
    };

    // Different NaNs
    let _ = if true {
        0.0 / 0.0
    } else {
        std::f32::NAN
    };

    // Same NaNs
    let _ = if true {
        //~^NOTE same as this
        std::f32::NAN
    } else { //~ERROR this `if` has identical blocks
        std::f32::NAN
    };

    let _ = match Some(()) {
        Some(()) => 0.0,
        None => -0.0
    };

    match (Some(42), Some("")) {
        (Some(a), None) => bar(a),
        (None, Some(a)) => bar(a), // bindings have different types
        _ => (),
    }

    if true {
        //~^NOTE same as this
        try!(Ok("foo"));
    }
    else { //~ERROR this `if` has identical blocks
        try!(Ok("foo"));
    }

    if true {
        //~^NOTE same as this
        let foo = "";
        return Ok(&foo[0..]);
    }
    else if false {
        let foo = "bar";
        return Ok(&foo[0..]);
    }
    else { //~ERROR this `if` has identical blocks
        let foo = "";
        return Ok(&foo[0..]);
    }
}

#[deny(ifs_same_cond)]
#[allow(if_same_then_else)] // all empty blocks
fn ifs_same_cond() {
    let a = 0;
    let b = false;

    if b {
        //~^NOTE same as this
    }
    else if b { //~ERROR this `if` has the same condition as a previous if
    }

    if a == 1 {
        //~^NOTE same as this
    }
    else if a == 1 { //~ERROR this `if` has the same condition as a previous if
    }

    if 2*a == 1 {
        //~^NOTE same as this
    }
    else if 2*a == 2 {
    }
    else if 2*a == 1 { //~ERROR this `if` has the same condition as a previous if
    }
    else if a == 1 {
    }

    // See #659
    if cfg!(feature = "feature1-659") {
        1
    } else if cfg!(feature = "feature2-659") {
        2
    } else {
        3
    };

    let mut v = vec![1];
    if v.pop() == None { // ok, functions
    }
    else if v.pop() == None {
    }

    if v.len() == 42 { // ok, functions
    }
    else if v.len() == 42 {
    }
}

fn main() {}
<|endoftext|>


<commit_before>fn main() {
    build::main();
}

#[cfg(feature = "bundled")]
mod build {
    extern crate cc;
    use std::{env, fs};
    use std::ffi::OsString;
    use std::path::{Path, PathBuf};

    pub fn main() {
        let target = env::var("TARGET").unwrap();
        let host = env::var("HOST").unwrap();

        let mut cc = gcc::Build::new();
        cc.file("sqlite3/sqlite3.c")
            .flag("-DSQLITE_CORE")
            .flag("-DSQLITE_DEFAULT_FOREIGN_KEYS=1")
            .flag("-DSQLITE_ENABLE_API_ARMOR")
            .flag("-DSQLITE_ENABLE_COLUMN_METADATA")
            .flag("-DSQLITE_ENABLE_DBSTAT_VTAB")
            .flag("-DSQLITE_ENABLE_FTS3")
            .flag("-DSQLITE_ENABLE_FTS3_PARENTHESIS")
            .flag("-DSQLITE_ENABLE_FTS5")
            .flag("-DSQLITE_ENABLE_JSON1")
            .flag("-DSQLITE_HAS_CODEC")
            .flag("-DSQLITE_TEMP_STORE=2")
            .flag("-DSQLITE_ENABLE_LOAD_EXTENSION=1")
            .flag("-DSQLITE_ENABLE_MEMORY_MANAGEMENT")
            .flag("-DSQLITE_ENABLE_RTREE")
            .flag("-DSQLITE_ENABLE_STAT2")
            .flag("-DSQLITE_ENABLE_STAT4")
            .flag("-DSQLITE_HAVE_ISNAN")
            .flag("-DSQLITE_SOUNDEX")
            .flag("-DSQLITE_THREADSAFE=1")
            .flag("-DSQLITE_USE_URI")
            .flag("-DHAVE_USLEEP=1");

        let is_windows = host.contains("windows") && target.contains("windows");
        let is_apple = host.contains("apple") && target.contains("apple");

        let lib_dir = env("OPENSSL_LIB_DIR").map(PathBuf::from);
        let inc_dir = env("OPENSSL_INCLUDE_DIR").map(PathBuf::from);
        let mut use_openssl = false;

        let (lib_dir, inc_dir) = if lib_dir.is_none() || inc_dir.is_none() {
                match find_openssl_dir(&host, &target) {
                    None => {
                        if is_windows {
                            panic!("Missing environment variable OPENSSL_DIR or OPENSSL_DIR is not set")
                        }
                        (PathBuf::new(), PathBuf::new())
                    },
                    Some(openssl_dir) => {
                        let lib_dir = lib_dir.unwrap_or_else(|| openssl_dir.join("lib"));
                        let inc_dir = inc_dir.unwrap_or_else(|| openssl_dir.join("include"));

                        if !Path::new(&lib_dir).exists() {
                            panic!(
                                "OpenSSL library directory does not exist: {}",
                                lib_dir.to_string_lossy()
                            );
                        }

                        if !Path::new(&inc_dir).exists() {
                            panic!(
                                "OpenSSL include directory does not exist: {}",
                                inc_dir.to_string_lossy()
                            )
                        }

                        use_openssl = true;

                        (lib_dir, inc_dir)
                    }
            }
        } else {
            use_openssl = true;
            (lib_dir.unwrap(), inc_dir.unwrap())
        };

        if is_windows {
            let mut lib = String::new();
            lib.push_str(lib_dir.to_string_lossy().as_ref());
            lib.push_str("\\");
            lib.push_str("libeay32.lib");
            cc.flag(&lib);
            cc.include(inc_dir.to_string_lossy().as_ref());
        } else if use_openssl {
            cc.flag(lib_dir.to_string_lossy().as_ref());
            cc.include(inc_dir.to_string_lossy().as_ref());
            cc.flag("-lcrypto");
        } else if is_apple  {
            cc.flag("-DSQLCIPHER_CRYPTO_CC");
            cc.object("/System/Library/Frameworks/SecurityFoundation.framework/SecurityFoundation");
        } else {
            cc.flag("-lcrypto");
        }

        let out_dir = env::var("OUT_DIR").unwrap();
        let out_path = Path::new(&out_dir).join("bindgen.rs");
        fs::copy("sqlite3/bindgen_bundled_version.rs", out_path)
            .expect("Could not copy bindings to output directory");

        cc.compile("libsqlite3.a");
    }

    fn env(name: &str) -> Option<OsString> {
        let prefix = env::var("TARGET").unwrap().to_uppercase().replace("-", "_");
        let prefixed = format!("{}_{}", prefix, name);
        let var = env::var_os(&prefixed);

        match var {
            None => env::var_os(name),
            _ => var
        }
    }

    fn find_openssl_dir(host: &String, target: &String) -> Option<PathBuf> {
        let openssl_dir = env("OPENSSL_DIR");

        match openssl_dir {
            Some(path) => Some(PathBuf::from(path)),
            None => {
                let openssl_dir = env("OPENSSL_DIR");

                match openssl_dir {
                    Some(path) => Some(PathBuf::from(path)),
                    None => {
                        if host.contains("apple-darwin") && target.contains("apple-darwin") {
                            let homebrew = Path::new("/usr/local/opt/openssl@1.1");
                            if homebrew.exists() {
                                return Some(homebrew.to_path_buf().into());
                            }
                            let homebrew = Path::new("/usr/local/opt/openssl");
                            if homebrew.exists() {
                                return Some(homebrew.to_path_buf().into());
                            }
                            None
                        } else {
                            None
                        }
                    }
                }
            }
        }
    }
}

#[cfg(not(feature = "bundled"))]
mod build {
    extern crate pkg_config;

    #[cfg(all(feature = "vcpkg", target_env = "msvc"))]
    extern crate vcpkg;

    use std::env;
    use std::io::Write;

    pub enum HeaderLocation {
        FromEnvironment,
        Wrapper,
        FromPath(String),
    }

    impl From<HeaderLocation> for String {
        fn from(header: HeaderLocation) -> String {
            match header {
                HeaderLocation::FromEnvironment => {
                    let prefix = env_prefix();
                    let mut header = env::var(format!("{}_INCLUDE_DIR", prefix))
                        .expect(&format!("{}_INCLUDE_DIR must be set if {}_LIB_DIR is set", prefix, prefix));
                    header.push_str("/sqlite3.h");
                    header
                }
                HeaderLocation::Wrapper => "wrapper.h".into(),
                HeaderLocation::FromPath(path) => path,
            }
        }
    }

    pub fn main() {
        let header = find_sqlite();
        bindings::write_to_out_dir(header);
    }

    // Prints the necessary cargo link commands and returns the path to the header.
    fn find_sqlite() -> HeaderLocation {
        let link_lib = link_lib();

        // Allow users to specify where to find SQLite.
        if let Ok(dir) = env::var(format!("{}_LIB_DIR", env_prefix())) {
            println!("cargo:rustc-link-lib={}", link_lib);
            return HeaderLocation::FromEnvironment;
        }

        if let Some(header) = try_vcpkg() {
            return header;
        }

        // See if pkg-config can do everything for us.
        match pkg_config::Config::new().print_system_libs(false).probe(link_lib) {
            Ok(mut lib) => {
                if let Some(mut header) = lib.include_paths.pop() {
                    header.push("sqlite3.h");
                    HeaderLocation::FromPath(header.to_string_lossy().into())
                } else {
                    HeaderLocation::Wrapper
                }
            }
            Err(_) => {
                // No env var set and pkg-config couldn't help; just output the link-lib
                // request and hope that the library exists on the system paths. We used to
                // output /usr/lib explicitly, but that can introduce other linking problems; see
                // https://github.com/jgallagher/rusqlite/issues/207.
                println!("cargo:rustc-link-lib={}", link_lib);
                HeaderLocation::Wrapper
            }
        }
    }

    #[cfg(all(feature = "vcpkg", target_env = "msvc"))]
    fn try_vcpkg() -> Option<HeaderLocation> {
        // See if vcpkg can find it.
        if let Ok(mut lib) = vcpkg::Config::new().probe(link_lib()) {
            if let Some(mut header) = lib.include_paths.pop() {
                header.push("sqlite3.h");
                return Some(HeaderLocation::FromPath(header.to_string_lossy().into()));
            }
        }
        None
    }

    #[cfg(not(all(feature = "vcpkg", target_env = "msvc")))]
    fn try_vcpkg() -> Option<HeaderLocation> {
        None
    }

    fn env_prefix() -> &'static str {
        if cfg!(feature = "sqlcipher") {
            "SQLCIPHER"
        } else {
            "SQLITE3"
        }
    }

    fn link_lib() -> &'static str {
        if cfg!(feature = "sqlcipher") {
            "sqlcipher"
        } else {
            "sqlite3"
        }
    }

    #[cfg(not(feature = "buildtime_bindgen"))]
    mod bindings {
        use super::HeaderLocation;

        use std::{env, fs};
        use std::path::Path;

        #[cfg_attr(rustfmt, rustfmt_skip)]
        static PREBUILT_BINDGEN_PATHS: &'static [&'static str] = &[
            "bindgen-bindings/bindgen_3.6.8.rs",

            #[cfg(feature = "min_sqlite_version_3_6_11")]
            "bindgen-bindings/bindgen_3.6.11.rs",

            #[cfg(feature = "min_sqlite_version_3_6_23")]
            "bindgen-bindings/bindgen_3.6.23.rs",

            #[cfg(feature = "min_sqlite_version_3_7_3")]
            "bindgen-bindings/bindgen_3.7.3.rs",

            #[cfg(feature = "min_sqlite_version_3_7_4")]
            "bindgen-bindings/bindgen_3.7.4.rs",

            #[cfg(feature = "min_sqlite_version_3_7_16")]
            "bindgen-bindings/bindgen_3.7.16.rs",
        ];

        pub fn write_to_out_dir(_header: HeaderLocation) {
            let out_dir = env::var("OUT_DIR").unwrap();
            let out_path = Path::new(&out_dir).join("bindgen.rs");
            let in_path = PREBUILT_BINDGEN_PATHS[PREBUILT_BINDGEN_PATHS.len() - 1];
            fs::copy(in_path, out_path).expect("Could not copy bindings to output directory");
        }
    }

    #[cfg(feature = "buildtime_bindgen")]
    mod bindings {
        extern crate bindgen;

        use self::bindgen::callbacks::{ParseCallbacks, IntKind};
        use super::HeaderLocation;

        use std::env;
        use std::io::Write;
        use std::fs::OpenOptions;
        use std::path::Path;

        #[derive(Debug)]
        struct SqliteTypeChooser;

        impl ParseCallbacks for SqliteTypeChooser {
            fn int_macro(&self, _name: &str, value: i64) -> Option<IntKind> {
                if value >= i32::min_value() as i64 && value <= i32::max_value() as i64 {
                    Some(IntKind::I32)
                } else {
                    None
                }
            }
        }

        pub fn write_to_out_dir(header: HeaderLocation) {
            let header: String = header.into();
            let out_dir = env::var("OUT_DIR").unwrap();
            let mut output = Vec::new();
            bindgen::builder()
                .header(header.clone())
                .parse_callbacks(Box::new(SqliteTypeChooser))
                .rustfmt_bindings(true)
                .generate()
                .expect(&format!("could not run bindgen on header {}", header))
                .write(Box::new(&mut output))
                .expect("could not write output of bindgen");
            let mut output = String::from_utf8(output).expect("bindgen output was not UTF-8?!");

            // rusqlite's functions feature ors in the SQLITE_DETERMINISTIC flag when it can. This flag
            // was added in SQLite 3.8.3, but oring it in in prior versions of SQLite is harmless. We
            // don't want to not build just because this flag is missing (e.g., if we're linking against
            // SQLite 3.7.x), so append the flag manually if it isn't present in bindgen's output.
            if !output.contains("pub const SQLITE_DETERMINISTIC") {
                output.push_str("\npub const SQLITE_DETERMINISTIC: i32 = 2048;\n");
            }

            let path = Path::new(&out_dir).join("bindgen.rs");

            let mut file = OpenOptions::new()
                .write(true)
                .truncate(true)
                .create(true)
                .open(path.clone())
                .expect(&format!("Could not write to {:?}", path));

            file.write_all(output.as_bytes()).expect(&format!("Could not write to {:?}", path));
        }
    }
}
<commit_msg>Fixed warnings<commit_after>fn main() {
    build::main();
}

#[cfg(feature = "bundled")]
mod build {
    extern crate cc;
    use std::{env, fs};
    use std::ffi::OsString;
    use std::path::{Path, PathBuf};

    pub fn main() {
        let target = env::var("TARGET").unwrap();
        let host = env::var("HOST").unwrap();

        let mut cc = gcc::Build::new();
        cc.file("sqlite3/sqlite3.c")
            .flag("-DSQLITE_CORE")
            .flag("-DSQLITE_DEFAULT_FOREIGN_KEYS=1")
            .flag("-DSQLITE_ENABLE_API_ARMOR")
            .flag("-DSQLITE_ENABLE_COLUMN_METADATA")
            .flag("-DSQLITE_ENABLE_DBSTAT_VTAB")
            .flag("-DSQLITE_ENABLE_FTS3")
            .flag("-DSQLITE_ENABLE_FTS3_PARENTHESIS")
            .flag("-DSQLITE_ENABLE_FTS5")
            .flag("-DSQLITE_ENABLE_JSON1")
            .flag("-DSQLITE_HAS_CODEC")
            .flag("-DSQLITE_TEMP_STORE=2")
            .flag("-DSQLITE_ENABLE_LOAD_EXTENSION=1")
            .flag("-DSQLITE_ENABLE_MEMORY_MANAGEMENT")
            .flag("-DSQLITE_ENABLE_RTREE")
            .flag("-DSQLITE_ENABLE_STAT2")
            .flag("-DSQLITE_ENABLE_STAT4")
            .flag("-DSQLITE_HAVE_ISNAN")
            .flag("-DSQLITE_SOUNDEX")
            .flag("-DSQLITE_THREADSAFE=1")
            .flag("-DSQLITE_USE_URI")
            .flag("-DHAVE_USLEEP=1");

        let is_windows = host.contains("windows") && target.contains("windows");
        let is_apple = host.contains("apple") && target.contains("apple");

        let lib_dir = env("OPENSSL_LIB_DIR").map(PathBuf::from);
        let inc_dir = env("OPENSSL_INCLUDE_DIR").map(PathBuf::from);
        let mut use_openssl = false;

        let (lib_dir, inc_dir) = if lib_dir.is_none() || inc_dir.is_none() {
                match find_openssl_dir(&host, &target) {
                    None => {
                        if is_windows {
                            panic!("Missing environment variable OPENSSL_DIR or OPENSSL_DIR is not set")
                        }
                        (PathBuf::new(), PathBuf::new())
                    },
                    Some(openssl_dir) => {
                        let lib_dir = lib_dir.unwrap_or_else(|| openssl_dir.join("lib"));
                        let inc_dir = inc_dir.unwrap_or_else(|| openssl_dir.join("include"));

                        if !Path::new(&lib_dir).exists() {
                            panic!(
                                "OpenSSL library directory does not exist: {}",
                                lib_dir.to_string_lossy()
                            );
                        }

                        if !Path::new(&inc_dir).exists() {
                            panic!(
                                "OpenSSL include directory does not exist: {}",
                                inc_dir.to_string_lossy()
                            )
                        }

                        use_openssl = true;

                        (lib_dir, inc_dir)
                    }
            }
        } else {
            use_openssl = true;
            (lib_dir.unwrap(), inc_dir.unwrap())
        };

        if is_windows {
            let mut lib = String::new();
            lib.push_str(lib_dir.to_string_lossy().as_ref());
            lib.push_str("\\");
            lib.push_str("libeay32.lib");
            cc.flag(&lib);
            cc.include(inc_dir.to_string_lossy().as_ref());
        } else if use_openssl {
            cc.flag(lib_dir.to_string_lossy().as_ref());
            cc.include(inc_dir.to_string_lossy().as_ref());
            cc.flag("-lcrypto");
        } else if is_apple  {
            cc.flag("-DSQLCIPHER_CRYPTO_CC");
            cc.object("/System/Library/Frameworks/SecurityFoundation.framework/SecurityFoundation");
        } else {
            cc.flag("-lcrypto");
        }

        let out_dir = env::var("OUT_DIR").unwrap();
        let out_path = Path::new(&out_dir).join("bindgen.rs");
        fs::copy("sqlite3/bindgen_bundled_version.rs", out_path)
            .expect("Could not copy bindings to output directory");

        cc.compile("libsqlite3.a");
    }

    fn env(name: &str) -> Option<OsString> {
        let prefix = env::var("TARGET").unwrap().to_uppercase().replace("-", "_");
        let prefixed = format!("{}_{}", prefix, name);
        let var = env::var_os(&prefixed);

        match var {
            None => env::var_os(name),
            _ => var
        }
    }

    fn find_openssl_dir(host: &String, target: &String) -> Option<PathBuf> {
        let openssl_dir = env("OPENSSL_DIR");

        match openssl_dir {
            Some(path) => Some(PathBuf::from(path)),
            None => {
                let openssl_dir = env("OPENSSL_DIR");

                match openssl_dir {
                    Some(path) => Some(PathBuf::from(path)),
                    None => {
                        if host.contains("apple-darwin") && target.contains("apple-darwin") {
                            let homebrew = Path::new("/usr/local/opt/openssl@1.1");
                            if homebrew.exists() {
                                return Some(homebrew.to_path_buf().into());
                            }
                            let homebrew = Path::new("/usr/local/opt/openssl");
                            if homebrew.exists() {
                                return Some(homebrew.to_path_buf().into());
                            }
                            None
                        } else {
                            None
                        }
                    }
                }
            }
        }
    }
}

#[cfg(not(feature = "bundled"))]
mod build {
    extern crate pkg_config;

    #[cfg(all(feature = "vcpkg", target_env = "msvc"))]
    extern crate vcpkg;

    use std::env;

    pub enum HeaderLocation {
        FromEnvironment,
        Wrapper,
        FromPath(String),
    }

    impl From<HeaderLocation> for String {
        fn from(header: HeaderLocation) -> String {
            match header {
                HeaderLocation::FromEnvironment => {
                    let prefix = env_prefix();
                    let mut header = env::var(format!("{}_INCLUDE_DIR", prefix))
                        .expect(&format!("{}_INCLUDE_DIR must be set if {}_LIB_DIR is set", prefix, prefix));
                    header.push_str("/sqlite3.h");
                    header
                }
                HeaderLocation::Wrapper => "wrapper.h".into(),
                HeaderLocation::FromPath(path) => path,
            }
        }
    }

    pub fn main() {
        let header = find_sqlite();
        bindings::write_to_out_dir(header);
    }

    // Prints the necessary cargo link commands and returns the path to the header.
    fn find_sqlite() -> HeaderLocation {
        let link_lib = link_lib();

        // Allow users to specify where to find SQLite.
        if env::var(format!("{}_LIB_DIR", env_prefix())).is_ok() {
            println!("cargo:rustc-link-lib={}", link_lib);
            return HeaderLocation::FromEnvironment;
        }

        if let Some(header) = try_vcpkg() {
            return header;
        }

        // See if pkg-config can do everything for us.
        match pkg_config::Config::new().print_system_libs(false).probe(link_lib) {
            Ok(mut lib) => {
                if let Some(mut header) = lib.include_paths.pop() {
                    header.push("sqlite3.h");
                    HeaderLocation::FromPath(header.to_string_lossy().into())
                } else {
                    HeaderLocation::Wrapper
                }
            }
            Err(_) => {
                // No env var set and pkg-config couldn't help; just output the link-lib
                // request and hope that the library exists on the system paths. We used to
                // output /usr/lib explicitly, but that can introduce other linking problems; see
                // https://github.com/jgallagher/rusqlite/issues/207.
                println!("cargo:rustc-link-lib={}", link_lib);
                HeaderLocation::Wrapper
            }
        }
    }

    #[cfg(all(feature = "vcpkg", target_env = "msvc"))]
    fn try_vcpkg() -> Option<HeaderLocation> {
        // See if vcpkg can find it.
        if let Ok(mut lib) = vcpkg::Config::new().probe(link_lib()) {
            if let Some(mut header) = lib.include_paths.pop() {
                header.push("sqlite3.h");
                return Some(HeaderLocation::FromPath(header.to_string_lossy().into()));
            }
        }
        None
    }

    #[cfg(not(all(feature = "vcpkg", target_env = "msvc")))]
    fn try_vcpkg() -> Option<HeaderLocation> {
        None
    }

    fn env_prefix() -> &'static str {
        if cfg!(feature = "sqlcipher") {
            "SQLCIPHER"
        } else {
            "SQLITE3"
        }
    }

    fn link_lib() -> &'static str {
        if cfg!(feature = "sqlcipher") {
            "sqlcipher"
        } else {
            "sqlite3"
        }
    }

    #[cfg(not(feature = "buildtime_bindgen"))]
    mod bindings {
        use super::HeaderLocation;

        use std::{env, fs};
        use std::path::Path;

        #[cfg_attr(rustfmt, rustfmt_skip)]
        static PREBUILT_BINDGEN_PATHS: &'static [&'static str] = &[
            "bindgen-bindings/bindgen_3.6.8.rs",

            #[cfg(feature = "min_sqlite_version_3_6_11")]
            "bindgen-bindings/bindgen_3.6.11.rs",

            #[cfg(feature = "min_sqlite_version_3_6_23")]
            "bindgen-bindings/bindgen_3.6.23.rs",

            #[cfg(feature = "min_sqlite_version_3_7_3")]
            "bindgen-bindings/bindgen_3.7.3.rs",

            #[cfg(feature = "min_sqlite_version_3_7_4")]
            "bindgen-bindings/bindgen_3.7.4.rs",

            #[cfg(feature = "min_sqlite_version_3_7_16")]
            "bindgen-bindings/bindgen_3.7.16.rs",
        ];

        pub fn write_to_out_dir(_header: HeaderLocation) {
            let out_dir = env::var("OUT_DIR").unwrap();
            let out_path = Path::new(&out_dir).join("bindgen.rs");
            let in_path = PREBUILT_BINDGEN_PATHS[PREBUILT_BINDGEN_PATHS.len() - 1];
            fs::copy(in_path, out_path).expect("Could not copy bindings to output directory");
        }
    }

    #[cfg(feature = "buildtime_bindgen")]
    mod bindings {
        extern crate bindgen;

        use self::bindgen::callbacks::{ParseCallbacks, IntKind};
        use super::HeaderLocation;

        use std::env;
        use std::io::Write;
        use std::fs::OpenOptions;
        use std::path::Path;

        #[derive(Debug)]
        struct SqliteTypeChooser;

        impl ParseCallbacks for SqliteTypeChooser {
            fn int_macro(&self, _name: &str, value: i64) -> Option<IntKind> {
                if value >= i32::min_value() as i64 && value <= i32::max_value() as i64 {
                    Some(IntKind::I32)
                } else {
                    None
                }
            }
        }

        pub fn write_to_out_dir(header: HeaderLocation) {
            let header: String = header.into();
            let out_dir = env::var("OUT_DIR").unwrap();
            let mut output = Vec::new();
            bindgen::builder()
                .header(header.clone())
                .parse_callbacks(Box::new(SqliteTypeChooser))
                .rustfmt_bindings(true)
                .generate()
                .expect(&format!("could not run bindgen on header {}", header))
                .write(Box::new(&mut output))
                .expect("could not write output of bindgen");
            let mut output = String::from_utf8(output).expect("bindgen output was not UTF-8?!");

            // rusqlite's functions feature ors in the SQLITE_DETERMINISTIC flag when it can. This flag
            // was added in SQLite 3.8.3, but oring it in in prior versions of SQLite is harmless. We
            // don't want to not build just because this flag is missing (e.g., if we're linking against
            // SQLite 3.7.x), so append the flag manually if it isn't present in bindgen's output.
            if !output.contains("pub const SQLITE_DETERMINISTIC") {
                output.push_str("\npub const SQLITE_DETERMINISTIC: i32 = 2048;\n");
            }

            let path = Path::new(&out_dir).join("bindgen.rs");

            let mut file = OpenOptions::new()
                .write(true)
                .truncate(true)
                .create(true)
                .open(path.clone())
                .expect(&format!("Could not write to {:?}", path));

            file.write_all(output.as_bytes()).expect(&format!("Could not write to {:?}", path));
        }
    }
}
<|endoftext|>


<commit_before>use cairo;
use cairo::MatrixTrait;

use aspect_ratio::AspectRatio;
use drawing_ctx;
use drawing_ctx::RsvgDrawingCtx;
use util::*;
use viewbox::*;

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum ClipMode {
    ClipToViewport,
    ClipToVbox,
}

pub fn draw_in_viewport<F>(
    vx: f64,
    vy: f64,
    vw: f64,
    vh: f64,
    clip_mode: ClipMode,
    do_clip: bool,
    vbox: Option<ViewBox>,
    preserve_aspect_ratio: AspectRatio,
    affine: cairo::Matrix,
    draw_ctx: *const RsvgDrawingCtx,
    draw_fn: F,
) where
    F: FnOnce(),
{
    let mut ctx = RsvgDrawingCtxWrapper(draw_ctx);

    in_viewport(
        &mut ctx,
        vx,
        vy,
        vw,
        vh,
        clip_mode,
        do_clip,
        vbox,
        preserve_aspect_ratio,
        affine,
        draw_fn,
    );
}

trait ViewportCtx {
    fn push_view_box(&mut self, width: f64, height: f64);
    fn pop_view_box(&mut self);
    fn push_discrete_layer(&mut self);
    fn pop_discrete_layer(&mut self);
    fn add_clipping_rect(&mut self, x: f64, y: f64, w: f64, h: f64);
    fn set_affine(&mut self, affine: cairo::Matrix);
}

struct RsvgDrawingCtxWrapper(pub *const RsvgDrawingCtx);

impl ViewportCtx for RsvgDrawingCtxWrapper {
    fn push_view_box(&mut self, width: f64, height: f64) {
        drawing_ctx::push_view_box(self.0, width, height);
    }

    fn pop_view_box(&mut self) {
        drawing_ctx::pop_view_box(self.0);
    }

    fn push_discrete_layer(&mut self) {
        drawing_ctx::push_discrete_layer(self.0);
    }

    fn pop_discrete_layer(&mut self) {
        drawing_ctx::pop_discrete_layer(self.0);
    }

    fn add_clipping_rect(&mut self, x: f64, y: f64, w: f64, h: f64) {
        drawing_ctx::add_clipping_rect(self.0, x, y, w, h);
    }

    fn set_affine(&mut self, affine: cairo::Matrix) {
        drawing_ctx::set_current_state_affine(self.0, affine);
    }
}

fn in_viewport<F>(
    ctx: &mut ViewportCtx,
    vx: f64,
    vy: f64,
    vw: f64,
    vh: f64,
    clip_mode: ClipMode,
    do_clip: bool,
    vbox: Option<ViewBox>,
    preserve_aspect_ratio: AspectRatio,
    mut affine: cairo::Matrix,
    draw_fn: F,
) where
    F: FnOnce(),
{
    // width or height set to 0 disables rendering of the element
    // https://www.w3.org/TR/SVG/struct.html#SVGElementWidthAttribute
    // https://www.w3.org/TR/SVG/struct.html#UseElementWidthAttribute
    // https://www.w3.org/TR/SVG/struct.html#ImageElementWidthAttribute
    // https://www.w3.org/TR/SVG/painting.html#MarkerWidthAttribute

    if double_equals(vw, 0.0) || double_equals(vh, 0.0) {
        return;
    }

    let old_affine = affine;

    if let Some(vbox) = vbox {
        // the preserveAspectRatio attribute is only used if viewBox is specified
        // https://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute

        if double_equals(vbox.0.width, 0.0) || double_equals(vbox.0.height, 0.0) {
            // Width or height of 0 for the viewBox disables rendering of the element
            // https://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
            return;
        }

        ctx.push_view_box(vbox.0.width, vbox.0.height);
        ctx.push_discrete_layer();

        let (x, y, w, h) =
            preserve_aspect_ratio.compute(vbox.0.width, vbox.0.height, vx, vy, vw, vh);

        affine.translate(x, y);
        affine.scale(w / vbox.0.width, h / vbox.0.height);
        affine.translate(-vbox.0.x, -vbox.0.y);

        ctx.set_affine(affine);

        if do_clip && clip_mode == ClipMode::ClipToVbox {
            ctx.add_clipping_rect(vbox.0.x, vbox.0.y, vbox.0.width, vbox.0.height);
        }
    } else {
        ctx.push_view_box(vw, vh);
        ctx.push_discrete_layer();

        affine.translate(vx, vy);
        ctx.set_affine(affine);
    }

    if do_clip && clip_mode == ClipMode::ClipToViewport {
        ctx.set_affine(old_affine);
        ctx.add_clipping_rect(vx, vy, vw, vh);
        ctx.set_affine(affine);
    }

    draw_fn();

    ctx.pop_discrete_layer();
    ctx.pop_view_box();
}

#[cfg(test)]
mod tests {
    use super::*;
    use parsers::Parse;

    #[derive(Default, PartialEq)]
    struct Ctx {
        pub view_box_size: Option<(f64, f64)>,
        pub clipping_rect: Option<(f64, f64, f64, f64)>,
        pub affine: Option<cairo::Matrix>,

        pub expected_view_box_size: Option<(f64, f64)>,
        pub expected_clipping_rect: Option<(f64, f64, f64, f64)>,
        pub expected_affine: Option<cairo::Matrix>,
    }

    impl ViewportCtx for Ctx {
        fn push_view_box(&mut self, width: f64, height: f64) {
            self.view_box_size = Some((width, height));
        }

        fn pop_view_box(&mut self) {}

        fn push_discrete_layer(&mut self) {}

        fn pop_discrete_layer(&mut self) {}

        fn add_clipping_rect(&mut self, x: f64, y: f64, w: f64, h: f64) {
            self.clipping_rect = Some((x, y, w, h));
        }

        fn set_affine(&mut self, affine: cairo::Matrix) {
            self.affine = Some(affine);
        }
    }

    fn call_in_viewport(
        vx: f64,
        vy: f64,
        vw: f64,
        vh: f64,
        clip_mode: ClipMode,
        do_clip: bool,
        vbox: Option<ViewBox>,
        preserve_aspect_ratio: AspectRatio,
        affine: cairo::Matrix,
        ctx: &mut Ctx,
    ) {
        in_viewport(
            ctx,
            vx,
            vy,
            vw,
            vh,
            clip_mode,
            do_clip,
            vbox,
            preserve_aspect_ratio,
            affine,
            || (),
        );

        assert_eq!(ctx.view_box_size, ctx.expected_view_box_size);
        assert_eq!(ctx.clipping_rect, ctx.expected_clipping_rect);
        assert_eq!(ctx.affine, ctx.expected_affine);
    }

    #[test]
    fn clip_to_viewport() {
        let mut affine = cairo::Matrix::identity();
        affine.scale(0.25, 0.25);

        let mut ctx = Ctx {
            view_box_size: None,
            clipping_rect: None,
            affine: None,

            expected_view_box_size: Some((40.0, 40.0)),
            expected_clipping_rect: Some((10.0, 10.0, 10.0, 10.0)),
            expected_affine: Some(affine),
        };

        call_in_viewport(
            10.0,
            10.0,
            10.0,
            10.0,
            ClipMode::ClipToViewport,
            true,
            Some(ViewBox(cairo::Rectangle {
                x: 40.0,
                y: 40.0,
                width: 40.0,
                height: 40.0,
            })),
            AspectRatio::parse("xMidYMid meet", ()).unwrap(),
            cairo::Matrix::identity(),
            &mut ctx,
        );
    }

    #[test]
    fn clip_to_vbox() {
        let mut affine = cairo::Matrix::identity();
        affine.translate(10.0, 10.0);
        affine.scale(0.40, 0.40);

        let mut ctx = Ctx {
            view_box_size: None,
            clipping_rect: None,
            affine: None,

            expected_view_box_size: Some((50.0, 50.0)),
            expected_clipping_rect: Some((0.0, 0.0, 50.0, 50.0)),
            expected_affine: Some(affine),
        };

        call_in_viewport(
            10.0,
            10.0,
            20.0,
            20.0,
            ClipMode::ClipToVbox,
            true,
            Some(ViewBox(cairo::Rectangle {
                x: 0.0,
                y: 0.0,
                width: 50.0,
                height: 50.0,
            })),
            AspectRatio::parse("xMidYMid meet", ()).unwrap(),
            cairo::Matrix::identity(),
            &mut ctx,
        );
    }
}
<commit_msg>viewport.rs: Use approx_eq_cairo() instead of double_equals()<commit_after>use cairo;
use cairo::MatrixTrait;

use aspect_ratio::AspectRatio;
use drawing_ctx::{self, RsvgDrawingCtx};
use float_eq_cairo::ApproxEqCairo;
use viewbox::*;

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum ClipMode {
    ClipToViewport,
    ClipToVbox,
}

pub fn draw_in_viewport<F>(
    vx: f64,
    vy: f64,
    vw: f64,
    vh: f64,
    clip_mode: ClipMode,
    do_clip: bool,
    vbox: Option<ViewBox>,
    preserve_aspect_ratio: AspectRatio,
    affine: cairo::Matrix,
    draw_ctx: *const RsvgDrawingCtx,
    draw_fn: F,
) where
    F: FnOnce(),
{
    let mut ctx = RsvgDrawingCtxWrapper(draw_ctx);

    in_viewport(
        &mut ctx,
        vx,
        vy,
        vw,
        vh,
        clip_mode,
        do_clip,
        vbox,
        preserve_aspect_ratio,
        affine,
        draw_fn,
    );
}

trait ViewportCtx {
    fn push_view_box(&mut self, width: f64, height: f64);
    fn pop_view_box(&mut self);
    fn push_discrete_layer(&mut self);
    fn pop_discrete_layer(&mut self);
    fn add_clipping_rect(&mut self, x: f64, y: f64, w: f64, h: f64);
    fn set_affine(&mut self, affine: cairo::Matrix);
}

struct RsvgDrawingCtxWrapper(pub *const RsvgDrawingCtx);

impl ViewportCtx for RsvgDrawingCtxWrapper {
    fn push_view_box(&mut self, width: f64, height: f64) {
        drawing_ctx::push_view_box(self.0, width, height);
    }

    fn pop_view_box(&mut self) {
        drawing_ctx::pop_view_box(self.0);
    }

    fn push_discrete_layer(&mut self) {
        drawing_ctx::push_discrete_layer(self.0);
    }

    fn pop_discrete_layer(&mut self) {
        drawing_ctx::pop_discrete_layer(self.0);
    }

    fn add_clipping_rect(&mut self, x: f64, y: f64, w: f64, h: f64) {
        drawing_ctx::add_clipping_rect(self.0, x, y, w, h);
    }

    fn set_affine(&mut self, affine: cairo::Matrix) {
        drawing_ctx::set_current_state_affine(self.0, affine);
    }
}

fn in_viewport<F>(
    ctx: &mut ViewportCtx,
    vx: f64,
    vy: f64,
    vw: f64,
    vh: f64,
    clip_mode: ClipMode,
    do_clip: bool,
    vbox: Option<ViewBox>,
    preserve_aspect_ratio: AspectRatio,
    mut affine: cairo::Matrix,
    draw_fn: F,
) where
    F: FnOnce(),
{
    // width or height set to 0 disables rendering of the element
    // https://www.w3.org/TR/SVG/struct.html#SVGElementWidthAttribute
    // https://www.w3.org/TR/SVG/struct.html#UseElementWidthAttribute
    // https://www.w3.org/TR/SVG/struct.html#ImageElementWidthAttribute
    // https://www.w3.org/TR/SVG/painting.html#MarkerWidthAttribute

    if vw.approx_eq_cairo(&0.0) || vh.approx_eq_cairo(&0.0) {
        return;
    }

    let old_affine = affine;

    if let Some(vbox) = vbox {
        // the preserveAspectRatio attribute is only used if viewBox is specified
        // https://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute

        if vbox.0.width.approx_eq_cairo(&0.0) || vbox.0.height.approx_eq_cairo(&0.0) {
            // Width or height of 0 for the viewBox disables rendering of the element
            // https://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
            return;
        }

        ctx.push_view_box(vbox.0.width, vbox.0.height);
        ctx.push_discrete_layer();

        let (x, y, w, h) =
            preserve_aspect_ratio.compute(vbox.0.width, vbox.0.height, vx, vy, vw, vh);

        affine.translate(x, y);
        affine.scale(w / vbox.0.width, h / vbox.0.height);
        affine.translate(-vbox.0.x, -vbox.0.y);

        ctx.set_affine(affine);

        if do_clip && clip_mode == ClipMode::ClipToVbox {
            ctx.add_clipping_rect(vbox.0.x, vbox.0.y, vbox.0.width, vbox.0.height);
        }
    } else {
        ctx.push_view_box(vw, vh);
        ctx.push_discrete_layer();

        affine.translate(vx, vy);
        ctx.set_affine(affine);
    }

    if do_clip && clip_mode == ClipMode::ClipToViewport {
        ctx.set_affine(old_affine);
        ctx.add_clipping_rect(vx, vy, vw, vh);
        ctx.set_affine(affine);
    }

    draw_fn();

    ctx.pop_discrete_layer();
    ctx.pop_view_box();
}

#[cfg(test)]
mod tests {
    use super::*;
    use parsers::Parse;

    #[derive(Default, PartialEq)]
    struct Ctx {
        pub view_box_size: Option<(f64, f64)>,
        pub clipping_rect: Option<(f64, f64, f64, f64)>,
        pub affine: Option<cairo::Matrix>,

        pub expected_view_box_size: Option<(f64, f64)>,
        pub expected_clipping_rect: Option<(f64, f64, f64, f64)>,
        pub expected_affine: Option<cairo::Matrix>,
    }

    impl ViewportCtx for Ctx {
        fn push_view_box(&mut self, width: f64, height: f64) {
            self.view_box_size = Some((width, height));
        }

        fn pop_view_box(&mut self) {}

        fn push_discrete_layer(&mut self) {}

        fn pop_discrete_layer(&mut self) {}

        fn add_clipping_rect(&mut self, x: f64, y: f64, w: f64, h: f64) {
            self.clipping_rect = Some((x, y, w, h));
        }

        fn set_affine(&mut self, affine: cairo::Matrix) {
            self.affine = Some(affine);
        }
    }

    fn call_in_viewport(
        vx: f64,
        vy: f64,
        vw: f64,
        vh: f64,
        clip_mode: ClipMode,
        do_clip: bool,
        vbox: Option<ViewBox>,
        preserve_aspect_ratio: AspectRatio,
        affine: cairo::Matrix,
        ctx: &mut Ctx,
    ) {
        in_viewport(
            ctx,
            vx,
            vy,
            vw,
            vh,
            clip_mode,
            do_clip,
            vbox,
            preserve_aspect_ratio,
            affine,
            || (),
        );

        assert_eq!(ctx.view_box_size, ctx.expected_view_box_size);
        assert_eq!(ctx.clipping_rect, ctx.expected_clipping_rect);
        assert_eq!(ctx.affine, ctx.expected_affine);
    }

    #[test]
    fn clip_to_viewport() {
        let mut affine = cairo::Matrix::identity();
        affine.scale(0.25, 0.25);

        let mut ctx = Ctx {
            view_box_size: None,
            clipping_rect: None,
            affine: None,

            expected_view_box_size: Some((40.0, 40.0)),
            expected_clipping_rect: Some((10.0, 10.0, 10.0, 10.0)),
            expected_affine: Some(affine),
        };

        call_in_viewport(
            10.0,
            10.0,
            10.0,
            10.0,
            ClipMode::ClipToViewport,
            true,
            Some(ViewBox(cairo::Rectangle {
                x: 40.0,
                y: 40.0,
                width: 40.0,
                height: 40.0,
            })),
            AspectRatio::parse("xMidYMid meet", ()).unwrap(),
            cairo::Matrix::identity(),
            &mut ctx,
        );
    }

    #[test]
    fn clip_to_vbox() {
        let mut affine = cairo::Matrix::identity();
        affine.translate(10.0, 10.0);
        affine.scale(0.40, 0.40);

        let mut ctx = Ctx {
            view_box_size: None,
            clipping_rect: None,
            affine: None,

            expected_view_box_size: Some((50.0, 50.0)),
            expected_clipping_rect: Some((0.0, 0.0, 50.0, 50.0)),
            expected_affine: Some(affine),
        };

        call_in_viewport(
            10.0,
            10.0,
            20.0,
            20.0,
            ClipMode::ClipToVbox,
            true,
            Some(ViewBox(cairo::Rectangle {
                x: 0.0,
                y: 0.0,
                width: 50.0,
                height: 50.0,
            })),
            AspectRatio::parse("xMidYMid meet", ()).unwrap(),
            cairo::Matrix::identity(),
            &mut ctx,
        );
    }
}
<|endoftext|>


<commit_before><commit_msg>libcore: Remove all uses of `~str` from `libcore`.<commit_after><|endoftext|>


<commit_before>extern crate libloading;
extern crate rand;
extern crate test_server;

use std::fs;
use std::path::Path;
use std::str;
use test_server::futures::{Future, Stream};
use test_server::hyper;

#[cfg(target_os = "windows")]
const LOG_FILE_PATH: &str = "ctehxk2.log";
#[cfg(not(target_os = "windows"))]
const LOG_FILE_PATH: &str = "libctehxk2.log";

#[cfg(target_os = "windows")]
const LIB_PATH: &str = "../../target/debug/ctehxk2.dll";
#[cfg(target_os = "linux")]
const LIB_PATH: &str = "../../target/debug/libctehxk2.so";
#[cfg(target_os = "macos")]
const LIB_PATH: &str = "../../target/debug/libctehxk2.dylib";

#[test]
fn with_config_file() {
    let server = test_server::serve(Some(String::from("127.0.0.1:65432")));
    server.reply().status(hyper::Ok).body("0");

    match libloading::Library::new(LIB_PATH) {
        Ok(lib) => {
            let init: libloading::Symbol<fn(u16, u16) -> i8> =
                unsafe { lib.get(b"CT_init").unwrap() };

            let ctn = rand::random::<u16>();
            let pn = rand::random::<u16>();

            assert_eq!(0, init(ctn, pn));
        }
        _ => assert!(false, format!("loading library from {}", LIB_PATH)),
    }

    let (method, uri, _version, _headers, body) = server.request().unwrap().deconstruct();

    assert_eq!(hyper::Method::Post, method);
    assert_eq!("/yaml/ct_init/17/321", uri.path());
    assert!(body.concat2().wait().unwrap().is_empty());

    assert!(Path::new(LOG_FILE_PATH).exists());

    let metadata = fs::metadata(LOG_FILE_PATH).unwrap();
    assert!(metadata.len() > 0);
}
<commit_msg>adjust libloading usage<commit_after>extern crate libloading;
extern crate rand;
extern crate test_server;

use libloading::{Library, Symbol};
use std::fs;
use std::path::Path;
use std::str;
use test_server::futures::{Future, Stream};
use test_server::hyper;

#[cfg(target_os = "windows")]
const LOG_FILE_PATH: &str = "ctehxk2.log";
#[cfg(not(target_os = "windows"))]
const LOG_FILE_PATH: &str = "libctehxk2.log";

#[cfg(target_os = "windows")]
const LIB_PATH: &str = "../../target/debug/ctehxk2.dll";
#[cfg(target_os = "linux")]
const LIB_PATH: &str = "../../target/debug/libctehxk2.so";
#[cfg(target_os = "macos")]
const LIB_PATH: &str = "../../target/debug/libctehxk2.dylib";

#[test]
fn with_config_file() {
    let server = test_server::serve(Some(String::from("127.0.0.1:65432")));
    server.reply().status(hyper::Ok).body("0");

    match Library::new(LIB_PATH) {
        Ok(lib) => {
            let init: Symbol<unsafe extern "system" fn(u16, u16) -> i8> =
                unsafe { lib.get(b"CT_init").unwrap() };

            let ctn = rand::random::<u16>();
            let pn = rand::random::<u16>();

            unsafe {
                assert_eq!(0, init(ctn, pn));
            }
        }
        _ => assert!(false, format!("loading library from {}", LIB_PATH)),
    }

    let (method, uri, _version, _headers, body) = server.request().unwrap().deconstruct();

    assert_eq!(hyper::Method::Post, method);
    assert_eq!("/yaml/ct_init/17/321", uri.path());
    assert!(body.concat2().wait().unwrap().is_empty());

    assert!(Path::new(LOG_FILE_PATH).exists());

    let metadata = fs::metadata(LOG_FILE_PATH).unwrap();
    assert!(metadata.len() > 0);
}
<|endoftext|>


<commit_before>//! This example demonstrates asynchronous subscriptions with warp and tokio 0.2

use std::{pin::Pin, sync::Arc, time::Duration};

use futures::{Future, FutureExt as _, Stream};
use juniper::{DefaultScalarValue, EmptyMutation, FieldError, RootNode};
use juniper_subscriptions::Coordinator;
use juniper_warp::{playground_filter, subscriptions::graphql_subscriptions};
use warp::{http::Response, Filter};

#[derive(Clone)]
struct Context {}

impl juniper::Context for Context {}

#[derive(Clone, Copy, juniper::GraphQLEnum)]
enum UserKind {
    Admin,
    User,
    Guest,
}

struct User {
    id: i32,
    kind: UserKind,
    name: String,
}

// Field resolvers implementation
#[juniper::graphql_object(Context = Context)]
impl User {
    fn id(&self) -> i32 {
        self.id
    }

    fn kind(&self) -> UserKind {
        self.kind
    }

    fn name(&self) -> &str {
        &self.name
    }

    async fn friends(&self) -> Vec<User> {
        if self.id == 1 {
            return vec![
                User {
                    id: 11,
                    kind: UserKind::User,
                    name: "user11".into(),
                },
                User {
                    id: 12,
                    kind: UserKind::Admin,
                    name: "user12".into(),
                },
                User {
                    id: 13,
                    kind: UserKind::Guest,
                    name: "user13".into(),
                },
            ];
        } else if self.id == 2 {
            return vec![User {
                id: 21,
                kind: UserKind::User,
                name: "user21".into(),
            }];
        } else if self.id == 3 {
            return vec![
                User {
                    id: 31,
                    kind: UserKind::User,
                    name: "user31".into(),
                },
                User {
                    id: 32,
                    kind: UserKind::Guest,
                    name: "user32".into(),
                },
            ];
        } else {
            return vec![];
        }
    }
}

struct Query;

#[juniper::graphql_object(Context = Context)]
impl Query {
    async fn users(id: i32) -> Vec<User> {
        vec![User {
            id,
            kind: UserKind::Admin,
            name: "User Name".into(),
        }]
    }
}

type UsersStream = Pin<Box<dyn Stream<Item = Result<User, FieldError>> + Send>>;

struct Subscription;

#[juniper::graphql_subscription(Context = Context)]
impl Subscription {
    async fn users() -> UsersStream {
        let mut counter = 0;
        let stream = tokio::time::interval(Duration::from_secs(5)).map(move |_| {
            counter += 1;
            if counter == 2 {
                Err(FieldError::new(
                    "some field error from handler",
                    Value::Scalar(DefaultScalarValue::String(
                        "some additional string".to_string(),
                    )),
                ))
            } else {
                Ok(User {
                    id: counter,
                    kind: UserKind::Admin,
                    name: "stream user".to_string(),
                })
            }
        });

        Box::pin(stream)
    }
}

type Schema = RootNode<'static, Query, EmptyMutation<Context>, Subscription>;

fn schema() -> Schema {
    Schema::new(Query, EmptyMutation::new(), Subscription)
}

#[tokio::main]
async fn main() {
    ::std::env::set_var("RUST_LOG", "warp_subscriptions");
    env_logger::init();

    let log = warp::log("warp_server");

    let homepage = warp::path::end().map(|| {
        Response::builder()
            .header("content-type", "text/html")
            .body("
juniper_subscriptions demo

visit graphql playground".to_string())
    });

    let qm_schema = schema();
    let qm_state = warp::any().map(move || Context {});
    let qm_graphql_filter = juniper_warp::make_graphql_filter(qm_schema, qm_state.boxed());

    let sub_state = warp::any().map(move || Context {});
    let coordinator = Arc::new(juniper_subscriptions::Coordinator::new(schema()));

    log::info!("Listening on 127.0.0.1:8080");

    let routes = (warp::path("subscriptions")
        .and(warp::ws())
        .and(sub_state.clone())
        .and(warp::any().map(move || Arc::clone(&coordinator)))
        .map(
            |ws: warp::ws::Ws,
             ctx: Context,
             coordinator: Arc<Coordinator<'static, _, _, _, _, _>>| {
                ws.on_upgrade(|websocket| -> Pin<Box<dyn Future<Output = ()> + Send>> {
                    graphql_subscriptions(websocket, coordinator, ctx).boxed()
                })
            },
        ))
    .or(warp::post()
        .and(warp::path("graphql"))
        .and(qm_graphql_filter))
    .or(warp::get()
        .and(warp::path("playground"))
        .and(playground_filter("/graphql", Some("/subscriptions"))))
    .or(homepage)
    .with(log);

    warp::serve(routes).run(([127, 0, 0, 1], 8080)).await;
}
<commit_msg>Fix websocket connection in warp subscriptions example (#583)<commit_after>//! This example demonstrates asynchronous subscriptions with warp and tokio 0.2

use std::{pin::Pin, sync::Arc, time::Duration};

use futures::{Future, FutureExt as _, Stream};
use juniper::{DefaultScalarValue, EmptyMutation, FieldError, RootNode};
use juniper_subscriptions::Coordinator;
use juniper_warp::{playground_filter, subscriptions::graphql_subscriptions};
use warp::{http::Response, Filter};

#[derive(Clone)]
struct Context {}

impl juniper::Context for Context {}

#[derive(Clone, Copy, juniper::GraphQLEnum)]
enum UserKind {
    Admin,
    User,
    Guest,
}

struct User {
    id: i32,
    kind: UserKind,
    name: String,
}

// Field resolvers implementation
#[juniper::graphql_object(Context = Context)]
impl User {
    fn id(&self) -> i32 {
        self.id
    }

    fn kind(&self) -> UserKind {
        self.kind
    }

    fn name(&self) -> &str {
        &self.name
    }

    async fn friends(&self) -> Vec<User> {
        if self.id == 1 {
            return vec![
                User {
                    id: 11,
                    kind: UserKind::User,
                    name: "user11".into(),
                },
                User {
                    id: 12,
                    kind: UserKind::Admin,
                    name: "user12".into(),
                },
                User {
                    id: 13,
                    kind: UserKind::Guest,
                    name: "user13".into(),
                },
            ];
        } else if self.id == 2 {
            return vec![User {
                id: 21,
                kind: UserKind::User,
                name: "user21".into(),
            }];
        } else if self.id == 3 {
            return vec![
                User {
                    id: 31,
                    kind: UserKind::User,
                    name: "user31".into(),
                },
                User {
                    id: 32,
                    kind: UserKind::Guest,
                    name: "user32".into(),
                },
            ];
        } else {
            return vec![];
        }
    }
}

struct Query;

#[juniper::graphql_object(Context = Context)]
impl Query {
    async fn users(id: i32) -> Vec<User> {
        vec![User {
            id,
            kind: UserKind::Admin,
            name: "User Name".into(),
        }]
    }
}

type UsersStream = Pin<Box<dyn Stream<Item = Result<User, FieldError>> + Send>>;

struct Subscription;

#[juniper::graphql_subscription(Context = Context)]
impl Subscription {
    async fn users() -> UsersStream {
        let mut counter = 0;
        let stream = tokio::time::interval(Duration::from_secs(5)).map(move |_| {
            counter += 1;
            if counter == 2 {
                Err(FieldError::new(
                    "some field error from handler",
                    Value::Scalar(DefaultScalarValue::String(
                        "some additional string".to_string(),
                    )),
                ))
            } else {
                Ok(User {
                    id: counter,
                    kind: UserKind::Admin,
                    name: "stream user".to_string(),
                })
            }
        });

        Box::pin(stream)
    }
}

type Schema = RootNode<'static, Query, EmptyMutation<Context>, Subscription>;

fn schema() -> Schema {
    Schema::new(Query, EmptyMutation::new(), Subscription)
}

#[tokio::main]
async fn main() {
    ::std::env::set_var("RUST_LOG", "warp_subscriptions");
    env_logger::init();

    let log = warp::log("warp_server");

    let homepage = warp::path::end().map(|| {
        Response::builder()
            .header("content-type", "text/html")
            .body("
juniper_subscriptions demo

visit graphql playground".to_string())
    });

    let qm_schema = schema();
    let qm_state = warp::any().map(move || Context {});
    let qm_graphql_filter = juniper_warp::make_graphql_filter(qm_schema, qm_state.boxed());

    let sub_state = warp::any().map(move || Context {});
    let coordinator = Arc::new(juniper_subscriptions::Coordinator::new(schema()));

    log::info!("Listening on 127.0.0.1:8080");

    let routes = (warp::path("subscriptions")
        .and(warp::ws())
        .and(sub_state.clone())
        .and(warp::any().map(move || Arc::clone(&coordinator)))
        .map(
            |ws: warp::ws::Ws,
             ctx: Context,
             coordinator: Arc<Coordinator<'static, _, _, _, _, _>>| {
                ws.on_upgrade(|websocket| -> Pin<Box<dyn Future<Output = ()> + Send>> {
                    graphql_subscriptions(websocket, coordinator, ctx).boxed()
                })
            },
        ))
        .map(|reply| {
            // TODO#584: remove this workaround
            warp::reply::with_header(reply, "Sec-WebSocket-Protocol", "graphql-ws")
        })
    .or(warp::post()
        .and(warp::path("graphql"))
        .and(qm_graphql_filter))
    .or(warp::get()
        .and(warp::path("playground"))
        .and(playground_filter("/graphql", Some("/subscriptions"))))
    .or(homepage)
    .with(log);

    warp::serve(routes).run(([127, 0, 0, 1], 8080)).await;
}
<|endoftext|>