<commit_before>use std::env;
use std::io::{stderr, Read, Write};
use std::net::TcpStream;
use std::process;
use std::str;

fn main() {
    if let Some(url) = env::args().nth(1) {
        let (scheme, reference) = url.split_at(url.find(':').unwrap_or(0));
        if scheme == "http" {
            let mut parts = reference.split('/').skip(2); //skip first two slashes
            let remote = parts.next().unwrap_or("");
            let mut path = parts.next().unwrap_or("").to_string();
            for part in parts {
                path.push('/');
                path.push_str(part);
            }

            write!(stderr(), "* Connecting to {}\n", remote).unwrap();

            let mut stream = TcpStream::connect(&remote).unwrap();

            write!(stderr(), "* Requesting {}\n", path).unwrap();

            let request = format!("GET /{} HTTP/1.0\r\n\r\n", path);
            stream.write(request.as_bytes()).unwrap();
            stream.flush().unwrap();

            write!(stderr(), "* Waiting for response\n").unwrap();

            let mut response = [0; 8192];
            let count = stream.read(&mut response).unwrap();

            let mut headers = true;
            for line in unsafe { str::from_utf8_unchecked(&response[.. count]) }.lines() {
                if headers {
                    if line.is_empty() {
                        headers = false;
                    } else {
                        write!(stderr(), "> {}\n", line).unwrap();
                    }
                } else {
                    println!("{}", line);
                }
            }
        } else {
            write!(stderr(), "wget: unknown scheme '{}'\n", scheme).unwrap();
            process::exit(1);
        }
    } else {
        write!(stderr(), "wget: http://host:port/path\n").unwrap();
        process::exit(1);
    }
}
<commit_msg>Read to end<commit_after>use std::env;
use std::io::{stderr, Read, Write};
use std::net::TcpStream;
use std::process;
use std::str;

