<commit_before>/**
 *   Mles Asynchronous Server
 *
 *   Copyright (C) 2017  Mles developers
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
extern crate tokio_core;
extern crate futures;
extern crate mles_utils;

use std::collections::HashMap;
use std::rc::Rc;
use std::cell::RefCell;
use std::iter;
use std::io::{Error, ErrorKind};
use std::{process, env};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};

use tokio_core::net::TcpListener;
//use tokio_core::net::TcpStream;
use tokio_core::reactor::Core;
use tokio_core::io::{self, Io};

use futures::Future;
use futures::stream::{self, Stream};
use futures::sync::mpsc::unbounded;
use mles_utils::*;

const HDRL: usize = 4; //hdr len
const KEYL: usize = 8; //key len

fn main() {
    let mut peer = "".to_string();
    let mut argcnt = 0;
    for arg in env::args() {
        argcnt += 1;
        if 2 == argcnt {
            peer = arg;
            peer += ":8077";
            match peer.parse::<SocketAddr>() {
                Ok(_) => {},
                    Err(err) => {
                        println!("Error: {}\nUsage: mles [peer-address]", err);
                        process::exit(1);
                    },
            }
        }
        if argcnt > 2 {
            println!("Usage: mles [peer-address]");
            process::exit(1);
        }
    }

    let _peer = match peer.parse::<SocketAddr>() {
        Ok(addr) => addr,
        Err(_) => {
            SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0)
        },
    };

    let keyval = match env::var("MLES_KEY") {
        Ok(val) => val,
        Err(_) => "".to_string(),
    };

    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let address = "0.0.0.0:8077".parse().unwrap();
    let socket = match TcpListener::bind(&address, &handle) {
        Ok(listener) => listener,
        Err(err) => {
            println!("Error: {}", err);
            process::exit(1);
        },
    };
    println!("Listening on: {}", address);

    let spawned = Rc::new(RefCell::new(HashMap::new()));
    let channelmsgs = Rc::new(RefCell::new(HashMap::new()));
    let mut cnt = 0;

    //connect to peer
    //let tcp = TcpStream::connect(&peer, &handle);
    //let client = tcp.map_err(|_| ()).and_then(|pstream| {
    //    let _val = pstream.set_nodelay(true).map_err(|_| panic!("Cannot set peer to no delay"));
    //    println!("Adding peer {}", cnt);
    //    Ok((pstream))
    //});

    let srv = socket.incoming().for_each(move |(stream, addr)| {
        println!("New Connection: {}", addr);
        let paddr = match stream.peer_addr() {
                Ok(paddr) => paddr,
                Err(_) => {
                    let addr = "0.0.0.0:0";
                    let addr = addr.parse::<SocketAddr>().unwrap();
                    addr
                }
        };
        let _val = stream.set_nodelay(true).map_err(|_| panic!("Cannot set to no delay"));;

        let (reader, writer) = stream.split();

        let (tx, rx) = unbounded();

        cnt += 1;

        let frame = io::read_exact(reader, vec![0;HDRL]);
        let frame = frame.and_then(move |(reader, payload)| {
            if payload.len() == 0 {
                Err(Error::new(ErrorKind::BrokenPipe, "broken pipe"))
            } else {
                if read_hdr_type(payload.as_slice()) != 'M' as u32 {
                    return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header"));
                }
                let hdr_len = read_hdr_len(payload.as_slice());
                if 0 == hdr_len {
                    return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header len"));
                }
                Ok((reader, hdr_len))
            }
        });

        let paddr_inner = paddr.clone();
        let keyval_inner = keyval.clone();
        let frame = frame.and_then(move |(reader, hdr_len)| {
            let tframe = io::read_exact(reader, vec![0;KEYL]);
            // verify key
            let tframe = tframe.and_then(move |(reader, key)| {
                let hkey;
                let key = read_key(key);
                if 0 == keyval_inner.len() {
                    hkey = do_hash(&paddr_inner);
                }
                else {
                    hkey = do_hash(&keyval_inner);
                }
                if hkey != key {
                    return Err(Error::new(ErrorKind::BrokenPipe, "incorrect remote key"));
                }
                Ok((reader, hdr_len))
            });
            tframe
        });

        let tx_once = tx.clone();
        let spawned_inner = spawned.clone();
        let chanmsgs_inner = channelmsgs.clone();
        let socket_once = frame.and_then(move |(reader, hdr_len)| {
            let tframe = io::read_exact(reader, vec![0;hdr_len]);
            let tframe = tframe.and_then(move |(reader, message)| {
                if 0 == message.len() {
                    return Err(Error::new(ErrorKind::BrokenPipe, "incorrect message len"));
                }
                else {
                    let mut spawned_once = spawned_inner.borrow_mut();
                    let mut chanmsgs_once = chanmsgs_inner.borrow_mut();
                    let decoded_message = message_decode(message.as_slice());
                    let channel = decoded_message.channel.clone();
                    if !spawned_once.contains_key(&channel) {
                        let mut channel_entry = HashMap::new();
                        channel_entry.insert(cnt, tx_once);
                        spawned_once.insert(channel.clone(), channel_entry);

                        let messages: Vec<Vec<u8>> = Vec::new();
                        chanmsgs_once.insert(channel.clone(), messages);
                    }
                    else {
                        let mut channel_entry = spawned_once.get_mut(&channel).unwrap();
                        channel_entry.insert(cnt, tx_once);
                        let chanmsgs = chanmsgs_once.get(&channel).unwrap();
                        for msg in chanmsgs {
                            tx.send(msg.clone()).unwrap();
                        }
                        //TODO try to connect to peer
                    }
                    println!("User {}:{} joined channel {}", cnt, decoded_message.uid, channel);
                    Ok((reader, channel))
                }
            });
            tframe
        });

        let spawned_inner = spawned.clone();
        let chanmsgs_inner = channelmsgs.clone();
        let socket_next = socket_once.and_then(move |(reader, channel)| {
            let channel_next = channel.clone();
            let iter = stream::iter(iter::repeat(()).map(Ok::<(), Error>));
            iter.fold(reader, move |reader, _| {
                let frame = io::read_exact(reader, vec![0;HDRL]);
                let frame = frame.and_then(move |(reader, payload)| {
                    if payload.len() == 0 {
                        Err(Error::new(ErrorKind::BrokenPipe, "broken pipe"))
                    } else {
                        if read_hdr_type(payload.as_slice()) != 'M' as u32 {
                            return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header"));
                        }
                        let hdr_len = read_hdr_len(payload.as_slice());
                        if 0 == hdr_len {
                            return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header len"));
                        }
                        Ok((reader, payload, hdr_len))
                    }
                });

                let frame = frame.and_then(move |(reader, hdr, hdr_len)| {
                    //dummy read key
                    let tframe = io::read_exact(reader, vec![0;KEYL]);
                    let tframe = tframe.and_then(move |(reader, key)| {
                        Ok((reader, hdr, key, hdr_len))
                    });
                    tframe
                });

                let frame = frame.and_then(move |(reader, hdr, key, hdr_len)| {
                    let tframe = io::read_exact(reader, vec![0;hdr_len]);
                    let tframe = tframe.and_then(move |(reader, message)| {
                        if 0 == message.len() {
                            return Err(Error::new(ErrorKind::BrokenPipe, "incorrect message len"));
                        }
                        else {
                            Ok((reader, hdr, key, message))
                        }
                    });
                    tframe
                });

                let spawned = spawned_inner.clone();
                let chanmsgs = chanmsgs_inner.clone();
                let channel = channel_next.clone();
                frame.map(move |(reader, mut hdr, mut key, message)| {
                    key.extend(message);
                    hdr.extend(key);

                    // add to history
                    let mut channel_msgs = chanmsgs.borrow_mut();
                    let mut channel_msg = channel_msgs.get_mut(&channel).unwrap();
                    channel_msg.push(hdr.clone());

                    //distribute
                    let spawned = spawned.borrow();
                    let channels = spawned.get(&channel).unwrap();
                    for (ocnt, tx) in channels {
                        if *ocnt != cnt {
                            tx.send(hdr.clone()).unwrap();
                        }
                    }
                    reader
                })
            })
        });

        let socket_writer = rx.fold(writer, |writer, msg| {
            let amt = io::write_all(writer, msg);
            let amt = amt.map(|(writer, _)| writer);
            amt.map_err(|_| ())
        });

        let channels = spawned.clone();
        let chanmsgs = channelmsgs.clone();
        let socket_reader = socket_next.map_err(|_| ());
        let connection = socket_reader.map(|_| ()).select(socket_writer.map(|_| ()));
        handle.spawn(connection.then(move |_| {
            let mut chans = channels.borrow_mut();
            for (cname, channel) in chans.iter_mut() {
                if channel.contains_key(&cnt) {
                    channel.remove(&cnt);
                    if 0 == channel.len() {
                        let mut channelmsgs = chanmsgs.borrow_mut();
                        channelmsgs.remove(cname);
                        println!("Channel {} dropped.", cname);
                        drop(channel);
                    }
                    break;
                }
            }
            println!("Connection {} for user {} closed.", addr, cnt);
            Ok(())
        }));
        Ok(())
    });

    // execute server
    core.run(srv).unwrap();
}

<commit_msg>Peer thread addition. Tx side needs some tweaking still as rx cannot be copied.<commit_after>/**
 *   Mles Asynchronous Server
 *
 *   Copyright (C) 2017  Mles developers
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
extern crate tokio_core;
extern crate futures;
extern crate mles_utils;

use std::collections::HashMap;
use std::rc::Rc;
use std::cell::RefCell;
use std::iter;
use std::io::{Write, Error, ErrorKind};
use std::{process, env};
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::thread;

use tokio_core::net::TcpListener;
use tokio_core::net::TcpStream;
use tokio_core::reactor::Core;
use tokio_core::io::{self, Io};

use futures::Future;
use futures::stream::{self, Stream};
use futures::sync::mpsc::unbounded;
use mles_utils::*;

const HDRL: usize = 4; //hdr len
const KEYL: usize = 8; //key len

fn main() {
    let mut peer = "".to_string();
    let mut argcnt = 0;
    for arg in env::args() {
        argcnt += 1;
        if 2 == argcnt {
            peer = arg;
            peer += ":8077";
            match peer.parse::<SocketAddr>() {
                Ok(_) => {},
                    Err(err) => {
                        println!("Error: {}\nUsage: mles [peer-address]", err);
                        process::exit(1);
                    },
            }
        }
        if argcnt > 2 {
            println!("Usage: mles [peer-address]");
            process::exit(1);
        }
    }

    let peer = match peer.parse::<SocketAddr>() {
        Ok(addr) => addr,
        Err(_) => {
            SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0)
        },
    };

    let keyval = match env::var("MLES_KEY") {
        Ok(val) => val,
        Err(_) => "".to_string(),
    };

    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let address = "0.0.0.0:8077".parse().unwrap();
    let socket = match TcpListener::bind(&address, &handle) {
        Ok(listener) => listener,
        Err(err) => {
            println!("Error: {}", err);
            process::exit(1);
        },
    };
    println!("Listening on: {}", address);

    let spawned = Rc::new(RefCell::new(HashMap::new()));
    let channelmsgs = Rc::new(RefCell::new(HashMap::new()));
    let mut cnt = 0;

    // peer handling
    let (peer_tx, peer_rx) = unbounded();
    let (peer_tx_stream, peer_rx_stream) = unbounded();
    thread::spawn(move || peer_conn(peer, peer_rx, peer_rx_stream));

    let srv = socket.incoming().for_each(move |(stream, addr)| {
        println!("New Connection: {}", addr);
        let paddr = match stream.peer_addr() {
                Ok(paddr) => paddr,
                Err(_) => {
                    let addr = "0.0.0.0:0";
                    let addr = addr.parse::<SocketAddr>().unwrap();
                    addr
                }
        };
        let _val = stream.set_nodelay(true).map_err(|_| panic!("Cannot set to no delay"));;

        let (reader, writer) = stream.split();

        let (tx, rx) = unbounded();

        cnt += 1;

        let frame = io::read_exact(reader, vec![0;HDRL]);
        let frame = frame.and_then(move |(reader, payload)| {
            if payload.len() == 0 {
                Err(Error::new(ErrorKind::BrokenPipe, "broken pipe"))
            } else {
                if read_hdr_type(payload.as_slice()) != 'M' as u32 {
                    return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header"));
                }
                let hdr_len = read_hdr_len(payload.as_slice());
                if 0 == hdr_len {
                    return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header len"));
                }
                Ok((reader, hdr_len))
            }
        });

        let paddr_inner = paddr.clone();
        let keyval_inner = keyval.clone();
        let frame = frame.and_then(move |(reader, hdr_len)| {
            let tframe = io::read_exact(reader, vec![0;KEYL]);
            // verify key
            let tframe = tframe.and_then(move |(reader, key)| {
                let hkey;
                let key = read_key(key);
                if 0 == keyval_inner.len() {
                    hkey = do_hash(&paddr_inner);
                }
                else {
                    hkey = do_hash(&keyval_inner);
                }
                if hkey != key {
                    return Err(Error::new(ErrorKind::BrokenPipe, "incorrect remote key"));
                }
                Ok((reader, hdr_len))
            });
            tframe
        });

        let tx_once = tx.clone();
        let peer_tx_once = peer_tx.clone();
        let peer_tx_stream_once = peer_tx_stream.clone();
        let spawned_inner = spawned.clone();
        let chanmsgs_inner = channelmsgs.clone();
        let socket_once = frame.and_then(move |(reader, hdr_len)| {
            let tframe = io::read_exact(reader, vec![0;hdr_len]);
            let tframe = tframe.and_then(move |(reader, message)| {
                if 0 == message.len() {
                    return Err(Error::new(ErrorKind::BrokenPipe, "incorrect message len"));
                }
                else {
                    let mut spawned_once = spawned_inner.borrow_mut();
                    let mut chanmsgs_once = chanmsgs_inner.borrow_mut();
                    let decoded_message = message_decode(message.as_slice());
                    let channel = decoded_message.channel.clone();
                    if !spawned_once.contains_key(&channel) {
                        let mut channel_entry = HashMap::new();
                        channel_entry.insert(cnt, tx_once);
                        spawned_once.insert(channel.clone(), channel_entry);

                        let messages: Vec<Vec<u8>> = Vec::new();
                        chanmsgs_once.insert(channel.clone(), messages);
                        //try to connect to peer
                        peer_tx_stream_once.send(tx.clone()).unwrap();
                    }
                    else {
                        let mut channel_entry = spawned_once.get_mut(&channel).unwrap();
                        channel_entry.insert(cnt, tx_once);
                        let chanmsgs = chanmsgs_once.get(&channel).unwrap();
                        for msg in chanmsgs {
                            tx.send(msg.clone()).unwrap();
                        }
                    }
                    println!("User {}:{} joined channel {}", cnt, decoded_message.uid, channel);
                    // forward to peer
                    peer_tx_once.send(message).unwrap();
                    Ok((reader, channel))
                }
            });
            tframe
        });

        let spawned_inner = spawned.clone();
        let chanmsgs_inner = channelmsgs.clone();
        let peer_tx_inner = peer_tx.clone();
        let socket_next = socket_once.and_then(move |(reader, channel)| {
            let channel_next = channel.clone();
            let iter = stream::iter(iter::repeat(()).map(Ok::<(), Error>));
            iter.fold(reader, move |reader, _| {
                let frame = io::read_exact(reader, vec![0;HDRL]);
                let frame = frame.and_then(move |(reader, payload)| {
                    if payload.len() == 0 {
                        Err(Error::new(ErrorKind::BrokenPipe, "broken pipe"))
                    } else {
                        if read_hdr_type(payload.as_slice()) != 'M' as u32 {
                            return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header"));
                        }
                        let hdr_len = read_hdr_len(payload.as_slice());
                        if 0 == hdr_len {
                            return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header len"));
                        }
                        Ok((reader, payload, hdr_len))
                    }
                });

                let frame = frame.and_then(move |(reader, hdr, hdr_len)| {
                    //dummy read key
                    let tframe = io::read_exact(reader, vec![0;KEYL]);
                    let tframe = tframe.and_then(move |(reader, key)| {
                        Ok((reader, hdr, key, hdr_len))
                    });
                    tframe
                });

                let frame = frame.and_then(move |(reader, hdr, key, hdr_len)| {
                    let tframe = io::read_exact(reader, vec![0;hdr_len]);
                    let tframe = tframe.and_then(move |(reader, message)| {
                        if 0 == message.len() {
                            return Err(Error::new(ErrorKind::BrokenPipe, "incorrect message len"));
                        }
                        else {
                            Ok((reader, hdr, key, message))
                        }
                    });
                    tframe
                });

                let spawned = spawned_inner.clone();
                let chanmsgs = chanmsgs_inner.clone();
                let channel = channel_next.clone();
                let peer_tx = peer_tx_inner.clone();
                frame.map(move |(reader, mut hdr, mut key, message)| {
                    key.extend(message);
                    hdr.extend(key);

                    // add to history
                    let mut channel_msgs = chanmsgs.borrow_mut();
                    let mut channel_msg = channel_msgs.get_mut(&channel).unwrap();
                    channel_msg.push(hdr.clone());

                    //distribute
                    let spawned = spawned.borrow();
                    let channels = spawned.get(&channel).unwrap();
                    for (ocnt, tx) in channels {
                        if *ocnt != cnt {
                            tx.send(hdr.clone()).unwrap();
                        }
                    }
                    peer_tx.send(hdr.clone()).unwrap();
                    reader
                })
            })
        });

        let socket_writer = rx.fold(writer, |writer, msg| {
            let amt = io::write_all(writer, msg);
            let amt = amt.map(|(writer, _)| writer);
            amt.map_err(|_| ())
        });

        let channels = spawned.clone();
        let chanmsgs = channelmsgs.clone();
        let socket_reader = socket_next.map_err(|_| ());
        let connection = socket_reader.map(|_| ()).select(socket_writer.map(|_| ()));
        handle.spawn(connection.then(move |_| {
            let mut chans = channels.borrow_mut();
            for (cname, channel) in chans.iter_mut() {
                if channel.contains_key(&cnt) {
                    channel.remove(&cnt);
                    if 0 == channel.len() {
                        let mut channelmsgs = chanmsgs.borrow_mut();
                        channelmsgs.remove(cname);
                        println!("Channel {} dropped.", cname);
                        drop(channel);
                    }
                    break;
                }
            }
            println!("Connection {} for user {} closed.", addr, cnt);
            Ok(())
        }));
        Ok(())
    });

    // execute server
    core.run(srv).unwrap();
}

fn peer_conn(peer: SocketAddr, rx: futures::sync::mpsc::UnboundedReceiver<Vec<u8>>, tx: futures::sync::mpsc::UnboundedReceiver<futures::sync::mpsc::UnboundedSender<Vec<u8>>>) {
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    let srv = tx.for_each(|sink| {

        let tcp = TcpStream::connect(&peer, &handle);
        /*let client = rx.and_then(|msg| {
            let decoded_message = message_decode(msg.as_slice());
            let channel = decoded_message.channel.clone();
            println!("Peer connection {}", channel);
            //writer.write_all(&msg.clone()).unwrap();
            Ok(())
        }); */

        let client = tcp.and_then(|pstream| {
            let _val = pstream.set_nodelay(true).map_err(|_| panic!("Cannot set peer to no delay"));
            println!("Adding peer {}", 0);

            let (reader, mut writer) = pstream.split();

            let frame = io::read_exact(reader, vec![0;HDRL]);
            let frame = frame.and_then(move |(reader, payload)| {
                if payload.len() == 0 {
                    Err(Error::new(ErrorKind::BrokenPipe, "broken pipe"))
                } else {
                    if read_hdr_type(payload.as_slice()) != 'M' as u32 {
                        return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header"));
                    }
                    let hdr_len = read_hdr_len(payload.as_slice());
                    if 0 == hdr_len {
                        return Err(Error::new(ErrorKind::BrokenPipe, "incorrect header len"));
                    }
                    Ok((reader, payload, hdr_len))
                }
            });

            let frame = frame.and_then(move |(reader, hdr, hdr_len)| {
                //dummy read key
                let tframe = io::read_exact(reader, vec![0;KEYL]);
                let tframe = tframe.and_then(move |(reader, key)| {
                    Ok((reader, hdr, key, hdr_len))
                });
                tframe
            });

            let frame = frame.and_then(move |(reader, mut hdr, mut key, hdr_len)| {
                let tframe = io::read_exact(reader, vec![0;hdr_len]);
                let tframe = tframe.and_then(move |(_, message)| {
                    if 0 == message.len() {
                        return Err(Error::new(ErrorKind::BrokenPipe, "incorrect message len"));
                    }
                    else {
                        key.extend(message);
                        hdr.extend(key);
                        sink.send(hdr.clone()).unwrap();
                        //writer.write_all(&hdr.clone()).unwrap();
                        Ok(())
                    }
                });
                tframe
            });

            frame.map(|_| ())
        });

        let client = client.map_err(|_| ());
        handle.spawn(client);
        Ok(())
    });

    core.run(srv).unwrap();
}

