<commit_before>use {SendDgram, RecvDgram};

use tokio_reactor::{Handle, PollEvented};

use futures::{Async, Poll};
use mio::Ready;
use mio_uds;

use std::fmt;
use std::io;
use std::net::Shutdown;
use std::os::unix::io::{AsRawFd, RawFd};
use std::os::unix::net::{self, SocketAddr};
use std::path::Path;

/// An I/O object representing a Unix datagram socket.
pub struct UnixDatagram {
    io: PollEvented<mio_uds::UnixDatagram>,
}

impl UnixDatagram {
    /// Creates a new `UnixDatagram` bound to the specified path.
    pub fn bind<P>(path: P) -> io::Result<UnixDatagram>
    where
        P: AsRef<Path>,
    {
        let socket = mio_uds::UnixDatagram::bind(path)?;
        Ok(UnixDatagram::new(socket))
    }

    /// Creates an unnamed pair of connected sockets.
    ///
    /// This function will create a pair of interconnected Unix sockets for
    /// communicating back and forth between one another. Each socket will
    /// be associated with the default event loop's handle.
    pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> {
        let (a, b) = mio_uds::UnixDatagram::pair()?;
        let a = UnixDatagram::new(a);
        let b = UnixDatagram::new(b);

        Ok((a, b))
    }

    /// Consumes a `UnixDatagram` in the standard library and returns a
    /// nonblocking `UnixDatagram` from this crate.
    ///
    /// The returned datagram will be associated with the given event loop
    /// specified by `handle` and is ready to perform I/O.
    pub fn from_std(datagram: net::UnixDatagram, handle: &Handle) -> io::Result<UnixDatagram> {
        let socket = mio_uds::UnixDatagram::from_datagram(datagram)?;
        let io = PollEvented::new_with_handle(socket, handle)?;
        Ok(UnixDatagram { io })
    }

    fn new(socket: mio_uds::UnixDatagram) -> UnixDatagram {
        let io = PollEvented::new(socket);
        UnixDatagram { io }
    }

    /// Creates a new `UnixDatagram` which is not bound to any address.
    pub fn unbound() -> io::Result<UnixDatagram> {
        let socket = mio_uds::UnixDatagram::unbound()?;
        Ok(UnixDatagram::new(socket))
    }

    /// Connects the socket to the specified address.
    ///
    /// The `send` method may be used to send data to the specified address.
    /// `recv` and `recv_from` will only receive data from that address.
    pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
        self.io.get_ref().connect(path)
    }

    /// Test whether this socket is ready to be read or not.
    pub fn poll_read_ready(&self, ready: Ready) -> Poll<Ready, io::Error> {
        self.io.poll_read_ready(ready)
    }

    /// Test whether this socket is ready to be written to or not.
    pub fn poll_write_ready(&self) -> Poll<Ready, io::Error> {
        self.io.poll_write_ready()
    }

    /// Returns the local address that this socket is bound to.
    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.io.get_ref().local_addr()
    }

    /// Returns the address of this socket's peer.
    ///
    /// The `connect` method will connect the socket to a peer.
    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
        self.io.get_ref().peer_addr()
    }

    /// Receives data from the socket.
    ///
    /// On success, returns the number of bytes read and the address from
    /// whence the data came.
    pub fn poll_recv_from(&self, buf: &mut [u8]) -> Poll<(usize, SocketAddr), io::Error> {
        if self.io.poll_read_ready(Ready::readable())?.is_not_ready() {
            return Ok(Async::NotReady);
        }
        let r = self.io.get_ref().recv_from(buf);
        if is_wouldblock(&r) {
            self.io.clear_read_ready(Ready::readable())?;
            return Ok(Async::NotReady);
        }
        r.map(Async::Ready)
    }

    /// Receives data from the socket.
    ///
    /// On success, returns the number of bytes read.
    pub fn poll_recv(&self, buf: &mut [u8]) -> Poll<usize, io::Error> {
        if self.io.poll_read_ready(Ready::readable())?.is_not_ready() {
            return Ok(Async::NotReady);
        }
        let r = self.io.get_ref().recv(buf);
        if is_wouldblock(&r) {
            self.io.clear_read_ready(Ready::readable())?;
            return Ok(Async::NotReady);
        }
        r.map(Async::Ready)
    }

    /// Returns a future for receiving a datagram. See the documentation on RecvDgram for details.
    pub fn recv_dgram<T>(self, buf: T) -> RecvDgram<T>
    where
        T: AsMut<[u8]>,
    {
        RecvDgram::new(self, buf)
    }

    /// Sends data on the socket to the specified address.
    ///
    /// On success, returns the number of bytes written.
    pub fn poll_send_to<P>(&self, buf: &[u8], path: P) -> Poll<usize, io::Error>
    where
        P: AsRef<Path>,
    {
        if self.io.poll_write_ready()?.is_not_ready() {
            return Ok(Async::NotReady);
        }
        let r = self.io.get_ref().send_to(buf, path);
        if is_wouldblock(&r) {
            self.io.clear_write_ready()?;
        }
        r.map(Async::Ready)
    }

    /// Sends data on the socket to the socket's peer.
    ///
    /// The peer address may be set by the `connect` method, and this method
    /// will return an error if the socket has not already been connected.
    ///
    /// On success, returns the number of bytes written.
    pub fn poll_send(&self, buf: &[u8]) -> Poll<usize, io::Error> {
        if self.io.poll_write_ready()?.is_not_ready() {
            return Ok(Async::NotReady);
        }
        let r = self.io.get_ref().send(buf);
        if is_wouldblock(&r) {
            self.io.clear_write_ready()?;
        }
        r.map(Async::Ready)
    }

    /// Returns a future sending the data in buf to the socket at path.
    pub fn send_dgram<T, P>(self, buf: T, path: P) -> SendDgram<T, P>
    where
        T: AsRef<[u8]>,
        P: AsRef<Path>,
    {
        SendDgram::new(self, buf, path)
    }

    /// Returns the value of the `SO_ERROR` option.
    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
        self.io.get_ref().take_error()
    }

    /// Shut down the read, write, or both halves of this connection.
    ///
    /// This function will cause all pending and future I/O calls on the
    /// specified portions to immediately return with an appropriate value
    /// (see the documentation of `Shutdown`).
    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
        self.io.get_ref().shutdown(how)
    }
}

impl fmt::Debug for UnixDatagram {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.io.get_ref().fmt(f)
    }
}

impl AsRawFd for UnixDatagram {
    fn as_raw_fd(&self) -> RawFd {
        self.io.get_ref().as_raw_fd()
    }
}