fn main() {
    if let Some(url) = env::args().nth(1) {
        let (scheme, reference) = url.split_at(url.find(':').unwrap_or(0));
        if scheme == "http" {
            let mut parts = reference.split('/').skip(2); //skip first two slashes
            let remote = parts.next().unwrap_or("");
            let mut path = parts.next().unwrap_or("").to_string();
            for part in parts {
                path.push('/');
                path.push_str(part);
            }

            write!(stderr(), "* Connecting to {}\n", remote).unwrap();

            let mut stream = TcpStream::connect(&remote).unwrap();

            write!(stderr(), "* Requesting {}\n", path).unwrap();

            let request = format!("GET /{} HTTP/1.0\r\n\r\n", path);
            stream.write(request.as_bytes()).unwrap();
            stream.flush().unwrap();

            write!(stderr(), "* Waiting for response\n").unwrap();

            let mut response = Vec::new();
            let count = stream.read_to_end(&mut response).unwrap();

            let mut headers = true;
            for line in unsafe { str::from_utf8_unchecked(&response[.. count]) }.lines() {
                if headers {
                    if line.is_empty() {
                        headers = false;
                    } else {
                        write!(stderr(), "> {}\n", line).unwrap();
                    }
                } else {
                    println!("{}", line);
                }
            }
        } else {
            write!(stderr(), "wget: unknown scheme '{}'\n", scheme).unwrap();
            process::exit(1);
        }
    } else {
        write!(stderr(), "wget: http://host:port/path\n").unwrap();
        process::exit(1);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate gj;
extern crate nix;

use std::cell::{RefCell};
use std::rc::Rc;
use gj::{Promise, PromiseFulfiller};
use handle_table::{HandleTable, Handle};

mod handle_table;
mod sys;

/// A nonblocking input bytestream.
pub trait Read {
    /// Attempts to read `buf.len()` bytes from the stream, writing them into `buf`.
    /// Returns `self`, the modified `buf`, and the number of bytes actually read.
    /// Returns as soon as `min_bytes` are read or EOF is encountered.
    fn try_read<T>(&mut self, buf: T, min_bytes: usize) -> Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>;

    /// Like `try_read()`, but returns an error if EOF is encountered before `min_bytes`
    /// can be read.
    fn read<T>(&mut self, buf: T, min_bytes: usize) -> Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>
    {
        self.try_read(buf, min_bytes).map(move |(buf, n)| {
            if n < min_bytes {
                Err(::std::io::Error::new(::std::io::ErrorKind::Other, "Premature EOF"))
            } else {
                Ok((buf, n))
            }
        })
    }
}

/// A nonblocking output bytestream.
pub trait AsyncWrite {
    /// Attempts to write all `buf.len()` bytes from `buf` into the stream. Returns `self` and `buf`
    /// once all of the bytes have been written.
    fn write<T: AsRef<[u8]>>(&mut self, buf: T) -> Promise<T, ::std::io::Error>;
}

#[cfg(unix)]
type RawDescriptor = std::os::unix::io::RawFd;

pub struct EventPort {
    reactor: Rc<RefCell<::sys::Reactor>>,
}

impl EventPort {
    pub fn new() -> Result<EventPort, ::std::io::Error> {
        Ok( EventPort {
            reactor: Rc::new(RefCell::new(try!(sys::Reactor::new()))),
        })
    }

    pub fn get_network(&self) -> Network {
        Network::new(self.reactor.clone())
    }
}

impl gj::EventPort<::std::io::Error> for EventPort {
    fn wait(&mut self) -> Result<(), ::std::io::Error> {
        self.reactor.borrow_mut().run_once()
    }
}

pub struct Network {
    reactor: Rc<RefCell<::sys::Reactor>>,
}

impl Network {
    fn new(reactor: Rc<RefCell<::sys::Reactor>>) -> Network {
        Network { reactor: reactor }
    }

    pub fn get_tcp_address(&self, addr: ::std::net::SocketAddr) -> SocketAddress {
        SocketAddress::new(self.reactor.clone(),
                            ::nix::sys::socket::SockAddr::Inet(::nix::sys::socket::InetAddr::from_std(&addr)))
    }

    pub fn get_unix_address<P: AsRef<::std::path::Path>>(&self, addr: P)
                            -> Result<SocketAddress, ::std::io::Error>
    {
        // In what situations does this fail?
        Ok(SocketAddress::new(self.reactor.clone(),
                               ::nix::sys::socket::SockAddr::Unix(
                                   try!(::nix::sys::socket::UnixAddr::new(addr.as_ref())))))
    }
}

struct SocketListenerInner {
    reactor: Rc<RefCell<::sys::Reactor>>,
    handle: Handle,
    descriptor: RawDescriptor,

    // Ugh. If only std::io::Error were Clone...
    queue: Option<Promise<RawDescriptor, Rc<RefCell<Option<::std::io::Error>>>>>,
}

pub struct SocketAddress {
    reactor: Rc<RefCell<::sys::Reactor>>,
    addr: ::nix::sys::socket::SockAddr,
}

impl SocketAddress {
    fn new(reactor: Rc<RefCell<::sys::Reactor>>, addr: ::nix::sys::socket::SockAddr)
           -> SocketAddress
    {
        SocketAddress {
            reactor: reactor,
            addr: addr,
        }
    }

    fn connect(&self) -> Promise<SocketStream, ::std::io::Error>
    {
        let reactor = self.reactor.clone();
        let addr = self.addr;
        Promise::ok(()).then(move |()| {
            let mut reactor = reactor;

            let fd = pry!(nix::sys::socket::socket(addr.family(), nix::sys::socket::SockType::Stream,
                                                   nix::sys::socket::SOCK_NONBLOCK, 0));

            pry!(::nix::sys::socket::connect(fd, &addr));
            let handle = pry!(reactor.borrow_mut().new_observer(fd));

            // TODO: if we're not already connected, maybe only register writable interest,
            // and then reregister with read/write interested once we successfully connect.

            let promise = reactor.borrow_mut().observers[handle].when_becomes_writable();
            promise.map(move |()| {
//                try!(stream.take_socket_error());
                Ok(SocketStream::new(reactor, handle, fd))
            })
        })
    }

    fn bind(&mut self) -> Result<SocketListener, ::std::io::Error>
    {
        let fd = try!(nix::sys::socket::socket(self.addr.family(), nix::sys::socket::SockType::Stream,
                                               nix::sys::socket::SOCK_NONBLOCK, 0));

        try!(nix::sys::socket::bind(fd, &self.addr));
        let handle = try!(self.reactor.borrow_mut().new_observer(fd));
        Ok(SocketListener::new(self.reactor.clone(), handle, fd))
    }
}

impl Drop for SocketListenerInner {
    fn drop(&mut self) {
        let _ = ::nix::unistd::close(self.descriptor);
        self.reactor.borrow_mut().observers.remove(self.handle);
    }
}

pub struct SocketListener {
    inner: Rc<RefCell<SocketListenerInner>>,
}

impl Clone for SocketListener {
    fn clone(&self) -> SocketListener {
        SocketListener { inner: self.inner.clone() }
    }
}

impl SocketListener {
    fn new(reactor: Rc<RefCell<::sys::Reactor>>, handle: Handle, descriptor: RawDescriptor)
           -> SocketListener
    {
        SocketListener {
            inner: Rc::new(RefCell::new(SocketListenerInner {
                reactor: reactor,
                handle: handle,
                descriptor: descriptor,
                queue: None,
            })),
        }
    }

    fn accept_internal(inner: Rc<RefCell<SocketListenerInner>>) -> Promise<RawDescriptor, ::std::io::Error> {
        let fd = inner.borrow_mut().descriptor;
        match ::nix::sys::socket::accept4(fd, nix::sys::socket::SOCK_NONBLOCK) {
            Ok(fd) => {
                Promise::ok(fd)
            }
            Err(e) => {
                match e.errno() {
                    ::nix::Errno::EAGAIN => {
                        let handle = inner.borrow().handle;
                        let promise = {
                            let reactor = &inner.borrow().reactor;
                            let promise = // LOL borrow checker fail.
                                reactor.borrow_mut().observers[handle].when_becomes_readable();
                            promise
                        };
                        promise.then(|()| {
                            SocketListener::accept_internal(inner)
                        })
                    }
                    _ => {
                        Promise::err(e.into())
                    }
                }
            }
        }
    }

    pub fn accept(&mut self) -> Promise<SocketStream, ::std::io::Error> {
        let inner = self.inner.clone();
        let inner2 = inner.clone();
        let maybe_queue = inner.borrow_mut().queue.take();
        let promise = match maybe_queue {
            None => SocketListener::accept_internal(inner2),
            Some(queue) => {
                queue.then_else(move |_| SocketListener::accept_internal(inner2) )
            }
        };

        let mut forked = promise.map_err(|e| Rc::new(RefCell::new(Some(e)))).fork();
        inner.borrow_mut().queue = Some(forked.add_branch());
        forked.add_branch().map_err(|e| {
            e.borrow_mut().take().unwrap()
        }).map(move |fd| {
            let reactor = inner.borrow().reactor.clone();
            let handle = try!(reactor.borrow_mut().new_observer(fd));
            Ok(SocketStream::new(reactor, handle, fd))
        })
    }
}

struct SocketStreamInner {
    reactor: Rc<RefCell<::sys::Reactor>>,
    handle: Handle,
    descriptor: RawDescriptor,
}

impl Drop for SocketStreamInner {
    fn drop(&mut self) {
        let _ = ::nix::unistd::close(self.descriptor);
        self.reactor.borrow_mut().observers.remove(self.handle);
    }
}

pub struct SocketStream {
    inner: Rc<RefCell<SocketStreamInner>>,
}

impl Clone for SocketStream {
    fn clone(&self) -> SocketStream {
        SocketStream { inner: self.inner.clone() }
    }
}

impl SocketStream {
    fn new(reactor: Rc<RefCell<::sys::Reactor>>, handle: Handle, descriptor: RawDescriptor) -> SocketStream {
        SocketStream {
            inner: Rc::new(RefCell::new(SocketStreamInner {
                reactor: reactor,
                handle: handle,
                descriptor: descriptor,
            })),
        }
    }
}

<commit_msg>Read and Write impls<commit_after>#[macro_use]
extern crate gj;
extern crate nix;

use std::cell::{RefCell};
use std::rc::Rc;
use gj::{Promise, PromiseFulfiller};
use handle_table::{HandleTable, Handle};

mod handle_table;
mod sys;

/// A nonblocking input bytestream.
pub trait Read {
    /// Attempts to read `buf.len()` bytes from the stream, writing them into `buf`.
    /// Returns `self`, the modified `buf`, and the number of bytes actually read.
    /// Returns as soon as `min_bytes` are read or EOF is encountered.
    fn try_read<T>(&mut self, buf: T, min_bytes: usize) -> Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>;

    /// Like `try_read()`, but returns an error if EOF is encountered before `min_bytes`
    /// can be read.
    fn read<T>(&mut self, buf: T, min_bytes: usize) -> Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>
    {
        self.try_read(buf, min_bytes).map(move |(buf, n)| {
            if n < min_bytes {
                Err(::std::io::Error::new(::std::io::ErrorKind::Other, "Premature EOF"))
            } else {
                Ok((buf, n))
            }
        })
    }
}

/// A nonblocking output bytestream.
pub trait Write {
    /// Attempts to write all `buf.len()` bytes from `buf` into the stream. Returns `self` and `buf`
    /// once all of the bytes have been written.
    fn write<T: AsRef<[u8]>>(&mut self, buf: T) -> Promise<T, ::std::io::Error>;
}

#[cfg(unix)]
type RawDescriptor = std::os::unix::io::RawFd;

pub struct EventPort {
    reactor: Rc<RefCell<::sys::Reactor>>,
}

impl EventPort {
    pub fn new() -> Result<EventPort, ::std::io::Error> {
        Ok( EventPort {
            reactor: Rc::new(RefCell::new(try!(sys::Reactor::new()))),
        })
    }

    pub fn get_network(&self) -> Network {
        Network::new(self.reactor.clone())
    }
}

impl gj::EventPort<::std::io::Error> for EventPort {
    fn wait(&mut self) -> Result<(), ::std::io::Error> {
        self.reactor.borrow_mut().run_once()
    }
}

pub struct Network {
    reactor: Rc<RefCell<::sys::Reactor>>,
}

impl Network {
    fn new(reactor: Rc<RefCell<::sys::Reactor>>) -> Network {
        Network { reactor: reactor }
    }

    pub fn get_tcp_address(&self, addr: ::std::net::SocketAddr) -> SocketAddress {
        SocketAddress::new(self.reactor.clone(),
                            ::nix::sys::socket::SockAddr::Inet(::nix::sys::socket::InetAddr::from_std(&addr)))
    }

    pub fn get_unix_address<P: AsRef<::std::path::Path>>(&self, addr: P)
                            -> Result<SocketAddress, ::std::io::Error>
    {
        // In what situations does this fail?
        Ok(SocketAddress::new(self.reactor.clone(),
                               ::nix::sys::socket::SockAddr::Unix(
                                   try!(::nix::sys::socket::UnixAddr::new(addr.as_ref())))))
    }
}

struct SocketListenerInner {
    reactor: Rc<RefCell<::sys::Reactor>>,
    handle: Handle,
    descriptor: RawDescriptor,

    // Ugh. If only std::io::Error were Clone...
    queue: Option<Promise<RawDescriptor, Rc<RefCell<Option<::std::io::Error>>>>>,
}

pub struct SocketAddress {
    reactor: Rc<RefCell<::sys::Reactor>>,
    addr: ::nix::sys::socket::SockAddr,
}

impl SocketAddress {
    fn new(reactor: Rc<RefCell<::sys::Reactor>>, addr: ::nix::sys::socket::SockAddr)
           -> SocketAddress
    {
        SocketAddress {
            reactor: reactor,
            addr: addr,
        }
    }

    fn connect(&self) -> Promise<SocketStream, ::std::io::Error>
    {
        let reactor = self.reactor.clone();
        let addr = self.addr;
        Promise::ok(()).then(move |()| {
            let mut reactor = reactor;

            let fd = pry!(nix::sys::socket::socket(addr.family(), nix::sys::socket::SockType::Stream,
                                                   nix::sys::socket::SOCK_NONBLOCK, 0));

            pry!(::nix::sys::socket::connect(fd, &addr));
            let handle = pry!(reactor.borrow_mut().new_observer(fd));

            // TODO: if we're not already connected, maybe only register writable interest,
            // and then reregister with read/write interested once we successfully connect.

            let promise = reactor.borrow_mut().observers[handle].when_becomes_writable();
            promise.map(move |()| {
//                try!(stream.take_socket_error());
                Ok(SocketStream::new(reactor, handle, fd))
            })
        })
    }

    fn bind(&mut self) -> Result<SocketListener, ::std::io::Error>
    {
        let fd = try!(nix::sys::socket::socket(self.addr.family(), nix::sys::socket::SockType::Stream,
                                               nix::sys::socket::SOCK_NONBLOCK, 0));

        try!(nix::sys::socket::bind(fd, &self.addr));
        let handle = try!(self.reactor.borrow_mut().new_observer(fd));
        Ok(SocketListener::new(self.reactor.clone(), handle, fd))
    }
}

impl Drop for SocketListenerInner {
    fn drop(&mut self) {
        let _ = ::nix::unistd::close(self.descriptor);
        self.reactor.borrow_mut().observers.remove(self.handle);
    }
}

pub struct SocketListener {
    inner: Rc<RefCell<SocketListenerInner>>,
}

impl Clone for SocketListener {
    fn clone(&self) -> SocketListener {
        SocketListener { inner: self.inner.clone() }
    }
}

impl SocketListener {
    fn new(reactor: Rc<RefCell<::sys::Reactor>>, handle: Handle, descriptor: RawDescriptor)
           -> SocketListener
    {
        SocketListener {
            inner: Rc::new(RefCell::new(SocketListenerInner {
                reactor: reactor,
                handle: handle,
                descriptor: descriptor,
                queue: None,
            })),
        }
    }

    fn accept_internal(inner: Rc<RefCell<SocketListenerInner>>) -> Promise<RawDescriptor, ::std::io::Error> {
        let fd = inner.borrow_mut().descriptor;
        match ::nix::sys::socket::accept4(fd, nix::sys::socket::SOCK_NONBLOCK) {
            Ok(fd) => {
                Promise::ok(fd)
            }
            Err(e) => {
                match e.errno() {
                    ::nix::Errno::EAGAIN => {
                        let handle = inner.borrow().handle;
                        let promise = {
                            let reactor = &inner.borrow().reactor;
                            let promise = // LOL borrow checker fail.
                                reactor.borrow_mut().observers[handle].when_becomes_readable();
                            promise
                        };
                        promise.then(|()| {
                            SocketListener::accept_internal(inner)
                        })
                    }
                    _ => {
                        Promise::err(e.into())
                    }
                }
            }
        }
    }

    pub fn accept(&mut self) -> Promise<SocketStream, ::std::io::Error> {
        let inner = self.inner.clone();
        let inner2 = inner.clone();
        let maybe_queue = inner.borrow_mut().queue.take();
        let promise = match maybe_queue {
            None => SocketListener::accept_internal(inner2),
            Some(queue) => {
                queue.then_else(move |_| SocketListener::accept_internal(inner2) )
            }
        };

        let mut forked = promise.map_err(|e| Rc::new(RefCell::new(Some(e)))).fork();
        inner.borrow_mut().queue = Some(forked.add_branch());
        forked.add_branch().map_err(|e| {
            e.borrow_mut().take().unwrap()
        }).map(move |fd| {
            let reactor = inner.borrow().reactor.clone();
            let handle = try!(reactor.borrow_mut().new_observer(fd));
            Ok(SocketStream::new(reactor, handle, fd))
        })
    }
}

struct SocketStreamInner {
    reactor: Rc<RefCell<::sys::Reactor>>,
    handle: Handle,
    descriptor: RawDescriptor,
}

impl Drop for SocketStreamInner {
    fn drop(&mut self) {
        let _ = ::nix::unistd::close(self.descriptor);
        self.reactor.borrow_mut().observers.remove(self.handle);
    }
}

pub struct SocketStream {
    inner: Rc<RefCell<SocketStreamInner>>,
}

impl Clone for SocketStream {
    fn clone(&self) -> SocketStream {
        SocketStream { inner: self.inner.clone() }
    }
}

impl SocketStream {
    fn new(reactor: Rc<RefCell<::sys::Reactor>>, handle: Handle, descriptor: RawDescriptor) -> SocketStream {
        SocketStream {
            inner: Rc::new(RefCell::new(SocketStreamInner {
                reactor: reactor,
                handle: handle,
                descriptor: descriptor,
            })),
        }
    }

    fn try_read_internal<T>(inner: Rc<RefCell<SocketStreamInner>>,
                            mut buf: T,
                            mut already_read: usize,
                            min_bytes: usize)
                            -> Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>
    {
        while already_read < min_bytes {
            let descriptor = inner.borrow().descriptor;
            match ::nix::unistd::read(descriptor, &mut buf.as_mut()[already_read..]) {
                Ok(0) => {
                    // EOF
                    return Promise::ok((buf, already_read));
                }
                Ok(n) => {
                    already_read += n;
                }
                Err(e) => {
                    match e.errno() {
                        ::nix::Errno::EINTR => continue,
                        ::nix::Errno::EAGAIN => {
                            let handle = inner.borrow().handle;
                            let promise = {
                                let reactor = &inner.borrow().reactor;
                                let promise = // LOL borrow checker fail.
                                    reactor.borrow_mut().observers[handle].when_becomes_readable();
                                promise
                            };

                            return promise.then_else(move |r| match r {
                                Ok(()) => SocketStream::try_read_internal(inner, buf, already_read, min_bytes),
                                Err(e) => Promise::err(e)
                            });
                        }
                        _ => {
                            return Promise::err(e.into())
                        }
                    }
                }
            }
        }
        Promise::ok((buf, already_read))
    }

    fn write_internal<T>(inner: Rc<RefCell<SocketStreamInner>>,
                         buf: T,
                         mut already_written: usize) -> Promise<T, ::std::io::Error>
        where T: AsRef<[u8]>
    {
        while already_written < buf.as_ref().len() {
            let descriptor = inner.borrow().descriptor;
            match ::nix::unistd::write(descriptor, &buf.as_ref()[already_written..]) {
                Ok(n) => {
                    already_written += n;
                }
                Err(e) => {
                    match e.errno() {
                        ::nix::Errno::EINTR => continue,
                        ::nix::Errno::EAGAIN => {
                            let handle = inner.borrow().handle;
                            let promise = {
                                let reactor = &inner.borrow().reactor;
                                let promise = // LOL borrow checker fail.
                                    reactor.borrow_mut().observers[handle].when_becomes_writable();
                                promise
                            };
                            return promise.then_else(move |r| match r {
                                Ok(()) => SocketStream::write_internal(inner, buf, already_written),
                                Err(e) => Promise::err(e),
                            })
                        }
                        _ => {
                            return Promise::err(e.into());
                        }
                    }
                }
            }
        }
        Promise::ok(buf)
    }
}

impl Read for SocketStream {
    fn try_read<T>(&mut self, buf: T, min_bytes: usize) -> Promise<(T, usize), ::std::io::Error>
        where T: AsMut<[u8]>
    {
        SocketStream::try_read_internal(self.inner.clone(), buf, 0, min_bytes)
    }
}

impl Write for SocketStream {
    fn write<T>(&mut self, buf: T) -> Promise<T, ::std::io::Error>
        where T: AsRef<[u8]>
    {
        SocketStream::write_internal(self.inner.clone(), buf, 0)
    }
}
<|endoftext|>


<commit_before>use clap::Arg;
use clap::App;
use clap::{ArgMatches};
use loader;
use rusqlite::Connection;

pub fn cli_clap(number: &u32) -> ArgMatches{

    let application = App::new("whenenv")
                        .about("Parses an input file to do awesome things")
                        .version("0.0.1")
                        .author("Owen Synge <osynge@googlemail.com>")
                        .arg(Arg::with_name("verbose")
                                    .help("Increase log output.")
                                    .short("v")
                                    .multiple(true)
                                    .long("verbose"))
                        .arg(Arg::with_name("quiet")
                                    .help("Decrease log output.")
                                    .short("q")
                                    .multiple(true)
                                    .long("quiet"))
                        .arg(Arg::with_name("env")
                                    .short("e")
                                    .long("env")
                                    .value_name("ENVIROMENT_VARIABLE")
                                    .help("Which enviroment variables to process")
                                    .multiple(true)
                                    .takes_value(true))
                        .arg(Arg::with_name("dir-jobs")
                                    .long("dir-jobs")
                                    .value_name("DIR_JOB")
                                    .help("directory storing json jobs.")
                                    .multiple(true)
                                    .takes_value(true))
                        .arg(Arg::with_name("dir-sh")
                                    .long("dir-sh")
                                    .value_name("DIR_SHELL")
                                    .help("directory storing jobs shell scripts.")
                                    .multiple(true)
                                    .takes_value(true))
                        .arg(Arg::with_name("dir-py")
                                    .long("dir-py")
                                    .value_name("DIR_PYTHON")
                                    .help("directory storing jobs python scripts.")
                                    .multiple(true)
                                    .takes_value(true))
                        .arg(Arg::with_name("config")
                                    .short("c")
                                    .long("config")
                                    .value_name("FILE")
                                    .help("Sets a custom config file")
                                    .takes_value(true));
    let matches = application.get_matches();
    return matches;
}
<commit_msg>Add soem basic actions<commit_after>use clap::Arg;
use clap::App;
use clap::{ArgMatches};
use loader;
use rusqlite::Connection;

pub fn cli_clap(number: &u32) -> ArgMatches{

    let application = App::new("whenenv")
                        .about("Parses an input file to do awesome things")
                        .version("0.0.1")
                        .author("Owen Synge <osynge@googlemail.com>")
                        .arg(Arg::with_name("verbose")
                                    .help("Increase log output.")
                                    .short("v")
                                    .multiple(true)
                                    .long("verbose"))
                        .arg(Arg::with_name("quiet")
                                    .help("Decrease log output.")
                                    .short("q")
                                    .multiple(true)
                                    .long("quiet"))
                        .arg(Arg::with_name("env")
                                    .short("e")
                                    .long("env")
                                    .value_name("ENVIROMENT_VARIABLE")
                                    .help("Which enviroment variables to process")
                                    .multiple(true)
                                    .takes_value(true))
                        .arg(Arg::with_name("dir-jobs")
                                    .long("dir-jobs")
                                    .value_name("DIR_JOB")
                                    .help("directory storing json jobs.")
                                    .multiple(true)
                                    .takes_value(true))
                        .arg(Arg::with_name("dir-sh")
                                    .long("dir-sh")
                                    .value_name("DIR_SHELL")
                                    .help("directory storing jobs shell scripts.")
                                    .multiple(true)
                                    .takes_value(true))
                        .arg(Arg::with_name("dir-py")
                                    .long("dir-py")
                                    .value_name("DIR_PYTHON")
                                    .help("directory storing jobs python scripts.")
                                    .multiple(true)
                                    .takes_value(true))
                        .arg(Arg::with_name("config")
                                    .short("c")
                                    .long("config")
                                    .value_name("FILE")
                                    .help("Sets a custom config file")
                                    .takes_value(true))
                        .arg(Arg::with_name("target")
                                    .short("t")
                                    .long("target")
                                    .value_name("TARGET")
                                    .help("Sets the provider to be selected.")
                                    .takes_value(true))
                        .arg(Arg::with_name("list-provides")
                                    .long("list-provides")
                                    .help("list-provides"))
                        .arg(Arg::with_name("session")
                                    .long("session")
                                    .help("session"));
    let matches = application.get_matches();
    return matches;
}
<|endoftext|>


<commit_before>use std::cmp;

fn max_length(str1: &str, str2: &str) -> usize {
    if str1.len() > str2.len() {
      str1.len()
    } else {
      str2.len()
    }
}

fn get_common_chars(str1: &str, str2: &str, ordering: bool) -> Vec<char> {
    let mut common_chars = Vec::new();
    let max_length = max_length(str1, str2);
    let match_buffer = ( max_length / 2 ) - 1;
    let mut f = str1;
    let mut s = str2;

    if ordering {
        f = str2;
        s = str1;
    }

    for (i, c) in f.chars().enumerate() {
        let s_index: usize = if i < match_buffer {
            0
        } else {
            i - match_buffer
        };

        let e_index: usize = if s.len() <= (i + match_buffer) {
            s.len()
        } else {
            i + match_buffer + 1
        };

        let word_slice = &s[s_index..e_index];
        if word_slice.contains(c) {
            common_chars.push(c);
        }
    }

    common_chars
}

pub fn jaro_winkler_distance(str1: &str, str2: &str) -> f32 {
    let matches1 = get_common_chars(str1, str2, false);
    let matches2 = get_common_chars(str1, str2, true);

    if matches1.is_empty() || matches2.is_empty()
      || matches1.len() != matches2.len()
    {
      return 0.0;
    }

    let mut t = 0.0;
    for (a, b) in matches1.iter().zip(matches2.iter()) {
      if a != b {
        t += 0.5;
      }
    }

    let f1 = matches1.len() as f32 / str1.len() as f32;
    let f2 = matches2.len() as f32 / str2.len() as f32;
    let f3 = (matches1.len() as f32 - t) / matches1.len() as f32;
    (f1 + f2 + f3) / 3.0
}

/* pub fn levenshtein_distance(a: &str, b: &str) -> usize {
    // TODO: unimplemented
}*/
<commit_msg>Fix common chars not working for empty strings<commit_after>use std::cmp;

fn max_length(str1: &str, str2: &str) -> usize {
    if str1.len() > str2.len() {
      str1.len()
    } else {
      str2.len()
    }
}

fn get_common_chars(str1: &str, str2: &str, ordering: bool) -> Vec<char> {
    let mut common_chars = Vec::new();

    if str1.len() == 0 || str2.len() == 0 {
        return common_chars;
    }

    let max_length = max_length(str1, str2);
    let match_buffer = ( max_length / 2 ) - 1;
    let mut f = str1;
    let mut s = str2;

    if ordering {
        f = str2;
        s = str1;
    }

    for (i, c) in f.chars().enumerate() {
        let s_index: usize = if i < match_buffer {
            0
        } else {
            i - match_buffer
        };

        let e_index: usize = if s.len() <= (i + match_buffer) {
            s.len()
        } else {
            i + match_buffer + 1
        };

        let word_slice = &s[s_index..e_index];
        if word_slice.contains(c) {
            common_chars.push(c);
        }
    }

    common_chars
}

pub fn jaro_winkler_distance(str1: &str, str2: &str) -> f32 {
    let matches1 = get_common_chars(str1, str2, false);
    let matches2 = get_common_chars(str1, str2, true);

    if matches1.is_empty() || matches2.is_empty()
      || matches1.len() != matches2.len()
    {
      return 0.0;
    }

    let mut t = 0.0;
    for (a, b) in matches1.iter().zip(matches2.iter()) {
      if a != b {
        t += 0.5;
      }
    }

    let f1 = matches1.len() as f32 / str1.len() as f32;
    let f2 = matches2.len() as f32 / str2.len() as f32;
    let f3 = (matches1.len() as f32 - t) / matches1.len() as f32;
    (f1 + f2 + f3) / 3.0
}

/* pub fn levenshtein_distance(a: &str, b: &str) -> usize {
    // TODO: unimplemented
}*/
<|endoftext|>


<commit_before>//! Data structures containing extracted URL, mention, tag, and media information.
//!
//! These structures are meant to be received in an API call to describe the data they accompany.
//! For example, a `UrlEntity` describes a hyperlink in a tweet or user description text, and a
//! `HashtagEntity` describes a hashtag or stock symbol extracted from a tweet.
//!
//! For more information on the data in these structures, see Twitter's documentation for
//! [Entities][] and [Entities in Objects][obj].
//!
//! [Entities]: https://dev.twitter.com/overview/api/entities
//! [obj]: https://dev.twitter.com/overview/api/entities-in-twitter-objects
//!
//! ## Using indices and URLs
//!
//! When displaying text with accompanied entities, be wary about how you use the accompanied
//! indices. The indices given by Twitter reference the *graphemes* in the tweet, so something like
//! `char_indices` will fall flat when faced with text that uses combining characters. The
//! [unicode-segmentation][] crate provides a means to iterate over the graphemes of a string,
//! allowing you to make sure you hyperlink the right range of characters in the text.
//!
//! [unicode-segmentation]: https://crates.io/crates/unicode-segmentation
//!
//! Alternately, when substituting URLs for display, `str::replace` works just fine.
//!
//! ### Shortened, Display, and Expanded URLs
//!
//! URL and Media entities contain references to a URL within their parent text. However, due to
//! the nature of how Twitter handles URLs in tweets and user bios, each entity struct has three
//! URLs within it:
//!
//! - `url`: This is the `t.co` shortened URL as returned directly from twitter. This is what
//!   contributes to character count in tweets and user bios.
//! - `expanded_url`: This is the original URL the user entered in their tweet. While it is given
//!   to API client, Twitter recommends still sending users to the shortened link, for analytics
//!   purposes. Twitter Web uses this field to supply hover-text for where the URL resolves to.
//! - `display_url`: This is a truncated version of `expanded_url`, meant to be displayed inline
//!   with the parent text. This is useful to show users where the link resolves to, without
//!   potentially filling up a lot of space with the fullly expanded URL.
use common::*;
use error;
use error::Error::InvalidResponse;
use rustc_serialize::json;
use mime;

///Represents a hashtag or symbol extracted from another piece of text.
#[derive(Debug)]
pub struct HashtagEntity {
    ///The character indices where the hashtag is located. The first index is the location of the #
    ///or $ character; the second is the location of the first character following the hashtag.
    pub indices: (i32, i32),
    ///The text of the hashtag, without the leading # or $ character.
    pub text: String,
}

///Represents a piece of media attached to a tweet.
///
///The information in this struct is subtly different depending on what media is being referenced,
///and which entity container is holding this instance. For videos and GIFs, the `media_url` and
///`media_url_https` fields each link to a thumbnail image of the media, typically of the first
///frame. The real video information can be found on the `video_info` field, including various
///encodings if available.
///
///Image links available in `media_url` and `media_url_https` can be obtained in different sizes by
///appending a colon and one of the available sizes in the `MediaSizes` struct. For example, the
///cropped thumbnail can be viewed by appending `:thumb` to the end of the URL, and the full-size
///image can be viewed by appending `:large`.
#[derive(Debug)]
pub struct MediaEntity {
    ///A shortened URL to display to clients.
    pub display_url: String,
    ///An expanded version of `display_url`; links to the media display page.
    pub expanded_url: String,
    ///A numeric ID for the media.
    pub id: i64,
    ///Character indices where the media URL is located. The first index is the location of the
    ///first character of the URL; the second is the location of the first character following the
    ///URL.
    pub indices: (i32, i32),
    ///A URL pointing directly to the media file. Uses HTTP as the protocol.
    ///
    ///For videos and GIFs, this link will be to a thumbnail of the media, and the real video link
    ///will be contained in `video_info`.
    pub media_url: String,
    ///A URL pointing directly to the media file. Uses HTTPS as the protocol.
    ///
    ///For videos and GIFs, this link will be to a thumbnail of the media, and the real video link
    ///will be contained in `video_info`.
    pub media_url_https: String,
    ///Various sizes available for the media file.
    pub sizes: MediaSizes,
    ///For tweets containing media that was originally associated with a different tweet, this
    ///contains the ID of the original tweet.
    pub source_status_id: Option<i64>,
    ///The type of media being represented.
    pub media_type: MediaType,
    ///The t.co link from the original text.
    pub url: String,
    ///For media entities corresponding to videos, this contains extra information about the linked
    ///video.
    pub video_info: Option<VideoInfo>,
}

///Represents the types of media that can be attached to a tweet.
#[derive(Debug)]
pub enum MediaType {
    ///A static image.
    Photo,
    ///A video.
    Video,
    ///An animated GIF, delivered as a video without audio.
    Gif,
}

///Represents the available sizes for a media file.
#[derive(Debug)]
pub struct MediaSizes {
    ///Information for a thumbnail-sized version of the media.
    pub thumb: MediaSize,
    ///Information for a small-sized version of the media.
    pub small: MediaSize,
    ///Information for a medium-sized version of the media.
    pub medium: MediaSize,
    ///Information for a large-sized version of the media.
    pub large: MediaSize,
}

///Represents how an image has been resized for a given size variant.
#[derive(Debug)]
pub enum ResizeMode {
    ///The media was resized to fit one dimension, keeping its aspect ratio.
    Fit,
    ///The media was cropped to fit a specific resolution.
    Crop,
}

///Represents the dimensions of a media file.
#[derive(Debug)]
pub struct MediaSize {
    ///The size variant's width in pixels.
    pub w: i32,
    ///The size variant's height in pixels.
    pub h: i32,
    ///The method used to obtain the given dimensions.
    pub resize: ResizeMode,
}

///Represents metadata specific to videos.
#[derive(Debug)]
pub struct VideoInfo {
    ///The aspect ratio of the video.
    pub aspect_ratio: (i32, i32),
    ///The duration of the video, in milliseconds.
    ///
    ///This field is not given for animated GIFs.
    pub duration_millis: Option<i32>,
    ///Information about various encodings available for the video.
    pub variants: Vec<VideoVariant>,
}

///Represents information about a specific encoding of a video.
#[derive(Debug)]
pub struct VideoVariant {
    ///The bitrate of the video. This value is present for GIFs, but it will be zero.
    pub bitrate: Option<i32>,
    ///The file format of the video variant.
    pub content_type: mime::Mime,
    ///The URL for the video variant.
    pub url: String,
}

///Represents a link extracted from another piece of text.
#[derive(Debug)]
pub struct UrlEntity {
    ///A truncated URL meant to be displayed inline with the text.
    pub display_url: String,
    ///The URL that the t.co URL resolves to.
    ///
    ///Meant to be used as hover-text when a user mouses over a link.
    pub expanded_url: String,
    ///The character positions in the companion text the URL was extracted from.
    pub indices: (i32, i32),
    ///The t.co URL extracted from the companion text.
    pub url: String,
}

///Represnts a user mention extracted from another piece of text.
#[derive(Debug)]
pub struct MentionEntity {
    ///Numeric ID of the mentioned user.
    pub id: i64,
    ///Character indices where the user mention is located in the original text. The first index is
    ///the location of the @ symbol; the second is the location of the first character following
    ///the user screen name.
    pub indices: (i32, i32),
    ///Display name of the mentioned user.
    pub name: String,
    ///Screen name of the mentioned user, without the leading @ symbol.
    pub screen_name: String,
}

impl FromJson for HashtagEntity {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if !input.is_object() {
            return Err(InvalidResponse("HashtagEntity received json that wasn't an object", Some(input.to_string())));
        }

        Ok(HashtagEntity {
            indices: try!(field(input, "indices")),
            text: try!(field(input, "text")),
        })
    }
}

impl FromJson for MediaEntity {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if !input.is_object() {
            return Err(InvalidResponse("MediaEntity received json that wasn't an object", Some(input.to_string())));
        }

        Ok(MediaEntity {
            display_url: try!(field(input, "display_url")),
            expanded_url: try!(field(input, "expanded_url")),
            id: try!(field(input, "id")),
            indices: try!(field(input, "indices")),
            media_url: try!(field(input, "media_url")),
            media_url_https: try!(field(input, "media_url_https")),
            sizes: try!(field(input, "sizes")),
            source_status_id: try!(field(input, "source_status_id")),
            media_type: try!(field(input, "type")),
            url: try!(field(input, "url")),
            video_info: None,
        })
    }
}

