<commit_before>// Copyright (c) 2020 rust-mysql-simple contributors
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use socket2::{Domain, Socket, Type};

use std::{
    io,
    net::{SocketAddr, TcpStream, ToSocketAddrs},
    time::Duration,
};

pub struct MyTcpBuilder<T> {
    address: T,
    bind_address: Option<SocketAddr>,
    connect_timeout: Option<Duration>,
    read_timeout: Option<Duration>,
    write_timeout: Option<Duration>,
    keepalive_time_ms: Option<u32>,
    nodelay: bool,
}

impl<T: ToSocketAddrs> MyTcpBuilder<T> {
    pub fn keepalive_time_ms(&mut self, keepalive_time_ms: Option<u32>) -> &mut Self {
        self.keepalive_time_ms = keepalive_time_ms;
        self
    }

    pub fn nodelay(&mut self, nodelay: bool) -> &mut Self {
        self.nodelay = nodelay;
        self
    }

    pub fn write_timeout(&mut self, write_timeout: Option<Duration>) -> &mut Self {
        self.write_timeout = write_timeout;
        self
    }

    pub fn read_timeout(&mut self, read_timeout: Option<Duration>) -> &mut Self {
        self.read_timeout = read_timeout;
        self
    }

    pub fn bind_address<U>(&mut self, bind_address: Option<U>) -> &mut Self
    where
        U: Into<SocketAddr>,
    {
        self.bind_address = bind_address.map(Into::into);
        self
    }

    pub fn connect_timeout(&mut self, timeout: Option<Duration>) -> &mut Self {
        self.connect_timeout = timeout;
        self
    }

    pub fn new(address: T) -> MyTcpBuilder<T> {
        MyTcpBuilder {
            address,
            bind_address: None,
            connect_timeout: None,
            read_timeout: None,
            write_timeout: None,
            keepalive_time_ms: None,
            nodelay: true,
        }
    }

    pub fn connect(self) -> io::Result<TcpStream> {
        let MyTcpBuilder {
            address,
            bind_address,
            connect_timeout,
            read_timeout,
            write_timeout,
            keepalive_time_ms,
            nodelay,
        } = self;
        let err_msg = if bind_address.is_none() {
            "could not connect to any address"
        } else {
            "could not connect to any address with specified bind address"
        };
        let err = io::Error::new(io::ErrorKind::Other, err_msg);
        address
            .to_socket_addrs()?
            .fold(Err(err), |prev, sock_addr| {
                prev.or_else(|_| {
                    let domain = Domain::for_address(sock_addr);
                    let socket = Socket::new(domain, Type::STREAM, None)?;
                    if let Some(bind_address) = bind_address {
                        if bind_address.is_ipv4() == sock_addr.is_ipv4() {
                            socket.bind(&bind_address.into())?;
                        }
                    }
                    if let Some(connect_timeout) = connect_timeout {
                        socket.connect_timeout(&sock_addr.into(), connect_timeout)?;
                    } else {
                        socket.connect(&sock_addr.into())?;
                    }
                    Ok(socket)
                })
            })
            .and_then(|socket| {
                socket.set_read_timeout(read_timeout)?;
                socket.set_write_timeout(write_timeout)?;
                if let Some(duration) = keepalive_time_ms {
                    let conf = socket2::TcpKeepalive::new()
                        .with_time(Duration::from_millis(duration as u64));
                    socket.set_tcp_keepalive(&conf)?;
                }
                socket.set_nodelay(nodelay)?;
                Ok(TcpStream::from(socket))
            })
    }
}
<commit_msg>Update MyTcpBuilder::connect to properly bind to address<commit_after>// Copyright (c) 2020 rust-mysql-simple contributors
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use socket2::{Domain, SockAddr, Socket, Type};

use std::{
    io,
    net::{SocketAddr, TcpStream, ToSocketAddrs},
    time::Duration,
};

pub struct MyTcpBuilder<T> {
    address: T,
    bind_address: Option<SocketAddr>,
    connect_timeout: Option<Duration>,
    read_timeout: Option<Duration>,
    write_timeout: Option<Duration>,
    keepalive_time_ms: Option<u32>,
    nodelay: bool,
}

impl<T: ToSocketAddrs> MyTcpBuilder<T> {
    pub fn keepalive_time_ms(&mut self, keepalive_time_ms: Option<u32>) -> &mut Self {
        self.keepalive_time_ms = keepalive_time_ms;
        self
    }

    pub fn nodelay(&mut self, nodelay: bool) -> &mut Self {
        self.nodelay = nodelay;
        self
    }

    pub fn write_timeout(&mut self, write_timeout: Option<Duration>) -> &mut Self {
        self.write_timeout = write_timeout;
        self
    }

    pub fn read_timeout(&mut self, read_timeout: Option<Duration>) -> &mut Self {
        self.read_timeout = read_timeout;
        self
    }

    pub fn bind_address<U>(&mut self, bind_address: Option<U>) -> &mut Self
    where
        U: Into<SocketAddr>,
    {
        self.bind_address = bind_address.map(Into::into);
        self
    }

    pub fn connect_timeout(&mut self, timeout: Option<Duration>) -> &mut Self {
        self.connect_timeout = timeout;
        self
    }

    pub fn new(address: T) -> MyTcpBuilder<T> {
        MyTcpBuilder {
            address,
            bind_address: None,
            connect_timeout: None,
            read_timeout: None,
            write_timeout: None,
            keepalive_time_ms: None,
            nodelay: true,
        }
    }

    pub fn connect(self) -> io::Result<TcpStream> {
        let MyTcpBuilder {
            address,
            bind_address,
            connect_timeout,
            read_timeout,
            write_timeout,
            keepalive_time_ms,
            nodelay,
        } = self;
        let err_msg = if bind_address.is_none() {
            "could not connect to any address"
        } else {
            "could not connect to any address with specified bind address"
        };
        let err = io::Error::new(io::ErrorKind::Other, err_msg);

        let addrs = address.to_socket_addrs()?.collect::<Vec<_>>();

        let socket = if let Some(bind_address) = bind_address {
            let fold_fun = |prev, sock_addr: &SocketAddr| match prev {
                Ok(socket) => Ok(socket),
                Err(_) => {
                    let domain = Domain::for_address(*sock_addr);
                    let socket = Socket::new(domain, Type::STREAM, None)?;
                    socket.bind(&bind_address.into())?;
                    if let Some(connect_timeout) = connect_timeout {
                        socket.connect_timeout(&SockAddr::from(*sock_addr), connect_timeout)?;
                    } else {
                        socket.connect(&SockAddr::from(*sock_addr))?;
                    }
                    Ok(socket)
                }
            };

            if bind_address.is_ipv4() {
                // client wants to bind to ipv4, so let's look for ipv4 addresses first
                addrs
                    .iter()
                    .filter(|x| x.is_ipv4())
                    .fold(Err(err), fold_fun)
                    .or_else(|e| addrs.iter().filter(|x| x.is_ipv6()).fold(Err(e), fold_fun))
            } else {
                // client wants to bind to ipv6, so let's look for ipv6 addresses first
                addrs
                    .iter()
                    .filter(|x| x.is_ipv6())
                    .fold(Err(err), fold_fun)
                    .or_else(|e| addrs.iter().filter(|x| x.is_ipv4()).fold(Err(e), fold_fun))
            }
        } else {
            // no bind address
            addrs
                .into_iter()
                .fold(Err(err), |prev, sock_addr| match prev {
                    Ok(socket) => Ok(socket),
                    Err(_) => {
                        let domain = Domain::for_address(sock_addr);
                        let socket = Socket::new(domain, Type::STREAM, None)?;
                        if let Some(connect_timeout) = connect_timeout {
                            socket.connect_timeout(&sock_addr.into(), connect_timeout)?;
                        } else {
                            socket.connect(&sock_addr.into())?;
                        }
                        Ok(socket)
                    }
                })
        }?;

        socket.set_read_timeout(read_timeout)?;
        socket.set_write_timeout(write_timeout)?;
        if let Some(duration) = keepalive_time_ms {
            let conf =
                socket2::TcpKeepalive::new().with_time(Duration::from_millis(duration as u64));
            socket.set_tcp_keepalive(&conf)?;
        }
        socket.set_nodelay(nodelay)?;
        Ok(TcpStream::from(socket))
    }
}
<|endoftext|>


<commit_before>// extern crate libc;
use libc::{poll, pollfd, nfds_t, POLLIN, POLLOUT, POLLERR, POLLHUP, POLLNVAL, POLLPRI};

use std::io::Stdin;
use std::os::unix::io::{RawFd, AsRawFd};

use std::fmt;

#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub struct Token(pub i32);

pub struct EventLoop {
    pollfds: Vec<pollfd>,
    timeout: i32,
    active: bool,
}

pub trait EventHandler {
    fn ready_for_io(&mut self, event_loop: &mut EventLoop, stream_id: Token, eventset: EventSet);
    fn error(&mut self, event_loop: &mut EventLoop, stream_id: Token) {}
    fn hangup(&mut self, event_loop: &mut EventLoop, stream_id: Token) {}
    fn not_valid(&mut self, event_loop: &mut EventLoop, stream_id: Token) {
        let Token(fd) = stream_id;
        event_loop.remove_fd(fd);
    }
    fn timeout(&mut self, event_loop: &mut EventLoop) {}
}

pub const TIMEOUT_INFINITE: i32 = -1;

#[derive(Copy, Clone)]
pub struct EventSet {
    events: i16,
}

impl EventSet {
    pub fn empty() -> EventSet {
        EventSet { events: 0 }
    }

    pub fn is_readable(&self) -> bool {
        (self.events & POLLIN) == POLLIN || (self.events & POLLPRI) == POLLPRI
    }

    #[allow(unused)]
    pub fn is_high_prio_readable(&self) -> bool {
        (self.events & POLLPRI) == POLLPRI
    }

    pub fn is_writable(&self) -> bool {
        (self.events & POLLOUT) == POLLOUT
    }

    pub fn is_not_valid(&self) -> bool {
        (self.events & POLLNVAL) == POLLNVAL
    }

    pub fn is_error(&self) -> bool {
        (self.events & POLLERR) == POLLERR
    }

    pub fn is_hangup(&self) -> bool {
        (self.events & POLLHUP) == POLLHUP
    }

    pub fn is_empty(&self) -> bool {
        self.events == 0
    }
}

impl fmt::Display for EventSet {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        let mut events_str = String::new();

        if (self.events & POLLIN) == POLLIN {
            events_str.push_str("POLLIN|");
        }
        if (self.events & POLLOUT) == POLLOUT {
            events_str.push_str("POLLOUT|");
        }
        if (self.events & POLLERR) == POLLERR {
            events_str.push_str("POLLERR|");
        }
        if (self.events & POLLHUP) == POLLHUP {
            events_str.push_str("POLLHUP|");
        }
        if (self.events & POLLNVAL) == POLLNVAL {
            events_str.push_str("POLLNVAL|");
        }
        if (self.events & POLLPRI) == POLLPRI {
            events_str.push_str("POLLPRI|");
        }
        if !events_str.is_empty() {
            let last_char_idx = events_str.len() - 1;
            events_str.remove(last_char_idx);
        }
        write!(formatter, "{}", events_str)
    }
}

pub struct EventSetBuilder {
    eventset: EventSet,
}

impl EventSetBuilder {
    pub fn new() -> EventSetBuilder {
        EventSetBuilder { eventset: EventSet::empty() }
    }

    pub fn finalize(self) -> EventSet {
        self.eventset
    }
    pub fn readable(mut self) -> EventSetBuilder {
        self.eventset.events |= POLLIN | POLLPRI;
        self
    }

