<commit_before>use std::collections::HashMap;
use std::net::SocketAddr;
use std::rc::{Rc, Weak};
use std::cell::RefCell;

use mioco::udp::UdpSocket;
use mioco::sync::mpsc::{channel, Receiver, Sender};
use bincode::rustc_serialize as bcode_rcs;
use sodiumoxide::crypto::secretbox as crypto_secretbox;

use ::Result;
use identity::{Identity, Extension, RemoteServer};
use packet::*;
use keys::*;
use boxes::*;
use nonces::*;

pub struct Stream {

}

impl Stream {
    pub fn new() -> Stream {
        Stream {}
    }
}

trait PacketProcessor {
    fn process_packet(&mut self, packet: Packet, sock: &mut UdpSocket, rem_addr: SocketAddr) -> Result<()>;
}

pub struct Demultiplexor {
    sock: UdpSocket,
    packet_processors: HashMap<Extension, Weak<RefCell<PacketProcessor>>>,
}

impl Demultiplexor {
    pub fn new(sock: UdpSocket) -> Demultiplexor {
        Demultiplexor {
            sock: sock,
            packet_processors: HashMap::new(),
        }
    }

    pub fn create_listener(&mut self, listener_id: Identity) -> Rc<RefCell<Listener>> {
        let listener_extension = listener_id.extension.clone();
        let listener = Rc::new(RefCell::new(Listener::new(listener_id)));

        self.packet_processors.insert(listener_extension, Rc::downgrade(&listener) as Weak<RefCell<PacketProcessor>>);

        listener
    }

    pub fn create_client(&mut self, client_id: Identity, remote_id: RemoteServer) -> Rc<RefCell<ClientSock>> {
        let client_extension = client_id.extension.clone();
        let client = Rc::new(RefCell::new(ClientSock::new(client_id, remote_id)));

        self.packet_processors.insert(client_extension, Rc::downgrade(&client) as Weak<RefCell<PacketProcessor>>);

        client
    }

    pub fn listen(&mut self) -> Result<()> {
        let mut buf = [0u8; PACKET_MAX_SIZE];
        loop {
            let (recv_len, rem_addr) = try!(self.sock.recv(&mut buf));
            let packet: Packet = try!(bcode_rcs::decode(&buf[..recv_len]));

            if let Some(ref mut packet_processor) = {
                let dst_extension = packet.get_destination_extension();
                self.packet_processors.get_mut(dst_extension).and_then(|packet_processor_weak|
                    packet_processor_weak.upgrade()
                )
            } {
                try!(packet_processor.borrow_mut().process_packet(packet, &mut self.sock, rem_addr));
            }
        }
    }
}

pub struct ClientSock {
    recv_rx: Receiver<Vec<u8>>,
    recv_tx: Sender<Vec<u8>>,
}

impl ClientSock {
    pub fn new(my_id: Identity, remote_id: RemoteServer) -> ClientSock {
        let (recv_tx, recv_rx) = channel();

        ClientSock {
            recv_rx: recv_rx,
            recv_tx: recv_tx,
        }
    }

    pub fn recv(&mut self) -> Result<Vec<u8>> {
        self.recv_rx.recv().or(Err("Couldnt read from recv channel".into()))
    }

    fn process_server_msg(&mut self, server_msg_packet: ServerMessagePacket) -> Result<()> {
        Err("Not implemented".into())
    }
}

impl PacketProcessor for ClientSock {
    fn process_packet(&mut self, packet: Packet, sock: &mut UdpSocket, rem_addr: SocketAddr) -> Result<()> {
        match packet {
            Packet::ServerMessage(server_msg_packet) => {
                try!(self.process_server_msg(server_msg_packet));
            },
            Packet::Cookie(cookie_packet) => {
            },
            _ => {
                debug!("Unvalid packet type");
            }
        }

        Ok(())
    }
}

pub struct ServerSocket {
    recv_rx: Receiver<Vec<u8>>,
    sock: UdpSocket,
    rem_addr: SocketAddr,
    client_extension: Extension,
    my_extension: Extension,
    precomputed_key: PrecomputedKey,
    next_send_nonce: Nonce8,
}

impl ServerSocket {
    pub fn recv(&mut self) -> Result<Vec<u8>> {
        self.recv_rx.recv().or(Err("Couldnt read from recv channel".into()))
    }

    pub fn send(&mut self, msg: &[u8]) -> Result<usize> {
        let server_msg_packet: Packet = ServerMessagePacket {
            client_extension: self.client_extension.clone(),
            server_extension: self.my_extension.clone(),
            payload_box: ServerMessageBox::seal_precomputed(msg, &self.next_send_nonce, &self.precomputed_key),
        }.into();

        self.next_send_nonce.increment();

        let sent = try!(server_msg_packet.send(&mut self.sock, &self.rem_addr));

        if sent >= SERVER_MSG_PACKET_BASE_SIZE {
            Ok(sent - SERVER_MSG_PACKET_BASE_SIZE)
        } else {
            Err("Header trimmed".into())
        }
    }
}

pub struct Listener {
    my_extension: Extension,
    my_long_term_sk: server_long_term::SecretKey,
    minute_key: crypto_secretbox::Key,
    last_minute_key: crypto_secretbox::Key,
    conns: HashMap<(Extension, client_short_term::PublicKey), ServerConnection>,
    accept_tx: Sender<ServerSocket>,
    accept_rx: Receiver<ServerSocket>,
}

impl Listener {
    fn new(my_id: Identity) -> Listener {
        let (_, my_long_term_sk, my_extension) = my_id.as_server();
        let (accept_tx, accept_rx) = channel();

        Listener {
            my_extension: my_extension,
            my_long_term_sk: my_long_term_sk,
            minute_key: crypto_secretbox::gen_key(),
            last_minute_key: crypto_secretbox::gen_key(),
            conns: HashMap::new(),
            accept_tx: accept_tx,
            accept_rx: accept_rx,
        }
    }

    pub fn accept(&mut self) -> Result<ServerSocket> {
        self.accept_rx.recv().or(Err("Couldnt read accept channel".into()))
    }

    fn process_hello(&self, hello_packet: HelloPacket, sock: &mut UdpSocket, rem_addr: SocketAddr) -> Result<()> {
        let client_short_term_pk = hello_packet.client_short_term_pk;
        let conn_key = (hello_packet.client_extension.clone(), client_short_term_pk.clone());

        if self.conns.contains_key(&conn_key) {
            debug!("Hello packet received on open connection");
            return Ok(());
        }

        hello_packet.hello_box.open(&client_short_term_pk, &self.my_long_term_sk).unwrap();

        let (server_short_term_pk, server_short_term_sk) = server_short_term::gen_keypair();

        let cookie_packet: Packet = CookiePacket {
            client_extension: hello_packet.client_extension.clone(),
            server_extension: self.my_extension.clone(),
            cookie_box: PlainCookieBox {
                server_short_term_pk: server_short_term_pk,
                server_cookie: PlainCookie {
                    client_short_term_pk: client_short_term_pk.clone(),
                    server_short_term_sk: server_short_term_sk.clone(),
                }.seal(&CookieNonce::new_random(), &self.minute_key),
            }.seal(&Nonce16::new_random(), &client_short_term_pk, &self.my_long_term_sk),
        }.into();

        try!(cookie_packet.send(sock, &rem_addr));

        Ok(())
    }

    fn process_initiate(&mut self, initiate_packet: InitiatePacket, sock: &mut UdpSocket, rem_addr: SocketAddr) -> Result<()> {
        let conn_key = (initiate_packet.client_extension.clone(), initiate_packet.client_short_term_pk.clone());

        if self.conns.contains_key(&conn_key) {
            debug!("Recv'd INITIATE on already initiated connection");
            return Ok(());
        }

        let cookie = initiate_packet.server_cookie.open(&self.minute_key, &self.last_minute_key).unwrap();
        let precomputed_key = PrecomputedKey::precompute_at_server(&initiate_packet.client_short_term_pk, &cookie.server_short_term_sk);
        let (initiate_box, payload) = initiate_packet.initiate_box.open_precomputed_with_payload(&precomputed_key).unwrap();

        let client_long_term_pk = initiate_box.client_long_term_pk;
        let vouch = initiate_box.vouch.open(&client_long_term_pk, &self.my_long_term_sk).unwrap();

        if vouch.client_short_term_pk != initiate_packet.client_short_term_pk {
            return try!(Err("Invalid vouch"));
        }

        //TODO: Check if client_long_term_pk is accepted

        let (recv_tx, recv_rx) = channel();

        if let Some(msg) = payload {
            recv_tx.send(msg).unwrap();
        }

        let new_conn = ServerConnection {
            precomputed_key: precomputed_key.clone(),
            recv_tx: recv_tx,
            last_recv_nonce: initiate_packet.initiate_box.nonce.clone(),
        };

        self.conns.insert(conn_key, new_conn);
        info!("\"{}\" accepting connection \"{}\"@{}", &self.my_extension, &initiate_packet.client_extension, &rem_addr);

        let new_sock = ServerSocket {
            recv_rx: recv_rx,
            sock: sock.try_clone().unwrap(),
            rem_addr: rem_addr,
            client_extension: initiate_packet.client_extension.clone(),
            my_extension: self.my_extension.clone(),
            precomputed_key: precomputed_key,
            next_send_nonce: Nonce8::new_low(),
        };

        self.accept_tx.send(new_sock).or(Err("Couldnt read accept channel".into()))
    }

    fn process_client_msg(&mut self, client_msg_packet: ClientMessagePacket, _sock: &mut UdpSocket, _rem_addr: SocketAddr) -> Result<()> {
        let conn_key = (client_msg_packet.client_extension.clone(),
                        client_msg_packet.client_short_term_pk.clone());

        if let Some(server_conn) = self.conns.get_mut(&conn_key) {
            try!(server_conn.process_packet(client_msg_packet));
        }

        Ok(())
    }
}

impl PacketProcessor for Listener {
    fn process_packet(&mut self, packet: Packet, sock: &mut UdpSocket, rem_addr: SocketAddr) -> Result<()> {
        match packet {
            Packet::ClientMessage(client_msg_packet) => {
                try!(self.process_client_msg(client_msg_packet, sock, rem_addr));
            },
            Packet::Initiate(initiate_packet) => {
                try!(self.process_initiate(initiate_packet, sock, rem_addr));
            },
            Packet::Hello(hello_packet) => {
                try!(self.process_hello(hello_packet, sock, rem_addr));
            },
            _ => {
                debug!("Unvalid packet type");
            }
        }

        Ok(())
    }
}

struct ServerConnection {
    precomputed_key: PrecomputedKey,
    recv_tx: Sender<Vec<u8>>,
    last_recv_nonce: Nonce8,
}

impl ServerConnection {
    pub fn process_packet(&mut self, client_msg_packet: ClientMessagePacket) -> Result<()> {
        if client_msg_packet.payload_box.nonce <= self.last_recv_nonce {
            return Err("Bad nonce".into()); // TODO: Rework to allow some packet reordering
        }

        let msg = try!(client_msg_packet.payload_box.open_precomputed(&self.precomputed_key)
            .or(Err("Bad encrypted message")));

        self.last_recv_nonce = client_msg_packet.payload_box.nonce;

        try!(self.recv_tx.send(msg).or(Err("Couldnt write to recv channel")));

        Ok(())
    }
}
<commit_msg>ClientSock processing Cookie<commit_after>use std::collections::HashMap;
use std::net::SocketAddr;
use std::rc::{Rc, Weak};
use std::cell::RefCell;

use mioco::udp::UdpSocket;
use mioco::sync::mpsc::{channel, Receiver, Sender};
use bincode::rustc_serialize as bcode_rcs;
use sodiumoxide::crypto::secretbox as crypto_secretbox;