<|endoftext|>


<commit_before>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) Nathan Zadoks <nathan@nathan7.eu>,
//               whitequark <whitequark@whitequark.org>
// See the LICENSE file included in this distribution.
#![feature(thread_local)]
extern crate simd;
extern crate fringe;

use fringe::Context;

#[thread_local]
static mut ctx_slot: *mut Context<fringe::OsStack> = 0 as *mut Context<_>;

#[test]
fn context() {
  unsafe extern "C" fn adder(arg: usize) -> ! {
    println!("it's alive! arg: {}", arg);
    let arg = Context::swap(ctx_slot, ctx_slot, arg + 1);
    println!("still alive! arg: {}", arg);
    Context::swap(ctx_slot, ctx_slot, arg + 1);
    panic!("i should be dead");
  }

  unsafe {
    let stack = fringe::OsStack::new(4 << 20).unwrap();
    let mut ctx = Context::new(stack, adder);
    ctx_slot = &mut ctx;

    let ret = Context::swap(ctx_slot, ctx_slot, 10);
    assert_eq!(ret, 11);
    let ret = Context::swap(ctx_slot, ctx_slot, 50);
    assert_eq!(ret, 51);
  }
}

#[test]
fn simd() {
  unsafe extern "C" fn permuter(arg: usize) -> ! {
    // This will crash if the stack is not aligned properly.
    let x = simd::i32x4::splat(arg as i32);
    let y = x * x;
    println!("simd result: {:?}", y);
    Context::swap(ctx_slot, ctx_slot, 0);
    // And try again after a context switch.
    let x = simd::i32x4::splat(arg as i32);
    let y = x * x;
    println!("simd result: {:?}", y);
    Context::swap(ctx_slot, ctx_slot, 0);
    panic!("i should be dead");
  }

  unsafe {
    let stack = fringe::OsStack::new(4 << 20).unwrap();
    let mut ctx = Context::new(stack, permuter);
    ctx_slot = &mut ctx;

    Context::swap(ctx_slot, ctx_slot, 10);
    Context::swap(ctx_slot, ctx_slot, 20);
  }
}
<commit_msg>rename simd -> context_simd<commit_after>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) Nathan Zadoks <nathan@nathan7.eu>,
//               whitequark <whitequark@whitequark.org>
// See the LICENSE file included in this distribution.
#![feature(thread_local)]
extern crate simd;
extern crate fringe;