    #[allow(unused)]
    pub fn writable(mut self) -> EventSetBuilder {
        self.eventset.events |= POLLOUT;
        self
    }

    #[allow(unused)]
    pub fn all(mut self) -> EventSetBuilder {
        self.eventset.events = POLLIN | POLLPRI | POLLOUT;
        self
    }
}

impl EventLoop {
    pub fn new(timeout: Option<u32>) -> EventLoop {
        let mut my_timeout = TIMEOUT_INFINITE;
        if let Some(timeout) = timeout {
            my_timeout = timeout as i32;
        }
        EventLoop {
            pollfds: Vec::<pollfd>::new(),
            active: false,
            timeout: my_timeout,
        }
    }

    fn activate(&mut self) {
        self.active = true;
    }

    pub fn is_active(&self) -> bool {
        self.active
    }

    pub fn shutdown(&mut self) {
        self.active = false;

        trace!("Event loop deactivated");
    }

    pub fn remove_fd(&mut self, fd: RawFd) {
        let found = self.pollfds
            .iter()
            .enumerate()
            .find(|&(_, pollfd)| pollfd.fd == fd)
            .and_then(|(i, _)| Some(i));
        if let Some(index) = found {
            self.pollfds.remove(index);
        }
    }

    pub fn run(&mut self, event_handler: &mut EventHandler) -> Result<(), String> {
        let pollfds_ptr = self.pollfds.as_mut_ptr();
        self.activate();
        let mut result = Ok(());
        while self.is_active() {
            let mut remove_pollfds = Vec::<RawFd>::new();
            let poll_result =
                unsafe { poll(pollfds_ptr, self.pollfds.len() as nfds_t, self.timeout) };
            let mut shutdown_loop = false;
            match poll_result {
                -1 => {
                    shutdown_loop = true;
                }
                0 => {
                    event_handler.timeout(self);
                }
                _ => {
                    trace!("poll_result={} descriptors ready for io", poll_result);

                    let mut bla = Vec::<(RawFd, EventSet)>::new();
                    for pollfd in &mut self.pollfds {
                        let received_events = EventSet { events: pollfd.revents };
                        if !received_events.is_empty() {
                            bla.push((pollfd.fd, received_events));
                        }
                    }
                    for (nr, &(fd, eventset)) in bla.iter().enumerate() {
                        trace!("{}: event {} on fd {}", nr, eventset, fd);

                        if eventset.is_readable() || eventset.is_writable() {
                            event_handler.ready_for_io(self, Token(fd), eventset);
                        }
                        if eventset.is_hangup() {
                            event_handler.hangup(self, Token(fd));
                        }
                        if eventset.is_error() {
                            event_handler.error(self, Token(fd));
                        }
                        if eventset.is_not_valid() {
                            event_handler.not_valid(self, Token(fd));
                            remove_pollfds.push(fd);
                        }
                    }
                }
            }

            for fd in remove_pollfds {
                self.remove_fd(fd);
            }

            if shutdown_loop {
                trace!("Event loop is shut down");

                self.shutdown();
            }
        }
        result
    }

    fn register_fd(&mut self, fd: i32, eventset: EventSet) {
        let pollfd = pollfd {
            fd: fd,
            events: eventset.events,
            revents: 0,
        };
        self.pollfds.push(pollfd);
    }

    fn unregister_fd(&mut self, fd: i32) {
        let found = self.pollfds
            .iter()
            .enumerate()
            .find(|&(_, pollfd)| pollfd.fd == fd)
            .and_then(|(i, _)| Some(i));
        if let Some(index) = found {
            self.pollfds.remove(index);
        }
    }

    pub fn register_stdin(&mut self, stdin_stream: &Stdin) -> Token {
        let eventset = EventSetBuilder::new().readable().finalize();
        self.register_fd(0, eventset);
        Token(0)
    }

    pub fn unregister_stdin(&mut self) {
        self.unregister_fd(0);
    }

    pub fn register_read<T>(&mut self, io: &T) -> Token
    where
        T: AsRawFd,
    {
        let fd = io.as_raw_fd();
        self.register_fd(fd, EventSetBuilder::new().readable().finalize());
        Token(fd)
    }

    #[allow(unused)]
    pub fn register_write<T>(&mut self, io: &mut T) -> Token
    where
        T: AsRawFd,
    {
        let fd = io.as_raw_fd();
        self.register_fd(fd, EventSetBuilder::new().writable().finalize());
        Token(fd)
    }

    // pub fn register_read_write<T>(&mut self, io: &'a mut T)
    // where T: AsRawFd + Read + Write + 'a
    // {
    // let fd = io.as_raw_fd();
    // self.register_fd(fd, EventSetBuilder::new().all().finalize());
    // }
}
<commit_msg>Fix clippy<commit_after>// extern crate libc;
use libc::{nfds_t, poll, pollfd, POLLERR, POLLHUP, POLLIN, POLLNVAL, POLLOUT, POLLPRI};

use std::io::Stdin;
use std::os::unix::io::{AsRawFd, RawFd};

use std::fmt;

#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub struct Token(pub i32);

pub struct EventLoop {
    pollfds: Vec<pollfd>,
    timeout: i32,
    active: bool,
}

pub trait EventHandler {
    fn ready_for_io(&mut self, event_loop: &mut EventLoop, stream_id: Token, eventset: EventSet);
    fn error(&mut self, event_loop: &mut EventLoop, stream_id: Token) {}
    fn hangup(&mut self, event_loop: &mut EventLoop, stream_id: Token) {}
    fn not_valid(&mut self, event_loop: &mut EventLoop, stream_id: Token) {
        let Token(fd) = stream_id;
        event_loop.remove_fd(fd);
    }
    fn timeout(&mut self, event_loop: &mut EventLoop) {}
}

pub const TIMEOUT_INFINITE: i32 = -1;

#[derive(Copy, Clone)]
pub struct EventSet {
    events: i16,
}

impl EventSet {
    pub fn empty() -> EventSet {
        EventSet { events: 0 }
    }

    pub fn is_readable(&self) -> bool {
        (self.events & POLLIN) == POLLIN || (self.events & POLLPRI) == POLLPRI
    }

    #[allow(unused)]
    pub fn is_high_prio_readable(&self) -> bool {
        (self.events & POLLPRI) == POLLPRI
    }

    pub fn is_writable(&self) -> bool {
        (self.events & POLLOUT) == POLLOUT
    }

    pub fn is_not_valid(&self) -> bool {
        (self.events & POLLNVAL) == POLLNVAL
    }

    pub fn is_error(&self) -> bool {
        (self.events & POLLERR) == POLLERR
    }

    pub fn is_hangup(&self) -> bool {
        (self.events & POLLHUP) == POLLHUP
    }

    pub fn is_empty(&self) -> bool {
        self.events == 0
    }
}

impl fmt::Display for EventSet {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut events_str = String::new();

        if (self.events & POLLIN) == POLLIN {
            events_str.push_str("POLLIN|");
        }
        if (self.events & POLLOUT) == POLLOUT {
            events_str.push_str("POLLOUT|");
        }
        if (self.events & POLLERR) == POLLERR {
            events_str.push_str("POLLERR|");
        }
        if (self.events & POLLHUP) == POLLHUP {
            events_str.push_str("POLLHUP|");
        }
        if (self.events & POLLNVAL) == POLLNVAL {
            events_str.push_str("POLLNVAL|");
        }
        if (self.events & POLLPRI) == POLLPRI {
            events_str.push_str("POLLPRI|");
        }
        if !events_str.is_empty() {
            let last_char_idx = events_str.len() - 1;
            events_str.remove(last_char_idx);
        }
        write!(formatter, "{}", events_str)
    }
}

pub struct EventSetBuilder {
    eventset: EventSet,
}

impl EventSetBuilder {
    pub fn new() -> EventSetBuilder {
        EventSetBuilder {
            eventset: EventSet::empty(),
        }
    }

    pub fn finalize(self) -> EventSet {
        self.eventset
    }
    pub fn readable(mut self) -> EventSetBuilder {
        self.eventset.events |= POLLIN | POLLPRI;
        self
    }

    #[allow(unused)]
    pub fn writable(mut self) -> EventSetBuilder {
        self.eventset.events |= POLLOUT;
        self
    }

    #[allow(unused)]
    pub fn all(mut self) -> EventSetBuilder {
        self.eventset.events = POLLIN | POLLPRI | POLLOUT;
        self
    }
}

impl EventLoop {
    pub fn new(timeout: Option<u32>) -> EventLoop {
        let mut my_timeout = TIMEOUT_INFINITE;
        if let Some(timeout) = timeout {
            my_timeout = timeout as i32;
        }
        EventLoop {
            pollfds: Vec::<pollfd>::new(),
            active: false,
            timeout: my_timeout,
        }
    }

    fn activate(&mut self) {
        self.active = true;
    }

    pub fn is_active(&self) -> bool {
        self.active
    }

    pub fn shutdown(&mut self) {
        self.active = false;

        trace!("Event loop deactivated");
    }

    pub fn remove_fd(&mut self, fd: RawFd) {
        let found = self
            .pollfds
            .iter()
            .enumerate()
            .find(|&(_, pollfd)| pollfd.fd == fd)
            .map(|(i, _)| i);
        if let Some(index) = found {
            self.pollfds.remove(index);
        }
    }

    pub fn run(&mut self, event_handler: &mut dyn EventHandler) -> Result<(), String> {
        let pollfds_ptr = self.pollfds.as_mut_ptr();
        self.activate();
        let result = Ok(());
        while self.is_active() {
            let mut remove_pollfds = Vec::<RawFd>::new();
            let poll_result =
                unsafe { poll(pollfds_ptr, self.pollfds.len() as nfds_t, self.timeout) };
            let mut shutdown_loop = false;
            match poll_result {
                -1 => {
                    shutdown_loop = true;
                }
                0 => {
                    event_handler.timeout(self);
                }
                _ => {
                    trace!("poll_result={} descriptors ready for io", poll_result);

                    let mut bla = Vec::<(RawFd, EventSet)>::new();
                    for pollfd in &mut self.pollfds {
                        let received_events = EventSet {
                            events: pollfd.revents,
                        };
                        if !received_events.is_empty() {
                            bla.push((pollfd.fd, received_events));
                        }
                    }
                    for (nr, &(fd, eventset)) in bla.iter().enumerate() {
                        trace!("{}: event {} on fd {}", nr, eventset, fd);

                        if eventset.is_readable() || eventset.is_writable() {
                            event_handler.ready_for_io(self, Token(fd), eventset);
                        }
                        if eventset.is_hangup() {
                            event_handler.hangup(self, Token(fd));
                        }
                        if eventset.is_error() {
                            event_handler.error(self, Token(fd));
                        }
                        if eventset.is_not_valid() {
                            event_handler.not_valid(self, Token(fd));
                            remove_pollfds.push(fd);
                        }
                    }
                }
            }

            for fd in remove_pollfds {
                self.remove_fd(fd);
            }

            if shutdown_loop {
                trace!("Event loop is shut down");

                self.shutdown();
            }
        }
        result
    }

    fn register_fd(&mut self, fd: i32, eventset: EventSet) {
        let pollfd = pollfd {
            fd,
            events: eventset.events,
            revents: 0,
        };
        self.pollfds.push(pollfd);
    }

    fn unregister_fd(&mut self, fd: i32) {
        let found = self
            .pollfds
            .iter()
            .enumerate()
            .find(|&(_, pollfd)| pollfd.fd == fd)
            .map(|(i, _)| i);
        if let Some(index) = found {
            self.pollfds.remove(index);
        }
    }