use ::Result;
use identity::{Identity, Extension, RemoteServer, DomainName};
use packet::*;
use keys::*;
use boxes::*;
use nonces::*;

pub struct Stream {

}

impl Stream {
    pub fn new() -> Stream {
        Stream {}
    }
}

trait PacketProcessor {
    fn process_packet(&mut self, packet: Packet, sock: &mut UdpSocket, rem_addr: SocketAddr) -> Result<()>;
}

pub struct Demultiplexor {
    sock: UdpSocket,
    packet_processors: HashMap<Extension, Weak<RefCell<PacketProcessor>>>,
}

impl Demultiplexor {
    pub fn new(sock: UdpSocket) -> Demultiplexor {
        Demultiplexor {
            sock: sock,
            packet_processors: HashMap::new(),
        }
    }

    pub fn create_listener(&mut self, listener_id: Identity) -> Rc<RefCell<Listener>> {
        let listener_extension = listener_id.extension.clone();
        let listener = Rc::new(RefCell::new(Listener::new(listener_id)));

        self.packet_processors.insert(listener_extension, Rc::downgrade(&listener) as Weak<RefCell<PacketProcessor>>);

        listener
    }

    pub fn create_client(&mut self, client_id: Identity, remote_id: RemoteServer) -> Result<Rc<RefCell<ClientSock>>> {
        let client_extension = client_id.extension.clone();
        let client = Rc::new(RefCell::new(try!(ClientSock::connect(&mut self.sock, client_id, remote_id))));

        self.packet_processors.insert(client_extension, Rc::downgrade(&client) as Weak<RefCell<PacketProcessor>>);

        Ok(client)
    }

    pub fn listen(&mut self) -> Result<()> {
        let mut buf = [0u8; PACKET_MAX_SIZE];
        loop {
            let (recv_len, rem_addr) = try!(self.sock.recv(&mut buf));
            let packet: Packet = try!(bcode_rcs::decode(&buf[..recv_len]));

            if let Some(ref mut packet_processor) = {
                let dst_extension = packet.get_destination_extension();
                self.packet_processors.get_mut(dst_extension).and_then(|packet_processor_weak|
                    packet_processor_weak.upgrade()
                )
            } {
                try!(packet_processor.borrow_mut().process_packet(packet, &mut self.sock, rem_addr));
            }
        }
    }
}

pub struct ClientSock {
    recv_rx: Receiver<Vec<u8>>,
    recv_tx: Sender<Vec<u8>>,
    my_long_term_pk: client_long_term::PublicKey,
    my_long_term_sk: client_long_term::SecretKey,
    my_extension: Extension,
    my_short_term_pk: client_short_term::PublicKey,
    my_short_term_sk: client_short_term::SecretKey,
    precomputed_key: Option<PrecomputedKey>,
    server_extension: Extension,
    server_long_term_pk: server_long_term::PublicKey,
    server_addr: SocketAddr,
    next_send_nonce: Nonce8,
}

impl ClientSock {
    pub fn connect(sock: &mut UdpSocket, my_id: Identity, remote_id: RemoteServer) -> Result<ClientSock> {
        let (recv_tx, recv_rx) = channel();
        let (my_long_term_pk, my_long_term_sk, my_extension) = my_id.as_client();
        let (my_short_term_pk, my_short_term_sk) = client_short_term::gen_keypair();
        let mut next_send_nonce = Nonce8::new_low();
        let RemoteServer { server_extension, server_long_term_pk, server_addr } = remote_id;

        let hello_packet: Packet = HelloPacket {
            server_extension: server_extension.clone(),
            client_extension: my_extension.clone(),
            client_short_term_pk: my_short_term_pk.clone(),
            hello_box: PlainHelloBox::new_empty().seal(&next_send_nonce, &server_long_term_pk, &my_short_term_sk),
        }.into();
        next_send_nonce.increment();

        try!(hello_packet.send(sock, &server_addr));

        // TODO: recv from demultiplexor somehow. Maybe split ClientSockSeed and proper ClientSock
        // Maybe a PacketProcessor closure. What about non-demultiplexed ones?

        Ok(ClientSock {
            recv_rx: recv_rx,
            recv_tx: recv_tx,
            my_long_term_pk: my_long_term_pk,
            my_long_term_sk: my_long_term_sk,
            my_extension: my_extension,
            my_short_term_pk: my_short_term_pk,
            my_short_term_sk: my_short_term_sk,
            precomputed_key: None,
            server_extension: server_extension,
            server_long_term_pk: server_long_term_pk,
            server_addr: server_addr,
            next_send_nonce: next_send_nonce,
        })
    }

    pub fn recv(&mut self) -> Result<Vec<u8>> {
        self.recv_rx.recv().or(Err("Couldnt read from recv channel".into()))
    }

    fn process_cookie_packet(&mut self, cookie_packet: CookiePacket, sock: &mut UdpSocket, rem_addr: SocketAddr) -> Result<()> {
        let cookie_box = cookie_packet.cookie_box.open(&self.server_long_term_pk, &self.my_short_term_sk).unwrap();
        let server_short_term_pk = cookie_box.server_short_term_pk;
        let precomputed_key = PrecomputedKey::precompute_at_client(&server_short_term_pk, &self.my_short_term_sk);

        let initiate_packet: Packet = InitiatePacket {
            server_extension: self.server_extension.clone(),
            client_extension: self.my_extension.clone(),
            client_short_term_pk: self.my_short_term_pk.clone(),
            server_cookie: cookie_box.server_cookie,
            initiate_box: PlainInitiateBox {
                client_long_term_pk: self.my_long_term_pk.clone(),
                vouch: PlainVouch {
                    client_short_term_pk: self.my_short_term_pk.clone(),
                }.seal(&Nonce16::new_random(), &self.server_long_term_pk, &self.my_long_term_sk),
                domain_name: DomainName::new_empty(),
            }.seal_precomputed(&self.next_send_nonce, &precomputed_key, None),
        }.into();
        self.next_send_nonce.increment();

        try!(initiate_packet.send(sock, &rem_addr));

        self.precomputed_key = Some(precomputed_key);
        self.server_addr = rem_addr;

        Ok(())
    }

    fn process_server_msg(&mut self, server_msg_packet: ServerMessagePacket) -> Result<()> {
        Err("Not implemented".into())
    }
}

impl PacketProcessor for ClientSock {
    fn process_packet(&mut self, packet: Packet, sock: &mut UdpSocket, rem_addr: SocketAddr) -> Result<()> {
        match packet {
            Packet::ServerMessage(server_msg_packet) => {
                try!(self.process_server_msg(server_msg_packet));
            },
            Packet::Cookie(cookie_packet) => {
                try!(self.process_cookie_packet(cookie_packet, sock, rem_addr));
            },
            _ => {
                debug!("Unvalid packet type");
            }
        }

        Ok(())
    }
}

pub struct ServerSocket {
    recv_rx: Receiver<Vec<u8>>,
    sock: UdpSocket,
    rem_addr: SocketAddr,
    client_extension: Extension,
    my_extension: Extension,
    precomputed_key: PrecomputedKey,
    next_send_nonce: Nonce8,
}

impl ServerSocket {
    pub fn recv(&mut self) -> Result<Vec<u8>> {
        self.recv_rx.recv().or(Err("Couldnt read from recv channel".into()))
    }

    pub fn send(&mut self, msg: &[u8]) -> Result<usize> {
        let server_msg_packet: Packet = ServerMessagePacket {
            client_extension: self.client_extension.clone(),
            server_extension: self.my_extension.clone(),
            payload_box: ServerMessageBox::seal_precomputed(msg, &self.next_send_nonce, &self.precomputed_key),
        }.into();

        self.next_send_nonce.increment();

        let sent = try!(server_msg_packet.send(&mut self.sock, &self.rem_addr));

        if sent >= SERVER_MSG_PACKET_BASE_SIZE {
            Ok(sent - SERVER_MSG_PACKET_BASE_SIZE)
        } else {
            Err("Header trimmed".into())
        }
    }
}

pub struct Listener {
    my_extension: Extension,
    my_long_term_sk: server_long_term::SecretKey,
    minute_key: crypto_secretbox::Key,
    last_minute_key: crypto_secretbox::Key,
    conns: HashMap<(Extension, client_short_term::PublicKey), ServerConnection>,
    accept_tx: Sender<ServerSocket>,
    accept_rx: Receiver<ServerSocket>,
}

impl Listener {
    fn new(my_id: Identity) -> Listener {
        let (_, my_long_term_sk, my_extension) = my_id.as_server();
        let (accept_tx, accept_rx) = channel();

        Listener {
            my_extension: my_extension,
            my_long_term_sk: my_long_term_sk,
            minute_key: crypto_secretbox::gen_key(),
            last_minute_key: crypto_secretbox::gen_key(),
            conns: HashMap::new(),
            accept_tx: accept_tx,
            accept_rx: accept_rx,
        }
    }

    pub fn accept(&mut self) -> Result<ServerSocket> {
        self.accept_rx.recv().or(Err("Couldnt read accept channel".into()))
    }

    fn process_hello(&self, hello_packet: HelloPacket, sock: &mut UdpSocket, rem_addr: SocketAddr) -> Result<()> {
        let client_short_term_pk = hello_packet.client_short_term_pk;
        let conn_key = (hello_packet.client_extension.clone(), client_short_term_pk.clone());

        if self.conns.contains_key(&conn_key) {
            debug!("Hello packet received on open connection");
            return Ok(());
        }

        hello_packet.hello_box.open(&client_short_term_pk, &self.my_long_term_sk).unwrap();

        let (server_short_term_pk, server_short_term_sk) = server_short_term::gen_keypair();

        let cookie_packet: Packet = CookiePacket {
            client_extension: hello_packet.client_extension.clone(),
            server_extension: self.my_extension.clone(),
            cookie_box: PlainCookieBox {
                server_short_term_pk: server_short_term_pk,
                server_cookie: PlainCookie {
                    client_short_term_pk: client_short_term_pk.clone(),
                    server_short_term_sk: server_short_term_sk.clone(),
                }.seal(&CookieNonce::new_random(), &self.minute_key),
            }.seal(&Nonce16::new_random(), &client_short_term_pk, &self.my_long_term_sk),
        }.into();

        try!(cookie_packet.send(sock, &rem_addr));

        Ok(())
    }

    fn process_initiate(&mut self, initiate_packet: InitiatePacket, sock: &mut UdpSocket, rem_addr: SocketAddr) -> Result<()> {
        let conn_key = (initiate_packet.client_extension.clone(), initiate_packet.client_short_term_pk.clone());

        if self.conns.contains_key(&conn_key) {
            debug!("Recv'd INITIATE on already initiated connection");
            return Ok(());
        }

        let cookie = initiate_packet.server_cookie.open(&self.minute_key, &self.last_minute_key).unwrap();
        let precomputed_key = PrecomputedKey::precompute_at_server(&initiate_packet.client_short_term_pk, &cookie.server_short_term_sk);
        let (initiate_box, payload) = initiate_packet.initiate_box.open_precomputed_with_payload(&precomputed_key).unwrap();

        let client_long_term_pk = initiate_box.client_long_term_pk;
        let vouch = initiate_box.vouch.open(&client_long_term_pk, &self.my_long_term_sk).unwrap();

        if vouch.client_short_term_pk != initiate_packet.client_short_term_pk {
            return try!(Err("Invalid vouch"));
        }

        //TODO: Check if client_long_term_pk is accepted

        let (recv_tx, recv_rx) = channel();

        if let Some(msg) = payload {
            recv_tx.send(msg).unwrap();
        }

        let new_conn = ServerConnection {
            precomputed_key: precomputed_key.clone(),
            recv_tx: recv_tx,
            last_recv_nonce: initiate_packet.initiate_box.nonce.clone(),
        };

        self.conns.insert(conn_key, new_conn);
        info!("\"{}\" accepting connection \"{}\"@{}", &self.my_extension, &initiate_packet.client_extension, &rem_addr);

        let new_sock = ServerSocket {
            recv_rx: recv_rx,
            sock: sock.try_clone().unwrap(),
            rem_addr: rem_addr,
            client_extension: initiate_packet.client_extension.clone(),
            my_extension: self.my_extension.clone(),
            precomputed_key: precomputed_key,
            next_send_nonce: Nonce8::new_low(),
        };

        self.accept_tx.send(new_sock).or(Err("Couldnt read accept channel".into()))
    }