use fringe::Context;

#[thread_local]
static mut ctx_slot: *mut Context<fringe::OsStack> = 0 as *mut Context<_>;

#[test]
fn context() {
  unsafe extern "C" fn adder(arg: usize) -> ! {
    println!("it's alive! arg: {}", arg);
    let arg = Context::swap(ctx_slot, ctx_slot, arg + 1);
    println!("still alive! arg: {}", arg);
    Context::swap(ctx_slot, ctx_slot, arg + 1);
    panic!("i should be dead");
  }

  unsafe {
    let stack = fringe::OsStack::new(4 << 20).unwrap();
    let mut ctx = Context::new(stack, adder);
    ctx_slot = &mut ctx;

    let ret = Context::swap(ctx_slot, ctx_slot, 10);
    assert_eq!(ret, 11);
    let ret = Context::swap(ctx_slot, ctx_slot, 50);
    assert_eq!(ret, 51);
  }
}

#[test]
fn context_simd() {
  unsafe extern "C" fn permuter(arg: usize) -> ! {
    // This will crash if the stack is not aligned properly.
    let x = simd::i32x4::splat(arg as i32);
    let y = x * x;
    println!("simd result: {:?}", y);
    Context::swap(ctx_slot, ctx_slot, 0);
    // And try again after a context switch.
    let x = simd::i32x4::splat(arg as i32);
    let y = x * x;
    println!("simd result: {:?}", y);
    Context::swap(ctx_slot, ctx_slot, 0);
    panic!("i should be dead");
  }

  unsafe {
    let stack = fringe::OsStack::new(4 << 20).unwrap();
    let mut ctx = Context::new(stack, permuter);
    ctx_slot = &mut ctx;

    Context::swap(ctx_slot, ctx_slot, 10);
    Context::swap(ctx_slot, ctx_slot, 20);
  }
}
<|endoftext|>


<commit_before>extern crate futures;
extern crate futuremio;

use std::net::{TcpListener, TcpStream};
use std::sync::mpsc::channel;
use std::thread;

use futures::Future;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {:?}", stringify!($e), e),
    })
}

#[test]
fn connect() {
    let mut l = t!(futuremio::Loop::new());
    let srv = t!(TcpListener::bind("127.0.0.1:0"));
    let addr = t!(srv.local_addr());
    let t = thread::spawn(move || {
        t!(srv.accept()).0
    });

    let stream = l.tcp_connect(&addr);
    let mine = t!(l.await(stream));
    let theirs = t.join().unwrap();

    assert_eq!(t!(mine.local_addr()), t!(theirs.peer_addr()));
    assert_eq!(t!(theirs.local_addr()), t!(mine.peer_addr()));
}