impl FromJson for MediaType {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if let Some(s) = input.as_string() {
            if s == "photo" {
                Ok(MediaType::Photo)
            }
            else if s == "video" {
                Ok(MediaType::Video)
            }
            else if s == "animated_gif" {
                Ok(MediaType::Gif)
            }
            else {
                Err(InvalidResponse("unexpected string for MediaType", Some(s.to_string())))
            }
        }
        else {
            Err(InvalidResponse("MediaType received json that wasn't a string", Some(input.to_string())))
        }
    }
}

impl FromJson for ResizeMode {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if let Some(s) = input.as_string() {
            if s == "fit" {
                Ok(ResizeMode::Fit)
            }
            else if s == "crop" {
                Ok(ResizeMode::Crop)
            }
            else {
                Err(InvalidResponse("unexpected string for ResizeMode", Some(s.to_string())))
            }
        }
        else {
            Err(InvalidResponse("ResizeMode received json that wasn't an object", Some(input.to_string())))
        }
    }
}

impl FromJson for MediaSize {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if !input.is_object() {
            return Err(InvalidResponse("MediaSize received json that wasn't an object", Some(input.to_string())));
        }

        Ok(MediaSize {
            w: try!(field(input, "w")),
            h: try!(field(input, "h")),
            resize: try!(field(input, "resize")),
        })
    }
}