    fn process_client_msg(&mut self, client_msg_packet: ClientMessagePacket, _sock: &mut UdpSocket, _rem_addr: SocketAddr) -> Result<()> {
        let conn_key = (client_msg_packet.client_extension.clone(),
                        client_msg_packet.client_short_term_pk.clone());

        if let Some(server_conn) = self.conns.get_mut(&conn_key) {
            try!(server_conn.process_packet(client_msg_packet));
        }

        Ok(())
    }
}

impl PacketProcessor for Listener {
    fn process_packet(&mut self, packet: Packet, sock: &mut UdpSocket, rem_addr: SocketAddr) -> Result<()> {
        match packet {
            Packet::ClientMessage(client_msg_packet) => {
                try!(self.process_client_msg(client_msg_packet, sock, rem_addr));
            },
            Packet::Initiate(initiate_packet) => {
                try!(self.process_initiate(initiate_packet, sock, rem_addr));
            },
            Packet::Hello(hello_packet) => {
                try!(self.process_hello(hello_packet, sock, rem_addr));
            },
            _ => {
                debug!("Unvalid packet type");
            }
        }

        Ok(())
    }
}

struct ServerConnection {
    precomputed_key: PrecomputedKey,
    recv_tx: Sender<Vec<u8>>,
    last_recv_nonce: Nonce8,
}

impl ServerConnection {
    pub fn process_packet(&mut self, client_msg_packet: ClientMessagePacket) -> Result<()> {
        if client_msg_packet.payload_box.nonce <= self.last_recv_nonce {
            return Err("Bad nonce".into()); // TODO: Rework to allow some packet reordering
        }

        let msg = try!(client_msg_packet.payload_box.open_precomputed(&self.precomputed_key)
            .or(Err("Bad encrypted message")));

        self.last_recv_nonce = client_msg_packet.payload_box.nonce;

        try!(self.recv_tx.send(msg).or(Err("Couldnt write to recv channel")));

        Ok(())
    }
}
<|endoftext|>


<commit_before>#![allow(unused_imports)]

use {io, Evented, EventSet, Poll, PollOpt, Registration, SetReadiness, Token};
use lazy::{Lazy, AtomicLazy};
use std::sync::{mpsc, Arc};
use std::sync::atomic::{AtomicUsize, Ordering};

#[derive(Clone)]
pub struct SenderCtl {
    inner: Arc<Inner>,
}

pub struct ReceiverCtl {
    registration: Lazy<Registration>,
    inner: Arc<Inner>,
}

pub struct Sender<T> {
    tx: StdSender<T>,
    ctl: SenderCtl,
}

enum StdSender<T> {
    Bounded(mpsc::SyncSender<T>),
    Unbounded(mpsc::Sender<T>),
}

pub struct Receiver<T> {
    rx: mpsc::Receiver<T>,
    ctl: ReceiverCtl,
}

#[derive(Debug)]
pub enum SendError<T> {
    Io(io::Error),
    Disconnected(T),
}

#[derive(Debug)]
pub enum TrySendError<T> {
    Io(io::Error),
    Full(T),
    Disconnected(T),
}

struct Inner {
    pending: AtomicUsize,
    set_readiness: AtomicLazy<SetReadiness>,
}

pub fn from_std_channel<T>((tx, rx): (mpsc::Sender<T>, mpsc::Receiver<T>)) -> (Sender<T>, Receiver<T>)
{
    let (tx_ctl, rx_ctl) = ctl_pair();

    let tx = Sender {
        tx: StdSender::Unbounded(tx),
        ctl: tx_ctl,
    };

    let rx = Receiver {
        rx: rx,
        ctl: rx_ctl,
    };

    (tx, rx)
}

pub fn from_std_sync_channel<T>((tx, rx): (mpsc::SyncSender<T>, mpsc::Receiver<T>)) -> (Sender<T>, Receiver<T>)
{
    let (tx_ctl, rx_ctl) = ctl_pair();

    let tx = Sender {
        tx: StdSender::Bounded(tx),
        ctl: tx_ctl,
    };

    let rx = Receiver {
        rx: rx,
        ctl: rx_ctl,
    };

    (tx, rx)
}

pub fn ctl_pair() -> (SenderCtl, ReceiverCtl) {
    let inner = Arc::new(Inner {
        pending: AtomicUsize::new(0),
        set_readiness: AtomicLazy::new(),
    });

    let tx = SenderCtl {
        inner: inner.clone(),
    };

    let rx = ReceiverCtl {
        registration: Lazy::new(),
        inner: inner,
    };

    (tx, rx)
}

impl SenderCtl {
    /// Call to track that a message has been sent
    pub fn inc(&self) -> io::Result<()> {
        if 0 == self.inner.pending.fetch_add(1, Ordering::Acquire) {
            // Toggle readiness to readable
            if let Some(set_readiness) = self.inner.set_readiness.as_ref() {
                try!(set_readiness.set_readiness(EventSet::readable()));
            }
        }

        Ok(())
    }
}

impl ReceiverCtl {
    pub fn dec(&self) -> io::Result<()> {
        let first = self.inner.pending.load(Ordering::Acquire);

        if first == 1 {
            // Unset readiness
            if let Some(set_readiness) = self.inner.set_readiness.as_ref() {
                try!(set_readiness.set_readiness(EventSet::none()));
            }
        }

        // Decrement
        let second = self.inner.pending.fetch_sub(1, Ordering::AcqRel);

        if first == 1 && second > 0 {
            // There are still pending messages. Since readiness was
            // previously unset, it must be reset here
            if let Some(set_readiness) = self.inner.set_readiness.as_ref() {
                try!(set_readiness.set_readiness(EventSet::none()));
            }
        }

        Ok(())
    }
}

impl Evented for ReceiverCtl {
    fn register(&self, poll: &Poll, token: Token, interest: EventSet, opts: PollOpt) -> io::Result<()> {
        if self.registration.is_some() {
            return Err(io::Error::new(io::ErrorKind::Other, "receiver already registered"));
        }

        let (registration, set_readiness) = Registration::new(poll, token, interest, opts);

        if self.inner.pending.load(Ordering::Relaxed) > 0 {
            // TODO: Don't drop readiness
            let _ = set_readiness.set_readiness(EventSet::readable());
        }

        self.registration.set(registration).ok().expect("unexpected state encountered");
        self.inner.set_readiness.set(set_readiness).ok().expect("unexpected state encountered");

        Ok(())
    }

    fn reregister(&self, poll: &Poll, token: Token, interest: EventSet, opts: PollOpt) -> io::Result<()> {
        match self.registration.as_ref() {
            Some(registration) => registration.update(poll, token, interest, opts),
            None => Err(io::Error::new(io::ErrorKind::Other, "receiver not registered")),
        }
    }

    fn deregister(&self, poll: &Poll) -> io::Result<()> {
        match self.registration.as_ref() {
            Some(registration) => registration.deregister(poll),
            None => Err(io::Error::new(io::ErrorKind::Other, "receiver not registered")),
        }
    }
}

impl<T> Sender<T> {
    pub fn send(&self, t: T) -> Result<(), SendError<T>> {
        self.tx.send(t).and_then(|_| {
            try!(self.ctl.inc());
            Ok(())
        })
    }

    pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
        self.tx.try_send(t).and_then(|_| {
            try!(self.ctl.inc());
            Ok(())
        })
    }
}

impl<T> Clone for Sender<T> {
    fn clone(&self) -> Sender<T> {
        Sender {
            tx: self.tx.clone(),
            ctl: self.ctl.clone(),
        }
    }
}

impl<T> StdSender<T> {
    pub fn send(&self, t: T) -> Result<(), SendError<T>> {
        match *self {
            StdSender::Bounded(ref tx) => tx.send(t).map_err(SendError::from),
            StdSender::Unbounded(ref tx) => tx.send(t).map_err(SendError::from),
        }
    }

    pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
        match *self {
            StdSender::Bounded(ref tx) => tx.try_send(t).map_err(TrySendError::from),
            StdSender::Unbounded(ref tx) => tx.send(t).map_err(TrySendError::from),
        }
    }
}

impl<T> Clone for StdSender<T> {
    fn clone(&self) -> StdSender<T> {
        match *self {
            StdSender::Bounded(ref v) => StdSender::Bounded(v.clone()),
            StdSender::Unbounded(ref v) => StdSender::Unbounded(v.clone()),
        }
    }
}

impl<T> Receiver<T> {
    pub fn try_recv(&self) -> Result<T, mpsc::TryRecvError> {
        self.rx.try_recv().and_then(|res| {
            let _ = self.ctl.dec();
            Ok(res)
        })
    }
}

impl<T> Evented for Receiver<T> {
    fn register(&self, poll: &Poll, token: Token, interest: EventSet, opts: PollOpt) -> io::Result<()> {
        self.ctl.register(poll, token, interest, opts)
    }

    fn reregister(&self, poll: &Poll, token: Token, interest: EventSet, opts: PollOpt) -> io::Result<()> {
        self.ctl.reregister(poll, token, interest, opts)
    }

    fn deregister(&self, poll: &Poll) -> io::Result<()> {
        self.ctl.deregister(poll)
    }
}

impl<T> From<mpsc::SendError<T>> for SendError<T> {
    fn from(src: mpsc::SendError<T>) -> SendError<T> {
        SendError::Disconnected(src.0)
    }
}

impl<T> From<io::Error> for SendError<T> {
    fn from(src: io::Error) -> SendError<T> {
        SendError::Io(src)
    }
}

impl<T> From<mpsc::TrySendError<T>> for TrySendError<T> {
    fn from(src: mpsc::TrySendError<T>) -> TrySendError<T> {
        match src {
            mpsc::TrySendError::Full(v) => TrySendError::Full(v),
            mpsc::TrySendError::Disconnected(v) => TrySendError::Disconnected(v),
        }
    }
}

impl<T> From<mpsc::SendError<T>> for TrySendError<T> {
    fn from(src: mpsc::SendError<T>) -> TrySendError<T> {
        TrySendError::Disconnected(src.0)
    }
}

impl<T> From<io::Error> for TrySendError<T> {
    fn from(src: io::Error) -> TrySendError<T> {
        TrySendError::Io(src)
    }
}
<commit_msg>Add channel::channel()<commit_after>#![allow(unused_imports)]

use {io, Evented, EventSet, Poll, PollOpt, Registration, SetReadiness, Token};
use lazy::{Lazy, AtomicLazy};
use std::sync::{mpsc, Arc};
use std::sync::atomic::{AtomicUsize, Ordering};

#[derive(Clone)]
pub struct SenderCtl {
    inner: Arc<Inner>,
}

pub struct ReceiverCtl {
    registration: Lazy<Registration>,
    inner: Arc<Inner>,
}

pub struct Sender<T> {
    tx: StdSender<T>,
    ctl: SenderCtl,
}

enum StdSender<T> {
    Bounded(mpsc::SyncSender<T>),
    Unbounded(mpsc::Sender<T>),
}

pub struct Receiver<T> {
    rx: mpsc::Receiver<T>,
    ctl: ReceiverCtl,
}