#[test]
fn accept() {
    let mut l = t!(futuremio::Loop::new());
    let srv = t!(l.tcp_listen(&"127.0.0.1:0".parse().unwrap()));
    let addr = t!(srv.local_addr());

    let (tx, rx) = channel();
    let client = srv.accept().map(move |t| {
        tx.send(()).unwrap();
        t.0
    });
    assert!(rx.try_recv().is_err());
    let t = thread::spawn(move || {
        TcpStream::connect(&addr).unwrap()
    });

    let mine = t!(l.await(client));
    let theirs = t.join().unwrap();

    assert_eq!(t!(mine.local_addr()), t!(theirs.peer_addr()));
    assert_eq!(t!(theirs.local_addr()), t!(mine.peer_addr()));
}

#[test]
fn accept2() {
    let mut l = t!(futuremio::Loop::new());
    let srv = t!(l.tcp_listen(&"127.0.0.1:0".parse().unwrap()));
    let addr = t!(srv.local_addr());
    let t = thread::spawn(move || {
        TcpStream::connect(&addr).unwrap()
    });

    t!(l.await(srv.accept().map(|t| t.0)));
    t.join().unwrap();
}
<commit_msg>Fix mio tests<commit_after>extern crate futures;
extern crate futuremio;

use std::net::{TcpListener, TcpStream};
use std::sync::mpsc::channel;
use std::thread;

use futures::Future;
use futures::stream::Stream;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {:?}", stringify!($e), e),
    })
}

#[test]
fn connect() {
    let mut l = t!(futuremio::Loop::new());
    let srv = t!(TcpListener::bind("127.0.0.1:0"));
    let addr = t!(srv.local_addr());
    let t = thread::spawn(move || {
        t!(srv.accept()).0
    });

    let stream = l.handle().tcp_connect(&addr);
    let mine = t!(l.run(stream));
    let theirs = t.join().unwrap();

    assert_eq!(t!(mine.local_addr()), t!(theirs.peer_addr()));
    assert_eq!(t!(theirs.local_addr()), t!(mine.peer_addr()));
}

#[test]
fn accept() {
    let mut l = t!(futuremio::Loop::new());
    let srv = l.handle().tcp_listen(&"127.0.0.1:0".parse().unwrap());
    let srv = t!(l.run(srv));
    let addr = t!(srv.local_addr());

    let (tx, rx) = channel();
    let client = srv.incoming().map(move |t| {
        tx.send(()).unwrap();
        t.0
    }).into_future().map_err(|e| e.0);
    assert!(rx.try_recv().is_err());
    let t = thread::spawn(move || {
        TcpStream::connect(&addr).unwrap()
    });

    let (mine, _remaining) = t!(l.run(client));
    let mine = mine.unwrap();
    let theirs = t.join().unwrap();

    assert_eq!(t!(mine.local_addr()), t!(theirs.peer_addr()));
    assert_eq!(t!(theirs.local_addr()), t!(mine.peer_addr()));
}

#[test]
fn accept2() {
    let mut l = t!(futuremio::Loop::new());
    let srv = l.handle().tcp_listen(&"127.0.0.1:0".parse().unwrap());
    let srv = t!(l.run(srv));
    let addr = t!(srv.local_addr());

    let t = thread::spawn(move || {
        TcpStream::connect(&addr).unwrap()
    });

    let (tx, rx) = channel();
    let client = srv.incoming().map(move |t| {
        tx.send(()).unwrap();
        t.0
    }).into_future().map_err(|e| e.0);
    assert!(rx.try_recv().is_err());

    let (mine, _remaining) = t!(l.run(client));
    mine.unwrap();
    t.join().unwrap();
}
<|endoftext|>


<commit_before>//! An example of opening an image.
extern crate image;

use std::env;
use std::fs::File;
use std::path::PathBuf;

use image::GenericImage;

fn main() {
    let file = if env::args().count() == 2 {
        env::args().nth(1).unwrap()
    } else {
        panic!("Please enter a file")
    };

    // Use the open function to load an image from a PAth.
    // ```open``` returns a dynamic image.
    let im = image::open(&PathBuf::new(file.clone())).unwrap();

    // The dimensions method returns the images width and height
    println!("dimensions {:?}", im.dimensions());

    // The color method returns the image's ColorType
    println!("{:?}", im.color());

    let ref mut fout = File::create(&PathBuf::new(format!("{}.png", file))).unwrap();

    // Write the contents of this image to the Writer in PNG format.
    let _ = im.save(fout, image::PNG).unwrap();
}
<commit_msg>Upgrade examples to latest rust<commit_after>//! An example of opening an image.
extern crate image;

use std::env;
use std::fs::File;
use std::path::Path;

use image::GenericImage;

fn main() {
    let file = if env::args().count() == 2 {
        env::args().nth(1).unwrap()
    } else {
        panic!("Please enter a file")
    };

    // Use the open function to load an image from a PAth.
    // ```open``` returns a dynamic image.
    let im = image::open(&Path::new(&file)).unwrap();

    // The dimensions method returns the images width and height
    println!("dimensions {:?}", im.dimensions());

    // The color method returns the image's ColorType
    println!("{:?}", im.color());

    let ref mut fout = File::create(&Path::new(&format!("{}.png", file))).unwrap();

    // Write the contents of this image to the Writer in PNG format.
    let _ = im.save(fout, image::PNG).unwrap();
}
<|endoftext|>


<commit_before>use crate::utils::{implements_trait, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq};
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;

declare_clippy_lint! {
    /// **What it does:** Checks for equal operands to comparison, logical and
    /// bitwise, difference and division binary operators (`==`, `>`, etc., `&&`,
    /// `||`, `&`, `|`, `^`, `-` and `/`).
    ///
    /// **Why is this bad?** This is usually just a typo or a copy and paste error.
    ///
    /// **Known problems:** False negatives: We had some false positives regarding
    /// calls (notably [racer](https://github.com/phildawes/racer) had one instance
    /// of `x.pop() && x.pop()`), so we removed matching any function or method
    /// calls. We may introduce a whitelist of known pure functions in the future.
    ///
    /// **Example:**
    /// ```rust
    /// # let x = 1;
    /// if x + 1 == x + 1 {}
    /// ```
    pub EQ_OP,
    correctness,
    "equal operands on both sides of a comparison or bitwise combination (e.g., `x == x`)"
}

declare_clippy_lint! {
    /// **What it does:** Checks for arguments to `==` which have their address
    /// taken to satisfy a bound
    /// and suggests to dereference the other argument instead
    ///
    /// **Why is this bad?** It is more idiomatic to dereference the other argument.
    ///
    /// **Known problems:** None
    ///
    /// **Example:**
    /// ```ignore
    /// &x == y
    /// ```
    pub OP_REF,
    style,
    "taking a reference to satisfy the type constraints on `==`"
}