fn is_wouldblock<T>(r: &io::Result<T>) -> bool {
    match *r {
        Ok(_) => false,
        Err(ref e) => e.kind() == io::ErrorKind::WouldBlock,
    }
}
<commit_msg>uds: fix WouldBlock case in UnixDatagram send methods (#782)<commit_after>use {RecvDgram, SendDgram};

use tokio_reactor::{Handle, PollEvented};

use futures::{Async, Poll};
use mio::Ready;
use mio_uds;

use std::fmt;
use std::io;
use std::net::Shutdown;
use std::os::unix::io::{AsRawFd, RawFd};
use std::os::unix::net::{self, SocketAddr};
use std::path::Path;

/// An I/O object representing a Unix datagram socket.
pub struct UnixDatagram {
    io: PollEvented<mio_uds::UnixDatagram>,
}

impl UnixDatagram {
    /// Creates a new `UnixDatagram` bound to the specified path.
    pub fn bind<P>(path: P) -> io::Result<UnixDatagram>
    where
        P: AsRef<Path>,
    {
        let socket = mio_uds::UnixDatagram::bind(path)?;
        Ok(UnixDatagram::new(socket))
    }

    /// Creates an unnamed pair of connected sockets.
    ///
    /// This function will create a pair of interconnected Unix sockets for
    /// communicating back and forth between one another. Each socket will
    /// be associated with the default event loop's handle.
    pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> {
        let (a, b) = mio_uds::UnixDatagram::pair()?;
        let a = UnixDatagram::new(a);
        let b = UnixDatagram::new(b);

        Ok((a, b))
    }

    /// Consumes a `UnixDatagram` in the standard library and returns a
    /// nonblocking `UnixDatagram` from this crate.
    ///
    /// The returned datagram will be associated with the given event loop
    /// specified by `handle` and is ready to perform I/O.
    pub fn from_std(datagram: net::UnixDatagram, handle: &Handle) -> io::Result<UnixDatagram> {
        let socket = mio_uds::UnixDatagram::from_datagram(datagram)?;
        let io = PollEvented::new_with_handle(socket, handle)?;
        Ok(UnixDatagram { io })
    }

    fn new(socket: mio_uds::UnixDatagram) -> UnixDatagram {
        let io = PollEvented::new(socket);
        UnixDatagram { io }
    }

    /// Creates a new `UnixDatagram` which is not bound to any address.
    pub fn unbound() -> io::Result<UnixDatagram> {
        let socket = mio_uds::UnixDatagram::unbound()?;
        Ok(UnixDatagram::new(socket))
    }

    /// Connects the socket to the specified address.
    ///
    /// The `send` method may be used to send data to the specified address.
    /// `recv` and `recv_from` will only receive data from that address.
    pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
        self.io.get_ref().connect(path)
    }

    /// Test whether this socket is ready to be read or not.
    pub fn poll_read_ready(&self, ready: Ready) -> Poll<Ready, io::Error> {
        self.io.poll_read_ready(ready)
    }

    /// Test whether this socket is ready to be written to or not.
    pub fn poll_write_ready(&self) -> Poll<Ready, io::Error> {
        self.io.poll_write_ready()
    }

    /// Returns the local address that this socket is bound to.
    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.io.get_ref().local_addr()
    }

    /// Returns the address of this socket's peer.
    ///
    /// The `connect` method will connect the socket to a peer.
    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
        self.io.get_ref().peer_addr()
    }

    /// Receives data from the socket.
    ///
    /// On success, returns the number of bytes read and the address from
    /// whence the data came.
    pub fn poll_recv_from(&self, buf: &mut [u8]) -> Poll<(usize, SocketAddr), io::Error> {
        try_ready!(self.io.poll_read_ready(Ready::readable()));

        match self.io.get_ref().recv_from(buf) {
            Ok(ret) => Ok(ret.into()),
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                self.io.clear_read_ready(Ready::readable())?;
                Ok(Async::NotReady)
            }
            Err(e) => Err(e),
        }
    }

    /// Receives data from the socket.
    ///
    /// On success, returns the number of bytes read.
    pub fn poll_recv(&self, buf: &mut [u8]) -> Poll<usize, io::Error> {
        try_ready!(self.io.poll_read_ready(Ready::readable()));

        match self.io.get_ref().recv(buf) {
            Ok(ret) => Ok(ret.into()),
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                self.io.clear_read_ready(Ready::readable())?;
                Ok(Async::NotReady)
            }
            Err(e) => Err(e),
        }
    }

    /// Returns a future for receiving a datagram. See the documentation on RecvDgram for details.
    pub fn recv_dgram<T>(self, buf: T) -> RecvDgram<T>
    where
        T: AsMut<[u8]>,
    {
        RecvDgram::new(self, buf)
    }

    /// Sends data on the socket to the specified address.
    ///
    /// On success, returns the number of bytes written.
    pub fn poll_send_to<P>(&self, buf: &[u8], path: P) -> Poll<usize, io::Error>
    where
        P: AsRef<Path>,
    {
        try_ready!(self.io.poll_write_ready());

        match self.io.get_ref().send_to(buf, path) {
            Ok(ret) => Ok(ret.into()),
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                self.io.clear_write_ready()?;
                Ok(Async::NotReady)
            }
            Err(e) => Err(e),
        }
    }

    /// Sends data on the socket to the socket's peer.
    ///
    /// The peer address may be set by the `connect` method, and this method
    /// will return an error if the socket has not already been connected.
    ///
    /// On success, returns the number of bytes written.
    pub fn poll_send(&self, buf: &[u8]) -> Poll<usize, io::Error> {
        try_ready!(self.io.poll_write_ready());

        match self.io.get_ref().send(buf) {
            Ok(ret) => Ok(ret.into()),
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                self.io.clear_write_ready()?;
                Ok(Async::NotReady)
            }
            Err(e) => Err(e),
        }
    }

    /// Returns a future sending the data in buf to the socket at path.
    pub fn send_dgram<T, P>(self, buf: T, path: P) -> SendDgram<T, P>
    where
        T: AsRef<[u8]>,
        P: AsRef<Path>,
    {
        SendDgram::new(self, buf, path)
    }

    /// Returns the value of the `SO_ERROR` option.
    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
        self.io.get_ref().take_error()
    }

    /// Shut down the read, write, or both halves of this connection.
    ///
    /// This function will cause all pending and future I/O calls on the
    /// specified portions to immediately return with an appropriate value
    /// (see the documentation of `Shutdown`).
    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
        self.io.get_ref().shutdown(how)
    }
}

impl fmt::Debug for UnixDatagram {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.io.get_ref().fmt(f)
    }
}

impl AsRawFd for UnixDatagram {
    fn as_raw_fd(&self) -> RawFd {
        self.io.get_ref().as_raw_fd()
    }
}
<|endoftext|>


<commit_before>extern crate elf;
extern crate getopts;

use getopts::Options;
use std::cmp;
use std::env;
use std::fs::File;
use std::io;
use std::io::Write;
use std::mem;
use std::path::Path;
use std::slice;

#[repr(C)]
#[derive(Clone, Copy, Debug)]
struct LoadInfo {
    total_size: u32,
    entry_offset: u32,
    rel_data_offset: u32,
    rel_data_size: u32,
    text_offset: u32,
    text_size: u32,
    got_offset: u32,
    got_size: u32,
    data_offset: u32,
    data_size: u32,
    bss_start_offset: u32,
    bss_size: u32,
    pkg_name_offset: u32,
    pkg_name_size: u32,
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optopt("o", "", "set output file name", "OUTFILE");
    opts.optopt("n", "", "set package name", "PKG_NAME");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string()),
    };
    let output = matches.opt_str("o");
    let pkg_name = matches.opt_str("n");
    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts);
        return;
    };

    let path = Path::new(&input);
    let file = match elf::File::open_path(&path) {
        Ok(f) => f,
        Err(e) => panic!("Error: {:?}", e),
    };

    match output {
            None => {
                let mut out = io::stdout();
                do_work(&file, &mut out, pkg_name)
            }
            Some(name) => {
                match File::create(Path::new(&name)) {
                    Ok(mut f) => do_work(&file, &mut f, pkg_name),
                    Err(e) => panic!("Error: {:?}", e),
                }
            }
        }
        .expect("Failed to write output");
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [-o OUTFILE] FILE", program);
    print!("{}", opts.usage(&brief));
}

fn get_section<'a>(input: &'a elf::File, name: &str) -> elf::Section {
    match input.get_section(name) {
        Some(section) => {
            elf::Section {
                data: section.data.clone(),
                shdr: section.shdr.clone(),
            }
        }
        None => {
            elf::Section {
                data: Vec::new(),
                shdr: elf::types::SectionHeader {
                    name: String::from(name),
                    shtype: elf::types::SHT_NULL,
                    flags: elf::types::SHF_NONE,
                    addr: 0,
                    offset: 0,
                    size: 0,
                    link: 0,
                    info: 0,
                    addralign: 0,
                    entsize: 0,
                },
            }
        }
    }
}

unsafe fn as_byte_slice<'a, T: Copy>(input: &'a T) -> &'a [u8] {
    slice::from_raw_parts(input as *const T as *const u8, mem::size_of::<T>())
}