#[derive(Debug)]
pub enum SendError<T> {
    Io(io::Error),
    Disconnected(T),
}

#[derive(Debug)]
pub enum TrySendError<T> {
    Io(io::Error),
    Full(T),
    Disconnected(T),
}

struct Inner {
    pending: AtomicUsize,
    set_readiness: AtomicLazy<SetReadiness>,
}

pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
    from_std_channel(mpsc::channel())
}

pub fn from_std_channel<T>((tx, rx): (mpsc::Sender<T>, mpsc::Receiver<T>)) -> (Sender<T>, Receiver<T>)
{
    let (tx_ctl, rx_ctl) = ctl_pair();

    let tx = Sender {
        tx: StdSender::Unbounded(tx),
        ctl: tx_ctl,
    };

    let rx = Receiver {
        rx: rx,
        ctl: rx_ctl,
    };

    (tx, rx)
}

pub fn from_std_sync_channel<T>((tx, rx): (mpsc::SyncSender<T>, mpsc::Receiver<T>)) -> (Sender<T>, Receiver<T>)
{
    let (tx_ctl, rx_ctl) = ctl_pair();

    let tx = Sender {
        tx: StdSender::Bounded(tx),
        ctl: tx_ctl,
    };

    let rx = Receiver {
        rx: rx,
        ctl: rx_ctl,
    };

    (tx, rx)
}

pub fn ctl_pair() -> (SenderCtl, ReceiverCtl) {
    let inner = Arc::new(Inner {
        pending: AtomicUsize::new(0),
        set_readiness: AtomicLazy::new(),
    });

    let tx = SenderCtl {
        inner: inner.clone(),
    };

    let rx = ReceiverCtl {
        registration: Lazy::new(),
        inner: inner,
    };

    (tx, rx)
}

impl SenderCtl {
    /// Call to track that a message has been sent
    pub fn inc(&self) -> io::Result<()> {
        if 0 == self.inner.pending.fetch_add(1, Ordering::Acquire) {
            // Toggle readiness to readable
            if let Some(set_readiness) = self.inner.set_readiness.as_ref() {
                try!(set_readiness.set_readiness(EventSet::readable()));
            }
        }

        Ok(())
    }
}

impl ReceiverCtl {
    pub fn dec(&self) -> io::Result<()> {
        let first = self.inner.pending.load(Ordering::Acquire);

        if first == 1 {
            // Unset readiness
            if let Some(set_readiness) = self.inner.set_readiness.as_ref() {
                try!(set_readiness.set_readiness(EventSet::none()));
            }
        }

        // Decrement
        let second = self.inner.pending.fetch_sub(1, Ordering::AcqRel);

        if first == 1 && second > 0 {
            // There are still pending messages. Since readiness was
            // previously unset, it must be reset here
            if let Some(set_readiness) = self.inner.set_readiness.as_ref() {
                try!(set_readiness.set_readiness(EventSet::none()));
            }
        }

        Ok(())
    }
}

impl Evented for ReceiverCtl {
    fn register(&self, poll: &Poll, token: Token, interest: EventSet, opts: PollOpt) -> io::Result<()> {
        if self.registration.is_some() {
            return Err(io::Error::new(io::ErrorKind::Other, "receiver already registered"));
        }

        let (registration, set_readiness) = Registration::new(poll, token, interest, opts);

        if self.inner.pending.load(Ordering::Relaxed) > 0 {
            // TODO: Don't drop readiness
            let _ = set_readiness.set_readiness(EventSet::readable());
        }

        self.registration.set(registration).ok().expect("unexpected state encountered");
        self.inner.set_readiness.set(set_readiness).ok().expect("unexpected state encountered");

        Ok(())
    }

    fn reregister(&self, poll: &Poll, token: Token, interest: EventSet, opts: PollOpt) -> io::Result<()> {
        match self.registration.as_ref() {
            Some(registration) => registration.update(poll, token, interest, opts),
            None => Err(io::Error::new(io::ErrorKind::Other, "receiver not registered")),
        }
    }

    fn deregister(&self, poll: &Poll) -> io::Result<()> {
        match self.registration.as_ref() {
            Some(registration) => registration.deregister(poll),
            None => Err(io::Error::new(io::ErrorKind::Other, "receiver not registered")),
        }
    }
}

impl<T> Sender<T> {
    pub fn send(&self, t: T) -> Result<(), SendError<T>> {
        self.tx.send(t).and_then(|_| {
            try!(self.ctl.inc());
            Ok(())
        })
    }

    pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
        self.tx.try_send(t).and_then(|_| {
            try!(self.ctl.inc());
            Ok(())
        })
    }
}

impl<T> Clone for Sender<T> {
    fn clone(&self) -> Sender<T> {
        Sender {
            tx: self.tx.clone(),
            ctl: self.ctl.clone(),
        }
    }
}

impl<T> StdSender<T> {
    pub fn send(&self, t: T) -> Result<(), SendError<T>> {
        match *self {
            StdSender::Bounded(ref tx) => tx.send(t).map_err(SendError::from),
            StdSender::Unbounded(ref tx) => tx.send(t).map_err(SendError::from),
        }
    }

    pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
        match *self {
            StdSender::Bounded(ref tx) => tx.try_send(t).map_err(TrySendError::from),
            StdSender::Unbounded(ref tx) => tx.send(t).map_err(TrySendError::from),
        }
    }
}

impl<T> Clone for StdSender<T> {
    fn clone(&self) -> StdSender<T> {
        match *self {
            StdSender::Bounded(ref v) => StdSender::Bounded(v.clone()),
            StdSender::Unbounded(ref v) => StdSender::Unbounded(v.clone()),
        }
    }
}

impl<T> Receiver<T> {
    pub fn try_recv(&self) -> Result<T, mpsc::TryRecvError> {
        self.rx.try_recv().and_then(|res| {
            let _ = self.ctl.dec();
            Ok(res)
        })
    }
}

impl<T> Evented for Receiver<T> {
    fn register(&self, poll: &Poll, token: Token, interest: EventSet, opts: PollOpt) -> io::Result<()> {
        self.ctl.register(poll, token, interest, opts)
    }

    fn reregister(&self, poll: &Poll, token: Token, interest: EventSet, opts: PollOpt) -> io::Result<()> {
        self.ctl.reregister(poll, token, interest, opts)
    }

    fn deregister(&self, poll: &Poll) -> io::Result<()> {
        self.ctl.deregister(poll)
    }
}

impl<T> From<mpsc::SendError<T>> for SendError<T> {
    fn from(src: mpsc::SendError<T>) -> SendError<T> {
        SendError::Disconnected(src.0)
    }
}

impl<T> From<io::Error> for SendError<T> {
    fn from(src: io::Error) -> SendError<T> {
        SendError::Io(src)
    }
}

impl<T> From<mpsc::TrySendError<T>> for TrySendError<T> {
    fn from(src: mpsc::TrySendError<T>) -> TrySendError<T> {
        match src {
            mpsc::TrySendError::Full(v) => TrySendError::Full(v),
            mpsc::TrySendError::Disconnected(v) => TrySendError::Disconnected(v),
        }
    }
}

impl<T> From<mpsc::SendError<T>> for TrySendError<T> {
    fn from(src: mpsc::SendError<T>) -> TrySendError<T> {
        TrySendError::Disconnected(src.0)
    }
}

impl<T> From<io::Error> for TrySendError<T> {
    fn from(src: io::Error) -> TrySendError<T> {
        TrySendError::Io(src)
    }
}
<|endoftext|>


<commit_before>use std::str::{self, FromStr};
use std::collections::HashMap;

use quick_xml::{XmlReader, XmlWriter, Event, Element};
use quick_xml::error::Error as XmlError;

use fromxml::{self, FromXml};
use toxml::{ToXml, XmlWriterExt};
use error::Error;
use category::Category;
use cloud::Cloud;
use image::Image;
use textinput::TextInput;
use item::Item;
use extension::{self, ExtensionMap};
use extension::itunes::ITunesChannelExtension;
use extension::dublincore::DublinCoreExtension;

/// A representation of the `<channel>` element.
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Channel {
    /// The name of the channel.
    pub title: String,
    /// The URL for the website corresponding to the channel.
    pub link: String,
    /// A description of the channel.
    pub description: String,
    /// The language of the channel.
    pub language: Option<String>,
    /// The copyright notice for the channel.
    pub copyright: Option<String>,
    /// The email address for the managing editor.
    pub managing_editor: Option<String>,
    /// The email address for the webmaster.
    pub webmaster: Option<String>,
    /// The publication date for the content of the channel.
    pub pub_date: Option<String>,
    /// The date that the contents of the channel last changed.
    pub last_build_date: Option<String>,
    /// The categories the channel belongs to.
    pub categories: Vec<Category>,
    /// The program used to generate the channel.
    pub generator: Option<String>,
    /// A URL that points to the documentation for the RSS format.
    pub docs: Option<String>,
    /// The cloud to register with to be notified of updates to the channel.
    pub cloud: Option<Cloud>,
    /// The number of minutes the channel can be cached before refreshing.
    pub ttl: Option<String>,
    /// An image that can be displayed with the channel.
    pub image: Option<Image>,
    /// A text input box that can be displayed with the channel.
    pub text_input: Option<TextInput>,
    /// A hint to tell the aggregator which hours it can skip.
    pub skip_hours: Vec<String>,
    /// A hint to tell the aggregator which days it can skip.
    pub skip_days: Vec<String>,
    /// The items in the channel.
    pub items: Vec<Item>,
    /// The extensions for the channel.
    pub extensions: ExtensionMap,
    /// The iTunes extension for the channel.
    pub itunes_ext: Option<ITunesChannelExtension>,
    /// The Dublin Core extension for the channel.
    pub dublin_core_ext: Option<DublinCoreExtension>,
    /// The namespaces present in the RSS tag.
    pub namespaces: HashMap<String, String>,
}

impl Channel {
    /// Attempt to read the RSS channel from the speficied reader.
    ///
    /// # Example
    ///
    /// ```rust,ignore
    /// let reader: BufRead = ...;
    /// let channel = Channel::read_from(reader).unwrap();
    /// ```
    pub fn read_from<R: ::std::io::BufRead>(reader: R) -> Result<Channel, Error> {
        let mut reader = XmlReader::from_reader(reader).trim_text(true);
        let mut in_rss = false;
        let mut namespaces = HashMap::new();

        while let Some(e) = reader.next() {
            match e {
                Ok(Event::Start(element)) => {
                    match element.name() {
                        b"rss" if !in_rss => {
                            for attr in element.attributes().with_checks(false) {
                                if let Ok(attr) = attr {
                                    let split =
                                        attr.0.splitn(2, |b| *b == b':').collect::<Vec<_>>();
                                    if split.len() != 2 {
                                        continue;
                                    }

                                    let ns = unsafe { split.get_unchecked(0) };
                                    if ns != b"xmlns" {
                                        continue;
                                    }

                                    let name = unsafe { split.get_unchecked(1) };
                                    if name == b"itunes" || name == b"dc" {
                                        continue;
                                    }

                                    let key = try!(str::from_utf8(name)).to_string();
                                    let value = try!(String::from_utf8(attr.1.into_owned()));
                                    namespaces.insert(key, value);
                                }
                            }

                            in_rss = true;
                        }
                        b"channel" if in_rss => {
                            let mut channel = try!(Channel::from_xml(reader, element).map(|v| v.0));
                            channel.namespaces = namespaces;
                            return Ok(channel);
                        }
                        _ => skip_element!(reader),
                    }
                }
                Ok(Event::End(_)) => in_rss = false,
                Err(err) => return Err(err.into()),
                _ => {}
            }
        }

        Err(Error::EOF)
    }