declare_lint_pass!(EqOp => [EQ_OP, OP_REF]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
    #[allow(clippy::similar_names, clippy::too_many_lines)]
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        if let ExprKind::Binary(op, ref left, ref right) = e.node {
            if e.span.from_expansion() {
                return;
            }
            if is_valid_operator(op) && SpanlessEq::new(cx).ignore_fn().eq_expr(left, right) {
                span_lint(
                    cx,
                    EQ_OP,
                    e.span,
                    &format!("equal expressions as operands to `{}`", op.node.as_str()),
                );
                return;
            }
            let (trait_id, requires_ref) = match op.node {
                BinOpKind::Add => (cx.tcx.lang_items().add_trait(), false),
                BinOpKind::Sub => (cx.tcx.lang_items().sub_trait(), false),
                BinOpKind::Mul => (cx.tcx.lang_items().mul_trait(), false),
                BinOpKind::Div => (cx.tcx.lang_items().div_trait(), false),
                BinOpKind::Rem => (cx.tcx.lang_items().rem_trait(), false),
                // don't lint short circuiting ops
                BinOpKind::And | BinOpKind::Or => return,
                BinOpKind::BitXor => (cx.tcx.lang_items().bitxor_trait(), false),
                BinOpKind::BitAnd => (cx.tcx.lang_items().bitand_trait(), false),
                BinOpKind::BitOr => (cx.tcx.lang_items().bitor_trait(), false),
                BinOpKind::Shl => (cx.tcx.lang_items().shl_trait(), false),
                BinOpKind::Shr => (cx.tcx.lang_items().shr_trait(), false),
                BinOpKind::Ne | BinOpKind::Eq => (cx.tcx.lang_items().eq_trait(), true),
                BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ge | BinOpKind::Gt => {
                    (cx.tcx.lang_items().ord_trait(), true)
                },
            };
            if let Some(trait_id) = trait_id {
                #[allow(clippy::match_same_arms)]
                match (&left.node, &right.node) {
                    // do not suggest to dereference literals
                    (&ExprKind::Lit(..), _) | (_, &ExprKind::Lit(..)) => {},
                    // &foo == &bar
                    (&ExprKind::AddrOf(_, ref l), &ExprKind::AddrOf(_, ref r)) => {
                        let lty = cx.tables.expr_ty(l);
                        let rty = cx.tables.expr_ty(r);
                        let lcpy = is_copy(cx, lty);
                        let rcpy = is_copy(cx, rty);
                        // either operator autorefs or both args are copyable
                        if (requires_ref || (lcpy && rcpy)) && implements_trait(cx, lty, trait_id, &[rty.into()]) {
                            span_lint_and_then(
                                cx,
                                OP_REF,
                                e.span,
                                "needlessly taken reference of both operands",
                                |db| {
                                    let lsnip = snippet(cx, l.span, "...").to_string();
                                    let rsnip = snippet(cx, r.span, "...").to_string();
                                    multispan_sugg(
                                        db,
                                        "use the values directly".to_string(),
                                        vec![(left.span, lsnip), (right.span, rsnip)],
                                    );
                                },
                            )
                        } else if lcpy
                            && !rcpy
                            && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()])
                        {
                            span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| {
                                let lsnip = snippet(cx, l.span, "...").to_string();
                                db.span_suggestion(
                                    left.span,
                                    "use the left value directly",
                                    lsnip,
                                    Applicability::MachineApplicable, // snippet
                                );
                            })
                        } else if !lcpy
                            && rcpy
                            && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()])
                        {
                            span_lint_and_then(
                                cx,
                                OP_REF,
                                e.span,
                                "needlessly taken reference of right operand",
                                |db| {
                                    let rsnip = snippet(cx, r.span, "...").to_string();
                                    db.span_suggestion(
                                        right.span,
                                        "use the right value directly",
                                        rsnip,
                                        Applicability::MachineApplicable, // snippet
                                    );
                                },
                            )
                        }
                    },
                    // &foo == bar
                    (&ExprKind::AddrOf(_, ref l), _) => {
                        let lty = cx.tables.expr_ty(l);
                        let lcpy = is_copy(cx, lty);
                        if (requires_ref || lcpy)
                            && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()])
                        {
                            span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| {
                                let lsnip = snippet(cx, l.span, "...").to_string();
                                db.span_suggestion(
                                    left.span,
                                    "use the left value directly",
                                    lsnip,
                                    Applicability::MachineApplicable, // snippet
                                );
                            })
                        }
                    },
                    // foo == &bar
                    (_, &ExprKind::AddrOf(_, ref r)) => {
                        let rty = cx.tables.expr_ty(r);
                        let rcpy = is_copy(cx, rty);
                        if (requires_ref || rcpy)
                            && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()])
                        {
                            span_lint_and_then(cx, OP_REF, e.span, "taken reference of right operand", |db| {
                                let rsnip = snippet(cx, r.span, "...").to_string();
                                db.span_suggestion(
                                    right.span,
                                    "use the right value directly",
                                    rsnip,
                                    Applicability::MachineApplicable, // snippet
                                );
                            })
                        }
                    },
                    _ => {},
                }
            }
        }
    }
}

fn is_valid_operator(op: BinOp) -> bool {
    match op.node {
        BinOpKind::Sub
        | BinOpKind::Div
        | BinOpKind::Eq
        | BinOpKind::Lt
        | BinOpKind::Le
        | BinOpKind::Gt
        | BinOpKind::Ge
        | BinOpKind::Ne
        | BinOpKind::And
        | BinOpKind::Or
        | BinOpKind::BitXor
        | BinOpKind::BitAnd
        | BinOpKind::BitOr => true,
        _ => false,
    }
}
<commit_msg>Downgrade op_ref to a MaybeIncorrect suggestion<commit_after>use crate::utils::{implements_trait, is_copy, multispan_sugg, snippet, span_lint, span_lint_and_then, SpanlessEq};
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;

declare_clippy_lint! {
    /// **What it does:** Checks for equal operands to comparison, logical and
    /// bitwise, difference and division binary operators (`==`, `>`, etc., `&&`,
    /// `||`, `&`, `|`, `^`, `-` and `/`).
    ///
    /// **Why is this bad?** This is usually just a typo or a copy and paste error.
    ///
    /// **Known problems:** False negatives: We had some false positives regarding
    /// calls (notably [racer](https://github.com/phildawes/racer) had one instance
    /// of `x.pop() && x.pop()`), so we removed matching any function or method
    /// calls. We may introduce a whitelist of known pure functions in the future.
    ///
    /// **Example:**
    /// ```rust
    /// # let x = 1;
    /// if x + 1 == x + 1 {}
    /// ```
    pub EQ_OP,
    correctness,
    "equal operands on both sides of a comparison or bitwise combination (e.g., `x == x`)"
}

declare_clippy_lint! {
    /// **What it does:** Checks for arguments to `==` which have their address
    /// taken to satisfy a bound
    /// and suggests to dereference the other argument instead
    ///
    /// **Why is this bad?** It is more idiomatic to dereference the other argument.
    ///
    /// **Known problems:** None
    ///
    /// **Example:**
    /// ```ignore
    /// &x == y
    /// ```
    pub OP_REF,
    style,
    "taking a reference to satisfy the type constraints on `==`"
}

declare_lint_pass!(EqOp => [EQ_OP, OP_REF]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
    #[allow(clippy::similar_names, clippy::too_many_lines)]
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        if let ExprKind::Binary(op, ref left, ref right) = e.node {
            if e.span.from_expansion() {
                return;
            }
            if is_valid_operator(op) && SpanlessEq::new(cx).ignore_fn().eq_expr(left, right) {
                span_lint(
                    cx,
                    EQ_OP,
                    e.span,
                    &format!("equal expressions as operands to `{}`", op.node.as_str()),
                );
                return;
            }
            let (trait_id, requires_ref) = match op.node {
                BinOpKind::Add => (cx.tcx.lang_items().add_trait(), false),
                BinOpKind::Sub => (cx.tcx.lang_items().sub_trait(), false),
                BinOpKind::Mul => (cx.tcx.lang_items().mul_trait(), false),
                BinOpKind::Div => (cx.tcx.lang_items().div_trait(), false),
                BinOpKind::Rem => (cx.tcx.lang_items().rem_trait(), false),
                // don't lint short circuiting ops
                BinOpKind::And | BinOpKind::Or => return,
                BinOpKind::BitXor => (cx.tcx.lang_items().bitxor_trait(), false),
                BinOpKind::BitAnd => (cx.tcx.lang_items().bitand_trait(), false),
                BinOpKind::BitOr => (cx.tcx.lang_items().bitor_trait(), false),
                BinOpKind::Shl => (cx.tcx.lang_items().shl_trait(), false),
                BinOpKind::Shr => (cx.tcx.lang_items().shr_trait(), false),
                BinOpKind::Ne | BinOpKind::Eq => (cx.tcx.lang_items().eq_trait(), true),
                BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ge | BinOpKind::Gt => {
                    (cx.tcx.lang_items().ord_trait(), true)
                },
            };
            if let Some(trait_id) = trait_id {
                #[allow(clippy::match_same_arms)]
                match (&left.node, &right.node) {
                    // do not suggest to dereference literals
                    (&ExprKind::Lit(..), _) | (_, &ExprKind::Lit(..)) => {},
                    // &foo == &bar
                    (&ExprKind::AddrOf(_, ref l), &ExprKind::AddrOf(_, ref r)) => {
                        let lty = cx.tables.expr_ty(l);
                        let rty = cx.tables.expr_ty(r);
                        let lcpy = is_copy(cx, lty);
                        let rcpy = is_copy(cx, rty);
                        // either operator autorefs or both args are copyable
                        if (requires_ref || (lcpy && rcpy)) && implements_trait(cx, lty, trait_id, &[rty.into()]) {
                            span_lint_and_then(
                                cx,
                                OP_REF,
                                e.span,
                                "needlessly taken reference of both operands",
                                |db| {
                                    let lsnip = snippet(cx, l.span, "...").to_string();
                                    let rsnip = snippet(cx, r.span, "...").to_string();
                                    multispan_sugg(
                                        db,
                                        "use the values directly".to_string(),
                                        vec![(left.span, lsnip), (right.span, rsnip)],
                                    );
                                },
                            )
                        } else if lcpy
                            && !rcpy
                            && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()])
                        {
                            span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| {
                                let lsnip = snippet(cx, l.span, "...").to_string();
                                db.span_suggestion(
                                    left.span,
                                    "use the left value directly",
                                    lsnip,
                                    Applicability::MaybeIncorrect, // FIXME #2597
                                );
                            })
                        } else if !lcpy
                            && rcpy
                            && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()])
                        {
                            span_lint_and_then(
                                cx,
                                OP_REF,
                                e.span,
                                "needlessly taken reference of right operand",
                                |db| {
                                    let rsnip = snippet(cx, r.span, "...").to_string();
                                    db.span_suggestion(
                                        right.span,
                                        "use the right value directly",
                                        rsnip,
                                        Applicability::MaybeIncorrect, // FIXME #2597
                                    );
                                },
                            )
                        }
                    },
                    // &foo == bar
                    (&ExprKind::AddrOf(_, ref l), _) => {
                        let lty = cx.tables.expr_ty(l);
                        let lcpy = is_copy(cx, lty);
                        if (requires_ref || lcpy)
                            && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right).into()])
                        {
                            span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| {
                                let lsnip = snippet(cx, l.span, "...").to_string();
                                db.span_suggestion(
                                    left.span,
                                    "use the left value directly",
                                    lsnip,
                                    Applicability::MachineApplicable, // snippet
                                );
                            })
                        }
                    },
                    // foo == &bar
                    (_, &ExprKind::AddrOf(_, ref r)) => {
                        let rty = cx.tables.expr_ty(r);
                        let rcpy = is_copy(cx, rty);
                        if (requires_ref || rcpy)
                            && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty.into()])
                        {
                            span_lint_and_then(cx, OP_REF, e.span, "taken reference of right operand", |db| {
                                let rsnip = snippet(cx, r.span, "...").to_string();
                                db.span_suggestion(
                                    right.span,
                                    "use the right value directly",
                                    rsnip,
                                    Applicability::MachineApplicable, // snippet
                                );
                            })
                        }
                    },
                    _ => {},
                }
            }
        }
    }
}