impl FromJson for MediaSizes {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if !input.is_object() {
            return Err(InvalidResponse("MediaSizes received json that wasn't an object", Some(input.to_string())));
        }

        Ok(MediaSizes {
            thumb: try!(field(input, "thumb")),
            small: try!(field(input, "small")),
            medium: try!(field(input, "medium")),
            large: try!(field(input, "large")),
        })
    }
}

impl FromJson for UrlEntity {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if !input.is_object() {
            return Err(InvalidResponse("UrlEntity received json that wasn't an object", Some(input.to_string())));
        }

        Ok(UrlEntity {
            display_url: try!(field(input, "display_url")),
            expanded_url: try!(field(input, "expanded_url")),
            indices: try!(field(input, "indices")),
            url: try!(field(input, "url")),
        })
    }
}

impl FromJson for VideoInfo {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if !input.is_object() {
            return Err(InvalidResponse("VideoInfo received json that wasn't an object", Some(input.to_string())));
        }

        Ok(VideoInfo {
            aspect_ratio: try!(field(input, "aspect_ratio")),
            duration_millis: try!(field(input, "duration_millis")),
            variants: try!(field(input, "variants")),
        })
    }
}

impl FromJson for VideoVariant {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if !input.is_object() {
            return Err(InvalidResponse("VideoVariant received json that wasn't an object", Some(input.to_string())));
        }