    pub fn register_stdin(&mut self, stdin_stream: &Stdin) -> Token {
        let eventset = EventSetBuilder::new().readable().finalize();
        self.register_fd(0, eventset);
        Token(0)
    }

    pub fn unregister_stdin(&mut self) {
        self.unregister_fd(0);
    }

    pub fn register_read<T>(&mut self, io: &T) -> Token
    where
        T: AsRawFd,
    {
        let fd = io.as_raw_fd();
        self.register_fd(fd, EventSetBuilder::new().readable().finalize());
        Token(fd)
    }

    #[allow(unused)]
    pub fn register_write<T>(&mut self, io: &mut T) -> Token
    where
        T: AsRawFd,
    {
        let fd = io.as_raw_fd();
        self.register_fd(fd, EventSetBuilder::new().writable().finalize());
        Token(fd)
    }

    // pub fn register_read_write<T>(&mut self, io: &'a mut T)
    // where T: AsRawFd + Read + Write + 'a
    // {
    // let fd = io.as_raw_fd();
    // self.register_fd(fd, EventSetBuilder::new().all().finalize());
    // }
}
<|endoftext|>


<commit_before>use super::irq::{Interrupt, IrqHandler};
use super::memory::Memory;
use self::JoypadKey::*;

pub const JOYPAD_ADDRESS: u16 = 0xFF00;
pub const JOYPAD_KEYS: [&'static str; 8] = ["Up", "Down", "Left", "Right",
    "Select", "Start", "A", "B"];
pub const JOYPAD_SELECT_DIRECTIONAL: u8 = 1 << 4;
pub const JOYPAD_SELECT_BUTTON     : u8 = 1 << 5;

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum JoypadKey {
    Up,
    Down,
    Right,
    Left,
    A,
    B,
    Select,
    Start,
}

impl JoypadKey {
    /// Build and return a JoypadKey corresponding to the given symbol, if possible.
    pub fn from_str(symbol: &str) -> Option<JoypadKey> {
        match symbol {
            "Up"     => Some(JoypadKey::Up),
            "Down"   => Some(JoypadKey::Down),
            "Right"  => Some(JoypadKey::Right),
            "Left"   => Some(JoypadKey::Left),
            "A"      => Some(JoypadKey::A),
            "B"      => Some(JoypadKey::B),
            "Select" => Some(JoypadKey::Select),
            "Start"  => Some(JoypadKey::Start),
            _        => None,
        }
    }
}

/// The structure representing the joypad on the Game Boy (Color).
///
/// A single byte, mapped at the 0xFF00 address in memory, allows to read
/// the user input as following (from highest to lowest bit) :
///
/// 7 : not used
/// 6 : not used
/// 5 : if 0, will read button keys from lowest nibble of row 2
/// 4 : if 0, will read direction keys from lowest nibble of row 1
/// | read-only >>
/// 3 : if 0, down / start button is pressed
/// 2 : if 0, up / select button is pressed
/// 1 : if 0, left / B button is pressed
/// 0 : if 0, right / A button is pressed
///
/// TODO :
/// On a real device, the down and left directions cannot be simultaneously
/// pressed with respectively the up and right directions.
///
pub struct Joypad {
    /// The 2x4 matrix holding the key states (0 = pressed).
    /// row 1 : direction / row 2 : buttons
    rows: [u8; 2],
    /// The currently selected row (0 = none).
    selection: usize,
}

impl Joypad {
    pub fn new() -> Joypad {
        Joypad {
            rows: [0x0F, 0x0F],
            selection: 0,
        }
    }

    pub fn key_down(&mut self, key: &JoypadKey, irq_handler: &mut IrqHandler) {
        match *key {
            Down   => self.rows[0] &= 0x07,
            Up     => self.rows[0] &= 0x0B,
            Left   => self.rows[0] &= 0x0D,
            Right  => self.rows[0] &= 0x0E,
            Start  => self.rows[1] &= 0x07,
            Select => self.rows[1] &= 0x0B,
            B      => self.rows[1] &= 0x0D,
            A      => self.rows[1] &= 0x0E,
        }
        irq_handler.request_interrupt(Interrupt::Joypad);
    }

    pub fn key_up(&mut self, key: &JoypadKey) {
        match *key {
            Down   => self.rows[0] |= 0x08,
            Up     => self.rows[0] |= 0x04,
            Left   => self.rows[0] |= 0x02,
            Right  => self.rows[0] |= 0x01,
            Start  => self.rows[1] |= 0x08,
            Select => self.rows[1] |= 0x04,
            B      => self.rows[1] |= 0x02,
            A      => self.rows[1] |= 0x01,
        }
    }
}

impl Memory for Joypad {
    fn read_byte(&mut self, address: u16) -> u8 {
        debug_assert!(address == JOYPAD_ADDRESS);
        match self.selection {
            0     => 0x00,
            1 | 2 => self.rows[self.selection - 1],
            _     => unreachable!(),
        }
    }

    fn write_byte(&mut self, address: u16, byte: u8) {
        debug_assert!(address == JOYPAD_ADDRESS);
        // filter bits 4 and 5
        self.selection = match byte & 0x30 {
            JOYPAD_SELECT_DIRECTIONAL => 1, // bit 4 = row 1
            JOYPAD_SELECT_BUTTON => 2, // bit 5 = row 2
            0x00 => 0,
            _ => unreachable!(),
        }
    }
}

#[cfg(test)]
mod test {
    use super::{Joypad, JoypadKey, JOYPAD_KEYS, JOYPAD_ADDRESS,
        JOYPAD_SELECT_DIRECTIONAL, JOYPAD_SELECT_BUTTON};
    use super::JoypadKey::*;
    use super::super::memory::Memory;
    use super::super::irq::EmptyIrqHandler;

    #[test]
    fn test_keys_from_str() {
        assert_eq!(JoypadKey::from_str("Up"), Some(Up));
        assert_eq!(JoypadKey::from_str("Down"), Some(Down));
        assert_eq!(JoypadKey::from_str("Left"), Some(Left));
        assert_eq!(JoypadKey::from_str("Right"), Some(Right));
        assert_eq!(JoypadKey::from_str("Select"), Some(Select));
        assert_eq!(JoypadKey::from_str("Start"), Some(Start));
        assert_eq!(JoypadKey::from_str("A"), Some(A));
        assert_eq!(JoypadKey::from_str("B"), Some(B));
    }

    #[test]
    fn test_keys_down_and_up() {
        let mut irq_handler = EmptyIrqHandler;
        let mut joypad = Joypad::new();
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0x00);

        for key_str in JOYPAD_KEYS.iter() {
            joypad.key_down(&JoypadKey::from_str(key_str).unwrap(), &mut irq_handler);
        }
        joypad.write_byte(JOYPAD_ADDRESS, JOYPAD_SELECT_DIRECTIONAL);
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0x00);
        joypad.write_byte(JOYPAD_ADDRESS, JOYPAD_SELECT_BUTTON);
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0x00);

        for key_str in JOYPAD_KEYS.iter() {
            joypad.key_up(&JoypadKey::from_str(key_str).unwrap());
        }
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0x0F);
        joypad.write_byte(JOYPAD_ADDRESS, JOYPAD_SELECT_DIRECTIONAL);
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0x0F);
    }

    #[test]
    fn test_key_sequence() {
        let mut irq_handler = EmptyIrqHandler;
        let mut joypad = Joypad::new();
        // up+right+A
        joypad.key_down(&Up, &mut irq_handler);
        joypad.key_down(&Right, &mut irq_handler);
        joypad.key_down(&A, &mut irq_handler);
        joypad.write_byte(JOYPAD_ADDRESS, JOYPAD_SELECT_DIRECTIONAL);
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0b1010);
        joypad.write_byte(JOYPAD_ADDRESS, JOYPAD_SELECT_BUTTON);
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0b1110);
        // right+A+Start
        joypad.key_up(&Up);
        joypad.key_down(&Start, &mut irq_handler);
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0b0110);
        joypad.write_byte(JOYPAD_ADDRESS, JOYPAD_SELECT_DIRECTIONAL);
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0b1110);
        // none
        joypad.key_up(&Right);
        joypad.key_up(&A);
        joypad.key_up(&Start);
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0x0F);
        joypad.write_byte(JOYPAD_ADDRESS, JOYPAD_SELECT_BUTTON);
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0x0F);
    }
}
<commit_msg>Fix joypad bug (can now display Tetris main menu)<commit_after>use irq::{Interrupt, IrqHandler};
use memory::Memory;
use self::JoypadKey::*;

pub const JOYPAD_ADDRESS: u16 = 0xFF00;
pub const JOYPAD_KEYS: [&'static str; 8] = ["Up", "Down", "Left", "Right",
    "Select", "Start", "A", "B"];
pub const JOYPAD_SELECT_DIRECTIONAL: u8 = 1 << 4;
pub const JOYPAD_SELECT_BUTTON     : u8 = 1 << 5;

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum JoypadKey {
    Up,
    Down,
    Right,
    Left,
    A,
    B,
    Select,
    Start,
}

impl JoypadKey {
    /// Build and return a JoypadKey corresponding to the given symbol, if possible.
    pub fn from_str(symbol: &str) -> Option<JoypadKey> {
        match symbol {
            "Up"     => Some(JoypadKey::Up),
            "Down"   => Some(JoypadKey::Down),
            "Right"  => Some(JoypadKey::Right),
            "Left"   => Some(JoypadKey::Left),
            "A"      => Some(JoypadKey::A),
            "B"      => Some(JoypadKey::B),
            "Select" => Some(JoypadKey::Select),
            "Start"  => Some(JoypadKey::Start),
            _        => None,
        }
    }
}

/// The structure representing the joypad on the Game Boy (Color).
///
/// A single byte, mapped at the 0xFF00 address in memory, allows to read
/// the user input as following (from highest to lowest bit) :
///
/// 7 : not used
/// 6 : not used
/// 5 : if 0, will read button keys from lowest nibble of row 2
/// 4 : if 0, will read direction keys from lowest nibble of row 1
/// | read-only >>
/// 3 : if 0, down / start button is pressed
/// 2 : if 0, up / select button is pressed
/// 1 : if 0, left / B button is pressed
/// 0 : if 0, right / A button is pressed
///
/// TODO:
/// On a real device, the down and left directions cannot be simultaneously
/// pressed with respectively the up and right directions.
///
pub struct Joypad {
    /// The 2x4 matrix holding the key states (0 = pressed).
    /// row 1 : direction / row 2 : buttons
    rows: [u8; 2],
    /// The currently selected row (0 = none).
    selection: usize,
}

impl Joypad {
    pub fn new() -> Joypad {
        Joypad {
            rows: [0x0F, 0x0F],
            selection: 0,
        }
    }

    pub fn key_down(&mut self, key: &JoypadKey, irq_handler: &mut IrqHandler) {
        match *key {
            Down   => self.rows[0] &= 0x07,
            Up     => self.rows[0] &= 0x0B,
            Left   => self.rows[0] &= 0x0D,
            Right  => self.rows[0] &= 0x0E,
            Start  => self.rows[1] &= 0x07,
            Select => self.rows[1] &= 0x0B,
            B      => self.rows[1] &= 0x0D,
            A      => self.rows[1] &= 0x0E,
        }
        irq_handler.request_interrupt(Interrupt::Joypad);
    }

    pub fn key_up(&mut self, key: &JoypadKey) {
        match *key {
            Down   => self.rows[0] |= 0x08,
            Up     => self.rows[0] |= 0x04,
            Left   => self.rows[0] |= 0x02,
            Right  => self.rows[0] |= 0x01,
            Start  => self.rows[1] |= 0x08,
            Select => self.rows[1] |= 0x04,
            B      => self.rows[1] |= 0x02,
            A      => self.rows[1] |= 0x01,
        }
    }
}