fn is_valid_operator(op: BinOp) -> bool {
    match op.node {
        BinOpKind::Sub
        | BinOpKind::Div
        | BinOpKind::Eq
        | BinOpKind::Lt
        | BinOpKind::Le
        | BinOpKind::Gt
        | BinOpKind::Ge
        | BinOpKind::Ne
        | BinOpKind::And
        | BinOpKind::Or
        | BinOpKind::BitXor
        | BinOpKind::BitAnd
        | BinOpKind::BitOr => true,
        _ => false,
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use chrono::prelude::*;
use serde_derive::{Deserialize, Serialize};
use strum_macros::Display;

/// This enum represents the status of the internal task handling of Pueue.
/// They basically represent the internal task life-cycle.
#[derive(Clone, Debug, Display, PartialEq, Serialize, Deserialize)]
pub enum TaskStatus {
    /// The task is queued and waiting for a free slot
    Queued,
    /// The task has been manually stashed. It won't be executed until it's manually enqueued
    Stashed,
    /// The task is started and running
    Running,
    /// A previously running task has been paused
    Paused,
    /// Task finished successfully
    Done,
    /// Used while the command of a task is edited (to prevent starting the task)
    Locked,
}

/// This enum represents the exit status of an actually spawned program.
/// It's only of relevance, once a task actually spawned and somehow finished.
#[derive(Clone, Debug, Display, PartialEq, Serialize, Deserialize)]
pub enum TaskResult {
    /// Task exited with 0
    Success,
    /// The task failed in some other kind of way (error code != 0)
    Failed(i32),
    /// The task couldn't be spawned. Probably a typo in the command
    FailedToSpawn(String),
    /// Task has been actively killed by either the user or the daemon on shutdown
    Killed,
    /// A dependency of the task failed.
    DependencyFailed,
}

/// Representation of a task.
/// start will be set the second the task starts processing.
/// exit_code, output and end won't be initialized, until the task has finished.
/// The output of the task is written into seperate files.
/// Upon task completion, the output is read from the files and put into the struct.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Task {
    pub id: usize,
    pub command: String,
    pub path: String,
    pub envs: HashMap<String, String>,
    pub group: Option<String>,
    pub enqueue_at: Option<DateTime<Local>>,
    pub dependencies: Vec<usize>,
    pub status: TaskStatus,
    pub prev_status: TaskStatus,
    pub result: Option<TaskResult>,
    pub start: Option<DateTime<Local>>,
    pub end: Option<DateTime<Local>>,
}

impl Task {
    pub fn new(
        command: String,
        path: String,
        envs: HashMap<String, String>,
        group: Option<String>,
        starting_status: TaskStatus,
        enqueue_at: Option<DateTime<Local>>,
        dependencies: Vec<usize>,
    ) -> Task {
        Task {
            id: 0,
            command,
            path,
            envs,
            group,
            enqueue_at,
            dependencies,
            status: starting_status.clone(),
            prev_status: starting_status,
            result: None,
            start: None,
            end: None,
        }
    }

    /// A convenience function, which is used to create a duplicate task.
    pub fn from_task(task: &Task) -> Task {
        Task {
            id: 0,
            command: task.command.clone(),
            path: task.path.clone(),
            envs: task.envs.clone(),
            group: None,
            enqueue_at: None,
            dependencies: Vec::new(),
            status: TaskStatus::Queued,
            prev_status: TaskStatus::Queued,
            result: None,
            start: None,
            end: None,
        }
    }

    pub fn is_running(&self) -> bool {
        self.status == TaskStatus::Running || self.status == TaskStatus::Paused
    }

    pub fn is_done(&self) -> bool {
        self.status == TaskStatus::Done
    }

    /// Check if the task errored.
    /// The only case when it didn't error is if it didn't run yet or if the task exited successfully.
    pub fn failed(&self) -> bool {
        !matches!(self.result, None | Some(TaskResult::Success))
    }

    pub fn is_queued(&self) -> bool {
        self.status == TaskStatus::Queued || self.status == TaskStatus::Stashed
    }
}
<commit_msg>Update TaskResult and TaskStatus docs<commit_after>use std::collections::HashMap;

use chrono::prelude::*;
use serde_derive::{Deserialize, Serialize};
use strum_macros::Display;

/// This enum represents the status of the internal task handling of Pueue.
/// They basically represent the internal task life-cycle.
#[derive(Clone, Debug, Display, PartialEq, Serialize, Deserialize)]
pub enum TaskStatus {
    /// The task is queued and waiting for a free slot
    Queued,
    /// The task has been manually stashed. It won't be executed until it's manually enqueued
    Stashed,
    /// The task is started and running
    Running,
    /// A previously running task has been paused
    Paused,
    /// Task finished. The actual result of the task is handled by the [TaskResult] enum.
    Done,
    /// Used while the command of a task is edited (to prevent starting the task)
    Locked,
}

/// This enum represents the exit status of an actually spawned program.
/// It's only used, once a task finished or failed in some kind of way.
#[derive(Clone, Debug, Display, PartialEq, Serialize, Deserialize)]
pub enum TaskResult {
    /// Task exited with 0
    Success,
    /// The task failed in some other kind of way (error code != 0)
    Failed(i32),
    /// The task couldn't be spawned. Probably a typo in the command
    FailedToSpawn(String),
    /// Task has been actively killed by either the user or the daemon on shutdown
    Killed,
    /// A dependency of the task failed.
    DependencyFailed,
}

/// Representation of a task.
/// start will be set the second the task starts processing.
/// exit_code, output and end won't be initialized, until the task has finished.
/// The output of the task is written into seperate files.
/// Upon task completion, the output is read from the files and put into the struct.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Task {
    pub id: usize,
    pub command: String,
    pub path: String,
    pub envs: HashMap<String, String>,
    pub group: Option<String>,
    pub enqueue_at: Option<DateTime<Local>>,
    pub dependencies: Vec<usize>,
    pub status: TaskStatus,
    pub prev_status: TaskStatus,
    pub result: Option<TaskResult>,
    pub start: Option<DateTime<Local>>,
    pub end: Option<DateTime<Local>>,
}

impl Task {
    pub fn new(
        command: String,
        path: String,
        envs: HashMap<String, String>,
        group: Option<String>,
        starting_status: TaskStatus,
        enqueue_at: Option<DateTime<Local>>,
        dependencies: Vec<usize>,
    ) -> Task {
        Task {
            id: 0,
            command,
            path,
            envs,
            group,
            enqueue_at,
            dependencies,
            status: starting_status.clone(),
            prev_status: starting_status,
            result: None,
            start: None,
            end: None,
        }
    }

    /// A convenience function, which is used to create a duplicate task.
    pub fn from_task(task: &Task) -> Task {
        Task {
            id: 0,
            command: task.command.clone(),
            path: task.path.clone(),
            envs: task.envs.clone(),
            group: None,
            enqueue_at: None,
            dependencies: Vec::new(),
            status: TaskStatus::Queued,
            prev_status: TaskStatus::Queued,
            result: None,
            start: None,
            end: None,
        }
    }

    pub fn is_running(&self) -> bool {
        self.status == TaskStatus::Running || self.status == TaskStatus::Paused
    }

    pub fn is_done(&self) -> bool {
        self.status == TaskStatus::Done
    }

    /// Check if the task errored.
    /// The only case when it didn't error is if it didn't run yet or if the task exited successfully.
    pub fn failed(&self) -> bool {
        !matches!(self.result, None | Some(TaskResult::Success))
    }

    pub fn is_queued(&self) -> bool {
        self.status == TaskStatus::Queued || self.status == TaskStatus::Stashed
    }
}
<|endoftext|>