    /// Attempt to write the RSS channel as XML to the speficied writer.
    ///
    /// # Example
    ///
    /// ```rust,ignore
    /// let channel: Channel = ...;
    /// let writer: Write = ...;
    /// channel.write_to(writer).unwrap();
    /// ```
    pub fn write_to<W: ::std::io::Write>(&self, writer: W) -> Result<W, Error> {
        let mut writer = ::quick_xml::XmlWriter::new(writer);

        let element = Element::new(b"rss");

        try!(writer.write(Event::Start({
            let mut element = element.clone();
            element.extend_attributes(::std::iter::once((b"version", b"2.0")));

            let mut itunes_ns = self.itunes_ext.is_some();
            let mut dc_ns = self.dublin_core_ext.is_some();

            if !itunes_ns || dc_ns {
                for item in &self.items {
                    if !itunes_ns {
                        itunes_ns = item.itunes_ext.is_some();
                    }

                    if !dc_ns {
                        dc_ns = item.dublin_core_ext.is_some();
                    }

                    if itunes_ns && dc_ns {
                        break;
                    }
                }
            }

            if itunes_ns {
                element.extend_attributes(::std::iter::once((b"xmlns:itunes",
                                                             extension::itunes::NAMESPACE)));
            }

            if dc_ns {
                element.extend_attributes(::std::iter::once((b"xmlns:dc",
                                                             extension::dublincore::NAMESPACE)));
            }

            element.extend_attributes(self.namespaces
                .iter()
                .map(|(name, url)| (format!("xmlns:{}", name), url)));

            element
        })));

        try!(self.to_xml(&mut writer));

        try!(writer.write(Event::End(element)));

        Ok(writer.into_inner())
    }
}

impl ToString for Channel {
    fn to_string(&self) -> String {
        let buf = self.write_to(Vec::new()).unwrap_or(Vec::new());
        // this unwrap should be safe since the bytes written from the Channel are all valid utf8
        String::from_utf8(buf).unwrap()
    }
}

impl FromXml for Channel {
    fn from_xml<R: ::std::io::BufRead>(mut reader: XmlReader<R>,
                                       _: Element)
                                       -> Result<(Self, XmlReader<R>), Error> {
        let mut channel = Channel::default();

        while let Some(e) = reader.next() {
            match e {
                Ok(Event::Start(element)) => {
                    match element.name() {
                        b"category" => {
                            let (category, reader_) = try!(Category::from_xml(reader, element));
                            reader = reader_;
                            channel.categories.push(category);
                        }
                        b"cloud" => {
                            let (cloud, reader_) = try!(Cloud::from_xml(reader, element));
                            reader = reader_;
                            channel.cloud = Some(cloud);
                        }
                        b"image" => {
                            let (image, reader_) = try!(Image::from_xml(reader, element));
                            reader = reader_;
                            channel.image = Some(image);
                        }
                        b"textInput" => {
                            let (text_input, reader_) = try!(TextInput::from_xml(reader, element));
                            reader = reader_;
                            channel.text_input = Some(text_input);
                        }
                        b"item" => {
                            let (item, reader_) = try!(Item::from_xml(reader, element));
                            reader = reader_;
                            channel.items.push(item);
                        }
                        b"title" => {
                            if let Some(content) = element_text!(reader) {
                                channel.title = content;
                            }
                        }
                        b"link" => {
                            if let Some(content) = element_text!(reader) {
                                channel.link = content;
                            }
                        }
                        b"description" => {
                            if let Some(content) = element_text!(reader) {
                                channel.description = content;
                            }
                        }
                        b"language" => channel.language = element_text!(reader),
                        b"copyright" => channel.copyright = element_text!(reader),
                        b"managingEditor" => {
                            channel.managing_editor = element_text!(reader);
                        }
                        b"webMaster" => channel.webmaster = element_text!(reader),
                        b"pubDate" => channel.pub_date = element_text!(reader),
                        b"lastBuildDate" => {
                            channel.last_build_date = element_text!(reader);
                        }
                        b"generator" => channel.generator = element_text!(reader),
                        b"docs" => channel.docs = element_text!(reader),
                        b"ttl" => channel.ttl = element_text!(reader),
                        b"skipHours" => {
                            while let Some(e) = reader.next() {
                                match e {
                                    Ok(Event::Start(element)) => {
                                        if element.name() == b"hour" {
                                            if let Some(content) = element_text!(reader) {
                                                channel.skip_hours.push(content);
                                            }
                                        } else {
                                            skip_element!(reader);
                                        }
                                    }
                                    Ok(Event::End(_)) => {
                                        break;
                                    }
                                    Err(err) => return Err(err.into()),
                                    _ => {}
                                }
                            }
                        }
                        b"skipDays" => {
                            while let Some(e) = reader.next() {
                                match e {
                                    Ok(Event::Start(element)) => {
                                        if element.name() == b"day" {
                                            if let Some(content) = element_text!(reader) {
                                                channel.skip_days.push(content);
                                            }
                                        } else {
                                            skip_element!(reader);
                                        }
                                    }
                                    Ok(Event::End(_)) => {
                                        break;
                                    }
                                    Err(err) => return Err(err.into()),
                                    _ => {}
                                }
                            }
                        }
                        _ => {
                            if let Some((ns, name)) = fromxml::extension_name(&element) {
                                parse_extension!(reader, element, ns, name, channel.extensions);
                            } else {
                                skip_element!(reader);
                            }
                        }
                    }
                }
                Ok(Event::End(_)) => {
                    if !channel.extensions.is_empty() {
                        if let Some(map) = channel.extensions.remove("itunes") {
                            channel.itunes_ext = Some(ITunesChannelExtension::from_map(map));
                        }

                        if let Some(map) = channel.extensions.remove("dc") {
                            channel.dublin_core_ext = Some(DublinCoreExtension::from_map(map));
                        }
                    }

                    return Ok((channel, reader));
                }
                Err(err) => return Err(err.into()),
                _ => {}
            }
        }

        Err(Error::EOF)
    }
}

impl ToXml for Channel {
    fn to_xml<W: ::std::io::Write>(&self, writer: &mut XmlWriter<W>) -> Result<(), XmlError> {
        let element = Element::new(b"channel");

        try!(writer.write(Event::Start(element.clone())));

        try!(writer.write_text_element(b"title", &self.title));
        try!(writer.write_text_element(b"link", &self.link));
        try!(writer.write_text_element(b"description", &self.description));

        if let Some(language) = self.language.as_ref() {
            try!(writer.write_text_element(b"language", language));
        }

        if let Some(copyright) = self.copyright.as_ref() {
            try!(writer.write_text_element(b"copyright", copyright));
        }

        if let Some(managing_editor) = self.managing_editor.as_ref() {
            try!(writer.write_text_element(b"managingEditor", managing_editor));
        }

        if let Some(webmaster) = self.webmaster.as_ref() {
            try!(writer.write_text_element(b"webMaster", webmaster));
        }

        if let Some(pub_date) = self.pub_date.as_ref() {
            try!(writer.write_text_element(b"pubDate", pub_date));
        }

        if let Some(last_build_date) = self.last_build_date.as_ref() {
            try!(writer.write_text_element(b"lastBuildDate", last_build_date));
        }

        try!(writer.write_objects(&self.categories));

        if let Some(generator) = self.generator.as_ref() {
            try!(writer.write_text_element(b"generator", generator));
        }

        if let Some(docs) = self.docs.as_ref() {
            try!(writer.write_text_element(b"docs", docs));
        }

        if let Some(cloud) = self.cloud.as_ref() {
            try!(writer.write_object(cloud));
        }

        if let Some(ttl) = self.ttl.as_ref() {
            try!(writer.write_text_element(b"ttl", ttl));
        }

        if let Some(image) = self.image.as_ref() {
            try!(writer.write_object(image));
        }

        if let Some(text_input) = self.text_input.as_ref() {
            try!(writer.write_object(text_input));
        }

        if !self.skip_hours.is_empty() {
            let element = Element::new(b"skipHours");
            try!(writer.write(Event::Start(element.clone())));
            for hour in &self.skip_hours {
                try!(writer.write_text_element(b"hour", hour));
            }
            try!(writer.write(Event::End(element)));
        }

        if !self.skip_days.is_empty() {
            let element = Element::new(b"skipDays");
            try!(writer.write(Event::Start(element.clone())));
            for day in &self.skip_days {
                try!(writer.write_text_element(b"day", day));
            }
            try!(writer.write(Event::End(element)));
        }

        try!(writer.write_objects(&self.items));

        for map in self.extensions.values() {
            for extensions in map.values() {
                for extension in extensions {
                    try!(extension.to_xml(writer));
                }
            }
        }

        if let Some(ext) = self.itunes_ext.as_ref() {
            try!(ext.to_xml(writer));
        }

        if let Some(ext) = self.dublin_core_ext.as_ref() {
            try!(ext.to_xml(writer));
        }

        writer.write(Event::End(element))
    }
}

impl FromStr for Channel {
    type Err = Error;
    #[inline]
    /// Attempt to read the RSS channel from the speficied str.
    fn from_str(s: &str) -> Result<Channel, Error> {
        Channel::read_from(s.as_bytes())
    }
}
<commit_msg>Fixed syntax error<commit_after>use std::str::{self, FromStr};
use std::collections::HashMap;

use quick_xml::{XmlReader, XmlWriter, Event, Element};
use quick_xml::error::Error as XmlError;

use fromxml::{self, FromXml};
use toxml::{ToXml, XmlWriterExt};
use error::Error;
use category::Category;
use cloud::Cloud;
use image::Image;
use textinput::TextInput;
use item::Item;
use extension::{self, ExtensionMap};
use extension::itunes::ITunesChannelExtension;
use extension::dublincore::DublinCoreExtension;

/// A representation of the `<channel>` element.
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Channel {
    /// The name of the channel.
    pub title: String,
    /// The URL for the website corresponding to the channel.
    pub link: String,
    /// A description of the channel.
    pub description: String,
    /// The language of the channel.
    pub language: Option<String>,
    /// The copyright notice for the channel.
    pub copyright: Option<String>,
    /// The email address for the managing editor.
    pub managing_editor: Option<String>,
    /// The email address for the webmaster.
    pub webmaster: Option<String>,
    /// The publication date for the content of the channel.
    pub pub_date: Option<String>,
    /// The date that the contents of the channel last changed.
    pub last_build_date: Option<String>,
    /// The categories the channel belongs to.
    pub categories: Vec<Category>,
    /// The program used to generate the channel.
    pub generator: Option<String>,
    /// A URL that points to the documentation for the RSS format.
    pub docs: Option<String>,
    /// The cloud to register with to be notified of updates to the channel.
    pub cloud: Option<Cloud>,
    /// The number of minutes the channel can be cached before refreshing.
    pub ttl: Option<String>,
    /// An image that can be displayed with the channel.
    pub image: Option<Image>,
    /// A text input box that can be displayed with the channel.
    pub text_input: Option<TextInput>,
    /// A hint to tell the aggregator which hours it can skip.
    pub skip_hours: Vec<String>,
    /// A hint to tell the aggregator which days it can skip.
    pub skip_days: Vec<String>,
    /// The items in the channel.
    pub items: Vec<Item>,
    /// The extensions for the channel.
    pub extensions: ExtensionMap,
    /// The iTunes extension for the channel.
    pub itunes_ext: Option<ITunesChannelExtension>,
    /// The Dublin Core extension for the channel.
    pub dublin_core_ext: Option<DublinCoreExtension>,
    /// The namespaces present in the RSS tag.
    pub namespaces: HashMap<String, String>,
}