fn do_work(input: &elf::File, output: &mut Write, pkg_name: Option<String>) -> io::Result<()> {
    let pkg_name = pkg_name.unwrap_or(String::new());
    let (rel_data_size, rel_data) = match input.sections
        .iter()
        .find(|section| section.shdr.name == ".rel.data".as_ref()) {
        Some(section) => (section.shdr.size, section.data.as_ref()),
        None => (0 as u64, &[] as &[u8]),

    };
    let text = get_section(input, ".text");
    let got = get_section(input, ".got");
    let data = get_section(input, ".data");
    let bss = get_section(input, ".bss");

    let mut total_len = (mem::size_of::<LoadInfo>() + rel_data.len() + text.data.len() +
                         got.data.len() + data.data.len() +
                         pkg_name.len()) as u32;

    let pad = if total_len.count_ones() > 1 {
        let power2len = 1 << (32 - total_len.leading_zeros());
        power2len - total_len
    } else {
        0
    };
    total_len = total_len + pad;

    let rel_data_offset = mem::size_of::<LoadInfo>() as u32;
    let text_offset = rel_data_offset + (rel_data_size as u32);
    let text_size = text.shdr.size as u32;
    let entry_offset = (input.ehdr.entry ^ 0x80000000) as u32 + text_offset;
    let got_offset = text_offset + text_size;
    let got_size = got.shdr.size as u32;
    let data_offset = got_offset + got_size;
    let data_size = data.shdr.size as u32;
    let pkg_name_offset = data_offset + data_size;
    let pkg_name_size = pkg_name.len() as u32;

    let load_info = LoadInfo {
        total_size: total_len,
        entry_offset: entry_offset,
        rel_data_offset: rel_data_offset,
        rel_data_size: rel_data_size as u32,
        text_offset: text_offset,
        text_size: text_size,
        got_offset: got_offset,
        got_size: got_size,
        data_offset: data_offset,
        data_size: data_size,
        bss_start_offset: bss.shdr.addr as u32,
        bss_size: bss.shdr.size as u32,
        pkg_name_offset: pkg_name_offset,
        pkg_name_size: pkg_name_size,
    };

    try!(output.write_all(unsafe { as_byte_slice(&load_info) }));
    try!(output.write_all(rel_data.as_ref()));
    try!(output.write_all(text.data.as_ref()));
    try!(output.write_all(got.data.as_ref()));
    try!(output.write_all(data.data.as_ref()));
    try!(output.write_all(pkg_name.as_ref()));

    let mut pad = pad as usize;
    let zero_buf = [0u8; 512];
    while pad > 0 {
        let amount_to_write = cmp::min(zero_buf.len(), pad);
        pad -= try!(output.write(&zero_buf[..amount_to_write]));
    }

    Ok(())
}
<commit_msg>Rename bss_start_offset to bss_mem_offset<commit_after>extern crate elf;
extern crate getopts;

use getopts::Options;
use std::cmp;
use std::env;
use std::fs::File;
use std::io;
use std::io::Write;
use std::mem;
use std::path::Path;
use std::slice;

#[repr(C)]
#[derive(Clone, Copy, Debug)]
struct LoadInfo {
    total_size: u32,
    entry_offset: u32,
    rel_data_offset: u32,
    rel_data_size: u32,
    text_offset: u32,
    text_size: u32,
    got_offset: u32,
    got_size: u32,
    data_offset: u32,
    data_size: u32,
    bss_mem_offset: u32,
    bss_size: u32,
    pkg_name_offset: u32,
    pkg_name_size: u32,
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optopt("o", "", "set output file name", "OUTFILE");
    opts.optopt("n", "", "set package name", "PKG_NAME");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string()),
    };
    let output = matches.opt_str("o");
    let pkg_name = matches.opt_str("n");
    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts);
        return;
    };

    let path = Path::new(&input);
    let file = match elf::File::open_path(&path) {
        Ok(f) => f,
        Err(e) => panic!("Error: {:?}", e),
    };

    match output {
            None => {
                let mut out = io::stdout();
                do_work(&file, &mut out, pkg_name)
            }
            Some(name) => {
                match File::create(Path::new(&name)) {
                    Ok(mut f) => do_work(&file, &mut f, pkg_name),
                    Err(e) => panic!("Error: {:?}", e),
                }
            }
        }
        .expect("Failed to write output");
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [-o OUTFILE] FILE", program);
    print!("{}", opts.usage(&brief));
}

fn get_section<'a>(input: &'a elf::File, name: &str) -> elf::Section {
    match input.get_section(name) {
        Some(section) => {
            elf::Section {
                data: section.data.clone(),
                shdr: section.shdr.clone(),
            }
        }
        None => {
            elf::Section {
                data: Vec::new(),
                shdr: elf::types::SectionHeader {
                    name: String::from(name),
                    shtype: elf::types::SHT_NULL,
                    flags: elf::types::SHF_NONE,
                    addr: 0,
                    offset: 0,
                    size: 0,
                    link: 0,
                    info: 0,
                    addralign: 0,
                    entsize: 0,
                },
            }
        }
    }
}

unsafe fn as_byte_slice<'a, T: Copy>(input: &'a T) -> &'a [u8] {
    slice::from_raw_parts(input as *const T as *const u8, mem::size_of::<T>())
}

fn do_work(input: &elf::File, output: &mut Write, pkg_name: Option<String>) -> io::Result<()> {
    let pkg_name = pkg_name.unwrap_or(String::new());
    let (rel_data_size, rel_data) = match input.sections
        .iter()
        .find(|section| section.shdr.name == ".rel.data".as_ref()) {
        Some(section) => (section.shdr.size, section.data.as_ref()),
        None => (0 as u64, &[] as &[u8]),

    };
    let text = get_section(input, ".text");
    let got = get_section(input, ".got");
    let data = get_section(input, ".data");
    let bss = get_section(input, ".bss");

    let mut total_len = (mem::size_of::<LoadInfo>() + rel_data.len() + text.data.len() +
                         got.data.len() + data.data.len() +
                         pkg_name.len()) as u32;

    let pad = if total_len.count_ones() > 1 {
        let power2len = 1 << (32 - total_len.leading_zeros());
        power2len - total_len
    } else {
        0
    };
    total_len = total_len + pad;

    let rel_data_offset = mem::size_of::<LoadInfo>() as u32;
    let text_offset = rel_data_offset + (rel_data_size as u32);
    let text_size = text.shdr.size as u32;
    let entry_offset = (input.ehdr.entry ^ 0x80000000) as u32 + text_offset;
    let got_offset = text_offset + text_size;
    let got_size = got.shdr.size as u32;
    let data_offset = got_offset + got_size;
    let data_size = data.shdr.size as u32;
    let pkg_name_offset = data_offset + data_size;
    let pkg_name_size = pkg_name.len() as u32;

    let load_info = LoadInfo {
        total_size: total_len,
        entry_offset: entry_offset,
        rel_data_offset: rel_data_offset,
        rel_data_size: rel_data_size as u32,
        text_offset: text_offset,
        text_size: text_size,
        got_offset: got_offset,
        got_size: got_size,
        data_offset: data_offset,
        data_size: data_size,
        bss_mem_offset: bss.shdr.addr as u32,
        bss_size: bss.shdr.size as u32,
        pkg_name_offset: pkg_name_offset,
        pkg_name_size: pkg_name_size,
    };

    try!(output.write_all(unsafe { as_byte_slice(&load_info) }));
    try!(output.write_all(rel_data.as_ref()));
    try!(output.write_all(text.data.as_ref()));
    try!(output.write_all(got.data.as_ref()));
    try!(output.write_all(data.data.as_ref()));
    try!(output.write_all(pkg_name.as_ref()));

    let mut pad = pad as usize;
    let zero_buf = [0u8; 512];
    while pad > 0 {
        let amount_to_write = cmp::min(zero_buf.len(), pad);
        pad -= try!(output.write(&zero_buf[..amount_to_write]));
    }

    Ok(())
}
<|endoftext|>