        Ok(VideoVariant {
            bitrate: try!(field(input, "bitrate")),
            content_type: try!(field(input, "content_type")),
            url: try!(field(input, "url")),
        })
    }
}

impl FromJson for MentionEntity {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if !input.is_object() {
            return Err(InvalidResponse("MentionEntity received json that wasn't an object", Some(input.to_string())));
        }

        Ok(MentionEntity {
            id: try!(field(input, "id")),
            indices: try!(field(input, "indices")),
            name: try!(field(input, "name")),
            screen_name: try!(field(input, "screen_name")),
        })
    }
}
<commit_msg>i was mistaken about the indices in entities, fix that<commit_after>//! Data structures containing extracted URL, mention, tag, and media information.
//!
//! These structures are meant to be received in an API call to describe the data they accompany.
//! For example, a `UrlEntity` describes a hyperlink in a tweet or user description text, and a
//! `HashtagEntity` describes a hashtag or stock symbol extracted from a tweet.
//!
//! For more information on the data in these structures, see Twitter's documentation for
//! [Entities][] and [Entities in Objects][obj].
//!
//! [Entities]: https://dev.twitter.com/overview/api/entities
//! [obj]: https://dev.twitter.com/overview/api/entities-in-twitter-objects
//!
//! ## Using indices and URLs
//!
//! When displaying text with accompanied entities, be wary about how you use the accompanied
//! indices. The indices given by Twitter reference *codepoints* within the tweet, so you'll need
//! to use something like .char_indices().enumerate() to turn them into byte offsets or to replace
//! the character range with another substring.
//!
//! Alternately, when substituting URLs for display, `str::replace` works just fine.
//!
//! ### Shortened, Display, and Expanded URLs
//!
//! URL and Media entities contain references to a URL within their parent text. However, due to
//! the nature of how Twitter handles URLs in tweets and user bios, each entity struct has three
//! URLs within it:
//!
//! - `url`: This is the `t.co` shortened URL as returned directly from twitter. This is what
//!   contributes to character count in tweets and user bios.
//! - `expanded_url`: This is the original URL the user entered in their tweet. While it is given
//!   to API client, Twitter recommends still sending users to the shortened link, for analytics
//!   purposes. Twitter Web uses this field to supply hover-text for where the URL resolves to.
//! - `display_url`: This is a truncated version of `expanded_url`, meant to be displayed inline
//!   with the parent text. This is useful to show users where the link resolves to, without
//!   potentially filling up a lot of space with the fullly expanded URL.
use common::*;
use error;
use error::Error::InvalidResponse;
use rustc_serialize::json;
use mime;

///Represents a hashtag or symbol extracted from another piece of text.
#[derive(Debug)]
pub struct HashtagEntity {
    ///The character indices where the hashtag is located. The first index is the location of the #
    ///or $ character; the second is the location of the first character following the hashtag.
    pub indices: (i32, i32),
    ///The text of the hashtag, without the leading # or $ character.
    pub text: String,
}

///Represents a piece of media attached to a tweet.
///
///The information in this struct is subtly different depending on what media is being referenced,
///and which entity container is holding this instance. For videos and GIFs, the `media_url` and
///`media_url_https` fields each link to a thumbnail image of the media, typically of the first
///frame. The real video information can be found on the `video_info` field, including various
///encodings if available.
///
///Image links available in `media_url` and `media_url_https` can be obtained in different sizes by
///appending a colon and one of the available sizes in the `MediaSizes` struct. For example, the
///cropped thumbnail can be viewed by appending `:thumb` to the end of the URL, and the full-size
///image can be viewed by appending `:large`.
#[derive(Debug)]
pub struct MediaEntity {
    ///A shortened URL to display to clients.
    pub display_url: String,
    ///An expanded version of `display_url`; links to the media display page.
    pub expanded_url: String,
    ///A numeric ID for the media.
    pub id: i64,
    ///Character indices where the media URL is located. The first index is the location of the
    ///first character of the URL; the second is the location of the first character following the
    ///URL.
    pub indices: (i32, i32),
    ///A URL pointing directly to the media file. Uses HTTP as the protocol.
    ///
    ///For videos and GIFs, this link will be to a thumbnail of the media, and the real video link
    ///will be contained in `video_info`.
    pub media_url: String,
    ///A URL pointing directly to the media file. Uses HTTPS as the protocol.
    ///
    ///For videos and GIFs, this link will be to a thumbnail of the media, and the real video link
    ///will be contained in `video_info`.
    pub media_url_https: String,
    ///Various sizes available for the media file.
    pub sizes: MediaSizes,
    ///For tweets containing media that was originally associated with a different tweet, this
    ///contains the ID of the original tweet.
    pub source_status_id: Option<i64>,
    ///The type of media being represented.
    pub media_type: MediaType,
    ///The t.co link from the original text.
    pub url: String,
    ///For media entities corresponding to videos, this contains extra information about the linked
    ///video.
    pub video_info: Option<VideoInfo>,
}

///Represents the types of media that can be attached to a tweet.
#[derive(Debug)]
pub enum MediaType {
    ///A static image.
    Photo,
    ///A video.
    Video,
    ///An animated GIF, delivered as a video without audio.
    Gif,
}

///Represents the available sizes for a media file.
#[derive(Debug)]
pub struct MediaSizes {
    ///Information for a thumbnail-sized version of the media.
    pub thumb: MediaSize,
    ///Information for a small-sized version of the media.
    pub small: MediaSize,
    ///Information for a medium-sized version of the media.
    pub medium: MediaSize,
    ///Information for a large-sized version of the media.
    pub large: MediaSize,
}

///Represents how an image has been resized for a given size variant.
#[derive(Debug)]
pub enum ResizeMode {
    ///The media was resized to fit one dimension, keeping its aspect ratio.
    Fit,
    ///The media was cropped to fit a specific resolution.
    Crop,
}

///Represents the dimensions of a media file.
#[derive(Debug)]
pub struct MediaSize {
    ///The size variant's width in pixels.
    pub w: i32,
    ///The size variant's height in pixels.
    pub h: i32,
    ///The method used to obtain the given dimensions.
    pub resize: ResizeMode,
}

///Represents metadata specific to videos.
#[derive(Debug)]
pub struct VideoInfo {
    ///The aspect ratio of the video.
    pub aspect_ratio: (i32, i32),
    ///The duration of the video, in milliseconds.
    ///
    ///This field is not given for animated GIFs.
    pub duration_millis: Option<i32>,
    ///Information about various encodings available for the video.
    pub variants: Vec<VideoVariant>,
}

///Represents information about a specific encoding of a video.
#[derive(Debug)]
pub struct VideoVariant {
    ///The bitrate of the video. This value is present for GIFs, but it will be zero.
    pub bitrate: Option<i32>,
    ///The file format of the video variant.
    pub content_type: mime::Mime,
    ///The URL for the video variant.
    pub url: String,
}

///Represents a link extracted from another piece of text.
#[derive(Debug)]
pub struct UrlEntity {
    ///A truncated URL meant to be displayed inline with the text.
    pub display_url: String,
    ///The URL that the t.co URL resolves to.
    ///
    ///Meant to be used as hover-text when a user mouses over a link.
    pub expanded_url: String,
    ///The character positions in the companion text the URL was extracted from.
    pub indices: (i32, i32),
    ///The t.co URL extracted from the companion text.
    pub url: String,
}

///Represnts a user mention extracted from another piece of text.
#[derive(Debug)]
pub struct MentionEntity {
    ///Numeric ID of the mentioned user.
    pub id: i64,
    ///Character indices where the user mention is located in the original text. The first index is
    ///the location of the @ symbol; the second is the location of the first character following
    ///the user screen name.
    pub indices: (i32, i32),
    ///Display name of the mentioned user.
    pub name: String,
    ///Screen name of the mentioned user, without the leading @ symbol.
    pub screen_name: String,
}