<commit_before>extern crate futures;

use futures::{failed, finished, Future, oneshot, Poll, Task};
use futures::stream::*;

mod support;
use support::*;

// #[test]
// fn smoke() {
//     let (tx, rx) = channel::<i32, u32>();
//     tx.send(Ok(1))
//       .and_then(|tx| tx.send(Ok(2)))
//       .and_then(|tx| tx.send(Ok(3)))
//       .schedule(|r| assert!(r.is_ok()));
//     assert_eq!(rx.collect(), Ok(vec![1, 2, 3]));
//
//     let (tx, rx) = channel::<i32, u32>();
//     tx.send(Ok(1))
//       .and_then(|tx| tx.send(Err(2)))
//       .and_then(|tx| tx.send(Ok(3)))
//       .schedule(|r| assert!(r.is_ok()));
//     assert_eq!(rx.collect(), Err(2));
// }

fn list() -> Receiver<i32, u32> {
    let (tx, rx) = channel();
    tx.send(Ok(1))
      .and_then(|tx| tx.send(Ok(2)))
      .and_then(|tx| tx.send(Ok(3)))
      .forget();
    return rx
}

fn err_list() -> Receiver<i32, u32> {
    let (tx, rx) = channel();
    tx.send(Ok(1))
      .and_then(|tx| tx.send(Ok(2)))
      .and_then(|tx| tx.send(Err(3)))
      .forget();
    return rx
}

// fn collect_poll<S: Stream>(mut s: S) -> Result<Vec<S::Item>, S::Error> {
//     let mut base = Vec::new();
//     loop {
//         match s.poll() {
//             Ok(item) => base.push(item),
//             Err(PollError::Empty) => return Ok(base),
//             Err(PollError::Other(e)) => return Err(e),
//             Err(PollError::NotReady) => panic!("blocked?"),
//         }
//     }
// }
//
#[test]
fn adapters() {
    assert_done(|| list().map(|a| a + 1).collect(), Ok(vec![2, 3, 4]));
    assert_done(|| err_list().map_err(|a| a + 1).collect(), Err(4));
    assert_done(|| list().fold(0, |a, b| finished::<i32, u32>(a + b)), Ok(6));
    assert_done(|| err_list().fold(0, |a, b| finished::<i32, u32>(a + b)), Err(3));
    assert_done(|| list().filter(|a| *a % 2 == 0).collect(), Ok(vec![2]));
    assert_done(|| list().filter_map(|x| {
        if x % 2 == 0 {
            Some(x + 10)
        } else {
            None
        }
    }).collect(), Ok(vec![12]));
    assert_done(|| list().and_then(|a| Ok(a + 1)).collect(), Ok(vec![2, 3, 4]));
    assert_done(|| list().then(|a| a.map(|e| e + 1)).collect(), Ok(vec![2, 3, 4]));
    assert_done(|| list().and_then(|a| failed::<i32, u32>(a as u32)).collect(),
                Err(1));
    assert_done(|| err_list().or_else(|a| {
        finished::<i32, u32>(a as i32)
    }).collect(), Ok(vec![1, 2, 3]));
    assert_done(|| list().map(|_| list()).flatten().collect(),
                Ok(vec![1, 2, 3, 1, 2, 3, 1, 2, 3]));
//     assert_eq!(list().map(|i| finished::<_, u32>(i)).flatten().collect(),
//                Ok(vec![1, 2, 3]));
    assert_done(|| list().skip_while(|e| Ok(*e % 2 == 1)).collect(),
                Ok(vec![2, 3]));
    assert_done(|| list().take(2).collect(), Ok(vec![1, 2]));
    assert_done(|| list().skip(2).collect(), Ok(vec![3]));
    assert_done(|| list().peekable().collect(), Ok(vec![1, 2, 3]));
}

#[test]
fn fuse() {
    let mut stream = list().fuse();
    let mut task = Task::new();
    assert_eq!(stream.poll(&mut task), Poll::Ok(Some(1)));
    assert_eq!(stream.poll(&mut task), Poll::Ok(Some(2)));
    assert_eq!(stream.poll(&mut task), Poll::Ok(Some(3)));
    assert_eq!(stream.poll(&mut task), Poll::Ok(None));
    assert_eq!(stream.poll(&mut task), Poll::Ok(None));
    assert_eq!(stream.poll(&mut task), Poll::Ok(None));
}

// #[test]
// fn adapters_poll() {
//     assert_eq!(collect_poll(list().map(|a| a + 1)), Ok(vec![2, 3, 4]));
//     assert_eq!(collect_poll(err_list().map_err(|a| a + 1)), Err(4));
//     assert_eq!(collect_poll(list().filter(|a| *a % 2 == 0)), Ok(vec![2]));
//     assert_eq!(collect_poll(list().and_then(|a| Ok(a + 1))), Ok(vec![2, 3, 4]));
//     assert_eq!(collect_poll(err_list().and_then(|a| Ok(a + 1))), Err(3));
//     assert_eq!(collect_poll(err_list().and_then(|a| {
//         failed::<i32, _>(a as u32)
//     })), Err(1));
//     assert_eq!(collect_poll(err_list().or_else(|a| finished::<_, u32>(a as i32))),
//                Ok(vec![1, 2, 3]));
//
//     let (tx, rx) = channel::<i32, u32>();
//     let (rx2, tx2) = oneshot::pair();
//     let mut rx2 = Some(rx2);
//     let mut rx = rx.and_then(move |_a| rx2.take().unwrap());
//     match rx.poll() {
//         Err(PollError::NotReady) => {}
//         _ => panic!("ready?"),
//     }
//     tx.send(Ok(1)).schedule(|_| ());
//     match rx.poll() {
//         Err(PollError::NotReady) => {}
//         _ => panic!("ready?"),
//     }
//     match rx.poll() {
//         Err(PollError::NotReady) => {}
//         _ => panic!("ready?"),
//     }
//     tx2.finish(1);
//     match rx.poll() {
//         Ok(1) => {},
//         Err(PollError::NotReady) => panic!("not ready?"),
//         Err(PollError::Empty) => panic!("empty?"),
//         _ => panic!("not ready?"),
//     }
//
//     // let (tx, rx) = channel::<i32, u32>();
//     // let rx = rx.and_then(|a| failed::<i32, _>(a as u32));
//     // tx.send(Ok(1)).schedule(|_| ());
//     // assert_eq!(rx.collect(), Err(1));
//     // assert_eq!(list().fold(0, |a, b| a + b), Ok(6));
//     // assert_eq!(list().and_then(|a| Ok(a + 1)).collect(),
//     //            Ok(vec![2, 3, 4]));
//     // assert_eq!(err_list().or_else(|a| {
//     //     finished::<i32, u32>(a as i32)
//     // }).collect(), Ok(vec![1, 2, 3]));
//     // assert_eq!(list().map(|_| list()).flat_map().collect(),
//     //            Ok(vec![1, 2, 3, 1, 2, 3, 1, 2, 3]));
//     // assert_eq!(list().map(|i| finished::<_, u32>(i)).flatten().collect(),
//     //            Ok(vec![1, 2, 3]));
//
//     assert_eq!(list().collect().poll().ok().unwrap(), Ok(vec![1, 2, 3]));
//     assert_eq!(err_list().collect().poll().ok().unwrap(), Err(3));
//     assert_eq!(list().fold(0, |a, b| a + b).poll().ok().unwrap(), Ok(6));
//     assert_eq!(err_list().fold(0, |a, b| a + b).poll().ok().unwrap(), Err(3));
//     assert_eq!(list().map(|a| finished::<_, u32>(a))
//                      .flatten().collect().poll().ok().unwrap(),
//                Ok(vec![1, 2, 3]));
//     assert_eq!(list().map(|_a| list()).flat_map()
//                      .collect().poll().ok().unwrap(),
//                Ok(vec![1, 2, 3, 1, 2, 3, 1, 2, 3]));
// }
//
// #[test]
// fn rxdrop() {
//     let (tx, rx) = channel::<i32, u32>();
//     drop(rx);
//     assert!(tx.send(Ok(1)).is_err());
// }
//
// #[test]
// fn bufstream_smoke() {
//     let (tx, mut rx) = bufstream::<i32, u32>(4);
//     let (vrx, mut vtx): (Vec<_>, Vec<_>) = (0..4).map(|_| {
//         let (a, b) = oneshot::pair::<i32, u32>();
//         (a, Some(b))
//     }).unzip();
//     for (a, b) in tx.zip(vrx) {
//         b.schedule(|val| a.send(val));
//     }
//
//     assert_eq!(rx.poll(), Err(PollError::NotReady));
//     vtx[0].take().unwrap().finish(2);
//     assert_eq!(rx.poll(), Ok(2));
//     assert_eq!(rx.poll(), Err(PollError::NotReady));
//     vtx[3].take().unwrap().finish(4);
//     assert_eq!(rx.poll(), Ok(4));
//     assert_eq!(rx.poll(), Err(PollError::NotReady));
//     vtx[1].take().unwrap().fail(3);
//     assert_eq!(rx.poll(), Err(PollError::Other(3)));
//     assert_eq!(rx.poll(), Err(PollError::NotReady));
//     vtx[2].take().unwrap().finish(1);
//     assert_eq!(rx.poll(), Ok(1));
//     assert_eq!(rx.poll(), Err(PollError::Empty));
// }
//
// #[test]
// fn bufstream_concurrent() {
//     let (tx, rx) = bufstream::<i32, u32>(4);
//     let (vrx, vtx): (Vec<_>, Vec<_>) = (0..4).map(|_| {
//         oneshot::pair::<i32, u32>()
//     }).unzip();
//     for (a, b) in tx.zip(vrx) {
//         b.schedule(|val| a.send(val));
//     }
//
//     let t = thread::spawn(|| {
//         let mut it = vtx.into_iter();
//         it.next().unwrap().finish(2);
//         it.next_back().unwrap().finish(4);
//         it.next().unwrap().finish(3);
//         it.next_back().unwrap().finish(1);
//         assert!(it.next().is_none());
//     });
//
//     assert_eq!(rx.collect(), Ok(vec![2, 4, 3, 1]));
//     t.join().unwrap();
// }