impl Memory for Joypad {
    fn read_byte(&mut self, address: u16) -> u8 {
        debug_assert!(address == JOYPAD_ADDRESS);
        match self.selection {
            0     => 0x00,
            1 | 2 => self.rows[self.selection - 1],
            _     => unreachable!(),
        }
    }

    fn write_byte(&mut self, address: u16, byte: u8) {
        debug_assert!(address == JOYPAD_ADDRESS);
        // filter bits 4 and 5
        self.selection = match byte & 0x30 {
            JOYPAD_SELECT_DIRECTIONAL => 1, // bit 4 = row 1
            JOYPAD_SELECT_BUTTON => 2, // bit 5 = row 2
            0x30 => 0,
            0x00 => 0,
            _ => unreachable!(),
        }
    }
}

#[cfg(test)]
mod test {
    use super::{Joypad, JoypadKey, JOYPAD_KEYS, JOYPAD_ADDRESS,
        JOYPAD_SELECT_DIRECTIONAL, JOYPAD_SELECT_BUTTON};
    use super::JoypadKey::*;
    use memory::Memory;
    use irq::EmptyIrqHandler;

    #[test]
    fn test_keys_from_str() {
        assert_eq!(JoypadKey::from_str("Up"), Some(Up));
        assert_eq!(JoypadKey::from_str("Down"), Some(Down));
        assert_eq!(JoypadKey::from_str("Left"), Some(Left));
        assert_eq!(JoypadKey::from_str("Right"), Some(Right));
        assert_eq!(JoypadKey::from_str("Select"), Some(Select));
        assert_eq!(JoypadKey::from_str("Start"), Some(Start));
        assert_eq!(JoypadKey::from_str("A"), Some(A));
        assert_eq!(JoypadKey::from_str("B"), Some(B));
    }

    #[test]
    fn test_keys_down_and_up() {
        let mut irq_handler = EmptyIrqHandler;
        let mut joypad = Joypad::new();
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0x00);

        for key_str in JOYPAD_KEYS.iter() {
            joypad.key_down(&JoypadKey::from_str(key_str).unwrap(), &mut irq_handler);
        }
        joypad.write_byte(JOYPAD_ADDRESS, JOYPAD_SELECT_DIRECTIONAL);
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0x00);
        joypad.write_byte(JOYPAD_ADDRESS, JOYPAD_SELECT_BUTTON);
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0x00);

        for key_str in JOYPAD_KEYS.iter() {
            joypad.key_up(&JoypadKey::from_str(key_str).unwrap());
        }
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0x0F);
        joypad.write_byte(JOYPAD_ADDRESS, JOYPAD_SELECT_DIRECTIONAL);
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0x0F);
    }

    #[test]
    fn test_key_sequence() {
        let mut irq_handler = EmptyIrqHandler;
        let mut joypad = Joypad::new();
        // up+right+A
        joypad.key_down(&Up, &mut irq_handler);
        joypad.key_down(&Right, &mut irq_handler);
        joypad.key_down(&A, &mut irq_handler);
        joypad.write_byte(JOYPAD_ADDRESS, JOYPAD_SELECT_DIRECTIONAL);
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0b1010);
        joypad.write_byte(JOYPAD_ADDRESS, JOYPAD_SELECT_BUTTON);
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0b1110);
        // right+A+Start
        joypad.key_up(&Up);
        joypad.key_down(&Start, &mut irq_handler);
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0b0110);
        joypad.write_byte(JOYPAD_ADDRESS, JOYPAD_SELECT_DIRECTIONAL);
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0b1110);
        // none
        joypad.key_up(&Right);
        joypad.key_up(&A);
        joypad.key_up(&Start);
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0x0F);
        joypad.write_byte(JOYPAD_ADDRESS, JOYPAD_SELECT_BUTTON);
        assert_eq!(joypad.read_byte(JOYPAD_ADDRESS), 0x0F);
    }
}
<|endoftext|>


<commit_before>#![feature(alloc)]
#![feature(asm)]
#![feature(box_syntax)]
#![feature(core_simd)]
#![feature(core_slice_ext)]
#![feature(core_str_ext)]
#![feature(fnbox)]
#![feature(fundamental)]
#![feature(lang_items)]
#![feature(no_std)]
#![feature(rc_unique)]
#![feature(unboxed_closures)]
#![feature(unsafe_no_drop_flag)]
#![no_std]

extern crate alloc;

#[macro_use]
extern crate mopa;

use core::fmt;
use core::mem::size_of;
use core::mem::swap;
use core::ptr;

use common::pio::*;
use common::memory::*;

use drivers::keyboard::keyboard_init;
use drivers::mouse::mouse_init;
use drivers::pci::*;
use drivers::ps2::*;
use drivers::serial::*;

use graphics::bmp::*;

use programs::filemanager::*;
use programs::common::*;
use programs::session::*;

use schemes::file::*;
use schemes::http::*;
use schemes::memory::*;
use schemes::pci::*;
use schemes::random::*;

mod common {
    pub mod debug;
    pub mod elf;
    pub mod event;
    pub mod memory;
    pub mod pci;
    pub mod pio;
    pub mod random;
    pub mod resource;
    pub mod string;
    pub mod vec;
}

mod drivers {
    pub mod disk;
    pub mod keyboard;
    pub mod mouse;
    pub mod pci;
    pub mod ps2;
    pub mod serial;
}

mod filesystems {
    pub mod unfs;
}

mod graphics {
    pub mod bmp;
    pub mod color;
    pub mod display;
    pub mod point;
    pub mod size;
    pub mod window;
}

mod network {
    pub mod arp;
    pub mod common;
    pub mod ethernet;
    pub mod icmp;
    pub mod intel8254x;
    pub mod ipv4;
    pub mod rtl8139;
    pub mod tcp;
    pub mod udp;
}

mod programs {
    pub mod common;
    pub mod editor;
    pub mod executor;
    pub mod filemanager;
    pub mod session;
    pub mod viewer;
}

mod schemes {
    pub mod file;
    pub mod http;
    pub mod ide;
    pub mod memory;
    pub mod pci;
    pub mod random;
}

mod usb {
    pub mod xhci;
}

static mut session_ptr: *mut Session = 0 as *mut Session;
static mut events_ptr: *mut Vec<Event> = 0 as *mut Vec<Event>;

unsafe fn init(){
    serial_init();

    dd(size_of::<usize>() * 8);
    d(" bits");
    dl();

    page_init();
    cluster_init();

    session_ptr = alloc(size_of::<Session>()) as *mut Session;
    *session_ptr = Session::new();
    events_ptr = alloc(size_of::<Vec<Event>>()) as *mut Vec<Event>;
    *events_ptr = Vec::new();

    let session = &mut *session_ptr;

    session.items.insert(0, Rc::new(FileManager::new()));

    keyboard_init();
    mouse_init();

    session.modules.push(Rc::new(PS2));
    session.modules.push(Rc::new(Serial::new(0x3F8, 0x4)));

    pci_init(session);

    session.modules.push(Rc::new(FileScheme));
    session.modules.push(Rc::new(HTTPScheme));
    session.modules.push(Rc::new(MemoryScheme));
    session.modules.push(Rc::new(PCIScheme));
    session.modules.push(Rc::new(RandomScheme));

    URL::from_string("file:///background.bmp".to_string()).open_async(box |mut resource: Box<Resource>|{
        let mut vec: Vec<u8> = Vec::new();
        match resource.read_to_end(&mut vec) {
            Option::Some(0) => d("No background data\n"),
            Option::Some(len) => {
                (*session_ptr).display.background = BMP::from_data(vec.as_ptr() as usize);
            },
            Option::None => d("Background load error\n")
        }
    });
}

fn dr(reg: &str, value: u32){
    d(reg);
    d(": ");
    dh(value as usize);
    dl();
}

#[no_mangle]
//Take regs for kernel calls and exceptions
pub unsafe fn kernel(interrupt: u32, edi: u32, esi: u32, ebp: u32, esp: u32, ebx: u32, edx: u32, ecx: u32, eax: u32, eip: u32, eflags: u32) {
    let exception = |name: &str|{
        d(name);
        dl();

        dr("INT", interrupt);
        dr("EIP", eip);
        dr("EFLAGS", eflags);
        dr("EAX", eax);
        dr("EBX", ebx);
        dr("ECX", ecx);
        dr("EDX", edx);
        dr("EDI", edi);
        dr("ESI", esi);
        dr("EBP", ebp);
        dr("ESP", esp);

        asm!("cli");
        asm!("hlt");
        loop{}
    };

    match interrupt {
        0x20 => (), //timer
        0x21 => (*session_ptr).on_irq(0x1), //keyboard
        0x23 => (*session_ptr).on_irq(0x3), // serial 2 and 4
        0x24 => (*session_ptr).on_irq(0x4), // serial 1 and 3
        0x29 => (*session_ptr).on_irq(0x9), //pci
        0x2A => (*session_ptr).on_irq(0xA), //pci
        0x2B => (*session_ptr).on_irq(0xB), //pci
        0x2C => (*session_ptr).on_irq(0xC), //mouse
        0x2E => (*session_ptr).on_irq(0xE), //disk
        0x2F => (*session_ptr).on_irq(0xF), //disk
        0x80 => { // kernel calls
            match eax {
                0x1 => {
                    d("Open: ");
                    let url: &URL = &*(ebx as *const URL);
                    url.d();

                    let session = &mut *session_ptr;
                    ptr::write(ecx as *mut Box<Resource>, session.open(url));
                },
                0x2 => {
                    d("Open Async: ");
                    let url: &URL = &*(ebx as *const URL);
                    let callback: Box<FnBox(Box<Resource>)> = ptr::read(ecx as *const Box<FnBox(Box<Resource>)>);
                    unalloc(ecx as usize);
                    url.d();

                    let session = &mut *session_ptr;
                    session.open_async(url, callback);
                },
                0x3 => {
                    (*events_ptr).push(*(ebx as *const Event));
                }
                _ => {
                    d("System Call");
                    d(" EAX:");
                    dh(eax as usize);
                    d(" EBX:");
                    dh(ebx as usize);
                    d(" ECX:");
                    dh(ecx as usize);
                    d(" EDX:");
                    dh(edx as usize);
                    dl();
                }
            }
        },
        0xFF => { // main loop
            init();

            let session = &mut *session_ptr;
            (*events_ptr).push(RedrawEvent {
                redraw: REDRAW_ALL
            }.to_event());
            loop {
                asm!("cli");
                while (*events_ptr).len() > 0 {
                    session.on_poll();

                    let mut events_copy: Vec<Event> = Vec::new();
                    swap(&mut events_copy, &mut *(events_ptr));

                    asm!("sti");
                    //Can preempt event handling and redraw
                    session.handle_events(&mut events_copy);
                    session.redraw();
                    asm!("cli");
                }
                asm!("sti");
                asm!("hlt");
            }
        },
        0x0 => exception("Divide by zero exception"),
        0x1 => exception("Debug exception"),
        0x2 => exception("Non-maskable interrupt"),
        0x3 => exception("Breakpoint exception"),
        0x4 => exception("Overflow exception"),
        0x5 => exception("Bound range exceeded exception"),
        0x6 => exception("Invalid opcode exception"),
        0x7 => exception("Device not available exception"),
        0x8 => exception("Double fault"),
        0xA => exception("Invalid TSS exception"),
        0xB => exception("Segment not present exception"),
        0xC => exception("Stack-segment fault"),
        0xD => exception("General protection fault"),
        0xE => exception("Page fault"),
        0x10 => exception("x87 floating-point exception"),
        0x11 => exception("Alignment check exception"),
        0x12 => exception("Machine check exception"),
        0x13 => exception("SIMD floating-point exception"),
        0x14 => exception("Virtualization exception"),
        0x1E => exception("Security exception"),
        _ => {
            d("Interrupt: ");
            dh(interrupt as usize);
            dl();
        }
    }

    if interrupt >= 0x20 && interrupt < 0x30 {
        if interrupt >= 0x28 {
            outb(0xA0, 0x20);
        }

        outb(0x20, 0x20);
    }
}