impl FromJson for HashtagEntity {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if !input.is_object() {
            return Err(InvalidResponse("HashtagEntity received json that wasn't an object", Some(input.to_string())));
        }

        Ok(HashtagEntity {
            indices: try!(field(input, "indices")),
            text: try!(field(input, "text")),
        })
    }
}

impl FromJson for MediaEntity {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if !input.is_object() {
            return Err(InvalidResponse("MediaEntity received json that wasn't an object", Some(input.to_string())));
        }

        Ok(MediaEntity {
            display_url: try!(field(input, "display_url")),
            expanded_url: try!(field(input, "expanded_url")),
            id: try!(field(input, "id")),
            indices: try!(field(input, "indices")),
            media_url: try!(field(input, "media_url")),
            media_url_https: try!(field(input, "media_url_https")),
            sizes: try!(field(input, "sizes")),
            source_status_id: try!(field(input, "source_status_id")),
            media_type: try!(field(input, "type")),
            url: try!(field(input, "url")),
            video_info: None,
        })
    }
}

impl FromJson for MediaType {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if let Some(s) = input.as_string() {
            if s == "photo" {
                Ok(MediaType::Photo)
            }
            else if s == "video" {
                Ok(MediaType::Video)
            }
            else if s == "animated_gif" {
                Ok(MediaType::Gif)
            }
            else {
                Err(InvalidResponse("unexpected string for MediaType", Some(s.to_string())))
            }
        }
        else {
            Err(InvalidResponse("MediaType received json that wasn't a string", Some(input.to_string())))
        }
    }
}

impl FromJson for ResizeMode {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if let Some(s) = input.as_string() {
            if s == "fit" {
                Ok(ResizeMode::Fit)
            }
            else if s == "crop" {
                Ok(ResizeMode::Crop)
            }
            else {
                Err(InvalidResponse("unexpected string for ResizeMode", Some(s.to_string())))
            }
        }
        else {
            Err(InvalidResponse("ResizeMode received json that wasn't an object", Some(input.to_string())))
        }
    }
}

impl FromJson for MediaSize {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if !input.is_object() {
            return Err(InvalidResponse("MediaSize received json that wasn't an object", Some(input.to_string())));
        }

        Ok(MediaSize {
            w: try!(field(input, "w")),
            h: try!(field(input, "h")),
            resize: try!(field(input, "resize")),
        })
    }
}

impl FromJson for MediaSizes {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if !input.is_object() {
            return Err(InvalidResponse("MediaSizes received json that wasn't an object", Some(input.to_string())));
        }

        Ok(MediaSizes {
            thumb: try!(field(input, "thumb")),
            small: try!(field(input, "small")),
            medium: try!(field(input, "medium")),
            large: try!(field(input, "large")),
        })
    }
}

impl FromJson for UrlEntity {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if !input.is_object() {
            return Err(InvalidResponse("UrlEntity received json that wasn't an object", Some(input.to_string())));
        }

        Ok(UrlEntity {
            display_url: try!(field(input, "display_url")),
            expanded_url: try!(field(input, "expanded_url")),
            indices: try!(field(input, "indices")),
            url: try!(field(input, "url")),
        })
    }
}

impl FromJson for VideoInfo {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if !input.is_object() {
            return Err(InvalidResponse("VideoInfo received json that wasn't an object", Some(input.to_string())));
        }

        Ok(VideoInfo {
            aspect_ratio: try!(field(input, "aspect_ratio")),
            duration_millis: try!(field(input, "duration_millis")),
            variants: try!(field(input, "variants")),
        })
    }
}

impl FromJson for VideoVariant {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if !input.is_object() {
            return Err(InvalidResponse("VideoVariant received json that wasn't an object", Some(input.to_string())));
        }

        Ok(VideoVariant {
            bitrate: try!(field(input, "bitrate")),
            content_type: try!(field(input, "content_type")),
            url: try!(field(input, "url")),
        })
    }
}