<commit_before>pub fn dirt() -> String {
  struct Wave {
    freq: f32,
    amp: f32,
  }

  let mut waves = Vec::new();
  for i in 0..10 {
    waves.push(
      Wave { freq:  ((1 << i) as f32) / 128.0, amp: 1.0 / (1 << i) as f32 }
    );
  }

  let mut contents = String::new();
  for wave in waves.iter() {
    contents.push_str(format!(r#"
    {{
      float freq = {};
      float amp = {};

      float dnoise = abs(cnoise(freq * world_position));
      noise += dnoise * amp;
      total_amp += amp;
    }}
    "#, wave.freq, wave.amp).as_str());
  }

  format!(r#"
  float total_amp = 0.0;
  float noise = 0.0;
  {}
  noise /= total_amp;
  return mix(vec3(0.4, 0.3, 0.1), vec3(0.7, 0.6, 0.4), noise);
  "#, contents)
}
<commit_msg>rescale dirt shader<commit_after>pub fn dirt() -> String {
  struct Wave {
    freq: f32,
    amp: f32,
  }

  let mut waves = Vec::new();
  for i in 0..10 {
    waves.push(
      Wave { freq:  ((1 << i) as f32) / 4.0, amp: 1.0 / (1 << i) as f32 }
    );
  }

  let mut contents = String::new();
  for wave in waves.iter() {
    contents.push_str(format!(r#"
    {{
      float freq = {};
      float amp = {};

      float dnoise = abs(cnoise(freq * world_position));
      noise += dnoise * amp;
      total_amp += amp;
    }}
    "#, wave.freq, wave.amp).as_str());
  }

  format!(r#"
  float total_amp = 0.0;
  float noise = 0.0;
  {}
  noise /= total_amp;
  return mix(vec3(0.4, 0.3, 0.1), vec3(0.7, 0.6, 0.4), noise);
  "#, contents)
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]
extern crate string_telephone;

use string_telephone::{ConnectionConfig, ClientConnectionConfig, Client, Packet, PollEmpty};

use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::io::net::udp::UdpSocket;
use std::io::Timer;
use std::time::duration::Duration;

fn deserializer(message: &Vec<u8>) -> Option<Vec<u8>> {
    Some(message.clone())
}

fn serializer(packet: &Vec<u8>) -> Vec<u8> {
    packet.clone()
}

fn generate_settings(port: u16, protocol_id: u32) -> (SocketAddr, SocketAddr, ConnectionConfig<Vec<u8>>, ClientConnectionConfig) {
    let my_addr = SocketAddr{ ip: Ipv4Addr(0, 0, 0, 0), port: 0 };
    let target_addr = SocketAddr{ ip: Ipv4Addr(127, 0, 0, 1), port: port };
    let settings = ConnectionConfig::new(protocol_id, 10, deserializer, serializer);
    let client_settings = ClientConnectionConfig::new(1, Duration::seconds(1));
    (my_addr, target_addr, settings, client_settings)
}

fn get_message(socket: &mut UdpSocket) -> (Vec<u8>, SocketAddr) {
    let mut buf = [0, ..255];
    match socket.recv_from(buf) {
        Ok((amt, src)) => (buf.slice_to(amt).to_owned(), src),
        Err(e) => fail!("Socket didn't get a message")
    }
}

macro_rules! with_bound_socket(
    ($socket:ident, ($variable:ident)$code:block) => (
        spawn(proc() {
            match UdpSocket::bind($socket) {
                Ok(mut $variable) => $code,
                Err(e) => fail!(e)
            }
        });
    )
)

/**
 * Test when there isn't a backend to connect to
 * Connect should return an IOResult stating we can't get there
 */
#[test]
fn connection_ignored() {
    let port = 65000;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(_) => fail!("Reported connected when there is no server!"),
        Err(e) => {
            assert!(e.desc == "Failed to connect")
        }
    };
}

/**
 * Test a normal connection where the backend replies with an accept
 */
#[test]
fn standard_connection() {
    let port = 65001;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(1000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(121).serialize().unwrap()[], src);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(client) => {
            //Success!
        },
        Err(e) => fail!(e)
    };
}

/**
 * If the server gives us back a different protocol id, we shouldn't accept it
 */
#[test]
fn connection_different_protocol_id() {
    let port = 65002;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(1000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(122).serialize().unwrap()[], src);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(_) => fail!("Connected to a server with a different protocol ID!"),
        Err(e) => {
            assert!(e.desc == "Failed to connect")
        }
    };
}

/**
 * If the server specifically rejects us, we should give up
 */
#[test]
fn connection_rejected() {
    let port = 65003;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(1000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::reject(121).serialize().unwrap()[], src);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(_) => fail!("Connected to a server that rejected us!"),
        Err(e) => {
            assert!(e.desc == "Failed to connect")
        }
    };
}

/**
 * We should be able to specify how many retries we want
 */
#[test]
fn different_retry_count() {
    let port = 65004;
    let (my_addr, target_addr, settings, mut client_settings) = generate_settings(port, 121);
    client_settings.max_connect_retries = 3;

    let (tx, rx) = channel();
    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(10000));
        let mut attempts = 0u8;
        while attempts < 3 {
            get_message(&mut socket);
            attempts += 1;
        }

        tx.send(attempts);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(_) => (),
        Err(_) => ()
    };

    assert!(rx.recv() == 3);
}

//TODO: Find a sensible way of testing timeout lengths

/**
 * We should instantly return when polling and there's no data available
 */
#[test]
fn empty_polling() {
    let port = 65005;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(1000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(121).serialize().unwrap()[], src);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(ref mut client) => {
            assert!(match client.poll() { Err(PollEmpty) => true, _ => false});
        },
        Err(e) => fail!(e)
    };
}

/**
 * We should return an item if there's one there
 */
#[test]
fn single_item_polling() {
    let port = 65006;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(10000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(121).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
        socket.send_to(Packet::message(121, vec![1]).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(ref mut client) => {
            //May have to wait a bit
            //FIXME: There must be a better way of doing this
            Timer::new().unwrap().sleep(Duration::seconds(1));
            match client.poll() {
                Ok(packet) => {
                    assert!(packet == vec![1]);
                },
                Err(e) => fail!("Couldn't match a polled message! - {}", e)
            };
        },
        Err(e) => fail!(e)
    };
}

/**
 * We should be able to pump multiple items
 */
#[test]
fn multiple_item_polling() {
    let port = 65007;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(10000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(121).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
        socket.send_to(Packet::message(121, vec![1]).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
        socket.send_to(Packet::message(121, vec![2]).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
        socket.send_to(Packet::message(121, vec![3]).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
    });

    let mut packets: Vec<Vec<u8>> = vec![];

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(ref mut client) => {
            //FIXME: There must be a better way of doing this
            Timer::new().unwrap().sleep(Duration::seconds(1));
            loop {
                match client.poll() {
                    Ok(packet) => packets.push(packet),
                    Err(PollEmpty) => break,
                    Err(e) => fail!("Unexpected failure - {}", e)
                };
            }
        },
        Err(e) => fail!("{}", e)
    };

    assert!(packets.len() == 3);
    assert!(packets[0] == vec![1]);
    assert!(packets[1] == vec![2]);
    assert!(packets[2] == vec![3]);
}

/**
 * Messages not intended for us shouldn't be forwarded to us
 */
#[test]
fn ignore_bad_queue_items_polling() {
    let port = 65008;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(10000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(121).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
        socket.send_to(Packet::message(121, vec![1]).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
        socket.send_to(Packet::message(122, vec![2]).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
        socket.send_to(Packet::message(121, vec![3]).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
    });

    let mut packets: Vec<Vec<u8>> = vec![];

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(ref mut client) => {
            //FIXME: There must be a better way of doing this
            Timer::new().unwrap().sleep(Duration::seconds(1));
            loop {
                match client.poll() {
                    Ok(packet) => packets.push(packet),
                    Err(PollEmpty) => break,
                    Err(e) => fail!("Unexpected failure - {}", e)
                };
            }
        },
        Err(e) => fail!("{}", e)
    };

    assert!(packets.len() == 2);
    assert!(packets[0] == vec![1]);
    assert!(packets[1] == vec![3]);
}

/**
 * If the other end tells us to hang up, we better listen
 */
#[test]
fn disconnection() {
    let port = 65008;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(10000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(121).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
        socket.send_to(Packet::disconnect(121).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(ref mut client) => {
            //FIXME: There must be a better way of doing this
            Timer::new().unwrap().sleep(Duration::seconds(1));
            loop {
                match client.poll() {
                    Err(Disconnected) => break,
                    _ => fail!("Unexpected failure")
                };
            }
        },
        Err(e) => fail!("{}", e)
    };
}

/**
 * If the remote end doesn't reply in time, we should time out and disconnect
 */
#[test]
fn timeout() {
    let port = 65009;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(10000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(121).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
        //Don't send any more data
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(ref mut client) => {
            //FIXME: There must be a better way of doing this
            Timer::new().unwrap().sleep(Duration::seconds(1));
            loop {
                match client.poll() {
                    Err(Disconnected) => break,
                    _ => fail!("Unexpected failure")
                };
            }
        },
        Err(e) => fail!("{}", e)
    };
}

/**
 * When trying to connect, we should send a connect request message
 */
#[test]
fn send_correct_handshake() {
    unimplemented!();
}

/**
 * We should be able to send data that can be read by the server
 */
#[test]
fn send_data() {
    unimplemented!();
}

/**
 * We should be able to tell the server when we're done
 */
#[test]
fn client_disconnect() {
    unimplemented!();
}
<commit_msg>Switching to longer connection attempts in an attempt to make things a bit less fragile<commit_after>#![feature(macro_rules)]
extern crate string_telephone;

use string_telephone::{ConnectionConfig, ClientConnectionConfig, Client, Packet, PollEmpty};

use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::io::net::udp::UdpSocket;
use std::io::Timer;
use std::time::duration::Duration;

fn deserializer(message: &Vec<u8>) -> Option<Vec<u8>> {
    Some(message.clone())
}

fn serializer(packet: &Vec<u8>) -> Vec<u8> {
    packet.clone()
}

fn generate_settings(port: u16, protocol_id: u32) -> (SocketAddr, SocketAddr, ConnectionConfig<Vec<u8>>, ClientConnectionConfig) {
    let my_addr = SocketAddr{ ip: Ipv4Addr(0, 0, 0, 0), port: 0 };
    let target_addr = SocketAddr{ ip: Ipv4Addr(127, 0, 0, 1), port: port };
    let settings = ConnectionConfig::new(protocol_id, 10, deserializer, serializer);
    let client_settings = ClientConnectionConfig::new(3, Duration::seconds(2));
    (my_addr, target_addr, settings, client_settings)
}

fn get_message(socket: &mut UdpSocket) -> (Vec<u8>, SocketAddr) {
    let mut buf = [0, ..255];
    match socket.recv_from(buf) {
        Ok((amt, src)) => (buf.slice_to(amt).to_owned(), src),
        Err(e) => fail!("Socket didn't get a message")
    }
}

macro_rules! with_bound_socket(
    ($socket:ident, ($variable:ident)$code:block) => (
        spawn(proc() {
            match UdpSocket::bind($socket) {
                Ok(mut $variable) => $code,
                Err(e) => fail!(e)
            }
        });
    )
)

/**
 * Test when there isn't a backend to connect to
 * Connect should return an IOResult stating we can't get there
 */
#[test]
fn connection_ignored() {
    let port = 65000;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(_) => fail!("Reported connected when there is no server!"),
        Err(e) => {
            assert!(e.desc == "Failed to connect")
        }
    };
}

/**
 * Test a normal connection where the backend replies with an accept
 */
#[test]
fn standard_connection() {
    let port = 65001;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(1000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(121).serialize().unwrap()[], src);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(client) => {
            //Success!
        },
        Err(e) => fail!(e)
    };
}

/**
 * If the server gives us back a different protocol id, we shouldn't accept it
 */
#[test]
fn connection_different_protocol_id() {
    let port = 65002;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(1000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(122).serialize().unwrap()[], src);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(_) => fail!("Connected to a server with a different protocol ID!"),
        Err(e) => {
            assert!(e.desc == "Failed to connect")
        }
    };
}

/**
 * If the server specifically rejects us, we should give up
 */
#[test]
fn connection_rejected() {
    let port = 65003;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(1000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::reject(121).serialize().unwrap()[], src);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(_) => fail!("Connected to a server that rejected us!"),
        Err(e) => {
            assert!(e.desc == "Failed to connect")
        }
    };
}