#[lang = "panic_fmt"]
pub extern fn panic_fmt(fmt: fmt::Arguments, file: &'static str, line: u32) -> ! {
    d("PANIC: ");
    d(file);
    d(": ");
    dh(line as usize);
    dl();
    unsafe{
        asm!("cli");
        asm!("hlt");
    }
    loop{}
}

#[no_mangle]
pub extern "C" fn memcmp(a: *mut u8, b: *const u8, len: isize) -> isize {
    unsafe {
        let mut i = 0;
        while i < len {
            let c_a = *a.offset(i);
            let c_b = *b.offset(i);
            if c_a != c_b{
                return c_a as isize - c_b as isize;
            }
            i += 1;
        }
        return 0;
    }
}

#[no_mangle]
pub extern "C" fn memmove(dst: *mut u8, src: *const u8, len: isize){
    unsafe {
        if src < dst {
            let mut i = len;
            while i > 0 {
                i -= 1;
                *dst.offset(i) = *src.offset(i);
            }
        }else{
            let mut i = 0;
            while i < len {
                *dst.offset(i) = *src.offset(i);
                i += 1;
            }
        }
    }
}

#[no_mangle]
pub extern "C" fn memcpy(dst: *mut u8, src: *const u8, len: isize){
    unsafe {
        let mut i = 0;
        while i < len {
            *dst.offset(i) = *src.offset(i);
            i += 1;
        }
    }
}

#[no_mangle]
pub extern "C" fn memset(src: *mut u8, c: i32, len: isize) {
    unsafe {
        let mut i = 0;
        while i < len {
            *src.offset(i) = c as u8;
            i += 1;
        }
    }
}
<commit_msg>Preempting cleanup<commit_after>#![feature(alloc)]
#![feature(asm)]
#![feature(box_syntax)]
#![feature(core_simd)]
#![feature(core_slice_ext)]
#![feature(core_str_ext)]
#![feature(fnbox)]
#![feature(fundamental)]
#![feature(lang_items)]
#![feature(no_std)]
#![feature(rc_unique)]
#![feature(unboxed_closures)]
#![feature(unsafe_no_drop_flag)]
#![no_std]

extern crate alloc;

#[macro_use]
extern crate mopa;

use core::fmt;
use core::mem::size_of;
use core::mem::swap;
use core::ptr;

use common::pio::*;
use common::memory::*;

use drivers::keyboard::keyboard_init;
use drivers::mouse::mouse_init;
use drivers::pci::*;
use drivers::ps2::*;
use drivers::serial::*;

use graphics::bmp::*;

use programs::filemanager::*;
use programs::common::*;
use programs::session::*;

use schemes::file::*;
use schemes::http::*;
use schemes::memory::*;
use schemes::pci::*;
use schemes::random::*;

mod common {
    pub mod debug;
    pub mod elf;
    pub mod event;
    pub mod memory;
    pub mod pci;
    pub mod pio;
    pub mod random;
    pub mod resource;
    pub mod string;
    pub mod vec;
}

mod drivers {
    pub mod disk;
    pub mod keyboard;
    pub mod mouse;
    pub mod pci;
    pub mod ps2;
    pub mod serial;
}

mod filesystems {
    pub mod unfs;
}

mod graphics {
    pub mod bmp;
    pub mod color;
    pub mod display;
    pub mod point;
    pub mod size;
    pub mod window;
}

mod network {
    pub mod arp;
    pub mod common;
    pub mod ethernet;
    pub mod icmp;
    pub mod intel8254x;
    pub mod ipv4;
    pub mod rtl8139;
    pub mod tcp;
    pub mod udp;
}

mod programs {
    pub mod common;
    pub mod editor;
    pub mod executor;
    pub mod filemanager;
    pub mod session;
    pub mod viewer;
}

mod schemes {
    pub mod file;
    pub mod http;
    pub mod ide;
    pub mod memory;
    pub mod pci;
    pub mod random;
}

mod usb {
    pub mod xhci;
}

static mut session_ptr: *mut Session = 0 as *mut Session;
static mut events_ptr: *mut Vec<Event> = 0 as *mut Vec<Event>;

unsafe fn init(){
    serial_init();

    dd(size_of::<usize>() * 8);
    d(" bits");
    dl();

    page_init();
    cluster_init();

    session_ptr = alloc(size_of::<Session>()) as *mut Session;
    *session_ptr = Session::new();
    events_ptr = alloc(size_of::<Vec<Event>>()) as *mut Vec<Event>;
    *events_ptr = Vec::new();

    let session = &mut *session_ptr;

    session.items.insert(0, Rc::new(FileManager::new()));

    keyboard_init();
    mouse_init();

    session.modules.push(Rc::new(PS2));
    session.modules.push(Rc::new(Serial::new(0x3F8, 0x4)));

    pci_init(session);

    session.modules.push(Rc::new(FileScheme));
    session.modules.push(Rc::new(HTTPScheme));
    session.modules.push(Rc::new(MemoryScheme));
    session.modules.push(Rc::new(PCIScheme));
    session.modules.push(Rc::new(RandomScheme));

    URL::from_string("file:///background.bmp".to_string()).open_async(box |mut resource: Box<Resource>|{
        let mut vec: Vec<u8> = Vec::new();
        match resource.read_to_end(&mut vec) {
            Option::Some(0) => d("No background data\n"),
            Option::Some(len) => {
                (*session_ptr).display.background = BMP::from_data(vec.as_ptr() as usize);
            },
            Option::None => d("Background load error\n")
        }
    });
}

fn dr(reg: &str, value: u32){
    d(reg);
    d(": ");
    dh(value as usize);
    dl();
}

#[no_mangle]
//Take regs for kernel calls and exceptions
pub unsafe fn kernel(interrupt: u32, edi: u32, esi: u32, ebp: u32, esp: u32, ebx: u32, edx: u32, ecx: u32, eax: u32, eip: u32, eflags: u32) {
    let exception = |name: &str|{
        d(name);
        dl();

        dr("INT", interrupt);
        dr("EIP", eip);
        dr("EFLAGS", eflags);
        dr("EAX", eax);
        dr("EBX", ebx);
        dr("ECX", ecx);
        dr("EDX", edx);
        dr("EDI", edi);
        dr("ESI", esi);
        dr("EBP", ebp);
        dr("ESP", esp);

        asm!("cli");
        asm!("hlt");
        loop{}
    };

    match interrupt {
        0x20 => (), //timer
        0x21 => (*session_ptr).on_irq(0x1), //keyboard
        0x23 => (*session_ptr).on_irq(0x3), // serial 2 and 4
        0x24 => (*session_ptr).on_irq(0x4), // serial 1 and 3
        0x29 => (*session_ptr).on_irq(0x9), //pci
        0x2A => (*session_ptr).on_irq(0xA), //pci
        0x2B => (*session_ptr).on_irq(0xB), //pci
        0x2C => (*session_ptr).on_irq(0xC), //mouse
        0x2E => (*session_ptr).on_irq(0xE), //disk
        0x2F => (*session_ptr).on_irq(0xF), //disk
        0x80 => { // kernel calls
            match eax {
                0x1 => {
                    d("Open: ");
                    let url: &URL = &*(ebx as *const URL);
                    url.d();

                    let session = &mut *session_ptr;
                    ptr::write(ecx as *mut Box<Resource>, session.open(url));
                },
                0x2 => {
                    d("Open Async: ");
                    let url: &URL = &*(ebx as *const URL);
                    let callback: Box<FnBox(Box<Resource>)> = ptr::read(ecx as *const Box<FnBox(Box<Resource>)>);
                    unalloc(ecx as usize);
                    url.d();

                    let session = &mut *session_ptr;
                    session.open_async(url, callback);
                },
                0x3 => {
                    (*events_ptr).push(*(ebx as *const Event));
                }
                _ => {
                    d("System Call");
                    d(" EAX:");
                    dh(eax as usize);
                    d(" EBX:");
                    dh(ebx as usize);
                    d(" ECX:");
                    dh(ecx as usize);
                    d(" EDX:");
                    dh(edx as usize);
                    dl();
                }
            }
        },
        0xFF => { // main loop
            init();

            let session = &mut *session_ptr;
            (*events_ptr).push(RedrawEvent {
                redraw: REDRAW_ALL
            }.to_event());
            loop {
                //Polling must take place without interrupts to avoid interruption during I/O logic
                asm!("cli");
                    session.on_poll();
                loop {
                    //Copying the events must take place without interrupts to avoid pushes of events
                    asm!("cli");
                        let mut events_copy: Vec<Event> = Vec::new();
                        swap(&mut events_copy, &mut *events_ptr);

                    //Can preempt event handling and redraw
                    asm!("sti");
                        session.handle_events(&mut events_copy);
                        session.redraw();

                    //Checking for new events must take place without interrupts to avoid pushes of events
                    asm!("cli");
                        if (*events_ptr).len() == 0 {
                            break;
                        }
                }
                //On no new events, halt
                asm!("sti");
                asm!("hlt");
            }
        },
        0x0 => exception("Divide by zero exception"),
        0x1 => exception("Debug exception"),
        0x2 => exception("Non-maskable interrupt"),
        0x3 => exception("Breakpoint exception"),
        0x4 => exception("Overflow exception"),
        0x5 => exception("Bound range exceeded exception"),
        0x6 => exception("Invalid opcode exception"),
        0x7 => exception("Device not available exception"),
        0x8 => exception("Double fault"),
        0xA => exception("Invalid TSS exception"),
        0xB => exception("Segment not present exception"),
        0xC => exception("Stack-segment fault"),
        0xD => exception("General protection fault"),
        0xE => exception("Page fault"),
        0x10 => exception("x87 floating-point exception"),
        0x11 => exception("Alignment check exception"),
        0x12 => exception("Machine check exception"),
        0x13 => exception("SIMD floating-point exception"),
        0x14 => exception("Virtualization exception"),
        0x1E => exception("Security exception"),
        _ => {
            d("Interrupt: ");
            dh(interrupt as usize);
            dl();
        }
    }

    if interrupt >= 0x20 && interrupt < 0x30 {
        if interrupt >= 0x28 {
            outb(0xA0, 0x20);
        }

        outb(0x20, 0x20);
    }
}

#[lang = "panic_fmt"]
pub extern fn panic_fmt(fmt: fmt::Arguments, file: &'static str, line: u32) -> ! {
    d("PANIC: ");
    d(file);
    d(": ");
    dh(line as usize);
    dl();
    unsafe{
        asm!("cli");
        asm!("hlt");
    }
    loop{}
}

#[no_mangle]
pub extern "C" fn memcmp(a: *mut u8, b: *const u8, len: isize) -> isize {
    unsafe {
        let mut i = 0;
        while i < len {
            let c_a = *a.offset(i);
            let c_b = *b.offset(i);
            if c_a != c_b{
                return c_a as isize - c_b as isize;
            }
            i += 1;
        }
        return 0;
    }
}