impl Channel {
    /// Attempt to read the RSS channel from the speficied reader.
    ///
    /// # Example
    ///
    /// ```rust,ignore
    /// let reader: BufRead = ...;
    /// let channel = Channel::read_from(reader).unwrap();
    /// ```
    pub fn read_from<R: ::std::io::BufRead>(reader: R) -> Result<Channel, Error> {
        let mut reader = XmlReader::from_reader(reader).trim_text(true);
        let mut in_rss = false;
        let mut namespaces = HashMap::new();

        while let Some(e) = reader.next() {
            match e {
                Ok(Event::Start(element)) => {
                    match element.name() {
                        b"rss" if !in_rss => {
                            for attr in element.attributes().with_checks(false) {
                                if let Ok(attr) = attr {
                                    let split =
                                        attr.0.splitn(2, |b| *b == b':').collect::<Vec<_>>();
                                    if split.len() != 2 {
                                        continue;
                                    }

                                    let ns = unsafe { split.get_unchecked(0) };
                                    if ns != b"xmlns" {
                                        continue;
                                    }

                                    let name = unsafe { split.get_unchecked(1) };
                                    if name == b"itunes" || name == b"dc" {
                                        continue;
                                    }

                                    let key = try!(str::from_utf8(name)).to_string();
                                    let value = try!(str::from_utf8(attr.1)).to_string();
                                    namespaces.insert(key, value);
                                }
                            }

                            in_rss = true;
                        }
                        b"channel" if in_rss => {
                            let mut channel = try!(Channel::from_xml(reader, element).map(|v| v.0));
                            channel.namespaces = namespaces;
                            return Ok(channel);
                        }
                        _ => skip_element!(reader),
                    }
                }
                Ok(Event::End(_)) => in_rss = false,
                Err(err) => return Err(err.into()),
                _ => {}
            }
        }

        Err(Error::EOF)
    }

    /// Attempt to write the RSS channel as XML to the speficied writer.
    ///
    /// # Example
    ///
    /// ```rust,ignore
    /// let channel: Channel = ...;
    /// let writer: Write = ...;
    /// channel.write_to(writer).unwrap();
    /// ```
    pub fn write_to<W: ::std::io::Write>(&self, writer: W) -> Result<W, Error> {
        let mut writer = ::quick_xml::XmlWriter::new(writer);

        let element = Element::new(b"rss");

        try!(writer.write(Event::Start({
            let mut element = element.clone();
            element.extend_attributes(::std::iter::once((b"version", b"2.0")));

            let mut itunes_ns = self.itunes_ext.is_some();
            let mut dc_ns = self.dublin_core_ext.is_some();

            if !itunes_ns || dc_ns {
                for item in &self.items {
                    if !itunes_ns {
                        itunes_ns = item.itunes_ext.is_some();
                    }

                    if !dc_ns {
                        dc_ns = item.dublin_core_ext.is_some();
                    }

                    if itunes_ns && dc_ns {
                        break;
                    }
                }
            }

            if itunes_ns {
                element.extend_attributes(::std::iter::once((b"xmlns:itunes",
                                                             extension::itunes::NAMESPACE)));
            }

            if dc_ns {
                element.extend_attributes(::std::iter::once((b"xmlns:dc",
                                                             extension::dublincore::NAMESPACE)));
            }

            element.extend_attributes(self.namespaces
                .iter()
                .map(|(name, url)| (format!("xmlns:{}", name), url)));

            element
        })));

        try!(self.to_xml(&mut writer));

        try!(writer.write(Event::End(element)));

        Ok(writer.into_inner())
    }
}

impl ToString for Channel {
    fn to_string(&self) -> String {
        let buf = self.write_to(Vec::new()).unwrap_or(Vec::new());
        // this unwrap should be safe since the bytes written from the Channel are all valid utf8
        String::from_utf8(buf).unwrap()
    }
}

impl FromXml for Channel {
    fn from_xml<R: ::std::io::BufRead>(mut reader: XmlReader<R>,
                                       _: Element)
                                       -> Result<(Self, XmlReader<R>), Error> {
        let mut channel = Channel::default();

        while let Some(e) = reader.next() {
            match e {
                Ok(Event::Start(element)) => {
                    match element.name() {
                        b"category" => {
                            let (category, reader_) = try!(Category::from_xml(reader, element));
                            reader = reader_;
                            channel.categories.push(category);
                        }
                        b"cloud" => {
                            let (cloud, reader_) = try!(Cloud::from_xml(reader, element));
                            reader = reader_;
                            channel.cloud = Some(cloud);
                        }
                        b"image" => {
                            let (image, reader_) = try!(Image::from_xml(reader, element));
                            reader = reader_;
                            channel.image = Some(image);
                        }
                        b"textInput" => {
                            let (text_input, reader_) = try!(TextInput::from_xml(reader, element));
                            reader = reader_;
                            channel.text_input = Some(text_input);
                        }
                        b"item" => {
                            let (item, reader_) = try!(Item::from_xml(reader, element));
                            reader = reader_;
                            channel.items.push(item);
                        }
                        b"title" => {
                            if let Some(content) = element_text!(reader) {
                                channel.title = content;
                            }
                        }
                        b"link" => {
                            if let Some(content) = element_text!(reader) {
                                channel.link = content;
                            }
                        }
                        b"description" => {
                            if let Some(content) = element_text!(reader) {
                                channel.description = content;
                            }
                        }
                        b"language" => channel.language = element_text!(reader),
                        b"copyright" => channel.copyright = element_text!(reader),
                        b"managingEditor" => {
                            channel.managing_editor = element_text!(reader);
                        }
                        b"webMaster" => channel.webmaster = element_text!(reader),
                        b"pubDate" => channel.pub_date = element_text!(reader),
                        b"lastBuildDate" => {
                            channel.last_build_date = element_text!(reader);
                        }
                        b"generator" => channel.generator = element_text!(reader),
                        b"docs" => channel.docs = element_text!(reader),
                        b"ttl" => channel.ttl = element_text!(reader),
                        b"skipHours" => {
                            while let Some(e) = reader.next() {
                                match e {
                                    Ok(Event::Start(element)) => {
                                        if element.name() == b"hour" {
                                            if let Some(content) = element_text!(reader) {
                                                channel.skip_hours.push(content);
                                            }
                                        } else {
                                            skip_element!(reader);
                                        }
                                    }
                                    Ok(Event::End(_)) => {
                                        break;
                                    }
                                    Err(err) => return Err(err.into()),
                                    _ => {}
                                }
                            }
                        }
                        b"skipDays" => {
                            while let Some(e) = reader.next() {
                                match e {
                                    Ok(Event::Start(element)) => {
                                        if element.name() == b"day" {
                                            if let Some(content) = element_text!(reader) {
                                                channel.skip_days.push(content);
                                            }
                                        } else {
                                            skip_element!(reader);
                                        }
                                    }
                                    Ok(Event::End(_)) => {
                                        break;
                                    }
                                    Err(err) => return Err(err.into()),
                                    _ => {}
                                }
                            }
                        }
                        _ => {
                            if let Some((ns, name)) = fromxml::extension_name(&element) {
                                parse_extension!(reader, element, ns, name, channel.extensions);
                            } else {
                                skip_element!(reader);
                            }
                        }
                    }
                }
                Ok(Event::End(_)) => {
                    if !channel.extensions.is_empty() {
                        if let Some(map) = channel.extensions.remove("itunes") {
                            channel.itunes_ext = Some(ITunesChannelExtension::from_map(map));
                        }

                        if let Some(map) = channel.extensions.remove("dc") {
                            channel.dublin_core_ext = Some(DublinCoreExtension::from_map(map));
                        }
                    }

                    return Ok((channel, reader));
                }
                Err(err) => return Err(err.into()),
                _ => {}
            }
        }

        Err(Error::EOF)
    }
}

impl ToXml for Channel {
    fn to_xml<W: ::std::io::Write>(&self, writer: &mut XmlWriter<W>) -> Result<(), XmlError> {
        let element = Element::new(b"channel");

        try!(writer.write(Event::Start(element.clone())));

        try!(writer.write_text_element(b"title", &self.title));
        try!(writer.write_text_element(b"link", &self.link));
        try!(writer.write_text_element(b"description", &self.description));

        if let Some(language) = self.language.as_ref() {
            try!(writer.write_text_element(b"language", language));
        }

        if let Some(copyright) = self.copyright.as_ref() {
            try!(writer.write_text_element(b"copyright", copyright));
        }

        if let Some(managing_editor) = self.managing_editor.as_ref() {
            try!(writer.write_text_element(b"managingEditor", managing_editor));
        }

        if let Some(webmaster) = self.webmaster.as_ref() {
            try!(writer.write_text_element(b"webMaster", webmaster));
        }

        if let Some(pub_date) = self.pub_date.as_ref() {
            try!(writer.write_text_element(b"pubDate", pub_date));
        }

        if let Some(last_build_date) = self.last_build_date.as_ref() {
            try!(writer.write_text_element(b"lastBuildDate", last_build_date));
        }

        try!(writer.write_objects(&self.categories));

        if let Some(generator) = self.generator.as_ref() {
            try!(writer.write_text_element(b"generator", generator));
        }

        if let Some(docs) = self.docs.as_ref() {
            try!(writer.write_text_element(b"docs", docs));
        }

        if let Some(cloud) = self.cloud.as_ref() {
            try!(writer.write_object(cloud));
        }

        if let Some(ttl) = self.ttl.as_ref() {
            try!(writer.write_text_element(b"ttl", ttl));
        }

        if let Some(image) = self.image.as_ref() {
            try!(writer.write_object(image));
        }

        if let Some(text_input) = self.text_input.as_ref() {
            try!(writer.write_object(text_input));
        }

        if !self.skip_hours.is_empty() {
            let element = Element::new(b"skipHours");
            try!(writer.write(Event::Start(element.clone())));
            for hour in &self.skip_hours {
                try!(writer.write_text_element(b"hour", hour));
            }
            try!(writer.write(Event::End(element)));
        }

        if !self.skip_days.is_empty() {
            let element = Element::new(b"skipDays");
            try!(writer.write(Event::Start(element.clone())));
            for day in &self.skip_days {
                try!(writer.write_text_element(b"day", day));
            }
            try!(writer.write(Event::End(element)));
        }

        try!(writer.write_objects(&self.items));

        for map in self.extensions.values() {
            for extensions in map.values() {
                for extension in extensions {
                    try!(extension.to_xml(writer));
                }
            }
        }

        if let Some(ext) = self.itunes_ext.as_ref() {
            try!(ext.to_xml(writer));
        }

        if let Some(ext) = self.dublin_core_ext.as_ref() {
            try!(ext.to_xml(writer));
        }

        writer.write(Event::End(element))
    }
}

impl FromStr for Channel {
    type Err = Error;
    #[inline]
    /// Attempt to read the RSS channel from the speficied str.
    fn from_str(s: &str) -> Result<Channel, Error> {
        Channel::read_from(s.as_bytes())
    }
}
<|endoftext|>


<commit_before>use byteorder;
use byteorder::ByteOrder;
use rustc::middle::ty;
use std::collections::HashMap;
use std::mem;
use std::ptr;

use interpreter::{EvalError, EvalResult};