#[test]
fn buffered() {
    let (tx, rx) = channel::<_, u32>();
    let (a, b) = oneshot::<u32>();
    let (c, d) = oneshot::<u32>();

    tx.send(Ok(b.map_err(|_| 2).boxed()))
      .and_then(|tx| tx.send(Ok(d.map_err(|_| 4).boxed())))
      .forget();

    let mut rx = rx.buffered(2);
    sassert_empty(&mut rx);
    c.complete(3);
    sassert_empty(&mut rx);
    a.complete(5);
    sassert_next(&mut rx, 5);
    sassert_next(&mut rx, 3);
    sassert_done(&mut rx);

    let (tx, rx) = channel::<_, u32>();
    let (a, b) = oneshot::<u32>();
    let (c, d) = oneshot::<u32>();

    tx.send(Ok(b.map_err(|_| 2).boxed()))
      .and_then(|tx| tx.send(Ok(d.map_err(|_| 4).boxed())))
      .forget();

    let mut rx = rx.buffered(1);
    sassert_empty(&mut rx);
    c.complete(3);
    sassert_empty(&mut rx);
    a.complete(5);
    sassert_next(&mut rx, 5);
    sassert_next(&mut rx, 3);
    sassert_done(&mut rx);
}

#[test]
fn zip() {
    assert_done(|| list().zip(list()).collect(),
                Ok(vec![(1, 1), (2, 2), (3, 3)]));
    assert_done(|| list().zip(list().take(2)).collect(),
                Ok(vec![(1, 1), (2, 2)]));
    assert_done(|| list().take(2).zip(list()).collect(),
                Ok(vec![(1, 1), (2, 2)]));
    assert_done(|| err_list().zip(list()).collect(), Err(3));
    assert_done(|| list().zip(list().map(|x| x + 1)).collect(),
                Ok(vec![(1, 2), (2, 3), (3, 4)]));
}

#[test]
fn peek() {
    let mut peekable = list().peekable();
    assert_eq!(peekable.peek(&mut Task::new()).unwrap(), Ok(Some(&1)));
    assert_eq!(peekable.peek(&mut Task::new()).unwrap(), Ok(Some(&1)));
    assert_eq!(peekable.poll(&mut Task::new()).unwrap(), Ok(Some(1)));
}
<commit_msg>removed outcommented code in test/streams.rs<commit_after>extern crate futures;

use futures::{failed, finished, Future, oneshot, Poll, Task};
use futures::stream::*;

mod support;
use support::*;

fn list() -> Receiver<i32, u32> {
    let (tx, rx) = channel();
    tx.send(Ok(1))
      .and_then(|tx| tx.send(Ok(2)))
      .and_then(|tx| tx.send(Ok(3)))
      .forget();
    return rx
}

fn err_list() -> Receiver<i32, u32> {
    let (tx, rx) = channel();
    tx.send(Ok(1))
      .and_then(|tx| tx.send(Ok(2)))
      .and_then(|tx| tx.send(Err(3)))
      .forget();
    return rx
}

#[test]
fn adapters() {
    assert_done(|| list().map(|a| a + 1).collect(), Ok(vec![2, 3, 4]));
    assert_done(|| err_list().map_err(|a| a + 1).collect(), Err(4));
    assert_done(|| list().fold(0, |a, b| finished::<i32, u32>(a + b)), Ok(6));
    assert_done(|| err_list().fold(0, |a, b| finished::<i32, u32>(a + b)), Err(3));
    assert_done(|| list().filter(|a| *a % 2 == 0).collect(), Ok(vec![2]));
    assert_done(|| list().filter_map(|x| {
        if x % 2 == 0 {
            Some(x + 10)
        } else {
            None
        }
    }).collect(), Ok(vec![12]));
    assert_done(|| list().and_then(|a| Ok(a + 1)).collect(), Ok(vec![2, 3, 4]));
    assert_done(|| list().then(|a| a.map(|e| e + 1)).collect(), Ok(vec![2, 3, 4]));
    assert_done(|| list().and_then(|a| failed::<i32, u32>(a as u32)).collect(),
                Err(1));
    assert_done(|| err_list().or_else(|a| {
        finished::<i32, u32>(a as i32)
    }).collect(), Ok(vec![1, 2, 3]));
    assert_done(|| list().map(|_| list()).flatten().collect(),
                Ok(vec![1, 2, 3, 1, 2, 3, 1, 2, 3]));
    assert_done(|| list().skip_while(|e| Ok(*e % 2 == 1)).collect(),
                Ok(vec![2, 3]));
    assert_done(|| list().take(2).collect(), Ok(vec![1, 2]));
    assert_done(|| list().skip(2).collect(), Ok(vec![3]));
    assert_done(|| list().peekable().collect(), Ok(vec![1, 2, 3]));
}

#[test]
fn fuse() {
    let mut stream = list().fuse();
    let mut task = Task::new();
    assert_eq!(stream.poll(&mut task), Poll::Ok(Some(1)));
    assert_eq!(stream.poll(&mut task), Poll::Ok(Some(2)));
    assert_eq!(stream.poll(&mut task), Poll::Ok(Some(3)));
    assert_eq!(stream.poll(&mut task), Poll::Ok(None));
    assert_eq!(stream.poll(&mut task), Poll::Ok(None));
    assert_eq!(stream.poll(&mut task), Poll::Ok(None));
}

#[test]
fn buffered() {
    let (tx, rx) = channel::<_, u32>();
    let (a, b) = oneshot::<u32>();
    let (c, d) = oneshot::<u32>();

    tx.send(Ok(b.map_err(|_| 2).boxed()))
      .and_then(|tx| tx.send(Ok(d.map_err(|_| 4).boxed())))
      .forget();

    let mut rx = rx.buffered(2);
    sassert_empty(&mut rx);
    c.complete(3);
    sassert_empty(&mut rx);
    a.complete(5);
    sassert_next(&mut rx, 5);
    sassert_next(&mut rx, 3);
    sassert_done(&mut rx);

    let (tx, rx) = channel::<_, u32>();
    let (a, b) = oneshot::<u32>();
    let (c, d) = oneshot::<u32>();

    tx.send(Ok(b.map_err(|_| 2).boxed()))
      .and_then(|tx| tx.send(Ok(d.map_err(|_| 4).boxed())))
      .forget();

    let mut rx = rx.buffered(1);
    sassert_empty(&mut rx);
    c.complete(3);
    sassert_empty(&mut rx);
    a.complete(5);
    sassert_next(&mut rx, 5);
    sassert_next(&mut rx, 3);
    sassert_done(&mut rx);
}

#[test]
fn zip() {
    assert_done(|| list().zip(list()).collect(),
                Ok(vec![(1, 1), (2, 2), (3, 3)]));
    assert_done(|| list().zip(list().take(2)).collect(),
                Ok(vec![(1, 1), (2, 2)]));
    assert_done(|| list().take(2).zip(list()).collect(),
                Ok(vec![(1, 1), (2, 2)]));
    assert_done(|| err_list().zip(list()).collect(), Err(3));
    assert_done(|| list().zip(list().map(|x| x + 1)).collect(),
                Ok(vec![(1, 2), (2, 3), (3, 4)]));
}

#[test]
fn peek() {
    let mut peekable = list().peekable();
    assert_eq!(peekable.peek(&mut Task::new()).unwrap(), Ok(Some(&1)));
    assert_eq!(peekable.peek(&mut Task::new()).unwrap(), Ok(Some(&1)));
    assert_eq!(peekable.poll(&mut Task::new()).unwrap(), Ok(Some(1)));
}
<|endoftext|>