#[no_mangle]
pub extern "C" fn memmove(dst: *mut u8, src: *const u8, len: isize){
    unsafe {
        if src < dst {
            let mut i = len;
            while i > 0 {
                i -= 1;
                *dst.offset(i) = *src.offset(i);
            }
        }else{
            let mut i = 0;
            while i < len {
                *dst.offset(i) = *src.offset(i);
                i += 1;
            }
        }
    }
}

#[no_mangle]
pub extern "C" fn memcpy(dst: *mut u8, src: *const u8, len: isize){
    unsafe {
        let mut i = 0;
        while i < len {
            *dst.offset(i) = *src.offset(i);
            i += 1;
        }
    }
}

#[no_mangle]
pub extern "C" fn memset(src: *mut u8, c: i32, len: isize) {
    unsafe {
        let mut i = 0;
        while i < len {
            *src.offset(i) = c as u8;
            i += 1;
        }
    }
}
<|endoftext|>


<commit_before>use runtime::Runtime;

use std::io;

pub fn repl(args: Vec<String>) {
    let mut runtime = Runtime::new();

    if args.len() > 1 {
        let path = Path::new(&args[1]);

        match runtime.eval_file(&path) {
            Ok(expr) => println!("{}", expr),
            Err(error) => println!("{}", error),
        }
    } else {
        enter_repl(&mut runtime);
    }
}

fn enter_repl(runtime: &mut Runtime) {
    let mut input = io::stdin();

    loop {
        print!("> ");

        match input.read_line() {
            Ok(line) => {
                match runtime.eval_str(line.as_slice()) {
                    Ok(exprs) => {
                        for expr in exprs.iter() {
                            println!("=> {}", expr);
                        }
                    },
                    Err(error) => println!("Error: {}", error),
                }
            },
            Err(error) => {
                match error.kind {
                    io::IoErrorKind::EndOfFile => break,
                    _ => panic!("{}", error),
                }
            },
        }
    }
}
<commit_msg>Added `exit` command to repl.<commit_after>use runtime::Runtime;

use std::io;

pub fn repl(args: Vec<String>) {
    let mut runtime = Runtime::new();

    if args.len() > 1 {
        let path = Path::new(&args[1]);

        match runtime.eval_file(&path) {
            Ok(expr) => println!("{}", expr),
            Err(error) => println!("{}", error),
        }
    } else {
        enter_repl(&mut runtime);
    }
}

fn enter_repl(runtime: &mut Runtime) {
    let mut input = io::stdin();

    loop {
        print!("> ");

        match input.read_line() {
            Ok(line) => {
                match line.as_slice() {
                    "exit\n" => break,
                    line => {
                        match runtime.eval_str(line) {
                            Ok(exprs) => {
                                for expr in exprs.iter() {
                                    println!("=> {}", expr);
                                }
                            },
                            Err(error) => println!("Error: {}", error),
                        }
                    }
                }
            },
            Err(error) => {
                match error.kind {
                    io::IoErrorKind::EndOfFile => break,
                    _ => panic!("{}", error),
                }
            },
        }
    }
}
<|endoftext|>


<commit_before>
use ndarray::*;
use lapack::c;

use super::error::*;

pub type LDA = i32;
pub type LEN = i32;
pub type Col = i32;
pub type Row = i32;

#[derive(Debug, Clone, Copy)]
pub enum Layout {
    C((Row, LDA)),
    F((Col, LDA)),
}

impl Layout {
    pub fn size(&self) -> (Row, Col) {
        match *self {
            Layout::C((row, lda)) => (row, lda),
            Layout::F((col, lda)) => (lda, col),
        }
    }

    pub fn resized(&self, row: Row, col: Col) -> Layout {
        match *self {
            Layout::C(_) => Layout::C((row, col)),
            Layout::F(_) => Layout::F((col, row)),
        }
    }

    pub fn lda(&self) -> LDA {
        match *self {
            Layout::C((_, lda)) => lda,
            Layout::F((_, lda)) => lda,
        }
    }

    pub fn len(&self) -> LEN {
        match *self {
            Layout::C((row, _)) => row,
            Layout::F((col, _)) => col,
        }
    }

    pub fn lapacke_layout(&self) -> c::Layout {
        match *self {
            Layout::C(_) => c::Layout::RowMajor,
            Layout::F(_) => c::Layout::ColumnMajor,
        }
    }

    pub fn same_order(&self, other: &Layout) -> bool {
        self.lapacke_layout() == other.lapacke_layout()
    }

    pub fn as_shape(&self) -> Shape<Ix2> {
        match *self {
            Layout::C((row, col)) => (row as usize, col as usize).into_shape(),
            Layout::F((col, row)) => (row as usize, col as usize).f().into_shape(),
        }
    }

    pub fn t(&self) -> Self {
        match *self {
            Layout::C((row, col)) => Layout::F((col, row)),
            Layout::F((col, row)) => Layout::C((row, col)),
        }
    }
}

pub trait AllocatedArray {
    type Elem;
    fn layout(&self) -> Result<Layout>;
    fn square_layout(&self) -> Result<Layout>;
    fn as_allocated(&self) -> Result<&[Self::Elem]>;
}

pub trait AllocatedArrayMut: AllocatedArray {
    fn as_allocated_mut(&mut self) -> Result<&mut [Self::Elem]>;
}

impl<A, S> AllocatedArray for ArrayBase<S, Ix2>
    where S: Data<Elem = A>
{
    type Elem = A;

    fn layout(&self) -> Result<Layout> {
        let strides = self.strides();
        if ::std::cmp::min(strides[0], strides[1]) != 1 {
            return Err(StrideError::new(strides[0], strides[1]).into());
        }
        if strides[0] > strides[1] {
            Ok(Layout::C((self.rows() as i32, self.cols() as i32)))
        } else {
            Ok(Layout::F((self.cols() as i32, self.rows() as i32)))
        }
    }

    fn square_layout(&self) -> Result<Layout> {
        let l = self.layout()?;
        let (n, m) = l.size();
        if n == m {
            Ok(l)
        } else {
            Err(NotSquareError::new(n, m).into())
        }
    }

    fn as_allocated(&self) -> Result<&[A]> {
        Ok(self.as_slice_memory_order().ok_or(MemoryContError::new())?)
    }
}

impl<A, S> AllocatedArrayMut for ArrayBase<S, Ix2>
    where S: DataMut<Elem = A>
{
    fn as_allocated_mut(&mut self) -> Result<&mut [A]> {
        Ok(self.as_slice_memory_order_mut().ok_or(MemoryContError::new())?)
    }
}

pub fn reconstruct<A, S>(l: Layout, a: Vec<A>) -> Result<ArrayBase<S, Ix2>>
    where S: DataOwned<Elem = A>
{
    Ok(ArrayBase::from_shape_vec(l.as_shape(), a)?)
}

pub fn uninitialized<A, S>(l: Layout) -> ArrayBase<S, Ix2>
    where A: Copy,
          S: DataOwned<Elem = A>
{
    unsafe { ArrayBase::uninitialized(l.as_shape()) }
}

pub fn replicate<A, Sv, So, D>(a: &ArrayBase<Sv, D>) -> ArrayBase<So, D>
    where A: Copy,
          Sv: Data<Elem = A>,
          So: DataOwned<Elem = A> + DataMut,
          D: Dimension
{
    let mut b = unsafe { ArrayBase::uninitialized(a.dim()) };
    b.assign(a);
    b
}

pub fn clone_with_layout<A, Si, So>(l: Layout, a: &ArrayBase<Si, Ix2>) -> ArrayBase<So, Ix2>
    where A: Copy,
          Si: Data<Elem = A>,
          So: DataOwned<Elem = A> + DataMut
{
    let mut b = uninitialized(l);
    b.assign(a);
    b
}
<commit_msg>Add data_transpose<commit_after>
use ndarray::*;
use lapack::c;

use super::error::*;

pub type LDA = i32;
pub type LEN = i32;
pub type Col = i32;
pub type Row = i32;

#[derive(Debug, Clone, Copy)]
pub enum Layout {
    C((Row, LDA)),
    F((Col, LDA)),
}

impl Layout {
    pub fn size(&self) -> (Row, Col) {
        match *self {
            Layout::C((row, lda)) => (row, lda),
            Layout::F((col, lda)) => (lda, col),
        }
    }

    pub fn resized(&self, row: Row, col: Col) -> Layout {
        match *self {
            Layout::C(_) => Layout::C((row, col)),
            Layout::F(_) => Layout::F((col, row)),
        }
    }

    pub fn lda(&self) -> LDA {
        match *self {
            Layout::C((_, lda)) => lda,
            Layout::F((_, lda)) => lda,
        }
    }

    pub fn len(&self) -> LEN {
        match *self {
            Layout::C((row, _)) => row,
            Layout::F((col, _)) => col,
        }
    }

    pub fn lapacke_layout(&self) -> c::Layout {
        match *self {
            Layout::C(_) => c::Layout::RowMajor,
            Layout::F(_) => c::Layout::ColumnMajor,
        }
    }

    pub fn same_order(&self, other: &Layout) -> bool {
        self.lapacke_layout() == other.lapacke_layout()
    }

    pub fn as_shape(&self) -> Shape<Ix2> {
        match *self {
            Layout::C((row, col)) => (row as usize, col as usize).into_shape(),
            Layout::F((col, row)) => (row as usize, col as usize).f().into_shape(),
        }
    }

    pub fn toggle_order(&self) -> Self {
        match *self {
            Layout::C((row, col)) => Layout::F((col, row)),
            Layout::F((col, row)) => Layout::C((row, col)),
        }
    }
}

pub trait AllocatedArray {
    type Elem;
    fn layout(&self) -> Result<Layout>;
    fn square_layout(&self) -> Result<Layout>;
    fn as_allocated(&self) -> Result<&[Self::Elem]>;
}

pub trait AllocatedArrayMut: AllocatedArray {
    fn as_allocated_mut(&mut self) -> Result<&mut [Self::Elem]>;
}

impl<A, S> AllocatedArray for ArrayBase<S, Ix2>
    where S: Data<Elem = A>
{
    type Elem = A;

    fn layout(&self) -> Result<Layout> {
        let strides = self.strides();
        if ::std::cmp::min(strides[0], strides[1]) != 1 {
            return Err(StrideError::new(strides[0], strides[1]).into());
        }
        if strides[0] > strides[1] {
            Ok(Layout::C((self.rows() as i32, self.cols() as i32)))
        } else {
            Ok(Layout::F((self.cols() as i32, self.rows() as i32)))
        }
    }

    fn square_layout(&self) -> Result<Layout> {
        let l = self.layout()?;
        let (n, m) = l.size();
        if n == m {
            Ok(l)
        } else {
            Err(NotSquareError::new(n, m).into())
        }
    }

    fn as_allocated(&self) -> Result<&[A]> {
        Ok(self.as_slice_memory_order().ok_or(MemoryContError::new())?)
    }
}

impl<A, S> AllocatedArrayMut for ArrayBase<S, Ix2>
    where S: DataMut<Elem = A>
{
    fn as_allocated_mut(&mut self) -> Result<&mut [A]> {
        Ok(self.as_slice_memory_order_mut().ok_or(MemoryContError::new())?)
    }
}

pub fn into_col_vec<S>(a: ArrayBase<S, Ix1>) -> ArrayBase<S, Ix2>
    where S: Data
{
    let n = a.len();
    a.into_shape((n, 1)).unwrap()
}

pub fn into_row_vec<S>(a: ArrayBase<S, Ix1>) -> ArrayBase<S, Ix2>
    where S: Data
{
    let n = a.len();
    a.into_shape((1, n)).unwrap()
}