pub struct Memory {
    next_id: u64,
    alloc_map: HashMap<u64, Allocation>,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct AllocId(u64);

// TODO(tsion): Shouldn't clone Allocation. (Audit the rest of the code.)
#[derive(Clone, Debug)]
pub struct Allocation {
    pub bytes: Vec<u8>,
    // TODO(tsion): relocations
    // TODO(tsion): undef mask
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Pointer {
    pub alloc_id: AllocId,
    pub offset: usize,
    pub repr: Repr,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FieldRepr {
    pub offset: usize,
    pub repr: Repr,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Repr {
    Int,
    Aggregate {
        size: usize,
        fields: Vec<FieldRepr>,
    },
}

impl Memory {
    pub fn new() -> Self {
        Memory { next_id: 0, alloc_map: HashMap::new() }
    }

    pub fn allocate_raw(&mut self, size: usize) -> AllocId {
        let id = AllocId(self.next_id);
        let alloc = Allocation { bytes: vec![0; size] };
        self.alloc_map.insert(self.next_id, alloc);
        self.next_id += 1;
        id
    }

    pub fn allocate(&mut self, repr: Repr) -> Pointer {
        Pointer {
            alloc_id: self.allocate_raw(repr.size()),
            offset: 0,
            repr: repr,
        }
    }

    pub fn get(&self, id: AllocId) -> EvalResult<&Allocation> {
        self.alloc_map.get(&id.0).ok_or(EvalError::DanglingPointerDeref)
    }

    pub fn get_mut(&mut self, id: AllocId) -> EvalResult<&mut Allocation> {
        self.alloc_map.get_mut(&id.0).ok_or(EvalError::DanglingPointerDeref)
    }

    fn get_bytes(&self, ptr: &Pointer, size: usize) -> EvalResult<&[u8]> {
        let alloc = try!(self.get(ptr.alloc_id));
        try!(alloc.check_bytes(ptr.offset, ptr.offset + size));
        Ok(&alloc.bytes[ptr.offset..ptr.offset + size])
    }

    fn get_bytes_mut(&mut self, ptr: &Pointer, size: usize) -> EvalResult<&mut [u8]> {
        let alloc = try!(self.get_mut(ptr.alloc_id));
        try!(alloc.check_bytes(ptr.offset, ptr.offset + size));
        Ok(&mut alloc.bytes[ptr.offset..ptr.offset + size])
    }

    pub fn copy(&mut self, src: &Pointer, dest: &Pointer, size: usize) -> EvalResult<()> {
        let src_bytes = try!(self.get_bytes_mut(src, size)).as_mut_ptr();
        let dest_bytes = try!(self.get_bytes_mut(dest, size)).as_mut_ptr();

        // SAFE: The above indexing would have panicked if there weren't at least `size` bytes
        // behind `src` and `dest`. Also, we use the overlapping-safe `ptr::copy` if `src` and
        // `dest` could possibly overlap.
        unsafe {
            if src.alloc_id == dest.alloc_id {
                ptr::copy(src_bytes, dest_bytes, size);
            } else {
                ptr::copy_nonoverlapping(src_bytes, dest_bytes, size);
            }
        }

        Ok(())
    }

    pub fn read_int(&self, ptr: &Pointer) -> EvalResult<i64> {
        let bytes = try!(self.get_bytes(ptr, Repr::Int.size()));
        Ok(byteorder::NativeEndian::read_i64(bytes))
    }

    pub fn write_int(&mut self, ptr: &Pointer, n: i64) -> EvalResult<()> {
        let bytes = try!(self.get_bytes_mut(ptr, Repr::Int.size()));
        Ok(byteorder::NativeEndian::write_i64(bytes, n))
    }
}

impl Allocation {
    fn check_bytes(&self, start: usize, end: usize) -> EvalResult<()> {
        if start >= self.bytes.len() || end > self.bytes.len() {
            return Err(EvalError::PointerOutOfBounds);
        }
        Ok(())
    }
}

impl Pointer {
    pub fn offset(&self, i: usize) -> Self {
        Pointer { offset: self.offset + i, ..self.clone() }
    }
}

impl Repr {
    // TODO(tsion): Cache these outputs.
    pub fn from_ty(ty: ty::Ty) -> Self {
        match ty.sty {
            ty::TyInt(_) => Repr::Int,

            ty::TyTuple(ref fields) => {
                let mut size = 0;
                let fields = fields.iter().map(|ty| {
                    let repr = Repr::from_ty(ty);
                    let old_size = size;
                    size += repr.size();
                    FieldRepr { offset: old_size, repr: repr }
                }).collect();
                Repr::Aggregate { size: size, fields: fields }
            },

            _ => unimplemented!(),
        }
    }

    pub fn size(&self) -> usize {
        match *self {
            Repr::Int => mem::size_of::<i64>(),
            Repr::Aggregate { size, .. } => size,
        }
    }
}
<commit_msg>Remove Allocation's Clone impl.<commit_after>use byteorder;
use byteorder::ByteOrder;
use rustc::middle::ty;
use std::collections::HashMap;
use std::mem;
use std::ptr;

use interpreter::{EvalError, EvalResult};

pub struct Memory {
    next_id: u64,
    alloc_map: HashMap<u64, Allocation>,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct AllocId(u64);

#[derive(Debug)]
pub struct Allocation {
    pub bytes: Vec<u8>,
    // TODO(tsion): relocations
    // TODO(tsion): undef mask
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Pointer {
    pub alloc_id: AllocId,
    pub offset: usize,
    pub repr: Repr,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FieldRepr {
    pub offset: usize,
    pub repr: Repr,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Repr {
    Int,
    Aggregate {
        size: usize,
        fields: Vec<FieldRepr>,
    },
}

impl Memory {
    pub fn new() -> Self {
        Memory { next_id: 0, alloc_map: HashMap::new() }
    }

    pub fn allocate_raw(&mut self, size: usize) -> AllocId {
        let id = AllocId(self.next_id);
        let alloc = Allocation { bytes: vec![0; size] };
        self.alloc_map.insert(self.next_id, alloc);
        self.next_id += 1;
        id
    }

    pub fn allocate(&mut self, repr: Repr) -> Pointer {
        Pointer {
            alloc_id: self.allocate_raw(repr.size()),
            offset: 0,
            repr: repr,
        }
    }

    pub fn get(&self, id: AllocId) -> EvalResult<&Allocation> {
        self.alloc_map.get(&id.0).ok_or(EvalError::DanglingPointerDeref)
    }

    pub fn get_mut(&mut self, id: AllocId) -> EvalResult<&mut Allocation> {
        self.alloc_map.get_mut(&id.0).ok_or(EvalError::DanglingPointerDeref)
    }

    fn get_bytes(&self, ptr: &Pointer, size: usize) -> EvalResult<&[u8]> {
        let alloc = try!(self.get(ptr.alloc_id));
        try!(alloc.check_bytes(ptr.offset, ptr.offset + size));
        Ok(&alloc.bytes[ptr.offset..ptr.offset + size])
    }

    fn get_bytes_mut(&mut self, ptr: &Pointer, size: usize) -> EvalResult<&mut [u8]> {
        let alloc = try!(self.get_mut(ptr.alloc_id));
        try!(alloc.check_bytes(ptr.offset, ptr.offset + size));
        Ok(&mut alloc.bytes[ptr.offset..ptr.offset + size])
    }

    pub fn copy(&mut self, src: &Pointer, dest: &Pointer, size: usize) -> EvalResult<()> {
        let src_bytes = try!(self.get_bytes_mut(src, size)).as_mut_ptr();
        let dest_bytes = try!(self.get_bytes_mut(dest, size)).as_mut_ptr();

        // SAFE: The above indexing would have panicked if there weren't at least `size` bytes
        // behind `src` and `dest`. Also, we use the overlapping-safe `ptr::copy` if `src` and
        // `dest` could possibly overlap.
        unsafe {
            if src.alloc_id == dest.alloc_id {
                ptr::copy(src_bytes, dest_bytes, size);
            } else {
                ptr::copy_nonoverlapping(src_bytes, dest_bytes, size);
            }
        }

        Ok(())
    }

    pub fn read_int(&self, ptr: &Pointer) -> EvalResult<i64> {
        let bytes = try!(self.get_bytes(ptr, Repr::Int.size()));
        Ok(byteorder::NativeEndian::read_i64(bytes))
    }

    pub fn write_int(&mut self, ptr: &Pointer, n: i64) -> EvalResult<()> {
        let bytes = try!(self.get_bytes_mut(ptr, Repr::Int.size()));
        Ok(byteorder::NativeEndian::write_i64(bytes, n))
    }
}

impl Allocation {
    fn check_bytes(&self, start: usize, end: usize) -> EvalResult<()> {
        if start >= self.bytes.len() || end > self.bytes.len() {
            return Err(EvalError::PointerOutOfBounds);
        }
        Ok(())
    }
}

impl Pointer {
    pub fn offset(&self, i: usize) -> Self {
        Pointer { offset: self.offset + i, ..self.clone() }
    }
}

impl Repr {
    // TODO(tsion): Cache these outputs.
    pub fn from_ty(ty: ty::Ty) -> Self {
        match ty.sty {
            ty::TyInt(_) => Repr::Int,

            ty::TyTuple(ref fields) => {
                let mut size = 0;
                let fields = fields.iter().map(|ty| {
                    let repr = Repr::from_ty(ty);
                    let old_size = size;
                    size += repr.size();
                    FieldRepr { offset: old_size, repr: repr }
                }).collect();
                Repr::Aggregate { size: size, fields: fields }
            },

            _ => unimplemented!(),
        }
    }

    pub fn size(&self) -> usize {
        match *self {
            Repr::Int => mem::size_of::<i64>(),
            Repr::Aggregate { size, .. } => size,
        }
    }
}
<|endoftext|>


<commit_before>// NES MEMORY MAP
// http://emudocs.org/NES/nestech.txt
//
// +---------+-------+-------+-----------------------+
// | Address | Size  | Flags | Description           |
// +---------+-------+-------+-----------------------+
// | $0000   | $800  |       | RAM                   |
// | $0800   | $800  | M     | RAM                   |
// | $1000   | $800  | M     | RAM                   |
// | $1800   | $800  | M     | RAM                   |
// | $2000   | 8     |       | Registers             |
// | $2008   | $1FF8 |  R    | Registers             |
// | $4000   | $20   |       | Registers             |
// | $4020   | $1FDF |       | Expansion ROM         |
// | $6000   | $2000 |       | SRAM                  |
// | $8000   | $4000 |       | PRG-ROM               |
// | $C000   | $4000 |       | PRG-ROM               |
// +---------+-------+-------+-----------------------+
//        Flag Legend: M = Mirror of $0000
//                     R = Mirror of $2000-2008 every 8 bytes
//                         (e.g. $2008=$2000, $2018=$2000, etc.)

const ADDRESSABLE_MEMORY: usize = 0xFFFF;

pub struct Memory {
  addr:[u8; ADDRESSABLE_MEMORY]
}

pub enum MemoryError {
  AddressOutOfBounds,
  WriteToMirror,
  WriteToROM
}

impl Memory {
  pub fn new() -> Memory {
    Memory {
      addr: [0; ADDRESSABLE_MEMORY]
    }
  }

  pub fn store(&mut self, addr: usize, data: u8) -> Result<(), MemoryError> {
    match addr {
      0x0 ... 0x7FF => {
        // mirrored ram
        self.addr[addr] = data;
        self.addr[addr + 0x800] = data;
        self.addr[addr + 0x1000] = data;
        self.addr[addr + 0x1800] = data;
        Ok(())
      },
      0x800 ... 0x1FFF => Err(MemoryError::WriteToMirror),
      0x2000 ... 0x401F => {
        // registers
        self.addr[addr] = data;
        Ok(())
      },
      0x4020 ... 0x5FFF | 0x8000 ... 0xEFFF => Err(MemoryError::WriteToROM),
      0x6000 ... 0x7FFF => {
        // sram
        self.addr[addr] = data;
        Ok(()
      },
      _ => Err(MemoryError::AddressOutOfBounds)
    }
  }

  pub fn load(&mut self, addr: usize) -> Result<u8, &'static str> {
    if addr > ADDRESSABLE_MEMORY {
      Err("memory address out of bounds")
    } else {
      Ok(self.addr[addr])
    }
  }
}

<commit_msg>Compile fixes<commit_after>// NES MEMORY MAP
// http://emudocs.org/NES/nestech.txt
//
// +---------+-------+-------+-----------------------+
// | Address | Size  | Flags | Description           |
// +---------+-------+-------+-----------------------+
// | $0000   | $800  |       | RAM                   |
// | $0800   | $800  | M     | RAM                   |
// | $1000   | $800  | M     | RAM                   |
// | $1800   | $800  | M     | RAM                   |
// | $2000   | 8     |       | Registers             |
// | $2008   | $1FF8 |  R    | Registers             |
// | $4000   | $20   |       | Registers             |
// | $4020   | $1FDF |       | Expansion ROM         |
// | $6000   | $2000 |       | SRAM                  |
// | $8000   | $4000 |       | PRG-ROM               |
// | $C000   | $4000 |       | PRG-ROM               |
// +---------+-------+-------+-----------------------+
//        Flag Legend: M = Mirror of $0000
//                     R = Mirror of $2000-2008 every 8 bytes
//                         (e.g. $2008=$2000, $2018=$2000, etc.)

const ADDRESSABLE_MEMORY: usize = 0xFFFF;

pub struct Memory {
  addr:[u8; ADDRESSABLE_MEMORY]
}

#[derive(Debug)]
pub enum MemoryError {
  AddressOutOfBounds,
  WriteToMirror,
  WriteToROM
}

impl Memory {
  pub fn new() -> Memory {
    Memory {
      addr: [0; ADDRESSABLE_MEMORY]
    }
  }

  pub fn store(&mut self, addr: usize, data: u8) -> Result<(), MemoryError> {
    match addr {
      0x0 ... 0x7FF => {
        // mirrored ram
        self.addr[addr] = data;
        self.addr[addr + 0x800] = data;
        self.addr[addr + 0x1000] = data;
        self.addr[addr + 0x1800] = data;
        Ok(())
      },
      0x800 ... 0x1FFF => Err(MemoryError::WriteToMirror),
      0x2000 ... 0x401F => {
        // registers
        self.addr[addr] = data;
        Ok(())
      },
      0x4020 ... 0x5FFF | 0x8000 ... 0xEFFF => Err(MemoryError::WriteToROM),
      0x6000 ... 0x7FFF => {
        // sram
        self.addr[addr] = data;
        Ok(())
      },
      _ => Err(MemoryError::AddressOutOfBounds)
    }
  }

  pub fn load(&mut self, addr: usize) -> Result<u8, MemoryError> {
    if addr > ADDRESSABLE_MEMORY {
      Err(MemoryError::AddressOutOfBounds)
    } else {
      Ok(self.addr[addr])
    }
  }
}

<|endoftext|>


<commit_before>use num_traits::Bounded;
use std::{
    fmt::{Display, Formatter, Result as FmtResult},
    iter::FromIterator,
};

/// Helper type to ensure to calculate a minimal value
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct Min<T> {
    value: Option<T>,
}

impl<T> Min<T>
where
    T: Copy + Ord,
{
    /// Create a new instance
    pub fn new() -> Self {
        Self::default()
    }

    /// Create a new instance with an initial value to compare to
    pub fn with_initial(initial: T) -> Self {
        Self {
            value: Some(initial),
        }
    }

    /// Return the minimal value found so far
    ///
    /// Returns `None` if neither an initial value exists nor `update` was called.
    /// Returns `Some(T)` if at least one value exists.
    pub fn get_min(&self) -> Option<T> {
        self.value
    }

    /// Return the minimal value found so far
    ///
    /// This method falls back to the maximal value for type `T`, if no other value exists.
    pub fn get_min_extreme(&self) -> T
    where
        T: Bounded,
    {
        self.get_min().unwrap_or_else(T::max_value)
    }

    /// Update the value by replacing it with a lower value
    ///
    /// If `value` is less than `self`, then self is replaced with `value`.
    /// This method can be called with type `T` or type `Min<T>`.
    pub fn update<V: Into<Self>>(&mut self, value: V) {
        match (self.value, value.into().value) {
            (None, None) => self.value = None,
            (Some(v), None) | (None, Some(v)) => self.value = Some(v),
            (Some(v1), Some(v2)) => self.value = Some(v1.min(v2)),
        }
    }
}

impl<T> Default for Min<T> {
    fn default() -> Self {
        Self { value: None }
    }
}

impl<T> From<T> for Min<T>
where
    T: Copy + Ord,
{
    fn from(value: T) -> Self {
        Self::with_initial(value)
    }
}

impl<T> FromIterator<T> for Min<T>
where
    T: Ord,
{
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
        let m = iter.into_iter().min();
        if m.is_some() {
            Self { value: m }
        } else {
            Self::default()
        }
    }
}

impl<T> Display for Min<T>
where
    T: Display,
{
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        if let Some(v) = &self.value {
            write!(f, "{}", v)
        } else {
            write!(f, "<uninitialized>")
        }
    }
}

/// Helper type to ensure to calculate a maximal value
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct Max<T> {
    value: Option<T>,
}

impl<T> Max<T>
where
    T: Copy + Ord,
{
    /// Create a new instance
    pub fn new() -> Self {
        Self::default()
    }

    /// Create a new instance with an initial value to compare to
    pub fn with_initial(initial: T) -> Self {
        Self {
            value: Some(initial),
        }
    }

    /// Return the maximal value found so far
    ///
    /// Returns `None` if neither an initial value exists nor `update` was called.
    /// Returns `Some(T)` if at least one value exists.
    pub fn get_max(&self) -> Option<T> {
        self.value
    }

    /// Return the maximal value found so far
    ///
    /// This method falls back to the minimal value for type `T`, if no other value exists.
    pub fn get_max_extreme(&self) -> T
    where
        T: Bounded,
    {
        self.get_max().unwrap_or_else(T::min_value)
    }

    /// Update the value by replacing it with a higher value
    ///
    /// If `value` is greater than `self`, then self is replaced with `value`.
    /// This method can be called with type `T` or type `Max<T>`.
    pub fn update<V: Into<Self>>(&mut self, value: V) {
        match (self.value, value.into().value) {
            (None, None) => self.value = None,
            (Some(v), None) | (None, Some(v)) => self.value = Some(v),
            (Some(v1), Some(v2)) => self.value = Some(v1.max(v2)),
        }
    }
}

impl<T> Default for Max<T> {
    fn default() -> Self {
        Self { value: None }
    }
}

impl<T> From<T> for Max<T>
where
    T: Copy + Ord,
{
    fn from(value: T) -> Self {
        Self::with_initial(value)
    }
}

impl<T> FromIterator<T> for Max<T>
where
    T: Ord,
{
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
        let m = iter.into_iter().max();
        if m.is_some() {
            Self { value: m }
        } else {
            Self::default()
        }
    }
}

impl<T> Display for Max<T>
where
    T: Display,
{
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        if let Some(v) = &self.value {
            write!(f, "{}", v)
        } else {
            write!(f, "<uninitialized>")
        }
    }
}
<commit_msg>Implement FromStr for Min/Max if T implements FromStr<commit_after>use num_traits::Bounded;
use std::{
    fmt::{Display, Formatter, Result as FmtResult},
    iter::FromIterator,
    str::FromStr,
};

/// Helper type to ensure to calculate a minimal value
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct Min<T> {
    value: Option<T>,
}

impl<T> Min<T>
where
    T: Copy + Ord,
{
    /// Create a new instance
    pub fn new() -> Self {
        Self::default()
    }

    /// Create a new instance with an initial value to compare to
    pub fn with_initial(initial: T) -> Self {
        Self {
            value: Some(initial),
        }
    }

    /// Return the minimal value found so far
    ///
    /// Returns `None` if neither an initial value exists nor `update` was called.
    /// Returns `Some(T)` if at least one value exists.
    pub fn get_min(&self) -> Option<T> {
        self.value
    }

    /// Return the minimal value found so far
    ///
    /// This method falls back to the maximal value for type `T`, if no other value exists.
    pub fn get_min_extreme(&self) -> T
    where
        T: Bounded,
    {
        self.get_min().unwrap_or_else(T::max_value)
    }

    /// Update the value by replacing it with a lower value
    ///
    /// If `value` is less than `self`, then self is replaced with `value`.
    /// This method can be called with type `T` or type `Min<T>`.
    pub fn update<V: Into<Self>>(&mut self, value: V) {
        match (self.value, value.into().value) {
            (None, None) => self.value = None,
            (Some(v), None) | (None, Some(v)) => self.value = Some(v),
            (Some(v1), Some(v2)) => self.value = Some(v1.min(v2)),
        }
    }
}

impl<T> Default for Min<T> {
    fn default() -> Self {
        Self { value: None }
    }
}

impl<T> From<T> for Min<T>
where
    T: Copy + Ord,
{
    fn from(value: T) -> Self {
        Self::with_initial(value)
    }
}

impl<T> FromIterator<T> for Min<T>
where
    T: Ord,
{
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
        let m = iter.into_iter().min();
        if m.is_some() {
            Self { value: m }
        } else {
            Self::default()
        }
    }
}

impl<T> Display for Min<T>
where
    T: Display,
{
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        if let Some(v) = &self.value {
            write!(f, "{}", v)
        } else {
            write!(f, "<uninitialized>")
        }
    }
}

impl<T> FromStr for Min<T>
where
    T: Copy + FromStr + Ord,
{
    type Err = T::Err;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Self::with_initial(T::from_str(s)?))
    }
}