/**
 * We should be able to specify how many retries we want
 */
#[test]
fn different_retry_count() {
    let port = 65004;
    let (my_addr, target_addr, settings, mut client_settings) = generate_settings(port, 121);
    client_settings.max_connect_retries = 6;
    client_settings.connect_attempt_timeout = Duration::milliseconds(100);

    let (tx, rx) = channel();
    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(10000));
        let mut attempts = 0u8;
        while attempts < 3 {
            get_message(&mut socket);
            attempts += 1;
        }

        tx.send(attempts);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(_) => (),
        Err(_) => ()
    };

    assert!(rx.recv() == 3);
}

//TODO: Find a sensible way of testing timeout lengths

/**
 * We should instantly return when polling and there's no data available
 */
#[test]
fn empty_polling() {
    let port = 65005;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(1000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(121).serialize().unwrap()[], src);
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(ref mut client) => {
            assert!(match client.poll() { Err(PollEmpty) => true, _ => false});
        },
        Err(e) => fail!(e)
    };
}

/**
 * We should return an item if there's one there
 */
#[test]
fn single_item_polling() {
    let port = 65006;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(10000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(121).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
        socket.send_to(Packet::message(121, vec![1]).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(ref mut client) => {
            //May have to wait a bit
            //FIXME: There must be a better way of doing this
            Timer::new().unwrap().sleep(Duration::seconds(1));
            match client.poll() {
                Ok(packet) => {
                    assert!(packet == vec![1]);
                },
                Err(e) => fail!("Couldn't match a polled message! - {}", e)
            };
        },
        Err(e) => fail!(e)
    };
}

/**
 * We should be able to pump multiple items
 */
#[test]
fn multiple_item_polling() {
    let port = 65007;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(10000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(121).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
        socket.send_to(Packet::message(121, vec![1]).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
        socket.send_to(Packet::message(121, vec![2]).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
        socket.send_to(Packet::message(121, vec![3]).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
    });

    let mut packets: Vec<Vec<u8>> = vec![];

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(ref mut client) => {
            //FIXME: There must be a better way of doing this
            Timer::new().unwrap().sleep(Duration::seconds(1));
            loop {
                match client.poll() {
                    Ok(packet) => packets.push(packet),
                    Err(PollEmpty) => break,
                    Err(e) => fail!("Unexpected failure - {}", e)
                };
            }
        },
        Err(e) => fail!("{}", e)
    };

    assert!(packets.len() == 3);
    assert!(packets[0] == vec![1]);
    assert!(packets[1] == vec![2]);
    assert!(packets[2] == vec![3]);
}

/**
 * Messages not intended for us shouldn't be forwarded to us
 */
#[test]
fn ignore_bad_queue_items_polling() {
    let port = 65008;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(10000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(121).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
        socket.send_to(Packet::message(121, vec![1]).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
        socket.send_to(Packet::message(122, vec![2]).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
        socket.send_to(Packet::message(121, vec![3]).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
    });

    let mut packets: Vec<Vec<u8>> = vec![];

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(ref mut client) => {
            //FIXME: There must be a better way of doing this
            Timer::new().unwrap().sleep(Duration::seconds(1));
            loop {
                match client.poll() {
                    Ok(packet) => packets.push(packet),
                    Err(PollEmpty) => break,
                    Err(e) => fail!("Unexpected failure - {}", e)
                };
            }
        },
        Err(e) => fail!("{}", e)
    };

    assert!(packets.len() == 2);
    assert!(packets[0] == vec![1]);
    assert!(packets[1] == vec![3]);
}

/**
 * If the other end tells us to hang up, we better listen
 */
#[test]
fn disconnection() {
    let port = 65008;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(10000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(121).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
        socket.send_to(Packet::disconnect(121).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(ref mut client) => {
            //FIXME: There must be a better way of doing this
            Timer::new().unwrap().sleep(Duration::seconds(1));
            loop {
                match client.poll() {
                    Err(Disconnected) => break,
                    _ => fail!("Unexpected failure")
                };
            }
        },
        Err(e) => fail!("{}", e)
    };
}

/**
 * If the remote end doesn't reply in time, we should time out and disconnect
 */
#[test]
fn timeout() {
    let port = 65009;
    let (my_addr, target_addr, settings, client_settings) = generate_settings(port, 121);

    with_bound_socket!(target_addr, (socket) {
        socket.set_timeout(Some(10000));
        let (_, src) = get_message(&mut socket);
        socket.send_to(Packet::accept(121).serialize().unwrap()[], src).ok().expect("Couldn't send a message");
        //Don't send any more data
    });

    match Client::connect(my_addr, target_addr, settings, client_settings) {
        Ok(ref mut client) => {
            //FIXME: There must be a better way of doing this
            Timer::new().unwrap().sleep(Duration::seconds(1));
            loop {
                match client.poll() {
                    Err(Disconnected) => break,
                    _ => fail!("Unexpected failure")
                };
            }
        },
        Err(e) => fail!("{}", e)
    };
}

/**
 * When trying to connect, we should send a connect request message
 */
#[test]
fn send_correct_handshake() {
    unimplemented!();
}

/**
 * We should be able to send data that can be read by the server
 */
#[test]
fn send_data() {
    unimplemented!();
}

/**
 * We should be able to tell the server when we're done
 */
#[test]
fn client_disconnect() {
    unimplemented!();
}
<|endoftext|>


<commit_before>//! A LinkedList that lets you insert elements from the front or the end of the list.
//! TODO: Add the ability to insert in-between a Node.
//! Lots of thanks to reem and Sharp for help with this from the #rust channel

use std::mem;

/// A Node is the basic unit in a LinkedList which stores the payload of type T.
#[derive(Debug,PartialEq)]
struct Node<T> {
    /// The payload of type T that is wrapped aorund a Node.
    pub payload: T,
    /// An Option of a boxed Node<T> that would point to the next Node<T>.
    next: Option<Box<Node<T>>>,
    /// An Option of a boxed Node<T> that would point to the previous Node<T>.
    prev: Option<Box<Node<T>>>,
}

impl<T> Node<T> {

    pub fn new(payload: T) -> Node<T> {
        //! Creates a instance of a `Node` with `next` and `prev` point to a Option::Node.
        Node::<T> {
            payload: payload,
            next: None,
            prev: None,
        }
    }

    pub fn payload(&mut self) -> Option<&T> {
        //! Access to a payload of Node.
        Some(&self.payload)
    }

    pub fn insert_after(&mut self, mut new: Box<Node<T>>) -> Option<Box<Node<T>>> {
        //! Takes a new boxed Node<T> and swaps it with any existing Node after the current one.
        //! We replace any Option::None or Option::Some with a new Option<Box<Node<T>>>
        mem::swap(&mut new.next, &mut self.next);
        mem::replace(&mut self.next, Some(new))
    }

    pub fn insert_before(&mut self, mut new: Box<Node<T>>) -> Option<Box<Node<T>>> {
        //! Takes a new boxed Node<T> and swaps it with any existing Node after the current one.
        //! We replace any Option::None or Option::Some with a new Option<Box<Node<T>>>
        mem::swap(&mut new.prev, &mut self.prev);
        mem::replace(&mut self.prev, Some(new))
    }

    /*pub fn remove_after(&mut self) -> Option<Box<Node<T>>> {
        //! Removes the Node after the current node.
        match self.next.take() {
            Some(mut next)  => {
                mem::swap(&mut self.next, &mut next.next);
                Some(next)
            },
            None => None,
        }
    }*/

    pub fn remove_before(&mut self) -> Option<Box<Node<T>>> {
        //! Removes the Node before the current node.
        match self.prev.take() {
            Some(mut prev)  => {
                mem::swap(&mut self.prev, &mut prev.prev);
                Some(prev)
            },
            None => None,
        }
    }

    pub fn next(&mut self) -> Option<&mut T> {
        //! Goes to the next Node and returns an Option to it.
        let Node {
            ref mut payload,
            ref mut prev,
            ref mut next,
        } = *self;

        match *next {
            Some(ref mut next) => {
                mem::swap(&mut next.payload, payload);

                let mut next = &mut **next;     // Cannot completely understand this bit yet.
                mem::swap(&mut next.next, &mut next.prev);

                mem::swap(&mut next.prev, prev);
            },
            None    => return None,
        }
        mem::swap(prev, next);
        Some(payload)
    }
}

/// A LinkedList is the struct that you would need to use to create a list of elements.
/// It contains a pointer to the first and last node in the list represented as `head and `tail`
/// respectively.
pub struct LinkedList<T> {
    /// First element in the list.
    head: Option<Box<Node<T>>>,
    /// Last element in the list.
    tail: Option<Box<Node<T>>>,
}

impl<T> LinkedList<T> {
    pub fn new() -> LinkedList<T> {
        //! Create a new LinkedList to contain a payloads with type T.
        LinkedList::<T> {
            head: None,
            tail: None,
        }
    }
}

#[test]
fn node_new() {
    let expected = Node {
        payload: "test",
        next: None,
        prev: None,
    };

    let node: Node<&str> = Node::new("test");

    assert_eq!(expected.payload,  node.payload);
    assert_eq!(expected.next,     node.next);
    assert_eq!(expected.prev,     node.prev);
}

#[test]
fn node_payload() {
    let node: Node<&str> = Node::new("test");
    assert_eq!(&"test", node.payload().unwrap());
}

#[test]
fn node_insert_after() {
    let mut node: Node<&str> = Node::new("one");
    node.insert_after(Box::new(Node::new("two")));
    assert_eq!("two", node.next.unwrap().payload);

}

#[test]
fn node_insert_before() {
    let mut node: Node<&str> = Node::new("two");
    node.insert_before(Box::new(Node::new("one")));
    assert_eq!("one", node.prev.unwrap().payload);
}

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

}
<commit_msg>Fixed payload back to &self<commit_after>//! A LinkedList that lets you insert elements from the front or the end of the list.
//! TODO: Add the ability to insert in-between a Node.
//! Lots of thanks to reem and Sharp for help with this from the #rust channel

use std::mem;

/// A Node is the basic unit in a LinkedList which stores the payload of type T.
#[derive(Debug,PartialEq)]
struct Node<T> {
    /// The payload of type T that is wrapped aorund a Node.
    pub payload: T,
    /// An Option of a boxed Node<T> that would point to the next Node<T>.
    next: Option<Box<Node<T>>>,
    /// An Option of a boxed Node<T> that would point to the previous Node<T>.
    prev: Option<Box<Node<T>>>,
}

impl<T> Node<T> {

    pub fn new(payload: T) -> Node<T> {
        //! Creates a instance of a `Node` with `next` and `prev` point to a Option::Node.
        Node::<T> {
            payload: payload,
            next: None,
            prev: None,
        }
    }

    pub fn payload(&self) -> Option<&T> {
        //! Access to a payload of Node.
        Some(&self.payload)
    }

    pub fn insert_after(&mut self, mut new: Box<Node<T>>) -> Option<Box<Node<T>>> {
        //! Takes a new boxed Node<T> and swaps it with any existing Node after the current one.
        //! We replace any Option::None or Option::Some with a new Option<Box<Node<T>>>
        mem::swap(&mut new.next, &mut self.next);
        mem::replace(&mut self.next, Some(new))
    }

    pub fn insert_before(&mut self, mut new: Box<Node<T>>) -> Option<Box<Node<T>>> {
        //! Takes a new boxed Node<T> and swaps it with any existing Node after the current one.
        //! We replace any Option::None or Option::Some with a new Option<Box<Node<T>>>
        mem::swap(&mut new.prev, &mut self.prev);
        mem::replace(&mut self.prev, Some(new))
    }

    /*pub fn remove_after(&mut self) -> Option<Box<Node<T>>> {
        //! Removes the Node after the current node.
        match self.next.take() {
            Some(mut next)  => {
                mem::swap(&mut self.next, &mut next.next);
                Some(next)
            },
            None => None,
        }
    }*/

    pub fn remove_before(&mut self) -> Option<Box<Node<T>>> {
        //! Removes the Node before the current node.
        match self.prev.take() {
            Some(mut prev)  => {
                mem::swap(&mut self.prev, &mut prev.prev);
                Some(prev)
            },
            None => None,
        }
    }

    pub fn next(&mut self) -> Option<&mut T> {
        //! Goes to the next Node and returns an Option to it.
        let Node {
            ref mut payload,
            ref mut prev,
            ref mut next,
        } = *self;

        match *next {
            Some(ref mut next) => {
                mem::swap(&mut next.payload, payload);

                let mut next = &mut **next;     // Cannot completely understand this bit yet.
                mem::swap(&mut next.next, &mut next.prev);

                mem::swap(&mut next.prev, prev);
            },
            None    => return None,
        }
        mem::swap(prev, next);
        Some(payload)
    }
}

/// A LinkedList is the struct that you would need to use to create a list of elements.
/// It contains a pointer to the first and last node in the list represented as `head and `tail`
/// respectively.
pub struct LinkedList<T> {
    /// First element in the list.
    head: Option<Box<Node<T>>>,
    /// Last element in the list.
    tail: Option<Box<Node<T>>>,
}

impl<T> LinkedList<T> {
    pub fn new() -> LinkedList<T> {
        //! Create a new LinkedList to contain a payloads with type T.
        LinkedList::<T> {
            head: None,
            tail: None,
        }
    }
}

#[test]
fn node_new() {
    let expected = Node {
        payload: "test",
        next: None,
        prev: None,
    };

    let node: Node<&str> = Node::new("test");

    assert_eq!(expected.payload,  node.payload);
    assert_eq!(expected.next,     node.next);
    assert_eq!(expected.prev,     node.prev);
}

#[test]
fn node_payload() {
    let node: Node<&str> = Node::new("test");
    assert_eq!(&"test", node.payload().unwrap());
}

#[test]
fn node_insert_after() {
    let mut node: Node<&str> = Node::new("one");
    node.insert_after(Box::new(Node::new("two")));
    assert_eq!("two", node.next.unwrap().payload);

}

#[test]
fn node_insert_before() {
    let mut node: Node<&str> = Node::new("two");
    node.insert_before(Box::new(Node::new("one")));
    assert_eq!("one", node.prev.unwrap().payload);
}

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

}
<|endoftext|>


<commit_before>use rustc::hir::intravisit as visit;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::middle::expr_use_visitor::*;
use rustc::middle::mem_categorization::{cmt_, Categorization};
use rustc::ty::layout::LayoutOf;
use rustc::ty::{self, Ty};
use rustc::util::nodemap::HirIdSet;
use rustc::{declare_tool_lint, lint_array};
use syntax::source_map::Span;

use crate::utils::span_lint;

pub struct Pass {
    pub too_large_for_stack: u64,
}

declare_clippy_lint! {
    /// **What it does:** Checks for usage of `Box<T>` where an unboxed `T` would
    /// work fine.
    ///
    /// **Why is this bad?** This is an unnecessary allocation, and bad for
    /// performance. It is only necessary to allocate if you wish to move the box
    /// into something.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// fn main() {
    ///     let x = Box::new(1);
    ///     foo(*x);
    ///     println!("{}", *x);
    /// }
    /// ```
    pub BOXED_LOCAL,
    perf,
    "using `Box<T>` where unnecessary"
}

fn is_non_trait_box(ty: Ty<'_>) -> bool {
    ty.is_box() && !ty.boxed_ty().is_trait()
}

struct EscapeDelegate<'a, 'tcx: 'a> {
    cx: &'a LateContext<'a, 'tcx>,
    set: HirIdSet,
    too_large_for_stack: u64,
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(BOXED_LOCAL)
    }

    fn name(&self) -> &'static str {
        "BoxedLocal"
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
    fn check_fn(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        _: visit::FnKind<'tcx>,
        _: &'tcx FnDecl,
        body: &'tcx Body,
        _: Span,
        hir_id: HirId,
    ) {
        // If the method is an impl for a trait, don't warn.
        let parent_id = cx.tcx.hir().get_parent_item(hir_id);
        let parent_node = cx.tcx.hir().find_by_hir_id(parent_id);

        if let Some(Node::Item(item)) = parent_node {
            if let ItemKind::Impl(_, _, _, _, Some(..), _, _) = item.node {
                return;
            }
        }

        let mut v = EscapeDelegate {
            cx,
            set: HirIdSet::default(),
            too_large_for_stack: self.too_large_for_stack,
        };

        let fn_def_id = cx.tcx.hir().local_def_id_from_hir_id(hir_id);
        let region_scope_tree = &cx.tcx.region_scope_tree(fn_def_id);
        ExprUseVisitor::new(&mut v, cx.tcx, cx.param_env, region_scope_tree, cx.tables, None).consume_body(body);

        for node in v.set {
            span_lint(
                cx,
                BOXED_LOCAL,
                cx.tcx.hir().span_by_hir_id(node),
                "local variable doesn't need to be boxed here",
            );
        }
    }
}

impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
    fn consume(&mut self, _: HirId, _: Span, cmt: &cmt_<'tcx>, mode: ConsumeMode) {
        if let Categorization::Local(lid) = cmt.cat {
            if let Move(DirectRefMove) = mode {
                // Moved out or in. Clearly can't be localized.
                self.set.remove(&lid);
            }
        }
    }
    fn matched_pat(&mut self, _: &Pat, _: &cmt_<'tcx>, _: MatchMode) {}
    fn consume_pat(&mut self, consume_pat: &Pat, cmt: &cmt_<'tcx>, _: ConsumeMode) {
        let map = &self.cx.tcx.hir();
        if map.is_argument(map.hir_to_node_id(consume_pat.hir_id)) {
            // Skip closure arguments
            if let Some(Node::Expr(..)) = map.find_by_hir_id(map.get_parent_node_by_hir_id(consume_pat.hir_id)) {
                return;
            }
            if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) {
                self.set.insert(consume_pat.hir_id);
            }
            return;
        }
        if let Categorization::Rvalue(..) = cmt.cat {
            let id = map.hir_to_node_id(cmt.hir_id);
            if let Some(Node::Stmt(st)) = map.find(map.get_parent_node(id)) {
                if let StmtKind::Local(ref loc) = st.node {
                    if let Some(ref ex) = loc.init {
                        if let ExprKind::Box(..) = ex.node {
                            if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) {
                                // let x = box (...)
                                self.set.insert(consume_pat.hir_id);
                            }
                            // TODO Box::new
                            // TODO vec![]
                            // TODO "foo".to_owned() and friends
                        }
                    }
                }
            }
        }
        if let Categorization::Local(lid) = cmt.cat {
            if self.set.contains(&lid) {
                // let y = x where x is known
                // remove x, insert y
                self.set.insert(consume_pat.hir_id);
                self.set.remove(&lid);
            }
        }
    }
    fn borrow(
        &mut self,
        _: HirId,
        _: Span,
        cmt: &cmt_<'tcx>,
        _: ty::Region<'_>,
        _: ty::BorrowKind,
        loan_cause: LoanCause,
    ) {
        if let Categorization::Local(lid) = cmt.cat {
            match loan_cause {
                // `x.foo()`
                // Used without autoderef-ing (i.e., `x.clone()`).
                LoanCause::AutoRef |

                // `&x`
                // `foo(&x)` where no extra autoref-ing is happening.
                LoanCause::AddrOf |

                // `match x` can move.
                LoanCause::MatchDiscriminant => {
                    self.set.remove(&lid);
                }

                // Do nothing for matches, etc. These can't escape.
                _ => {}
            }
        }
    }
    fn decl_without_init(&mut self, _: HirId, _: Span) {}
    fn mutate(&mut self, _: HirId, _: Span, _: &cmt_<'tcx>, _: MutateMode) {}
}

impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> {
    fn is_large_box(&self, ty: Ty<'tcx>) -> bool {
        // Large types need to be boxed to avoid stack overflows.
        if ty.is_box() {
            self.cx.layout_of(ty.boxed_ty()).ok().map_or(0, |l| l.size.bytes()) > self.too_large_for_stack
        } else {
            false
        }
    }
}
<commit_msg>Use `HirId` instead of `NodeId` for lookup<commit_after>use rustc::hir::intravisit as visit;
use rustc::hir::*;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::middle::expr_use_visitor::*;
use rustc::middle::mem_categorization::{cmt_, Categorization};
use rustc::ty::layout::LayoutOf;
use rustc::ty::{self, Ty};
use rustc::util::nodemap::HirIdSet;
use rustc::{declare_tool_lint, lint_array};
use syntax::source_map::Span;

use crate::utils::span_lint;

pub struct Pass {
    pub too_large_for_stack: u64,
}

declare_clippy_lint! {
    /// **What it does:** Checks for usage of `Box<T>` where an unboxed `T` would
    /// work fine.
    ///
    /// **Why is this bad?** This is an unnecessary allocation, and bad for
    /// performance. It is only necessary to allocate if you wish to move the box
    /// into something.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// fn main() {
    ///     let x = Box::new(1);
    ///     foo(*x);
    ///     println!("{}", *x);
    /// }
    /// ```
    pub BOXED_LOCAL,
    perf,
    "using `Box<T>` where unnecessary"
}