pub fn into_vec<S>(a: ArrayBase<S, Ix2>) -> ArrayBase<S, Ix1>
    where S: Data
{
    let n = a.len();
    a.into_shape((n)).unwrap()
}

pub fn reconstruct<A, S>(l: Layout, a: Vec<A>) -> Result<ArrayBase<S, Ix2>>
    where S: DataOwned<Elem = A>
{
    Ok(ArrayBase::from_shape_vec(l.as_shape(), a)?)
}

pub fn uninitialized<A, S>(l: Layout) -> ArrayBase<S, Ix2>
    where A: Copy,
          S: DataOwned<Elem = A>
{
    unsafe { ArrayBase::uninitialized(l.as_shape()) }
}

pub fn replicate<A, Sv, So, D>(a: &ArrayBase<Sv, D>) -> ArrayBase<So, D>
    where A: Copy,
          Sv: Data<Elem = A>,
          So: DataOwned<Elem = A> + DataMut,
          D: Dimension
{
    let mut b = unsafe { ArrayBase::uninitialized(a.dim()) };
    b.assign(a);
    b
}

pub fn clone_with_layout<A, Si, So>(l: Layout, a: &ArrayBase<Si, Ix2>) -> ArrayBase<So, Ix2>
    where A: Copy,
          Si: Data<Elem = A>,
          So: DataOwned<Elem = A> + DataMut
{
    let mut b = uninitialized(l);
    b.assign(a);
    b
}

pub fn data_transpose<A, S>(a: &mut ArrayBase<S, Ix2>) -> Result<&mut ArrayBase<S, Ix2>>
    where A: Copy,
          S: DataOwned<Elem = A> + DataMut
{
    let l = a.layout()?.toggle_order();
    let new = clone_with_layout(l, a);
    ::std::mem::replace(a, new);
    Ok(a)
}
<|endoftext|>


<commit_before>use std::vec::Vec;
use std::cell::RefCell;
use std::rc::Rc;
use std::cmp;
use rand::{Rng, sample, StdRng, SeedableRng};

use soliton::RobustSoliton;

/// Encoder for Luby transform codes
pub struct Encoder {
    data: Vec<u8>,
    len: usize,
    blocksize: usize,
    rng: StdRng,
    cnt_blocks: usize,
    sol: RobustSoliton
}

/// A Droplet is created by the Encoder.
#[derive(Debug)]
pub struct Droplet {
    /// How many chunks are used
    degree: usize,
    /// The seed of the Random number generator to create the indexes of the corresponding chunks
    seed: usize,
    /// The payload of the Droplet
    data: Vec<u8>
}

impl Droplet {
    fn new(degree: usize, seed: usize, data: Vec<u8>) -> Droplet {
        Droplet {degree: degree, seed: seed, data: data}
    }
}

impl Encoder {
    ///
    /// Constructs a new encoder for Luby transform codes.
    /// In case you send the packages over UDP, the blocksize
    /// should be the MTU size.
    ///
    /// The Encoder implements the iterator. You can use the iterator
    /// to produce an infinte stream of Droplets
    ///
    /// # Examples
    /// ```
    /// use ltcode::Encoder;
    ///
    /// let mut buf = Vec::new();
    /// let mut f = File::open("testfile.bin").unwrap();
    /// try!(f.read_to_end(&mut buf));
    ///
    /// let mut enc = Encoder::new(buf, 1300);
    ///
    pub fn new(data: Vec<u8>, blocksize: usize) -> Encoder {
        let mut rng = StdRng::new().unwrap();

        let len = data.len();
        let cnt_blocks = ((len as f32)/blocksize as f32).ceil() as usize;
        let sol = RobustSoliton::new(cnt_blocks, rng.gen::<usize>());
        Encoder{data: data, len: len, blocksize: blocksize, rng: rng, cnt_blocks: cnt_blocks, sol: sol}
    }
}

fn get_sample_from_rng_by_seed(seed: usize, n: usize, degree: usize) -> Vec<usize> {
    let seedarr: &[_] = &[seed];
    let mut rng:StdRng = SeedableRng::from_seed(seedarr);
    sample(&mut rng, 0..n, degree)
}

impl Iterator for Encoder {
    type Item = Droplet;

    fn next(&mut self) -> Option<Droplet> {
        let degree = self.sol.next().unwrap() as usize; //TODO: try! macro
        let seed = self.rng.gen::<u32>() as usize;
        let sample = get_sample_from_rng_by_seed(seed, self.cnt_blocks, degree);

        let mut r:Vec<u8> = vec![0; self.blocksize];

        for k in sample {
            let begin = k*self.blocksize;
            let end = cmp::min((k+1)* self.blocksize, self.len);
            let mut j = 0;

            for i in begin..end {
                r[j] ^= self.data[i];
                j +=1;
            }
        }

        Some(Droplet::new(degree, seed, r))
    }
}

pub struct Decoder {
    total_length: usize,
    blocksize: usize,
    unknown_chunks: usize,
    number_of_chunks: usize,
    cnt_received_drops: usize,
    blocks: Vec<Block>,
    data: Vec<u8>
}

#[derive(Debug)]
pub struct Statistics {
    cnt_droplets: usize,
    cnt_chunks: usize,
    overhead: f32,
    unknown_chunks: usize
}

#[derive(Debug)]
pub enum CatchResult {
    Finished(Vec<u8>, Statistics),
    Missing(Statistics)
}

#[derive(Debug)]
struct RxDroplet {
    edges_idx: Vec<usize>,
    data: Vec<u8>
}

struct Block {
    idx: usize,
    edges: Vec<Rc<RefCell<RxDroplet>>>,
    begin_at: usize,
    is_known: bool
}

impl Decoder {
    pub fn new(len: usize, blocksize: usize) -> Decoder {
        let data:Vec<u8> = vec![0; len];
        let number_of_chunks = ((len as f32)/blocksize as f32).ceil() as usize;
        let mut edges:Vec<Block> = Vec::with_capacity(number_of_chunks);
        for i in 0..number_of_chunks {
            let blk = Block{idx: i, edges: Vec::new(), begin_at: blocksize * i, is_known: false};
            edges.push(blk);
        }

        Decoder{ total_length: len,
                 number_of_chunks: number_of_chunks,
                 unknown_chunks: number_of_chunks,
                 cnt_received_drops: 0,
                 blocks: edges,
                 data: data,
                 blocksize: blocksize }
    }