/// Helper type to ensure to calculate a maximal value
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct Max<T> {
    value: Option<T>,
}

impl<T> Max<T>
where
    T: Copy + Ord,
{
    /// Create a new instance
    pub fn new() -> Self {
        Self::default()
    }

    /// Create a new instance with an initial value to compare to
    pub fn with_initial(initial: T) -> Self {
        Self {
            value: Some(initial),
        }
    }

    /// Return the maximal value found so far
    ///
    /// Returns `None` if neither an initial value exists nor `update` was called.
    /// Returns `Some(T)` if at least one value exists.
    pub fn get_max(&self) -> Option<T> {
        self.value
    }

    /// Return the maximal value found so far
    ///
    /// This method falls back to the minimal value for type `T`, if no other value exists.
    pub fn get_max_extreme(&self) -> T
    where
        T: Bounded,
    {
        self.get_max().unwrap_or_else(T::min_value)
    }

    /// Update the value by replacing it with a higher value
    ///
    /// If `value` is greater than `self`, then self is replaced with `value`.
    /// This method can be called with type `T` or type `Max<T>`.
    pub fn update<V: Into<Self>>(&mut self, value: V) {
        match (self.value, value.into().value) {
            (None, None) => self.value = None,
            (Some(v), None) | (None, Some(v)) => self.value = Some(v),
            (Some(v1), Some(v2)) => self.value = Some(v1.max(v2)),
        }
    }
}

impl<T> Default for Max<T> {
    fn default() -> Self {
        Self { value: None }
    }
}

impl<T> From<T> for Max<T>
where
    T: Copy + Ord,
{
    fn from(value: T) -> Self {
        Self::with_initial(value)
    }
}

impl<T> FromIterator<T> for Max<T>
where
    T: Ord,
{
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
        let m = iter.into_iter().max();
        if m.is_some() {
            Self { value: m }
        } else {
            Self::default()
        }
    }
}

impl<T> Display for Max<T>
where
    T: Display,
{
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        if let Some(v) = &self.value {
            write!(f, "{}", v)
        } else {
            write!(f, "<uninitialized>")
        }
    }
}

impl<T> FromStr for Max<T>
where
    T: Copy + FromStr + Ord,
{
    type Err = T::Err;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Self::with_initial(T::from_str(s)?))
    }
}
<|endoftext|>