impl FromJson for MentionEntity {
    fn from_json(input: &json::Json) -> Result<Self, error::Error> {
        if !input.is_object() {
            return Err(InvalidResponse("MentionEntity received json that wasn't an object", Some(input.to_string())));
        }

        Ok(MentionEntity {
            id: try!(field(input, "id")),
            indices: try!(field(input, "indices")),
            name: try!(field(input, "name")),
            screen_name: try!(field(input, "screen_name")),
        })
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Jonathan Anderson
 *
 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
 * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
 * http://opensource.org/licenses/MIT>, at your option. This file may not be
 * copied, modified, or distributed except according to those terms.
 */

//! Dissection of Ethernet (IEEE 802.3) frames.

use {
    Endianness,
    Error,
    NamedValue,
    Protocol,
    RawBytes,
    Result,
    Val,
    ip,
    unsigned,
};

/// The IEEE 802.3 Ethernet protocol.
pub struct Ethernet;

/// Parse a six-byte MAC address, which can be encoded as, e.g., ff:ff:ff:ff:ff:ff.
pub fn mac_address(raw: &[u8]) -> Result<Val> {
    if raw.len() != 6 {
        return Err(Error::InvalidData(format!["MAC address should have 6 B, not {}",
                                              raw.len()]));
    }

    let encoded = raw
                  .iter()
                  .map(|b| format!["{:02x}", b])
                  .collect::<Vec<String>>()
                  .join(":")
                  ;

    Ok(Val::Address { bytes: raw.to_vec(), encoded: encoded })
}

impl Protocol for Ethernet {
    fn short_name(&self) -> &str { "Ethernet" }
    fn full_name(&self) -> &str { "IEEE 802.3 Ethernet" }
    fn dissect(&self, data: &[u8]) -> Result {
        if data.len() < 14 {
            return Err(Error::Underflow { expected: 14, have: data.len(),
                message: "An Ethernet frame must be at least 14 B".to_string() })
        }

        let mut values:Vec<NamedValue> = vec![];
        values.push(("Destination".to_string(), mac_address(&data[0..6])));
        values.push(("Source".to_string(), mac_address(&data[6..12])));

        // The type/length field might be either a type or a length.
        let tlen = unsigned(&data[12..14], Endianness::BigEndian);
        let remainder = &data[14..];

        match tlen {
            Ok(i) if i <= 1500 => {
                values.push(("Length".to_string(), Ok(Val::Unsigned(i))));
            },

            Ok(i) => {
                let protocol: Box<Protocol> = match i {
                    // TODO: use the simple 'box' syntax once it hits stable
                    0x800 => Box::new(ip::IPv4),
                    0x806 => RawBytes::boxed("ARP", "Address Resolution Protocol"),
                    0x8138 => RawBytes::boxed("IPX", "Internetwork Packet Exchange"),
                    0x86dd => RawBytes::boxed("IPv6", "Internet Protocol version 6"),

                    _ => Box::new(RawBytes::unknown_protocol(&format!["0x{:x}", i])),
                };

                let protoname = protocol.short_name().to_string();
                let description = protocol.full_name().to_string();

                values.push(("Type".to_string(), Ok(Val::String(protoname))));
                values.push((description, protocol.dissect(remainder)));
            },
            Err(e) => {
                values.push(("Type/length".to_string(), Err(e)));
            },
        };

        Ok(Val::Subpacket(values))
    }
}
<commit_msg>Add parser for the Ethernet test protocol.<commit_after>/*
 * Copyright 2015 Jonathan Anderson
 *
 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
 * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
 * http://opensource.org/licenses/MIT>, at your option. This file may not be
 * copied, modified, or distributed except according to those terms.
 */

//! Dissection of Ethernet (IEEE 802.3) frames.

use {
    Endianness,
    Error,
    NamedValue,
    Protocol,
    RawBytes,
    Result,
    Val,
    ip,
    unsigned,
};

/// The IEEE 802.3 Ethernet protocol.
pub struct Ethernet;

/// Parse a six-byte MAC address, which can be encoded as, e.g., ff:ff:ff:ff:ff:ff.
pub fn mac_address(raw: &[u8]) -> Result<Val> {
    if raw.len() != 6 {
        return Err(Error::InvalidData(format!["MAC address should have 6 B, not {}",
                                              raw.len()]));
    }

    let encoded = raw
                  .iter()
                  .map(|b| format!["{:02x}", b])
                  .collect::<Vec<String>>()
                  .join(":")
                  ;

    Ok(Val::Address { bytes: raw.to_vec(), encoded: encoded })
}

impl Protocol for Ethernet {
    fn short_name(&self) -> &str { "Ethernet" }
    fn full_name(&self) -> &str { "IEEE 802.3 Ethernet" }
    fn dissect(&self, data: &[u8]) -> Result {
        if data.len() < 14 {
            return Err(Error::Underflow { expected: 14, have: data.len(),
                message: "An Ethernet frame must be at least 14 B".to_string() })
        }

        let mut values:Vec<NamedValue> = vec![];
        values.push(("Destination".to_string(), mac_address(&data[0..6])));
        values.push(("Source".to_string(), mac_address(&data[6..12])));

        // The type/length field might be either a type or a length.
        let tlen = unsigned(&data[12..14], Endianness::BigEndian);
        let remainder = &data[14..];

        match tlen {
            Ok(i) if i <= 1500 => {
                values.push(("Length".to_string(), Ok(Val::Unsigned(i))));
            },

            Ok(i) => {
                let protocol: Box<Protocol> = match i {
                    // TODO: use the simple 'box' syntax once it hits stable
                    0x800 => Box::new(ip::IPv4),
                    0x806 => RawBytes::boxed("ARP", "Address Resolution Protocol"),
                    0x8138 => RawBytes::boxed("IPX", "Internetwork Packet Exchange"),
                    0x86dd => RawBytes::boxed("IPv6", "Internet Protocol version 6"),

                    0x9000 => Box::new(TestProtocol),

                    _ => Box::new(RawBytes::unknown_protocol(&format!["0x{:x}", i])),
                };

                let protoname = protocol.short_name().to_string();
                let description = protocol.full_name().to_string();

                values.push(("Type".to_string(), Ok(Val::String(protoname))));
                values.push((description, protocol.dissect(remainder)));
            },
            Err(e) => {
                values.push(("Type/length".to_string(), Err(e)));
            },
        };

        Ok(Val::Subpacket(values))
    }
}

/// Testing protocol from the Xerox Blue Book.
///
/// A test packet can contain data to forward to another Ethernet address and/or
/// a reply to a previous test packet. See http://www.mit.edu/~jhawk/ctp.pdf for details.
pub struct TestProtocol;

enum TestMessage<'a> {
    Reply { receipt_number: Result<u64>, data: &'a [u8] },
    ForwardData { dest: Result<Val>, message: Result<Box<TestMessage<'a>>> },
}

impl Protocol for TestProtocol {
    fn short_name(&self) -> &str { "Loopback" }
    fn full_name(&self) -> &str { "Ethernet Configuration Testing Protocol" }
    fn dissect(&self, data: &[u8]) -> Result {
        let mut values:Vec<NamedValue> = vec![];

        let skip_count = unsigned(&data[0..2], Endianness::BigEndian);
        values.push(("Skip count".to_string(), skip_count.map(Val::Unsigned)));

        let top_message =
            TestMessage::parse(&data[2..])
                        .map(TestMessage::as_val)
                        .unwrap_or_else(|e| ("Error".to_string(), Err(e)))
                        ;

        values.push(top_message);

        Ok(Val::Subpacket(values))
    }
}

impl <'a> TestMessage <'a> {
    fn name(&self) -> &str {
        match self {
            &TestMessage::Reply{ .. } => "Reply Message",
            &TestMessage::ForwardData{ .. } => "Forward Data Message",
        }
    }

    fn as_val(self) -> NamedValue {
        let name = self.name().to_string();
        let val = match self {
            TestMessage::Reply{ receipt_number, data } =>
                vec![
                    ("Function Code".to_string(), Ok(Val::Unsigned(1))),
                    ("Receipt Number".to_string(), receipt_number.map(Val::Unsigned)),
                    ("Data".to_string(), Ok(Val::Bytes(data.to_vec()))),
                ],

            TestMessage::ForwardData{ dest, message } => {
                let data = match message.map(|b| (*b).as_val()) {
                    Ok((k,v)) => Ok(Val::Subpacket(vec![(k,v)])),
                    Err(e) => Err(e),
                };

                vec![
                    ("Function Code".to_string(), Ok(Val::Unsigned(2))),
                    ("Forward Address".to_string(), dest),
                    ("Data".to_string(), data),
                ]
            },
        };

        (name, Ok(Val::Subpacket(val)))
    }

    fn parse(data: &[u8]) -> Result<TestMessage> {
        let function_code = unsigned(&data[0..2], Endianness::LittleEndian);
        match function_code {
            Ok(1) => Ok({
                let receipt_number = unsigned(&data[2..4], Endianness::LittleEndian);

                TestMessage::Reply{
                    receipt_number: receipt_number,
                    data: &data[4..],
                }
            }),

            Ok(2) => Ok({
                TestMessage::ForwardData{
                    dest: mac_address(&data[2..8]),
                    message: TestMessage::parse(&data[8..]).map(Box::new),
                }
            }),

            Ok(x) => Err(Error::InvalidData(format!["invalid function code: {}", x])),
            Err(e) => Err(e),
        }
    }
}
<|endoftext|>


<commit_before>use std::sync::atomic;
use std::hash::Hash;
use crossbeam::mem::epoch::{Atomic, Owned, Shared};
use sponge::Sponge;

const ORDERING: atomic::Ordering = atomic::Ordering::Relaxed;

pub struct Pair<K, V> {
    key: K,
    val: V,
}

enum Node<K, V> {
    Leaf(Pair<K, V>),
    Branch(Table<K, V>),
}

impl<K, V> Atomic<Node<K, V>> {
    /// Insert a key-value pair into the node without squeezing the sponge.
    fn insert(&self, pair: Pair<K, V>, sponge: Sponge) -> Option<V> {
        // If the entry was empty, we will set it to a leaf with our key-value pair. If not, we
        // will handle the respective cases manually.
        match self.cas(None, Some(Owned::new(Node::Leaf(pair))), ORDERING) {
            // We successfully set an empty entry to the new key-value pair. This of course implies
            // that the key didn't exist at the time.
            Ok(()) => None,
            // A node was found, so we call `insert` on it.
            Err(Some(node)) => node.insert(pair, sponge),
            // It is not possible to get `Err(None)` as that was the value we are CAS-ing against.
            Err(None) => unreachable!(),
        }
    }

    fn remove(&self, key: &K, sponge: Sponge) -> Option<V> {
        // Load the node and handle its cases.
        if let Some(node) = self.load(ORDERING) {
            // A node was found.
            node.remove(key, sponge);
        } else {
            // No node was found; nothing to remove.
            None
        }
    }

    fn for_each<F: Fn(K, V)>(&self, f: F) {
        if let Some(node) = self.load(ORDERING) {
            node.for_each(f);
        }
    }

    fn take_each<F: Fn(K, V)>(&self, f: F) {
        if let Some(node) = self.swap(Owned::new(None)) {
            node.take_each(f);
        }
    }
}

impl<'a, K, V> Shared<'a, Node<K, V>> {
    fn insert(&self, pair: Pair<K, V>, sponge: Sponge) -> Option<V> {
        match self {
            // There is a branch table. Insert the key-value pair into it.
            Node::Branch(table) => table.insert(pair, sponge),
            // The key exists, so we can simply update the value.
            Node::Leaf(Pair { key }) if key == pair.key => Some(found_val.swap(pair.val, ORDERING)),
            // Another key exists at the position, so we need to extend the table with a branch,
            // containing both entries.
            Node::Leaf(mut old_pair) => {
                // The reason we use recursion is that the entry could be deleted and another
                // re-inserted on its place. While this in theory acts like a spin-lock, I doubt it
                // will EVER run more than one time in the real world, as it would require the
                // entry to be removed in another thread at the same time, while a new one being
                // inserted (requiring a whole lookup!) in the meantime on the same very place. It
                // is pretty damn unlikely, but it is needed for correctness nonetheless.

                // Create a table that contains both the key-value pair we're inserting and the one
                // on the place, where we want to insert.
                let new_table = Table::two_entries(pair, sponge, old_pair, {
                    // Generate the sponge of the old pair's key.
                    let mut old_sponge = Sponge::new(&old_pair.key);
                    // Truncate the sponge, so it is at the point, where we are right now, and the
                    // collision is happening.
                    old_sponge.matching(&sponge);

                    old_sponge
                });
                // We try to update the current entry to our table. The reason we use CAS is that
                // we want to ensure that the entry was not changed in the meantime, so we compare
                // to `old_pair`, which must be a leaf with the old key-value pair, as the epoch
                // system ensures that it doesn't change while we have the reference (therefore
                // there is no ABA problem here). So in essence, we check that our value is still
                // the same as the original, and if it is we update it. If not, we must handle the
                // new value, which could be anything else (e.g. another thread could have extended
                // the leaf too because it is inserting the same pair).
                match self.cas(old_pair, Some(Owned::new(Node::Branch(new_table))), ORDERING) {
                    // Our update went smooth, and we have extended the leaf to a branch,
                    // meaning that there now is a subtable containing the two key-value pairs.
                    Ok(()) => None,
                    // Something else was inserted in the meantime, so we must re-do the
                    // insertions.
                    Err(Some(node)) => node.insert(pair, sponge),
                    // The entry was removed, so we will again recurse to re-do.
                    Err(None) => self.insert(pair, sponge),
                }
            },
        }
    }

    fn remove(&self, key: &K, sponge: Sponge) -> Option<V> {
        match self {
            // There is a branch, so we must remove the key in the sub-table.
            Node::Branch(table) => table.remove(key, sponge),
            // There was a node with the key, which we will try to remove. We use CAS in order to
            // make sure that it is the same node as the one we read (`self`), otherwise we might
            // remove a wrong node.
            Node::Leaf(Pair { key: found_key, val }) if found_key == key
                => match self.cas(Some(self), None, ORDERING) {
                // Removing the node succeeded: It wasn't changed in the meantime.
                Ok(()) => Some(val),
                // The node was removed by another thread, so our job is done. We don't need to do
                // anything.
                Err(None) => None,
                // To solve the ABA problem, we're unfortunately forced to recurse/loop. As in
                // `insert()`, this is theoretically a spin-lock, however it is very rare to run
                // more than once, as it requires another thread to have removed the leaf and then
                // inserted a new one in the short meantime spanning only a few CPU cycles.
                Err(Some(node)) => node.remove(),
            },
            // A node with a non-matching key was found. Hence, we have nothing to remove.
            Node::Leaf(..) => None,
        }
    }

    fn for_each<F: Fn(K, V)>(&self, f: F) {
        match self {
            Node::Leaf(Pair { key, val }) => f(key, val),
            Node::Branch(table) => table.for_each(f),
        }
    }

    fn take_each<F: Fn(K, V)>(&self, f: F) {
        match self {
            Node::Leaf(Pair { key, val }) => f(key, val),
            Node::Branch(table) => table.take_each(f),
        }
    }
}

#[derive(Default)]
pub struct Table<K, V>  {
    table: [Atomic<Node<K, V>>; 256],
}

impl<K, V> Table<K, V> {
    fn two_entries(pair_a: Pair<K, V>, sponge_a: Sponge, pair_b: Pair<K, V>, sponge_b: Sponge)
        -> Table<K, V> {
        // Start with an empty table.
        let mut table = Table::default();

        // Squeeze the two sponges.
        let pos_a = sponge_a.squeeze();
        let pos_b = sponge_b.squeeze();

        if pos_a != pos_b {
            // The two position did not collide, so we can insert the two pairs at the respective
            // positions
            table[pos_a as usize] = Atomic::new(Some(Owned::new(Node::Leaf(pair_a))));
            table[pos_b as usize] = Atomic::new(Some(Owned::new(Node::Leaf(pair_b))));
        } else {
            // The two positions from the sponge matched, so we must place another branch.
            table[pos_a as usize] = Atomic::new(Some(Owned::new(Node::Branch(
                Table::two_entries(pair_a, sponge_a, pair_b, sponge_b)
            ))));
        }
    }

    pub fn get(&self, key: &K, sponge: Sponge) -> Option<Shared<V>> {
        // Load the entry and handle the respective cases.
        match self.table[sponge.squeeze()].load(ORDERING) {
            // The entry was a leaf and the keys match, so we can return the entry's value.
            Some(Node::Leaf(Pair { found_key, found_val })) if key == found_key => Some(found_val),
            // The entry is a branch with another table, so we recurse and look up in said
            // subtable.
            Some(Node::Branch(table)) => table.get(key, sponge),
            // The entry is either a leaf but doesn't match, or is a null pointer, meaning there is
            // no entry with the key.
            Some(Node::Leaf(_)) | None => None,
        }
    }

    pub fn remove(&self, key: &K, sponge: Sponge) -> Option<V> {
        // We squeeze the sponge to get the right entry of our table, in which we will potentially
        // remove the key.
        self.table[sponge.squeeze()].remove(key, sponge);
    }

    pub fn insert(&self, pair: Pair<K, V>, sponge: Sponge) -> Option<V> {
        // We squeeze the sponge to get the right entry of our table, in which we will insert our
        // key-value pair.
        self.table[sponge.squeeze()].load(ORDERING).insert(pair, sponge)
    }

    pub fn for_each<F: Fn(K, V)>(&self, f: F) {
        for i in self.table {
            i.for_each(f);
        }
    }

    pub fn take_each<F: Fn(K, V)>(&self, f: F) {
        for i in self.table {
            i.take_each(f);
        }
    }
}
<commit_msg>Make `AtomicHashMap` completely atomic through distinguishing between logical and physical updates.<commit_after>use std::sync::atomic;
use std::hash::Hash;
use crossbeam::mem::epoch::{Atomic, Owned, Shared};
use sponge::Sponge;

const ORDERING: atomic::Ordering = atomic::Ordering::Relaxed;

pub struct Pair<K, V> {
    key: K,
    val: V,
}

#[derive(Default)]
pub struct Table<K, V>  {
    table: [Atomic<Node<K, V>>; 256],
}

impl<K, V> Table<K, V> {
    fn two_entries(pair_a: Pair<K, V>, sponge_a: Sponge, pair_b: Pair<K, V>, sponge_b: Sponge)
        -> Table<K, V> {
        // Start with an empty table.
        let mut table = Table::default();

        // Squeeze the two sponges.
        let pos_a = sponge_a.squeeze();
        let pos_b = sponge_b.squeeze();

        if pos_a != pos_b {
            // The two position did not collide, so we can insert the two pairs at the respective
            // positions
            table[pos_a as usize] = Atomic::new(Some(Owned::new(Node::Leaf(pair_a))));
            table[pos_b as usize] = Atomic::new(Some(Owned::new(Node::Leaf(pair_b))));
        } else {
            // The two positions from the sponge matched, so we must place another branch.
            table[pos_a as usize] = Atomic::new(Some(Owned::new(Node::Branch(
                Table::two_entries(pair_a, sponge_a, pair_b, sponge_b)
            ))));
        }
    }

    pub fn get(&self, key: &K, sponge: Sponge) -> Option<Shared<V>> {
        // Load the entry and handle the respective cases.
        match self.table[sponge.squeeze()].load(ORDERING) {
            // The entry was a leaf and the keys match, so we can return the entry's value.
            Some(Node::Leaf(Pair { found_key, found_val })) if key == found_key => Some(found_val),
            // The entry is a branch with another table, so we recurse and look up in said
            // subtable.
            Some(Node::Branch(table)) => table.get(key, sponge),
            // The entry is either a leaf but doesn't match, or is a null pointer, meaning there is
            // no entry with the key.
            Some(Node::Leaf(_)) | None => None,
        }
    }

    pub fn remove(&self, key: &K, sponge: Sponge) -> Option<V> {
        // We squeeze the sponge to get the right entry of our table, in which we will potentially
        // remove the key.
        self.table[sponge.squeeze()].remove(key, sponge);
    }

    pub fn insert(&self, pair: Pair<K, V>, sponge: Sponge) -> Option<V> {
        // We squeeze the sponge to get the right entry of our table, in which we will insert our
        // key-value pair.
        self.table[sponge.squeeze()].load(ORDERING).insert(pair, sponge)
    }

    pub fn for_each<F: Fn(K, V)>(&self, f: F) {
        for i in self.table {
            i.for_each(f);
        }
    }

    pub fn take_each<F: Fn(K, V)>(&self, f: F) {
        for i in self.table {
            i.take_each(f);
        }
    }
}

enum Node<K, V> {
    Leaf(Pair<K, V>),
    Branch(Table<K, V>),
}

impl<K, V> Atomic<Node<K, V>> {
    /// Insert a key-value pair into the node without squeezing the sponge.
    fn insert(&self, pair: Pair<K, V>, sponge: Sponge) -> Option<V> {
        // If the entry was empty, we will set it to a leaf with our key-value pair. If not, we
        // will handle the respective cases manually.
        match self.cas(None, Some(Owned::new(Node::Leaf(pair))), ORDERING) {
            // We successfully set an empty entry to the new key-value pair. This of course implies
            // that the key didn't exist at the time.
            Ok(()) => None,
            // There is a branch table. Insert the key-value pair into it.
            Err(Some(Node::Branch(table))) => table.insert(pair, sponge),
            // The key exists, so we can simply update the value.
            Err(Some(Node::Leaf(found_pair))) if found_pair.key == pair.key
                // The reason we use CAS here is that the key could have been removed or updated
                // after we read it initially. If so, we won't update it for the reason that it was
                // logically inserted (`insert` was called) before it being removed or updated.
                // Hence the other version is used, and we don't touch it.
                => match self.cas(Some(Node::Leaf(found_pair)), Some(Node::Leaf(pair)), ORDERING) {
                    // Everything went well and the leaf was updated.
                    Ok(()) => Some(found_pair.val),
                    // Another node was inserted here, meaning that the table is simply extended,
                    // and the insertion is still potentially valid, so we try to insert in the
                    // inner table.
                    Err(Some(Node::Branch(table))) => table.insert(pair, sponge),
                    // The node was either modified or removed (and maybe replaced by another
                    // node). The insertion was hence invalidated, and we simply pretend we
                    // replaced the leaf we read earlier (even though that was another thread's
                    // work), which we did "logically" (at the point the leaf was read, it had
                    // matching keys).
                    _ => Some(found_pair.val),
                },
            // Another key exists at the position, so we need to extend the table with a branch,
            // containing both entries.
            Err(Some(Node::Leaf(mut old_pair))) => {
                // Create a table that contains both the key-value pair we're inserting and the one
                // on the place, where we want to insert.
                let new_table = Table::two_entries(pair, sponge, old_pair, {
                    // Generate the sponge of the old pair's key.
                    let mut old_sponge = Sponge::new(&old_pair.key);
                    // Truncate the sponge, so it is at the point, where we are right now, and the
                    // collision is happening.
                    old_sponge.matching(&sponge);

                    old_sponge
                });
                // We try to update the current entry to our table. The reason we use CAS is that
                // we want to ensure that the entry was not changed in the meantime, so we compare
                // to `old_pair`, which must be a leaf with the old key-value pair, as the epoch
                // system ensures that it doesn't change while we have the reference (therefore
                // there is no ABA problem here). So in essence, we check that our value is still
                // the same as the original, and if it is we update it. If not, we must handle the
                // new value, which could be anything else (e.g. another thread could have extended
                // the leaf too because it is inserting the same pair).
                match self.cas(old_pair, Some(Owned::new(Node::Branch(new_table))), ORDERING) {
                    // Our update went smooth, and we have extended the leaf to a branch,
                    // meaning that there now is a subtable containing the two key-value pairs.
                    Ok(()) => None,
                    // The update failed. Another thread extended the table, so we will simply use
                    // the table from the new leaf that the other thread created.
                    Err(Some(Node::Branch(table))) => table.insert(pair, sponge),
                    // The node was either updated or removed in the meantime (i.e. before we
                    // logically inserted/`insert` was called), hence we assume this has affected
                    // the logical insertion, which therefore means that it shouldn't be written as
                    // it was overwritten. As a result, we simply return `None`, marking that no
                    // value was replaced.
                    _ => None,
                }
            },
            // It is not possible to get `Err(None)` as that was the value we are CAS-ing against.
            Err(None) => unreachable!(),
        }
    }

    fn remove(&self, key: &K, sponge: Sponge) -> Option<V> {
        // Load the node and handle its cases.
        match self.load(ORDERING) {
            // There is a branch, so we must remove the key in the sub-table.
            Some(Node::Branch(table)) => table.remove(key, sponge),
            // There was a node with the key, which we will try to remove. We use CAS in order to
            // make sure that it is the same node as the one we read (`self`), otherwise we might
            // remove a wrong node.
            Some(Node::Leaf(Pair { key: found_key, val })) if found_key == key
                => match self.cas(Some(self), None, ORDERING) {
                // Removing the node succeeded: It wasn't changed in the meantime.
                Ok(()) => Some(val),
                Err(Some(Node::Branch(table))) => table.remove(key, sponge),
                // The node was removed or updated by another thread, so our removal is "logically"
                // done, as it was overruled by another thread in the meantime, either by insertion
                // or removal of the same node. We return the value it had at time of the logical
                // removal (i.e. when `remove` was called), as the function acts as if it removed
                // the node.
                _ => Some(val),
            },
            // A node with a non-matching key was found. Hence, we have nothing to remove.
            Some(Node::Leaf(..)) => None,
            // No node was found; nothing to remove.
            None => None,
        }
    }

    fn for_each<F: Fn(K, V)>(&self, f: F) {
        match self.load(ORDERING) {
            Some(Node::Leaf(Pair { key, val })) => f(key, val),
            Some(Node::Branch(table)) => table.for_each(f),
        }
    }

    fn take_each<F: Fn(K, V)>(&self, f: F) {
        match self.load(ORDERING) {
            Some(Node::Leaf(Pair { key, val })) => f(key, val),
            Some(Node::Branch(table)) => table.take_each(f),
        }
    }
}
<|endoftext|>