    fn process_droplet(&mut self, droplet: RxDroplet) {
        let mut drops:Vec<Rc<RefCell<RxDroplet>>> = Vec::new();
        drops.push(Rc::new(RefCell::new(droplet)));
        loop { //a loop is used instead of recursion
            match drops.pop() {
                None => return,
                Some(drop) => {
                    let edges = drop.borrow().edges_idx.clone();
                    for ed in edges { //the list is edited, hence we copy first
                        let block = self.blocks.get_mut(ed).unwrap();
                        if block.is_known {
                            let mut b_drop = drop.borrow_mut();
                            for i in 0..self.blocksize {
                                b_drop.data[i] ^= self.data[block.begin_at+i];
                            }
                            let pos = b_drop.edges_idx.iter().position(|x| x == &ed).unwrap();
                            b_drop.edges_idx.remove(pos);
                        }
                        else {
                            block.edges.push(drop.clone());
                        }
                    }
                    if drop.borrow().edges_idx.len() == 1 {
                        let first_idx = drop.borrow().edges_idx.clone().get(0).unwrap().clone();

                        let block = self.blocks.get_mut(first_idx).unwrap();

                        if block.is_known == false {
                            {
                                let b_drop = drop.borrow();
                                for i in 0..self.blocksize {
                                    self.data[block.begin_at+i] = b_drop.data[i];
                                }
                            }
                            block.is_known = true;
                            self.unknown_chunks -= 1;

                            while block.edges.len() > 0 {
                                let edge = block.edges.pop().unwrap();
                                {
                                    let mut m_edge = edge.borrow_mut();

                                    if m_edge.edges_idx.len() == 1 {
                                        drops.push(edge.clone());
                                    }
                                    else {
                                        for i in 0..self.blocksize {
                                            m_edge.data[i] ^= self.data[block.begin_at+i]
                                        }

                                        let pos = m_edge.edges_idx.iter().position(|x| x == &block.idx).unwrap();
                                        m_edge.edges_idx.remove(pos);

                                        if m_edge.edges_idx.len() == 1 {
                                            drops.push(edge.clone());
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    pub fn catch(&mut self, drop: Droplet) -> CatchResult {
        self.cnt_received_drops +=1;

        let sample = get_sample_from_rng_by_seed(drop.seed, self.number_of_chunks, drop.degree);
        let rxdrop = RxDroplet {edges_idx: sample, data: drop.data};
        self.process_droplet(rxdrop);
        let stats = Statistics {
            cnt_droplets: self.cnt_received_drops,
            cnt_chunks: self.number_of_chunks,
            overhead: self.cnt_received_drops as f32 * 100.0 / self.number_of_chunks as f32,
            unknown_chunks: self.unknown_chunks
        };

        if self.unknown_chunks == 0 {
            let mut result = Vec::with_capacity(self.total_length);
            debug!("element: {:?}", self.data[0]);
            debug!("total_length: {:?}, result: {:?}", self.total_length, self.data.len());
            for i in 0..self.total_length {
                result.push(self.data[i]);
            }
            CatchResult::Finished(result, stats) //TODO: there shouldn't be a copy
        }
        else {
            CatchResult::Missing(stats)
        }
    }
}
<commit_msg>removed unnecessary scopes<commit_after>use std::vec::Vec;
use std::cell::RefCell;
use std::rc::Rc;
use std::cmp;
use rand::{Rng, sample, StdRng, SeedableRng};

use soliton::RobustSoliton;

/// Encoder for Luby transform codes
pub struct Encoder {
    data: Vec<u8>,
    len: usize,
    blocksize: usize,
    rng: StdRng,
    cnt_blocks: usize,
    sol: RobustSoliton
}

/// A Droplet is created by the Encoder.
#[derive(Debug)]
pub struct Droplet {
    /// How many chunks are used
    degree: usize,
    /// The seed of the Random number generator to create the indexes of the corresponding chunks
    seed: usize,
    /// The payload of the Droplet
    data: Vec<u8>
}

impl Droplet {
    fn new(degree: usize, seed: usize, data: Vec<u8>) -> Droplet {
        Droplet {degree: degree, seed: seed, data: data}
    }
}

impl Encoder {
    ///
    /// Constructs a new encoder for Luby transform codes.
    /// In case you send the packages over UDP, the blocksize
    /// should be the MTU size.
    ///
    /// The Encoder implements the iterator. You can use the iterator
    /// to produce an infinte stream of Droplets
    ///
    /// # Examples
    /// ```
    /// use ltcode::Encoder;
    ///
    /// let mut buf = Vec::new();
    /// let mut f = File::open("testfile.bin").unwrap();
    /// try!(f.read_to_end(&mut buf));
    ///
    /// let mut enc = Encoder::new(buf, 1300);
    ///
    pub fn new(data: Vec<u8>, blocksize: usize) -> Encoder {
        let mut rng = StdRng::new().unwrap();

        let len = data.len();
        let cnt_blocks = ((len as f32)/blocksize as f32).ceil() as usize;
        let sol = RobustSoliton::new(cnt_blocks, rng.gen::<usize>());
        Encoder{data: data, len: len, blocksize: blocksize, rng: rng, cnt_blocks: cnt_blocks, sol: sol}
    }
}

fn get_sample_from_rng_by_seed(seed: usize, n: usize, degree: usize) -> Vec<usize> {
    let seedarr: &[_] = &[seed];
    let mut rng:StdRng = SeedableRng::from_seed(seedarr);
    sample(&mut rng, 0..n, degree)
}

impl Iterator for Encoder {
    type Item = Droplet;

    fn next(&mut self) -> Option<Droplet> {
        let degree = self.sol.next().unwrap() as usize; //TODO: try! macro
        let seed = self.rng.gen::<u32>() as usize;
        let sample = get_sample_from_rng_by_seed(seed, self.cnt_blocks, degree);

        let mut r:Vec<u8> = vec![0; self.blocksize];

        for k in sample {
            let begin = k*self.blocksize;
            let end = cmp::min((k+1)* self.blocksize, self.len);
            let mut j = 0;

            for i in begin..end {
                r[j] ^= self.data[i];
                j +=1;
            }
        }

        Some(Droplet::new(degree, seed, r))
    }
}

pub struct Decoder {
    total_length: usize,
    blocksize: usize,
    unknown_chunks: usize,
    number_of_chunks: usize,
    cnt_received_drops: usize,
    blocks: Vec<Block>,
    data: Vec<u8>
}

#[derive(Debug)]
pub struct Statistics {
    cnt_droplets: usize,
    cnt_chunks: usize,
    overhead: f32,
    unknown_chunks: usize
}

#[derive(Debug)]
pub enum CatchResult {
    Finished(Vec<u8>, Statistics),
    Missing(Statistics)
}

#[derive(Debug)]
struct RxDroplet {
    edges_idx: Vec<usize>,
    data: Vec<u8>
}

struct Block {
    idx: usize,
    edges: Vec<Rc<RefCell<RxDroplet>>>,
    begin_at: usize,
    is_known: bool
}

impl Decoder {
    pub fn new(len: usize, blocksize: usize) -> Decoder {
        let data:Vec<u8> = vec![0; len];
        let number_of_chunks = ((len as f32)/blocksize as f32).ceil() as usize;
        let mut edges:Vec<Block> = Vec::with_capacity(number_of_chunks);
        for i in 0..number_of_chunks {
            let blk = Block{idx: i, edges: Vec::new(), begin_at: blocksize * i, is_known: false};
            edges.push(blk);
        }

        Decoder{ total_length: len,
                 number_of_chunks: number_of_chunks,
                 unknown_chunks: number_of_chunks,
                 cnt_received_drops: 0,
                 blocks: edges,
                 data: data,
                 blocksize: blocksize }
    }

    fn process_droplet(&mut self, droplet: RxDroplet) {
        let mut drops:Vec<Rc<RefCell<RxDroplet>>> = Vec::new();
        drops.push(Rc::new(RefCell::new(droplet)));
        loop { //a loop is used instead of recursion
            match drops.pop() {
                None => return,
                Some(drop) => {
                    let edges = drop.borrow().edges_idx.clone();
                    for ed in edges { //the list is edited, hence we copy first
                        let block = self.blocks.get_mut(ed).unwrap();
                        if block.is_known {
                            let mut b_drop = drop.borrow_mut();
                            for i in 0..self.blocksize {
                                b_drop.data[i] ^= self.data[block.begin_at+i];
                            }
                            let pos = b_drop.edges_idx.iter().position(|x| x == &ed).unwrap();
                            b_drop.edges_idx.remove(pos);
                        }
                        else {
                            block.edges.push(drop.clone());
                        }
                    }
                    if drop.borrow().edges_idx.len() == 1 {
                        let first_idx = drop.borrow().edges_idx.clone().get(0).unwrap().clone();

                        let block = self.blocks.get_mut(first_idx).unwrap();

                        if block.is_known == false {
                            {
                                let b_drop = drop.borrow();
                                for i in 0..self.blocksize {
                                    self.data[block.begin_at+i] = b_drop.data[i];
                                }
                            }
                            block.is_known = true;
                            self.unknown_chunks -= 1;

                            while block.edges.len() > 0 {
                                let edge = block.edges.pop().unwrap();
                                let mut m_edge = edge.borrow_mut();

                                if m_edge.edges_idx.len() == 1 {
                                    drops.push(edge.clone());
                                }
                                else {
                                    for i in 0..self.blocksize {
                                        m_edge.data[i] ^= self.data[block.begin_at+i]
                                    }

                                    let pos = m_edge.edges_idx.iter().position(|x| x == &block.idx).unwrap();
                                    m_edge.edges_idx.remove(pos);
                                    if m_edge.edges_idx.len() == 1 {
                                        drops.push(edge.clone());
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    pub fn catch(&mut self, drop: Droplet) -> CatchResult {
        self.cnt_received_drops +=1;

        let sample = get_sample_from_rng_by_seed(drop.seed, self.number_of_chunks, drop.degree);
        let rxdrop = RxDroplet {edges_idx: sample, data: drop.data};
        self.process_droplet(rxdrop);
        let stats = Statistics {
            cnt_droplets: self.cnt_received_drops,
            cnt_chunks: self.number_of_chunks,
            overhead: self.cnt_received_drops as f32 * 100.0 / self.number_of_chunks as f32,
            unknown_chunks: self.unknown_chunks
        };

        if self.unknown_chunks == 0 {
            let mut result = Vec::with_capacity(self.total_length);
            debug!("element: {:?}", self.data[0]);
            debug!("total_length: {:?}, result: {:?}", self.total_length, self.data.len());
            for i in 0..self.total_length {
                result.push(self.data[i]);
            }
            CatchResult::Finished(result, stats) //TODO: there shouldn't be a copy
        }
        else {
            CatchResult::Missing(stats)
        }
    }
}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! exp {
    ($e1:expr, $o:expr, $e2:expr) => { BinExp(Box::new($e1), $o, Box::new($e2)) }
}

#[macro_export]
macro_rules! post_dec {
    ($e:expr) => { PostDec(Box::new($e)) }
}

#[macro_export]
macro_rules! post_inc {
    ($e:expr) => { PostInc(Box::new($e)) }
}

#[macro_export]
macro_rules! pre_dec {
    ($e:expr) => { PreDec(Box::new($e)) }
}

#[macro_export]
macro_rules! pre_inc {
    ($e:expr) => { PreInc(Box::new($e)) }
}

#[macro_export]
macro_rules! neg_var {
    ($e:expr) => { Neg(Box::new(var!($e))) }
}

#[macro_export]
macro_rules! pos_var {
    ($e:expr) => { Pos(Box::new(var!($e))) }
}

#[macro_export]
macro_rules! instance_var {
    ($o:expr, $name:expr) => { InstanceVar(Box::new($o), String::from($name)) }
}

#[macro_export]
macro_rules! call {
    ($name:expr, $args:expr) => {
        Call(Box::new($name), $args.into_iter().map(|x| Box::new(x)).collect())
    }
}

#[macro_export]
macro_rules! method {
    ($o:expr, $name:expr, [$($arg:expr),*]) => {
        Method(Box::new($o), String::from($name), vec![$(Box::new($arg)),*])
    }
}

#[macro_export]
macro_rules! assign {
    ($v:expr, $e:expr) => { Assign(String::from($v), $e) }
}

#[macro_export]
macro_rules! decl {
    ($v:expr, $e:expr) => { Decl(String::from($v), $e) }
}

#[macro_export]
macro_rules! seq {
    ($s1:expr, $s2:expr) => { Seq(Box::new($s1), Box::new($s2)) }
}

#[macro_export]
macro_rules! var {
    ($s:expr) => { Var(String::from($s)) }
}

#[macro_export]
macro_rules! defun {
    (($($param:expr),*) $stmt:expr) => {
        Defun(
            None,
            vec![
                $(String::from($param)),*
            ],
            Box::new($stmt)
        )
    };

    ($name:expr, ($($param:expr),*) $stmt:expr) => {
        Defun(
            Some(String::from($name)),
            vec![
                $(String::from($param)),*
            ],
            Box::new($stmt)
        )
    }
}

#[macro_export]
macro_rules! new_obj {
    ($name:expr) => { NewObject(Box::new($name), vec![]) };

    ($name:expr, $($arg:expr),*) => {
        NewObject(Box::new($name), vec![
            $(Box::new($arg)),*
        ])
    }
}

#[macro_export]
macro_rules! obj {
    ($($name:expr => $prop:expr),*) => {
        Object(vec![
            $((String::from($name), Box::new($prop))),*
        ])
    }
}

#[macro_export]
macro_rules! parse_exp {
    ($s:expr) => { parse_Exp($s).unwrap() }
}

#[macro_export]
macro_rules! parse_stmt {
    ($s:expr) => { parse_Stmt($s).unwrap() }
}
<commit_msg>Fix macros<commit_after>#[macro_export]
macro_rules! exp {
    ($e1:expr, $o:expr, $e2:expr) => { BinExp(Box::new($e1), $o, Box::new($e2)) }
}

#[macro_export]
macro_rules! post_dec {
    ($e:expr) => { PostDec(Box::new($e)) }
}

#[macro_export]
macro_rules! post_inc {
    ($e:expr) => { PostInc(Box::new($e)) }
}

#[macro_export]
macro_rules! pre_dec {
    ($e:expr) => { PreDec(Box::new($e)) }
}

#[macro_export]
macro_rules! pre_inc {
    ($e:expr) => { PreInc(Box::new($e)) }
}

#[macro_export]
macro_rules! neg_var {
    ($e:expr) => { Neg(Box::new(var!($e))) }
}

#[macro_export]
macro_rules! pos_var {
    ($e:expr) => { Pos(Box::new(var!($e))) }
}

#[macro_export]
macro_rules! instance_var {
    ($o:expr, $name:expr) => { InstanceVar(Box::new($o), String::from($name)) }
}

#[macro_export]
macro_rules! call {
    ($name:expr, $args:expr) => {
        Call(Box::new($name), $args.into_iter().map(|x| Box::new(x)).collect())
    }
}

#[macro_export]
macro_rules! method {
    ($o:expr, $name:expr, [$($arg:expr),*]) => {
        Method(Box::new($o), String::from($name), vec![$(Box::new($arg)),*])
    }
}

#[macro_export]
macro_rules! assign {
    ($v:expr, $e:expr) => { Assign(String::from($v), $e) }
}

#[macro_export]
macro_rules! decl {
    ($v:expr, $e:expr) => { Decl(String::from($v), $e) }
}

#[macro_export]
macro_rules! seq {
    ($s1:expr, $s2:expr) => { Seq(Box::new($s1), Box::new($s2)) }
}

#[macro_export]
macro_rules! var {
    ($s:expr) => { Var(String::from($s)) }
}

#[macro_export]
macro_rules! defun {
    (($($param:expr),*) $stmt:expr) => {
        Defun(
            None,
            vec![
                $(String::from($param)),*
            ],
            vec![$stmt]
        )
    };

    ($name:expr, ($($param:expr),*) $stmt:expr) => {
        Defun(
            Some(String::from($name)),
            vec![
                $(String::from($param)),*
            ],
            vec![$stmt]
        )
    }
}

#[macro_export]
macro_rules! new_obj {
    ($name:expr) => { NewObject(Box::new($name), vec![]) };

    ($name:expr, $($arg:expr),*) => {
        NewObject(Box::new($name), vec![
            $(Box::new($arg)),*
        ])
    }
}

#[macro_export]
macro_rules! obj {
    ($($name:expr => $prop:expr),*) => {
        Object(vec![
            $((String::from($name), Box::new($prop))),*
        ])
    }
}

#[macro_export]
macro_rules! parse_exp {
    ($s:expr) => { parse_Exp($s).unwrap() }
}

#[macro_export]
macro_rules! parse_stmt {
    ($s:expr) => { parse_Stmt($s).unwrap() }
}
<|endoftext|>