fn is_non_trait_box(ty: Ty<'_>) -> bool {
    ty.is_box() && !ty.boxed_ty().is_trait()
}

struct EscapeDelegate<'a, 'tcx: 'a> {
    cx: &'a LateContext<'a, 'tcx>,
    set: HirIdSet,
    too_large_for_stack: u64,
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(BOXED_LOCAL)
    }

    fn name(&self) -> &'static str {
        "BoxedLocal"
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
    fn check_fn(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        _: visit::FnKind<'tcx>,
        _: &'tcx FnDecl,
        body: &'tcx Body,
        _: Span,
        hir_id: HirId,
    ) {
        // If the method is an impl for a trait, don't warn.
        let parent_id = cx.tcx.hir().get_parent_item(hir_id);
        let parent_node = cx.tcx.hir().find_by_hir_id(parent_id);

        if let Some(Node::Item(item)) = parent_node {
            if let ItemKind::Impl(_, _, _, _, Some(..), _, _) = item.node {
                return;
            }
        }

        let mut v = EscapeDelegate {
            cx,
            set: HirIdSet::default(),
            too_large_for_stack: self.too_large_for_stack,
        };

        let fn_def_id = cx.tcx.hir().local_def_id_from_hir_id(hir_id);
        let region_scope_tree = &cx.tcx.region_scope_tree(fn_def_id);
        ExprUseVisitor::new(&mut v, cx.tcx, cx.param_env, region_scope_tree, cx.tables, None).consume_body(body);

        for node in v.set {
            span_lint(
                cx,
                BOXED_LOCAL,
                cx.tcx.hir().span_by_hir_id(node),
                "local variable doesn't need to be boxed here",
            );
        }
    }
}

impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
    fn consume(&mut self, _: HirId, _: Span, cmt: &cmt_<'tcx>, mode: ConsumeMode) {
        if let Categorization::Local(lid) = cmt.cat {
            if let Move(DirectRefMove) = mode {
                // Moved out or in. Clearly can't be localized.
                self.set.remove(&lid);
            }
        }
    }
    fn matched_pat(&mut self, _: &Pat, _: &cmt_<'tcx>, _: MatchMode) {}
    fn consume_pat(&mut self, consume_pat: &Pat, cmt: &cmt_<'tcx>, _: ConsumeMode) {
        let map = &self.cx.tcx.hir();
        if map.is_argument(map.hir_to_node_id(consume_pat.hir_id)) {
            // Skip closure arguments
            if let Some(Node::Expr(..)) = map.find_by_hir_id(map.get_parent_node_by_hir_id(consume_pat.hir_id)) {
                return;
            }
            if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) {
                self.set.insert(consume_pat.hir_id);
            }
            return;
        }
        if let Categorization::Rvalue(..) = cmt.cat {
            if let Some(Node::Stmt(st)) = map.find_by_hir_id(map.get_parent_node_by_hir_id(cmt.hir_id)) {
                if let StmtKind::Local(ref loc) = st.node {
                    if let Some(ref ex) = loc.init {
                        if let ExprKind::Box(..) = ex.node {
                            if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) {
                                // let x = box (...)
                                self.set.insert(consume_pat.hir_id);
                            }
                            // TODO Box::new
                            // TODO vec![]
                            // TODO "foo".to_owned() and friends
                        }
                    }
                }
            }
        }
        if let Categorization::Local(lid) = cmt.cat {
            if self.set.contains(&lid) {
                // let y = x where x is known
                // remove x, insert y
                self.set.insert(consume_pat.hir_id);
                self.set.remove(&lid);
            }
        }
    }
    fn borrow(
        &mut self,
        _: HirId,
        _: Span,
        cmt: &cmt_<'tcx>,
        _: ty::Region<'_>,
        _: ty::BorrowKind,
        loan_cause: LoanCause,
    ) {
        if let Categorization::Local(lid) = cmt.cat {
            match loan_cause {
                // `x.foo()`
                // Used without autoderef-ing (i.e., `x.clone()`).
                LoanCause::AutoRef |

                // `&x`
                // `foo(&x)` where no extra autoref-ing is happening.
                LoanCause::AddrOf |

                // `match x` can move.
                LoanCause::MatchDiscriminant => {
                    self.set.remove(&lid);
                }

                // Do nothing for matches, etc. These can't escape.
                _ => {}
            }
        }
    }
    fn decl_without_init(&mut self, _: HirId, _: Span) {}
    fn mutate(&mut self, _: HirId, _: Span, _: &cmt_<'tcx>, _: MutateMode) {}
}

impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> {
    fn is_large_box(&self, ty: Ty<'tcx>) -> bool {
        // Large types need to be boxed to avoid stack overflows.
        if ty.is_box() {
            self.cx.layout_of(ty.boxed_ty()).ok().map_or(0, |l| l.size.bytes()) > self.too_large_for_stack
        } else {
            false
        }
    }
}
<|endoftext|>


<commit_before>/// Figure 11.11 Using two mutexes
///
/// Findings:
/// - After wrestling with static mut again realized
///   that fh and hashlock are much better off stuffed into
///   a struct
///
/// Status: only partially implemented

extern crate libc;
use libc::{pthread_mutex_t, PTHREAD_MUTEX_INITIALIZER};
use libc::{pthread_mutex_init, pthread_mutex_lock};
use std::ptr::null;

const NHASH:usize = 29;
macro_rules! HASH {
    ($i:expr) => {{
        $i % NHASH as i64
    }}
}

#[derive(Clone)]
struct Foo {
    f_count: i64,
    f_lock: pthread_mutex_t,
    f_id: i64,
    f_next: Option<Box<Foo>>,
}

struct Hashmap {
    fh:[Foo;NHASH],
    hashlock:pthread_mutex_t,
}

impl Hashmap {
    fn foo_alloc(&mut self, id: i64) -> Option<Foo> {
        // allocate the object
        unsafe {
            let mut foo = Foo { f_count: 1, f_lock: std::mem::zeroed(), f_id: id, f_next: None };
            if pthread_mutex_init(&mut foo.f_lock, null()) != 0 {
                // does not need free as foo is dropped upon return
                return None
            }
            let idx = HASH!(id);
            pthread_mutex_lock(&mut self.hashlock);
            foo.f_next = Some(Box::new(self.fh[idx as usize]));
        }
        None
    }
}

fn main() {

}

<commit_msg>Add lifetimes needed to link hashmap to Foo<commit_after>/// Figure 11.11 Using two mutexes
///
/// Findings:
/// - After wrestling with static mut again realized
///   that fh and hashlock are much better off stuffed into
///   a struct
///
/// Status: only partially implemented

extern crate libc;
use libc::{pthread_mutex_t, PTHREAD_MUTEX_INITIALIZER};
use libc::{pthread_mutex_init, pthread_mutex_lock};
use std::ptr::null;

const NHASH:usize = 29;
macro_rules! HASH {
    ($i:expr) => {{
        $i % NHASH as i64
    }}
}

struct Foo<'a> {
    f_count: i64,
    f_lock: pthread_mutex_t,
    f_id: i64,
    f_next: Option<Box<&'a Foo<'a>>>,
}

struct Hashmap<'a> {
    fh:Vec<Foo<'a>>,
    hashlock:pthread_mutex_t,
}

impl <'a>Hashmap<'a> {
    fn new() -> Hashmap<'a> {
        let mut fh = Vec::with_capacity(NHASH);
        for i in 0..NHASH {
            fh[i] = Foo {f_count: 1, f_lock: PTHREAD_MUTEX_INITIALIZER, f_id: -1, f_next: None};
        }
        Hashmap{fh:fh, hashlock: PTHREAD_MUTEX_INITIALIZER}
    }

    fn foo_alloc(&mut self, id: i64) -> Option<Foo> {
        // allocate the object
        unsafe {
            let mut foo = Foo { f_count: 1, f_lock: std::mem::zeroed(), f_id: id, f_next: None };
            if pthread_mutex_init(&mut foo.f_lock, null()) != 0 {
                // does not need free as foo is dropped upon return
                return None
            }
            let idx = HASH!(id);
            pthread_mutex_lock(&mut self.hashlock);
            foo.f_next = Some(Box::new(&self.fh[idx as usize]));
        }
        None
    }
}

fn main() {

}

<|endoftext|>