<commit_before>extern crate failure;
#[macro_use]
extern crate failure_derive;
extern crate getopts;
extern crate libc;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate varlink;

use failure::Fail;
use org_example_ping::*;
use std::collections::HashMap;
use std::env;
use std::io::{self, BufRead, BufReader, Error, Read, Write};
use std::process::exit;
use std::sync::{Arc, RwLock};
use std::thread;
use varlink::{Call, Connection, ConnectionHandler, Listener, ServerStream, VarlinkService};

// Dynamically build the varlink rust code.
mod org_example_ping;

#[cfg(test)]
mod test;

// Main

fn print_usage(program: &str, opts: &getopts::Options) {
    let brief = format!("Usage: {} [--varlink=<address>] [--client]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<_> = env::args().collect();
    let program = args[0].clone();

    let mut opts = getopts::Options::new();
    opts.optopt("", "varlink", "varlink address URL", "<address>");
    opts.optflag("", "client", "run in client mode");
    opts.optflag("h", "help", "print this help menu");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            eprintln!("{}", f.to_string());
            print_usage(&program, &opts);
            return;
        }
    };

    if matches.opt_present("h") {
        print_usage(&program, &opts);
        return;
    }

    let client_mode = matches.opt_present("client");

    let ret = if client_mode {
        let connection = match matches.opt_str("varlink") {
            None => Connection::with_activate(&format!("{} --varlink=$VARLINK_ADDRESS", program))
                .unwrap(),
            Some(address) => Connection::with_address(&address).unwrap(),
        };
        run_client(connection)
    } else {
        if let Some(address) = matches.opt_str("varlink") {
            run_server(&address, 0, true).map_err(|e| e.into())
        } else {
            print_usage(&program, &opts);
            eprintln!("Need varlink address in server mode.");
            exit(1);
        }
    };
    exit(match ret {
        Ok(_) => 0,
        Err(err) => {
            eprintln!("error: {:?}", err);
            1
        }
    });
}

// Client

fn run_client(connection: Arc<RwLock<varlink::Connection>>) -> Result<()> {
    {
        let mut iface = VarlinkClient::new(connection.clone());
        let ping = String::from("Test");

        let reply = iface.ping(ping.clone()).call()?;
        assert_eq!(ping, reply.pong);
        println!("Pong: '{}'", reply.pong);

        let reply = iface.ping(ping.clone()).call()?;
        assert_eq!(ping, reply.pong);
        println!("Pong: '{}'", reply.pong);

        let reply = iface.ping(ping.clone()).call()?;
        assert_eq!(ping, reply.pong);
        println!("Pong: '{}'", reply.pong);

        let _reply = iface.upgrade().call()?;
        println!("Client: upgrade()");
    }
    {
        let mut conn = connection.write().unwrap();
        let mut writer = conn.writer.take().unwrap();
        writer.write_all("test test\nEnd\n".as_bytes())?;
        conn.writer = Some(writer);
        let mut buf = Vec::new();
        let mut reader = conn.reader.take().unwrap();
        if reader.read_until('\n' as u8, &mut buf)? == 0 {
            // incomplete data, in real life, store all bytes for the next call
            // for now just read the rest
            reader.read_to_end(&mut buf)?;
        };
        eprintln!("Client: upgraded got: {}", String::from_utf8_lossy(&buf));
        conn.reader = Some(reader);
    }
    Ok(())
}

// Server

struct MyOrgExamplePing;

impl org_example_ping::VarlinkInterface for MyOrgExamplePing {
    fn ping(&self, call: &mut Call_Ping, ping: String) -> varlink::Result<()> {
        call.reply(ping)
    }

    fn upgrade(&self, call: &mut Call_Upgrade) -> varlink::Result<()> {
        eprintln!("Server: called upgrade");
        call.to_upgraded();
        call.reply()
    }

    // An upgraded connection has its own application specific protocol.
    // Normally, there is no way back to the varlink protocol with this connection.
    fn call_upgraded(&self, call: &mut Call, bufreader: &mut BufRead) -> varlink::Result<Vec<u8>> {
        let mut buf = String::new();
        let len = bufreader.read_line(&mut buf)?;
        if len == 0 {
            eprintln!("Server: upgraded got: none");
            // incomplete data, in real life, store all bytes for the next call
            // return Ok(buf.as_bytes().to_vec());
            return Err(varlink::ErrorKind::ConnectionClosed.into());
        }
        eprintln!("Server: upgraded got: {}", buf);

        call.writer.write_all("server reply: ".as_bytes())?;
        call.writer.write_all(buf.as_bytes())?;

        Ok(Vec::new())
    }
}

struct FdTracker {
    stream: Option<ServerStream>,
    buffer: Option<Vec<u8>>,
}

impl FdTracker {
    fn shutdown(&mut self) -> varlink::Result<()> {
        self.stream.as_mut().unwrap().shutdown()
    }
    fn chain_buffer(&mut self, buf: &mut Vec<u8>) {
        self.buffer.as_mut().unwrap().append(buf);
    }
    fn fill_buffer(&mut self, buf: &Vec<u8>) {
        self.buffer.as_mut().unwrap().clone_from(buf);
    }
    fn buf_as_slice(&mut self) -> &[u8] {
        self.buffer.as_mut().unwrap().as_slice()
    }
    fn write(&mut self, out: &[u8]) -> io::Result<usize> {
        self.stream.as_mut().unwrap().write(out.as_ref())
    }
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.stream.as_mut().unwrap().read(buf)
    }
}

pub fn listen_multiplex<S: ?Sized + AsRef<str>, H: ::ConnectionHandler + Send + Sync + 'static>(
    handler: H,
    address: &S,
    accept_timeout: u64,
) -> varlink::Result<()> {
    let timeout: i32 = match accept_timeout {
        0 => -1,
        n => (n * 1000) as i32,
    };

    let handler = Arc::new(handler);
    let mut fdmap: HashMap<i32, FdTracker> = HashMap::new();
    let mut fds = Vec::new();
    let mut threads = Vec::new();
    let listener = Listener::new(address)?;
    listener.set_nonblocking(true)?;

    fds.push(libc::pollfd {
        fd: listener.as_raw_fd(),
        revents: 0,
        events: libc::POLLIN,
    });

    loop {
        // Read activity on listening socket
        if fds[0].revents != 0 {
            let mut client = listener.accept(0)?;

            client.set_nonblocking(true)?;

            let fd = client.as_raw_fd();
            fds.push(libc::pollfd {
                fd,
                revents: 0,
                events: libc::POLLIN,
            });

            fdmap.insert(
                fd,
                FdTracker {
                    stream: Some(client),
                    buffer: Some(Vec::new()),
                },
            );
        }

        // Store which indices to remove
        let mut indices_to_remove = vec![];

        // Check client connections ...
        for i in 1..fds.len() {
            if fds[i].revents != 0 {
                let mut upgraded_iface: Option<String> = None;
                let mut tracker = fdmap.get_mut(&fds[i].fd).unwrap();
                loop {
                    let mut readbuf: [u8; 8192] = [0; 8192];

                    match tracker.read(&mut readbuf) {
                        Ok(0) => {
                            let _ = tracker.shutdown();
                            indices_to_remove.push(i);
                            break;
                        }
                        Ok(len) => {
                            let mut out: Vec<u8> = Vec::new();
                            tracker.chain_buffer(&mut readbuf[0..len].to_vec());
                            eprintln!(
                                "Handling: {}",
                                String::from_utf8_lossy(&tracker.buf_as_slice())
                            );

                            match handler.handle(&mut tracker.buf_as_slice(), &mut out, None) {
                                // TODO: buffer output and write only on POLLOUT
                                Ok((unprocessed_bytes, last_iface)) => {
                                    upgraded_iface = last_iface;
                                    if unprocessed_bytes.len() > 0 {
                                        eprintln!(
                                            "Unprocessed bytes: {}",
                                            String::from_utf8_lossy(&unprocessed_bytes)
                                        );
                                    }
                                    tracker.fill_buffer(&unprocessed_bytes);

                                    match tracker.write(out.as_ref()) {
                                        Err(err) => {
                                            eprintln!("write error: {}", err);
                                            for cause in Fail::iter_causes(&err) {
                                                eprintln!("  caused by: {}", cause);
                                            }
                                            let _ = tracker.shutdown();
                                            indices_to_remove.push(i);
                                            break;
                                        }
                                        Ok(_) => {}
                                    }
                                }
                                Err(e) => match e.kind() {
                                    err => {
                                        eprintln!("handler error: {}", err);
                                        for cause in Fail::iter_causes(&err).skip(1) {
                                            eprintln!("  caused by: {}", cause);
                                        }
                                        let _ = tracker.shutdown();
                                        indices_to_remove.push(i);
                                        break;
                                    }
                                },
                            }
                        }
                        Err(e) => match e.kind() {
                            io::ErrorKind::WouldBlock => {
                                break;
                            }
                            _ => {
                                let _ = tracker.shutdown();
                                indices_to_remove.push(i);
                                eprintln!("IO error: {}", e);
                                break;
                            }
                        },
                    }
                }
                if upgraded_iface.is_some() {
                    eprintln!("Upgraded MODE");
                    // upgraded mode... thread away the server
                    // feed it directly with the client stream
                    // If you have a better idea, open an Issue or PR on github
                    indices_to_remove.push(i);

                    let j = thread::spawn({
                        eprintln!("upgraded thread");
                        let handler = handler.clone();
                        let mut stream = tracker.stream.take().unwrap();
                        let mut buffer = tracker.buffer.take().unwrap();
                        move || {
                            let _r = stream.set_nonblocking(false);
                            let (reader, mut writer) = stream.split().unwrap();
                            let br = BufReader::new(reader);
                            let mut bufreader = Box::new(buffer.chain(br));
                            let mut upgraded_iface = upgraded_iface.take();
                            loop {
                                match handler.handle(&mut bufreader, &mut writer, upgraded_iface) {
                                    Ok((_unread, iface)) => {
                                        upgraded_iface = iface;
                                        match bufreader.fill_buf() {
                                            Err(_) => {
                                                eprintln!("Upgraded end");
                                                break;
                                            }
                                            Ok(buf) if buf.len() == 0 => {
                                                eprintln!("Upgraded end");
                                                break;
                                            }
                                            _ => {}
                                        }
                                    }
                                    Err(err) => match err.kind() {
                                        | varlink::ErrorKind::ConnectionClosed
                                        | varlink::ErrorKind::Io(io::ErrorKind::BrokenPipe)
                                        | varlink::ErrorKind::Io(
                                            io::ErrorKind::ConnectionReset,
                                        )
                                        | varlink::ErrorKind::Io(
                                            io::ErrorKind::ConnectionAborted,
                                        ) => {
                                            eprintln!("Upgraded end");
                                            break;
                                        }
                                        _ => {
                                            eprintln!("Upgraded end: {}", err);
                                            for cause in Fail::iter_causes(&err).skip(1) {
                                                eprintln!("  caused by: {}", cause);
                                            }
                                            break;
                                        }
                                    },
                                }
                            }
                        }
                    });
                    threads.push(j);
                }
            }
        }

        // We can't modify the vector while we are traversing it, so update now.
        for i in indices_to_remove {
            fdmap.remove(&fds[i].fd);
            fds.remove(i);
        }

        let r = unsafe { libc::poll(fds.as_mut_ptr(), (fds.len() as u32).into(), timeout) };

        if r < 0 {
            return Err(Error::last_os_error().into());
        }

        if r == 0 && fds.len() == 1 {
            for t in threads {
                let _r = t.join();
            }

            return Err(varlink::Error::from(varlink::ErrorKind::Timeout));
        }
    }
}

fn run_server(address: &str, timeout: u64, multiplex: bool) -> varlink::Result<()> {
    let myorgexampleping = MyOrgExamplePing;
    let myinterface = org_example_ping::new(Box::new(myorgexampleping));
    let service = VarlinkService::new(
        "org.varlink",
        "test ping service",
        "0.1",
        "http://varlink.org",
        vec![Box::new(myinterface)],
    );

    if multiplex {
        // Demonstrate a single process, single-threaded service
        listen_multiplex(service, &address, timeout)?;
    } else {
        varlink::listen(service, &address, 10, timeout)?;
    }
    Ok(())
}
<commit_msg>examples/ping: add --multiplex flag<commit_after>extern crate failure;
#[macro_use]
extern crate failure_derive;
extern crate getopts;
extern crate libc;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate varlink;

use failure::Fail;
use org_example_ping::*;
use std::collections::HashMap;
use std::env;
use std::io::{self, BufRead, BufReader, Error, Read, Write};
use std::process::exit;
use std::sync::{Arc, RwLock};
use std::thread;
use varlink::{Call, Connection, ConnectionHandler, Listener, ServerStream, VarlinkService};

// Dynamically build the varlink rust code.
mod org_example_ping;

#[cfg(test)]
mod test;

// Main

fn print_usage(program: &str, opts: &getopts::Options) {
    let brief = format!("Usage: {} [--varlink=<address>] [--client]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<_> = env::args().collect();
    let program = args[0].clone();

    let mut opts = getopts::Options::new();
    opts.optopt("", "varlink", "varlink address URL", "<address>");
    opts.optflag("", "client", "run in client mode");
    opts.optflag("m", "multiplex", "run in multiplex mode");
    opts.optflag("h", "help", "print this help menu");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            eprintln!("{}", f.to_string());
            print_usage(&program, &opts);
            return;
        }
    };

    if matches.opt_present("h") {
        print_usage(&program, &opts);
        return;
    }

    let client_mode = matches.opt_present("client");

    let ret = if client_mode {
        let connection = match matches.opt_str("varlink") {
            None => Connection::with_activate(&format!("{} --varlink=$VARLINK_ADDRESS", program))
                .unwrap(),
            Some(address) => Connection::with_address(&address).unwrap(),
        };
        run_client(connection)
    } else {
        if let Some(address) = matches.opt_str("varlink") {
            run_server(&address, 0, matches.opt_present("m")).map_err(|e| e.into())
        } else {
            print_usage(&program, &opts);
            eprintln!("Need varlink address in server mode.");
            exit(1);
        }
    };
    exit(match ret {
        Ok(_) => 0,
        Err(err) => {
            eprintln!("error: {:?}", err);
            1
        }
    });
}

// Client

fn run_client(connection: Arc<RwLock<varlink::Connection>>) -> Result<()> {
    {
        let mut iface = VarlinkClient::new(connection.clone());
        let ping = String::from("Test");

        let reply = iface.ping(ping.clone()).call()?;
        assert_eq!(ping, reply.pong);
        println!("Pong: '{}'", reply.pong);

        let reply = iface.ping(ping.clone()).call()?;
        assert_eq!(ping, reply.pong);
        println!("Pong: '{}'", reply.pong);

        let reply = iface.ping(ping.clone()).call()?;
        assert_eq!(ping, reply.pong);
        println!("Pong: '{}'", reply.pong);

        let _reply = iface.upgrade().call()?;
        println!("Client: upgrade()");
    }
    {
        let mut conn = connection.write().unwrap();
        let mut writer = conn.writer.take().unwrap();
        writer.write_all("test test\nEnd\n".as_bytes())?;
        conn.writer = Some(writer);
        let mut buf = Vec::new();
        let mut reader = conn.reader.take().unwrap();
        if reader.read_until('\n' as u8, &mut buf)? == 0 {
            // incomplete data, in real life, store all bytes for the next call
            // for now just read the rest
            reader.read_to_end(&mut buf)?;
        };
        eprintln!("Client: upgraded got: {}", String::from_utf8_lossy(&buf));
        conn.reader = Some(reader);
    }
    Ok(())
}

// Server

struct MyOrgExamplePing;

impl org_example_ping::VarlinkInterface for MyOrgExamplePing {
    fn ping(&self, call: &mut Call_Ping, ping: String) -> varlink::Result<()> {
        call.reply(ping)
    }

    fn upgrade(&self, call: &mut Call_Upgrade) -> varlink::Result<()> {
        eprintln!("Server: called upgrade");
        call.to_upgraded();
        call.reply()
    }

    // An upgraded connection has its own application specific protocol.
    // Normally, there is no way back to the varlink protocol with this connection.
    fn call_upgraded(&self, call: &mut Call, bufreader: &mut BufRead) -> varlink::Result<Vec<u8>> {
        let mut buf = String::new();
        let len = bufreader.read_line(&mut buf)?;
        if len == 0 {
            eprintln!("Server: upgraded got: none");
            // incomplete data, in real life, store all bytes for the next call
            // return Ok(buf.as_bytes().to_vec());
            return Err(varlink::ErrorKind::ConnectionClosed.into());
        }
        eprintln!("Server: upgraded got: {}", buf);

        call.writer.write_all("server reply: ".as_bytes())?;
        call.writer.write_all(buf.as_bytes())?;

        Ok(Vec::new())
    }
}

struct FdTracker {
    stream: Option<ServerStream>,
    buffer: Option<Vec<u8>>,
}

impl FdTracker {
    fn shutdown(&mut self) -> varlink::Result<()> {
        self.stream.as_mut().unwrap().shutdown()
    }
    fn chain_buffer(&mut self, buf: &mut Vec<u8>) {
        self.buffer.as_mut().unwrap().append(buf);
    }
    fn fill_buffer(&mut self, buf: &Vec<u8>) {
        self.buffer.as_mut().unwrap().clone_from(buf);
    }
    fn buf_as_slice(&mut self) -> &[u8] {
        self.buffer.as_mut().unwrap().as_slice()
    }
    fn write(&mut self, out: &[u8]) -> io::Result<usize> {
        self.stream.as_mut().unwrap().write(out.as_ref())
    }
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.stream.as_mut().unwrap().read(buf)
    }
}

pub fn listen_multiplex<S: ?Sized + AsRef<str>, H: ::ConnectionHandler + Send + Sync + 'static>(
    handler: H,
    address: &S,
    accept_timeout: u64,
) -> varlink::Result<()> {
    let timeout: i32 = match accept_timeout {
        0 => -1,
        n => (n * 1000) as i32,
    };

    let handler = Arc::new(handler);
    let mut fdmap: HashMap<i32, FdTracker> = HashMap::new();
    let mut fds = Vec::new();
    let mut threads = Vec::new();
    let listener = Listener::new(address)?;
    listener.set_nonblocking(true)?;

    fds.push(libc::pollfd {
        fd: listener.as_raw_fd(),
        revents: 0,
        events: libc::POLLIN,
    });

    loop {
        // Read activity on listening socket
        if fds[0].revents != 0 {
            let mut client = listener.accept(0)?;

            client.set_nonblocking(true)?;

            let fd = client.as_raw_fd();
            fds.push(libc::pollfd {
                fd,
                revents: 0,
                events: libc::POLLIN,
            });

            fdmap.insert(
                fd,
                FdTracker {
                    stream: Some(client),
                    buffer: Some(Vec::new()),
                },
            );
        }

        // Store which indices to remove
        let mut indices_to_remove = vec![];

        // Check client connections ...
        for i in 1..fds.len() {
            if fds[i].revents != 0 {
                let mut upgraded_iface: Option<String> = None;
                let mut tracker = fdmap.get_mut(&fds[i].fd).unwrap();
                loop {
                    let mut readbuf: [u8; 8192] = [0; 8192];

                    match tracker.read(&mut readbuf) {
                        Ok(0) => {
                            let _ = tracker.shutdown();
                            indices_to_remove.push(i);
                            break;
                        }
                        Ok(len) => {
                            let mut out: Vec<u8> = Vec::new();
                            tracker.chain_buffer(&mut readbuf[0..len].to_vec());
                            eprintln!(
                                "Handling: {}",
                                String::from_utf8_lossy(&tracker.buf_as_slice())
                            );

                            match handler.handle(&mut tracker.buf_as_slice(), &mut out, None) {
                                // TODO: buffer output and write only on POLLOUT
                                Ok((unprocessed_bytes, last_iface)) => {
                                    upgraded_iface = last_iface;
                                    if unprocessed_bytes.len() > 0 {
                                        eprintln!(
                                            "Unprocessed bytes: {}",
                                            String::from_utf8_lossy(&unprocessed_bytes)
                                        );
                                    }
                                    tracker.fill_buffer(&unprocessed_bytes);

                                    match tracker.write(out.as_ref()) {
                                        Err(err) => {
                                            eprintln!("write error: {}", err);
                                            for cause in Fail::iter_causes(&err) {
                                                eprintln!("  caused by: {}", cause);
                                            }
                                            let _ = tracker.shutdown();
                                            indices_to_remove.push(i);
                                            break;
                                        }
                                        Ok(_) => {}
                                    }
                                }
                                Err(e) => match e.kind() {
                                    err => {
                                        eprintln!("handler error: {}", err);
                                        for cause in Fail::iter_causes(&err).skip(1) {
                                            eprintln!("  caused by: {}", cause);
                                        }
                                        let _ = tracker.shutdown();
                                        indices_to_remove.push(i);
                                        break;
                                    }
                                },
                            }
                        }
                        Err(e) => match e.kind() {
                            io::ErrorKind::WouldBlock => {
                                break;
                            }
                            _ => {
                                let _ = tracker.shutdown();
                                indices_to_remove.push(i);
                                eprintln!("IO error: {}", e);
                                break;
                            }
                        },
                    }
                }
                if upgraded_iface.is_some() {
                    eprintln!("Upgraded MODE");
                    // upgraded mode... thread away the server
                    // feed it directly with the client stream
                    // If you have a better idea, open an Issue or PR on github
                    indices_to_remove.push(i);

                    let j = thread::spawn({
                        eprintln!("upgraded thread");
                        let handler = handler.clone();
                        let mut stream = tracker.stream.take().unwrap();
                        let mut buffer = tracker.buffer.take().unwrap();
                        move || {
                            let _r = stream.set_nonblocking(false);
                            let (reader, mut writer) = stream.split().unwrap();
                            let br = BufReader::new(reader);
                            let mut bufreader = Box::new(buffer.chain(br));
                            let mut upgraded_iface = upgraded_iface.take();
                            loop {
                                match handler.handle(&mut bufreader, &mut writer, upgraded_iface) {
                                    Ok((_unread, iface)) => {
                                        upgraded_iface = iface;
                                        match bufreader.fill_buf() {
                                            Err(_) => {
                                                eprintln!("Upgraded end");
                                                break;
                                            }
                                            Ok(buf) if buf.len() == 0 => {
                                                eprintln!("Upgraded end");
                                                break;
                                            }
                                            _ => {}
                                        }
                                    }
                                    Err(err) => match err.kind() {
                                        | varlink::ErrorKind::ConnectionClosed
                                        | varlink::ErrorKind::Io(io::ErrorKind::BrokenPipe)
                                        | varlink::ErrorKind::Io(
                                            io::ErrorKind::ConnectionReset,
                                        )
                                        | varlink::ErrorKind::Io(
                                            io::ErrorKind::ConnectionAborted,
                                        ) => {
                                            eprintln!("Upgraded end");
                                            break;
                                        }
                                        _ => {
                                            eprintln!("Upgraded end: {}", err);
                                            for cause in Fail::iter_causes(&err).skip(1) {
                                                eprintln!("  caused by: {}", cause);
                                            }
                                            break;
                                        }
                                    },
                                }
                            }
                        }
                    });
                    threads.push(j);
                }
            }
        }

        // We can't modify the vector while we are traversing it, so update now.
        for i in indices_to_remove {
            fdmap.remove(&fds[i].fd);
            fds.remove(i);
        }

        let r = unsafe { libc::poll(fds.as_mut_ptr(), (fds.len() as u32).into(), timeout) };

        if r < 0 {
            return Err(Error::last_os_error().into());
        }

        if r == 0 && fds.len() == 1 {
            for t in threads {
                let _r = t.join();
            }

            return Err(varlink::Error::from(varlink::ErrorKind::Timeout));
        }
    }
}

fn run_server(address: &str, timeout: u64, multiplex: bool) -> varlink::Result<()> {
    let myorgexampleping = MyOrgExamplePing;
    let myinterface = org_example_ping::new(Box::new(myorgexampleping));
    let service = VarlinkService::new(
        "org.varlink",
        "test ping service",
        "0.1",
        "http://varlink.org",
        vec![Box::new(myinterface)],
    );

    if multiplex {
        // Demonstrate a single process, single-threaded service
        listen_multiplex(service, &address, timeout)?;
    } else {
        varlink::listen(service, &address, 10, timeout)?;
    }
    Ok(())
}
<|endoftext|>


<commit_before>//https://github.com/andelf/rust-postgis
use postgis as geom;
use postgis::{SRID,WGS84};
use core::screen;
use std::f64::consts;

#[allow(missing_copy_implementations)]
#[allow(non_camel_case_types)]
pub enum EPSG_3857 {}

impl SRID for EPSG_3857 {
    fn as_srid() -> Option<i32> { Some(3857) }
}

#[derive(PartialEq,Debug)]
pub struct LngLat {
    pub lon: f64,
    pub lat: f64,
}

#[derive(PartialEq,Debug)]
pub struct Extent {
    pub minx: f64,
    pub miny: f64,
    pub maxx: f64,
    pub maxy: f64,
}

impl Extent {
    /// Convert geometry to tile relative coordinates
    fn geom_in_tile_extent(&self, tile_size: u32, geom: geom::Point<EPSG_3857>) -> screen::Point {
        let x_span = self.maxx - self.minx;
        let y_span = self.maxy - self.miny;
        screen::Point {
            x: ((geom.x-self.minx) * tile_size as f64 / x_span) as i32,
            y: ((geom.y-self.miny) * tile_size as f64 / y_span) as i32 }
    }
}

#[test]
fn test_geom_in_tile_extent() {
    //let zh_mercator = geom::Point::<EPSG_3857>::new(949398.0, 6002729.0);
    let zh_mercator = geom::Point::<EPSG_3857>::new(960000.0, 6002729.0);
    //let zh_wgs84 = geom::Point::<WGS84>::new(47.3703149, 8.5285874);
    let tile_extent = Extent {minx: 958826.08, miny: 5987771.04, maxx: 978393.96, maxy: 6007338.92};
    let screen_pt = tile_extent.geom_in_tile_extent(
        4096, zh_mercator);
    assert_eq!(screen_pt, screen::Point { x: 245, y: 3131 });
    //assert_eq!(screen_pt.encode().0, &[9,490,6262]);
}

// Credits: MapCache by Thomas Bonfort (http://mapserver.org/mapcache/)
pub struct Grid {
    /// The width and height of an individual tile, in pixels. Must be specified as positive integers separated by a space character.
    width: u16,
    height: u16,
    /// The geographical extent covered by the grid, in ground units (e.g. meters, degrees, feet, etc.). Must be specified as 4 floating point numbers ordered as minx, miny, maxx, maxy.
    /// The (minx,miny) point defines the origin of the grid, i.e. the pixel at the bottom left of the bottom-left most tile is always placed on the (minx,miny) geographical point.
    /// The (maxx,maxy) point is used to determine how many tiles there are for each zoom level.
    extent: Extent,
    //srs: SRID,
    //units: m/dd/ft
    /// This is a list of resolutions for each of the zoom levels defined by the grid. This must be supplied as a list of positive floating point values, ordered from largest to smallest.
    /// The largest value will correspond to the grid’s zoom level 0. Resolutions are expressed in “units-per-pixel”, depending on the unit used by the grid (e.g. resolutions are in meters per pixel for most grids used in webmapping).
    resolutions: &'static[f64]
    //origin: top-left, bottom-left, top-right and bottom-right
}

// --- Predefined grids ---

const WGS84_RESOLUTIONS: [f64; 18] = [
    0.703125000000000,
    0.351562500000000,
    0.175781250000000,
    8.78906250000000e-2,
    4.39453125000000e-2,
    2.19726562500000e-2,
    1.09863281250000e-2,
    5.49316406250000e-3,
    2.74658203125000e-3,
    1.37329101562500e-3,
    6.86645507812500e-4,
    3.43322753906250e-4,
    1.71661376953125e-4,
    8.58306884765625e-5,
    4.29153442382812e-5,
    2.14576721191406e-5,
    1.07288360595703e-5,
    5.36441802978516e-6
];

const GOOGLE_RESOLUTIONS: [f64; 19] = [
    156543.0339280410,
    78271.51696402048,
    39135.75848201023,
    19567.87924100512,
    9783.939620502561,
    4891.969810251280,
    2445.984905125640,
    1222.992452562820,
    611.4962262814100,
    305.7481131407048,
    152.8740565703525,
    76.43702828517624,
    38.21851414258813,
    19.10925707129406,
    9.554628535647032,
    4.777314267823516,
    2.388657133911758,
    1.194328566955879,
    0.5971642834779395
];

static WGS84_GRID: Grid = Grid {
    width: 256, height: 256,
    extent: Extent {minx: -180.0, miny: -90.0, maxx: 180.0, maxy: 90.0},
    resolutions: &WGS84_RESOLUTIONS
};

static GOOGLE_GRID: Grid = Grid {
    width: 256, height: 256,
    extent: Extent {minx: -20037508.3427892480, miny: -20037508.3427892480,
                    maxx: 20037508.3427892480, maxy: 20037508.3427892480},
    resolutions: &GOOGLE_RESOLUTIONS
};

impl Grid {
    /// Extent of a given tile in the grid given its x, y, and z
    pub fn tile_extent(&self, xtile: u16, ytile: u16, zoom: u16) -> Extent {
        let res = self.resolutions[zoom as usize];
        let tile_sx = self.width as f64;
        let tile_sy = self.height as f64;
        Extent {
            minx: self.extent.minx + (res * xtile as f64 * tile_sx),
            miny: self.extent.miny + (res * ytile as f64 * tile_sy),
            maxx: self.extent.minx + (res * (xtile + 1) as f64 * tile_sx),
            maxy: self.extent.miny + (res * (ytile + 1) as f64 * tile_sy),
        }
        /* ORIGIN_TOP_LEFT:
            minx: self.extent.minx + (res * xtile as f64 * tile_sx),
            miny: self.extent.maxy - (res * (ytile + 1) as f64 * tile_sy),
            maxx: self.extent.minx + (res * (xtile + 1) as f64 * tile_sx),
            maxy: self.extent.maxy - (res * ytile as f64 * tile_sy)
        */
    }
    /// Extent of a given tile in GoogleMaps XYZ adressing scheme
    pub fn tile_extent_xyz(&self, xtile: u16, ytile: u16, zoom: u16) -> Extent {
        let res = self.resolutions[zoom as usize];
        let unitheight = self.height as f64 * res;
        let maxy = ((self.extent.maxy-self.extent.minx- 0.01* unitheight)/unitheight).ceil() as u16;
        let y = maxy-ytile-1;
        self.tile_extent(xtile, y, zoom)
    }
}

#[test]
fn test_bbox() {
    let grid = &GOOGLE_GRID;

    let extent000 = grid.tile_extent(0, 0, 0);
    assert_eq!(extent000, Extent {minx: -20037508.342789248, miny: -20037508.342789248, maxx: 20037508.342789248, maxy: 20037508.342789248});

    let extent = grid.tile_extent_xyz(486, 332, 10);
    assert_eq!(extent, Extent {minx: -1017529.7205322683, miny: 7005300.768279828, maxx: -978393.9620502591, maxy: 7044436.526761841});
}

// --- Google Mercator calculations ---
// Credits: Mercantile by Sean C. Gillies (https://github.com/mapbox/mercantile)

/// Returns the upper left (lon, lat) of a tile
fn ul(xtile: u16, ytile: u16, zoom: u16) -> LngLat {
    let n = (zoom as f64).exp2();
    let lon_deg = xtile as f64 / n * 360.0 - 180.0;
    let lat_rad = (consts::PI * (1.0_f64 - 2.0_f64 * ytile as f64 / n)).sinh().atan();
    let lat_deg = lat_rad.to_degrees();
    LngLat {lon: lon_deg, lat: lat_deg}
}

/// Returns the Spherical Mercator (x, y) in meters
fn xy(lon: f64, lat: f64) -> (f64, f64) {
    //lng, lat = truncate_lnglat(lng, lat)
    let x = 6378137.0_f64 * lon.to_radians();
    let y = 6378137.0_f64 *
        ((consts::PI*0.25) + (0.5_f64 * lat.to_radians())).tan().ln();
    (x, y)
}

/// Returns the Spherical Mercator bounding box of a tile
fn tile_extent(xtile: u16, ytile: u16, zoom: u16) -> Extent {
    let a = ul(xtile, ytile, zoom);
    let (ax, ay) = xy(a.lon, a.lat);
    let b = ul(xtile+1, ytile+1, zoom);
    let (bx, by) = xy(b.lon, b.lat);
    Extent {minx: ax, miny: by, maxx: bx, maxy: ay}
}

/// Returns the (lon, lat) bounding box of a tile
fn tile_bounds(xtile: u16, ytile: u16, zoom: u16) -> Extent {
    let a = ul(xtile, ytile, zoom);
    let b = ul(xtile+1, ytile+1, zoom);
    Extent {minx: a.lon, miny: b.lat, maxx: b.lon, maxy: a.lat}
}

#[test]
fn test_ul() {
    let lnglat = ul(486, 332, 10);
    assert_eq!(lnglat, LngLat {lon: -9.140625, lat: 53.33087298301705});
}

#[test]
fn test_xy() {
    let ul = ul(486, 332, 10);
    let xy_ = xy(ul.lon, ul.lat);
    assert_eq!(xy_, (-1017529.7205322663, 7044436.526761846));
    assert_eq!(xy(0.0, 0.0), (0.0, -0.0000000007081154551613622));
}

#[test]
fn test_merc_tile_extent() {
    let extent = tile_extent(486, 332, 10);
    assert_eq!(extent, Extent {minx: -1017529.7205322663, miny: 7005300.768279833, maxx: -978393.962050256, maxy: 7044436.526761846});
}

#[test]
fn test_merc_tile_bounds() {
    let bbox = tile_bounds(486, 332, 10);
    assert_eq!(bbox, Extent {minx: -9.140625, miny: 53.120405283106564, maxx: -8.7890625, maxy: 53.33087298301705});
}
<commit_msg>WGS84_GRID test<commit_after>//https://github.com/andelf/rust-postgis
use postgis as geom;
use postgis::{SRID,WGS84};
use core::screen;
use std::f64::consts;

#[allow(missing_copy_implementations)]
#[allow(non_camel_case_types)]
pub enum EPSG_3857 {}

impl SRID for EPSG_3857 {
    fn as_srid() -> Option<i32> { Some(3857) }
}

#[derive(PartialEq,Debug)]
pub struct LngLat {
    pub lon: f64,
    pub lat: f64,
}

#[derive(PartialEq,Debug)]
pub struct Extent {
    pub minx: f64,
    pub miny: f64,
    pub maxx: f64,
    pub maxy: f64,
}

impl Extent {
    /// Convert geometry to tile relative coordinates
    fn geom_in_tile_extent(&self, tile_size: u32, geom: geom::Point<EPSG_3857>) -> screen::Point {
        let x_span = self.maxx - self.minx;
        let y_span = self.maxy - self.miny;
        screen::Point {
            x: ((geom.x-self.minx) * tile_size as f64 / x_span) as i32,
            y: ((geom.y-self.miny) * tile_size as f64 / y_span) as i32 }
    }
}

#[test]
fn test_geom_in_tile_extent() {
    //let zh_mercator = geom::Point::<EPSG_3857>::new(949398.0, 6002729.0);
    let zh_mercator = geom::Point::<EPSG_3857>::new(960000.0, 6002729.0);
    //let zh_wgs84 = geom::Point::<WGS84>::new(47.3703149, 8.5285874);
    let tile_extent = Extent {minx: 958826.08, miny: 5987771.04, maxx: 978393.96, maxy: 6007338.92};
    let screen_pt = tile_extent.geom_in_tile_extent(
        4096, zh_mercator);
    assert_eq!(screen_pt, screen::Point { x: 245, y: 3131 });
    //assert_eq!(screen_pt.encode().0, &[9,490,6262]);
}

// Credits: MapCache by Thomas Bonfort (http://mapserver.org/mapcache/)
pub struct Grid {
    /// The width and height of an individual tile, in pixels. Must be specified as positive integers separated by a space character.
    width: u16,
    height: u16,
    /// The geographical extent covered by the grid, in ground units (e.g. meters, degrees, feet, etc.). Must be specified as 4 floating point numbers ordered as minx, miny, maxx, maxy.
    /// The (minx,miny) point defines the origin of the grid, i.e. the pixel at the bottom left of the bottom-left most tile is always placed on the (minx,miny) geographical point.
    /// The (maxx,maxy) point is used to determine how many tiles there are for each zoom level.
    extent: Extent,
    //srs: SRID,
    //units: m/dd/ft
    /// This is a list of resolutions for each of the zoom levels defined by the grid. This must be supplied as a list of positive floating point values, ordered from largest to smallest.
    /// The largest value will correspond to the grid’s zoom level 0. Resolutions are expressed in “units-per-pixel”, depending on the unit used by the grid (e.g. resolutions are in meters per pixel for most grids used in webmapping).
    resolutions: &'static[f64]
    //origin: top-left, bottom-left, top-right and bottom-right
}

// --- Predefined grids ---

const WGS84_RESOLUTIONS: [f64; 18] = [
    0.703125000000000,
    0.351562500000000,
    0.175781250000000,
    8.78906250000000e-2,
    4.39453125000000e-2,
    2.19726562500000e-2,
    1.09863281250000e-2,
    5.49316406250000e-3,
    2.74658203125000e-3,
    1.37329101562500e-3,
    6.86645507812500e-4,
    3.43322753906250e-4,
    1.71661376953125e-4,
    8.58306884765625e-5,
    4.29153442382812e-5,
    2.14576721191406e-5,
    1.07288360595703e-5,
    5.36441802978516e-6
];

const GOOGLE_RESOLUTIONS: [f64; 19] = [
    156543.0339280410,
    78271.51696402048,
    39135.75848201023,
    19567.87924100512,
    9783.939620502561,
    4891.969810251280,
    2445.984905125640,
    1222.992452562820,
    611.4962262814100,
    305.7481131407048,
    152.8740565703525,
    76.43702828517624,
    38.21851414258813,
    19.10925707129406,
    9.554628535647032,
    4.777314267823516,
    2.388657133911758,
    1.194328566955879,
    0.5971642834779395
];

static WGS84_GRID: Grid = Grid {
    width: 256, height: 256,
    extent: Extent {minx: -180.0, miny: -90.0, maxx: 180.0, maxy: 90.0},
    resolutions: &WGS84_RESOLUTIONS
};

static GOOGLE_GRID: Grid = Grid {
    width: 256, height: 256,
    extent: Extent {minx: -20037508.3427892480, miny: -20037508.3427892480,
                    maxx: 20037508.3427892480, maxy: 20037508.3427892480},
    resolutions: &GOOGLE_RESOLUTIONS
};

impl Grid {
    /// Extent of a given tile in the grid given its x, y, and z
    pub fn tile_extent(&self, xtile: u16, ytile: u16, zoom: u16) -> Extent {
        let res = self.resolutions[zoom as usize];
        let tile_sx = self.width as f64;
        let tile_sy = self.height as f64;
        Extent {
            minx: self.extent.minx + (res * xtile as f64 * tile_sx),
            miny: self.extent.miny + (res * ytile as f64 * tile_sy),
            maxx: self.extent.minx + (res * (xtile + 1) as f64 * tile_sx),
            maxy: self.extent.miny + (res * (ytile + 1) as f64 * tile_sy),
        }
        /* ORIGIN_TOP_LEFT:
            minx: self.extent.minx + (res * xtile as f64 * tile_sx),
            miny: self.extent.maxy - (res * (ytile + 1) as f64 * tile_sy),
            maxx: self.extent.minx + (res * (xtile + 1) as f64 * tile_sx),
            maxy: self.extent.maxy - (res * ytile as f64 * tile_sy)
        */
    }
    /// Extent of a given tile in GoogleMaps XYZ adressing scheme
    pub fn tile_extent_xyz(&self, xtile: u16, ytile: u16, zoom: u16) -> Extent {
        let res = self.resolutions[zoom as usize];
        let unitheight = self.height as f64 * res;
        let maxy = ((self.extent.maxy-self.extent.minx- 0.01* unitheight)/unitheight).ceil() as u16;
        let y = maxy-ytile-1;
        self.tile_extent(xtile, y, zoom)
    }
}

#[test]
fn test_bbox() {
    let grid = &GOOGLE_GRID;

    let extent000 = grid.tile_extent(0, 0, 0);
    assert_eq!(extent000, Extent {minx: -20037508.342789248, miny: -20037508.342789248, maxx: 20037508.342789248, maxy: 20037508.342789248});

    let extent = grid.tile_extent_xyz(486, 332, 10);
    assert_eq!(extent, Extent {minx: -1017529.7205322683, miny: 7005300.768279828, maxx: -978393.9620502591, maxy: 7044436.526761841});

    let wgs84extent000 = WGS84_GRID.tile_extent(0, 0, 0);
    assert_eq!(wgs84extent000, Extent { minx: -180.0, miny: -90.0, maxx: 0.0, maxy: 90.0 });
}

// --- Google Mercator calculations ---
// Credits: Mercantile by Sean C. Gillies (https://github.com/mapbox/mercantile)

/// Returns the upper left (lon, lat) of a tile
#[allow(dead_code)]
fn ul(xtile: u16, ytile: u16, zoom: u16) -> LngLat {
    let n = (zoom as f64).exp2();
    let lon_deg = xtile as f64 / n * 360.0 - 180.0;
    let lat_rad = (consts::PI * (1.0_f64 - 2.0_f64 * ytile as f64 / n)).sinh().atan();
    let lat_deg = lat_rad.to_degrees();
    LngLat {lon: lon_deg, lat: lat_deg}
}

/// Returns the Spherical Mercator (x, y) in meters
#[allow(dead_code)]
fn xy(lon: f64, lat: f64) -> (f64, f64) {
    //lng, lat = truncate_lnglat(lng, lat)
    let x = 6378137.0_f64 * lon.to_radians();
    let y = 6378137.0_f64 *
        ((consts::PI*0.25) + (0.5_f64 * lat.to_radians())).tan().ln();
    (x, y)
}

/// Returns the Spherical Mercator bounding box of a tile
#[allow(dead_code)]
fn tile_extent(xtile: u16, ytile: u16, zoom: u16) -> Extent {
    let a = ul(xtile, ytile, zoom);
    let (ax, ay) = xy(a.lon, a.lat);
    let b = ul(xtile+1, ytile+1, zoom);
    let (bx, by) = xy(b.lon, b.lat);
    Extent {minx: ax, miny: by, maxx: bx, maxy: ay}
}

/// Returns the (lon, lat) bounding box of a tile
#[allow(dead_code)]
fn tile_bounds(xtile: u16, ytile: u16, zoom: u16) -> Extent {
    let a = ul(xtile, ytile, zoom);
    let b = ul(xtile+1, ytile+1, zoom);
    Extent {minx: a.lon, miny: b.lat, maxx: b.lon, maxy: a.lat}
}

#[test]
fn test_ul() {
    let lnglat = ul(486, 332, 10);
    assert_eq!(lnglat, LngLat {lon: -9.140625, lat: 53.33087298301705});
}

#[test]
fn test_xy() {
    let ul = ul(486, 332, 10);
    let xy_ = xy(ul.lon, ul.lat);
    assert_eq!(xy_, (-1017529.7205322663, 7044436.526761846));
    assert_eq!(xy(0.0, 0.0), (0.0, -0.0000000007081154551613622));
}

#[test]
fn test_merc_tile_extent() {
    let extent = tile_extent(486, 332, 10);
    assert_eq!(extent, Extent {minx: -1017529.7205322663, miny: 7005300.768279833, maxx: -978393.962050256, maxy: 7044436.526761846});
}

#[test]
fn test_merc_tile_bounds() {
    let bbox = tile_bounds(486, 332, 10);
    assert_eq!(bbox, Extent {minx: -9.140625, miny: 53.120405283106564, maxx: -8.7890625, maxy: 53.33087298301705});
}
<|endoftext|>


<commit_before>extern crate openexr;

use std::slice;
use std::iter;
use std::path::Path;
use std::mem;

use openexr::{FrameBuffer, OutputFile, PixelType, Compression};

fn main() {
    let mut pixel_data: Vec<(f32, f32, f32)> =
        iter::repeat((0.82, 1.78, 0.21)).take(256 * 256).collect();

    let mut exr_file = OutputFile::from_file(Path::new("/tmp/test.exr"),
                                             (256, 256),
                                             &[("R", PixelType::FLOAT),
                                               ("G", PixelType::FLOAT),
                                               ("B", PixelType::FLOAT)],
                                             Compression::NO_COMPRESSION)
            .unwrap();

    let mut fb = {
        // Create the frame buffer
        let mut fb = FrameBuffer::new(256, 256);
        fb.insert_pixels(&[("R", 0.0), ("G", 0.0), ("B", 0.0)], &mut pixel_data);
        fb
    };

    exr_file.write_pixels(&mut fb);
}
<commit_msg>Changed example to use PIZ compression.<commit_after>extern crate openexr;

use std::slice;
use std::iter;
use std::path::Path;
use std::mem;

use openexr::{FrameBuffer, OutputFile, PixelType, Compression};

fn main() {
    let mut pixel_data: Vec<(f32, f32, f32)> =
        iter::repeat((0.82, 1.78, 0.21)).take(256 * 256).collect();

    let mut exr_file = OutputFile::from_file(Path::new("/tmp/test.exr"),
                                             (256, 256),
                                             &[("R", PixelType::FLOAT),
                                               ("G", PixelType::FLOAT),
                                               ("B", PixelType::FLOAT)],
                                             Compression::PIZ_COMPRESSION)
            .unwrap();

    let mut fb = {
        // Create the frame buffer
        let mut fb = FrameBuffer::new(256, 256);
        fb.insert_pixels(&[("R", 0.0), ("G", 0.0), ("B", 0.0)], &mut pixel_data);
        fb
    };

    exr_file.write_pixels(&mut fb);
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::fmt::{Debug, Formatter, Error as FmtError};

use toml::Value;
use git2::{Repository, Error as Git2Error};

use libimagstore::storeid::StoreId;
use libimagstore::hook::Hook;
use libimagstore::hook::result::HookResult;
use libimagstore::hook::position::HookPosition;
use libimagstore::hook::accessor::{HookDataAccessor, HookDataAccessorProvider};
use libimagstore::hook::accessor::StoreIdAccessor;
use libimagerror::trace::trace_error;

pub struct CreateHook<'a> {
    storepath: &'a PathBuf,

    repository: Option<Repository>,

    position: HookPosition,
    config: Option<Value>,
}

impl<'a> CreateHook<'a> {

    pub fn new(storepath: &'a PathBuf, p: HookPosition) -> CreateHook<'a> {
        let r = match Repository::open(storepath) {
            Ok(r) => Some(r),
            Err(e) => {
                trace_error(&e);
                None
            },
        };
        CreateHook {
            storepath: storepath,
            repository: r,
            position: p,
            config: None,
        }
    }

}

impl<'a> Debug for CreateHook<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
        write!(fmt, "CreateHook(storepath={:?}, repository={}, pos={:?}, cfg={:?}",
               self.storepath,
               (if self.repository.is_some() { "Some(_)" } else { "None" }),
               self.position,
               self.config)
    }
}

impl<'a> Hook for CreateHook<'a> {

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

    fn set_config(&mut self, config: &Value) {
        self.config = Some(config.clone());
    }

}

impl<'a> HookDataAccessorProvider for CreateHook<'a> {

    fn accessor(&self) -> HookDataAccessor {
        HookDataAccessor::StoreIdAccess(self)
    }
}

impl<'a> StoreIdAccessor for CreateHook<'a> {

    fn access(&self, id: &StoreId) -> HookResult<()> {
        debug!("[GIT CREATE HOOK]: {:?}", id);
        Ok(())
    }

}

<commit_msg>Start impl of StoreIdAccessor for CreateHook<commit_after>use std::path::PathBuf;
use std::fmt::{Debug, Formatter, Error as FmtError};
use std::result::Result as RResult;

use toml::Value;
use git2::{Reference as GitReference, Repository, Error as Git2Error};

use libimagstore::storeid::StoreId;
use libimagstore::hook::Hook;
use libimagstore::hook::error::HookError as HE;
use libimagstore::hook::error::HookErrorKind as HEK;
use libimagstore::hook::error::CustomData as HECD;
use libimagstore::hook::result::HookResult;
use libimagstore::hook::position::HookPosition;
use libimagstore::hook::accessor::{HookDataAccessor, HookDataAccessorProvider};
use libimagstore::hook::accessor::StoreIdAccessor;
use libimagerror::trace::trace_error;
use libimagerror::into::IntoError;

use vcs::git::result::Result;
use vcs::git::error::MapErrInto;
use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::GitHookError as GHE;
use vcs::git::config::ensure_branch;

pub struct CreateHook<'a> {
    storepath: &'a PathBuf,

    repository: Option<Repository>,

    position: HookPosition,
    config: Option<Value>,
}

impl<'a> CreateHook<'a> {

    pub fn new(storepath: &'a PathBuf, p: HookPosition) -> CreateHook<'a> {
        let r = match Repository::open(storepath) {
            Ok(r) => Some(r),
            Err(e) => {
                trace_error(&e);
                None
            },
        };
        CreateHook {
            storepath: storepath,
            repository: r,
            position: p,
            config: None,
        }
    }

    fn repository(&self) -> HookResult<&Repository> {
        use vcs::git::config::abort_on_repo_init_err;

        match self.repository.as_ref() {
            Some(r) => Ok(r),
            None    => {
                debug!("Repository isn't initialized... creating error object now");
                let he = GHEK::MkRepo.into_error();
                let he = HE::new(HEK::HookExecutionError, Some(Box::new(he)));
                let custom = HECD::default().aborting(abort_on_repo_init_err(self.config.as_ref()));
                return Err(he.with_custom_data(custom));
            }
        }
    }

}

impl<'a> Debug for CreateHook<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "CreateHook(storepath={:?}, repository={}, pos={:?}, cfg={:?}",
               self.storepath,
               (if self.repository.is_some() { "Some(_)" } else { "None" }),
               self.position,
               self.config)
    }
}

impl<'a> Hook for CreateHook<'a> {

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

    fn set_config(&mut self, config: &Value) {
        self.config = Some(config.clone());
    }

}

impl<'a> HookDataAccessorProvider for CreateHook<'a> {

    fn accessor(&self) -> HookDataAccessor {
        HookDataAccessor::StoreIdAccess(self)
    }
}

impl<'a> StoreIdAccessor for CreateHook<'a> {

    fn access(&self, id: &StoreId) -> HookResult<()> {
        debug!("[GIT CREATE HOOK]: {:?}", id);
        let repository = try!(self.repository());
        let head       = try!(repository.head().map_err_into(GHEK::HeadFetchError)
             .map_err(|e| HEK::HookExecutionError.into_error_with_cause(Box::new(e))));

        if head.is_branch() {
            return GHEK::NotOnBranch.into_error().inside_of(HEK::HookExecutionError)
        }

        try!(checkout_branch(self.config.as_ref(), &head)
             .map_err(|e| HEK::HookExecutionError.into_error_with_cause(Box::new(e))));

        // Now to the create() hook action

        unimplemented!()

        Ok(())
    }

}

fn checkout_branch(config: Option<&Value>, head: &GitReference) -> Result<()> {
    // Check out appropriate branch ... or fail
    match ensure_branch(config) {
        Ok(Some(s)) => {
            match head.name().map(|name| name == s) {
                Some(b) => {
                    if b {
                        debug!("Branch already checked out.");
                        Ok(())
                    } else {
                        debug!("Branch not checked out.");
                        unimplemented!()
                    }
                },

                None => Err(GHEK::RepositoryBranchNameFetchingError.into_error())
                    .map_err_into(GHEK::RepositoryBranchError)
                    .map_err_into(GHEK::RepositoryError),
            }
        },
        Ok(None) => {
            debug!("No branch to checkout");
            Ok(())
        },

        Err(e) => Err(e).map_err_into(GHEK::RepositoryError),
    }
}

<|endoftext|>


<commit_before>use sass::variable::SassVariable;

use std::borrow::Cow;
use std::borrow::Cow::Borrowed;
use std::collections::HashMap;

pub fn evaluate(original: &str, variables: &HashMap<String, String>) -> String {
    let vt = ValueTokenizer::new(original);
    original.split(' ').map(|original_part|
        match (*variables).get(original_part) {
            Some(v) => &v[..],
            None => original_part,
        }
    ).collect::<Vec<_>>().connect(" ")
}

#[derive(Debug, Clone, PartialEq)]
pub enum ValuePart<'a> {
    Variable(SassVariable<'a>),
    String(Cow<'a, str>),
}

#[derive(Debug)]
pub struct ValueTokenizer<'a> {
    value_str: &'a str,
    bytes: &'a [u8],
    offset: usize,
}

impl<'a> ValueTokenizer<'a> {
    pub fn new(value_str: &'a str) -> ValueTokenizer<'a> {
        ValueTokenizer {
            value_str: &value_str,
            bytes: &value_str.as_bytes(),
            offset: 0,
        }
    }

    pub fn parse(&mut self) -> Option<ValuePart<'a>> {
        let start = self.offset;
        let mut i = self.offset;
        let limit = self.value_str.len();

        match self.bytes[i..limit].iter().position(|&c| c == b' ' ) {
            Some(pos) => { i += pos; },
            None      => { i = limit },
        }
        self.offset = i + 1;
        Some(ValuePart::String(Borrowed(&self.value_str[start..i])))
    }
}

impl<'a> Iterator for ValueTokenizer<'a> {
    type Item = ValuePart<'a>;

    fn next(&mut self) -> Option<ValuePart<'a>> {
        if self.offset < self.value_str.len() {
            return self.parse()
        }
        None
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::borrow::Cow::Borrowed;

    #[test]
    fn it_returns_string_part() {
        let mut vt = ValueTokenizer::new("foo");
        assert_eq!(Some(ValuePart::String(Borrowed(&"foo"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_space_separated_string_parts() {
        let mut vt = ValueTokenizer::new("foo bar");
        assert_eq!(Some(ValuePart::String(Borrowed(&"foo"))), vt.next());
        assert_eq!(Some(ValuePart::String(Borrowed(&"bar"))), vt.next());
        assert_eq!(None, vt.next());
    }
}
<commit_msg>Differentiate between variables and strings<commit_after>use sass::variable::SassVariable;

use std::borrow::Cow;
use std::borrow::Cow::Borrowed;
use std::collections::HashMap;

pub fn evaluate(original: &str, variables: &HashMap<String, String>) -> String {
    let vt = ValueTokenizer::new(original);
    original.split(' ').map(|original_part|
        match (*variables).get(original_part) {
            Some(v) => &v[..],
            None => original_part,
        }
    ).collect::<Vec<_>>().connect(" ")
}

#[derive(Debug, Clone, PartialEq)]
pub enum ValuePart<'a> {
    Variable(Cow<'a, str>),
    String(Cow<'a, str>),
}

#[derive(Debug)]
pub struct ValueTokenizer<'a> {
    value_str: &'a str,
    bytes: &'a [u8],
    offset: usize,
}

impl<'a> ValueTokenizer<'a> {
    pub fn new(value_str: &'a str) -> ValueTokenizer<'a> {
        ValueTokenizer {
            value_str: &value_str,
            bytes: &value_str.as_bytes(),
            offset: 0,
        }
    }

    pub fn parse(&mut self) -> Option<ValuePart<'a>> {
        let start = self.offset;
        let mut i = self.offset;
        let limit = self.value_str.len();

        match self.bytes[i..limit].iter().position(|&c| c == b' ' ) {
            Some(pos) => { i += pos; },
            None      => { i = limit },
        }
        self.offset = i + 1;
        if self.bytes[start] == b'$' {
            Some(ValuePart::Variable(Borrowed(&self.value_str[start..i])))
        } else {
            Some(ValuePart::String(Borrowed(&self.value_str[start..i])))
        }
    }
}

impl<'a> Iterator for ValueTokenizer<'a> {
    type Item = ValuePart<'a>;

    fn next(&mut self) -> Option<ValuePart<'a>> {
        if self.offset < self.value_str.len() {
            return self.parse()
        }
        None
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::borrow::Cow::Borrowed;

    #[test]
    fn it_returns_string_part() {
        let mut vt = ValueTokenizer::new("foo");
        assert_eq!(Some(ValuePart::String(Borrowed(&"foo"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_space_separated_string_parts() {
        let mut vt = ValueTokenizer::new("foo bar");
        assert_eq!(Some(ValuePart::String(Borrowed(&"foo"))), vt.next());
        assert_eq!(Some(ValuePart::String(Borrowed(&"bar"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_variable() {
        let mut vt = ValueTokenizer::new("$foo");
        assert_eq!(Some(ValuePart::Variable(Borrowed(&"$foo"))), vt.next());
        assert_eq!(None, vt.next());
    }

    #[test]
    fn it_returns_variables_and_string_parts() {
        let mut vt = ValueTokenizer::new("foo $bar baz $quux");
        assert_eq!(Some(ValuePart::String(Borrowed(&"foo"))), vt.next());
        assert_eq!(Some(ValuePart::Variable(Borrowed(&"$bar"))), vt.next());
        assert_eq!(Some(ValuePart::String(Borrowed(&"baz"))), vt.next());
        assert_eq!(Some(ValuePart::Variable(Borrowed(&"$quux"))), vt.next());
        assert_eq!(None, vt.next());
    }

}
<|endoftext|>


<commit_before>//! Helper to run a callback in the libuv main thread.

use std::mem;
use std::os::raw::c_void;

use types::*;
use handle::{Handle, Managed};
use neon_runtime;
use neon_runtime::raw;
use std::sync::Arc;
use context::Context;

type EventContext<'a> = crate::context::TaskContext<'a>;

struct EventHandlerInner(*mut c_void);

unsafe impl Send for EventHandlerInner {}
unsafe impl Sync for EventHandlerInner {}

impl Drop for EventHandlerInner {
    fn drop(&mut self) {
        unsafe {
            neon_runtime::handler::delete(self.0);
        }
    }
}

#[derive(Clone)]
pub struct EventHandler(Arc<EventHandlerInner>);

impl EventHandler {
    #[cfg(feature = "napi-runtime")]
    pub fn new<'a, C: Context<'a>, T: Value>(cx: &C, this: Handle<T>, callback: Handle<JsFunction>) -> Self {
        unimplemented!()
    }

    #[cfg(feature = "legacy-runtime")]
    pub fn new<'a, C: Context<'a>, T: Value>(cx: &C, this: Handle<T>, callback: Handle<JsFunction>) -> Self {
        let cb = unsafe {
            neon_runtime::handler::new(cx.env().to_raw(), this.to_raw(), callback.to_raw())
        };
        EventHandler(Arc::new(EventHandlerInner(cb)))
    }

    pub fn schedule<T, F>(&self, arg_cb: F)
        where T: Value,
              F: for<'a> FnOnce(&mut EventContext<'a>) -> Vec<Handle<'a, T>>,
              F: Send + 'static {
        self.schedule_with(move |cx, this, callback| {
            let args = arg_cb(cx);
            let _result = callback.call(cx, this, args);
        })
    }

    pub fn schedule_with<F>(&self, arg_cb: F)
        where F: FnOnce(&mut EventContext, Handle<JsValue>, Handle<JsFunction>),
              F: Send + 'static {
        // HACK: Work around for race condition in `close`. `EventHandler` cannot be
        // dropped until all callbacks have executed.
        // NOTE: This will still leak memory if the callback is never called
        let cloned_cb = self.clone();
        let cb = move |cx, this, cb| {
            arg_cb(cx, this, cb);
            std::mem::drop(cloned_cb);
        };

        let callback = Box::into_raw(Box::new(cb)) as *mut c_void;
        unsafe {
            neon_runtime::handler::schedule((*self.0).0, callback, handle_callback::<F>);
        }
    }
}

unsafe extern "C" fn handle_callback<F>(this: raw::Local, func: raw::Local, callback: *mut c_void)
    where F: FnOnce(&mut EventContext, Handle<JsValue>, Handle<JsFunction>), F: Send + 'static {
    EventContext::with(|mut cx: EventContext| {
        let this = JsValue::new_internal(this);
        let func: Handle<JsFunction> = Handle::new_internal(JsFunction::from_raw(func));
        let callback: Box<F> = Box::from_raw(mem::transmute(callback));
        callback(&mut cx, this, func);
    })
}
<commit_msg>fixed incorrect unsafe closure usage in event handler<commit_after>//! Helper to run a callback in the libuv main thread.

use std::os::raw::c_void;

use types::*;
use handle::{Handle, Managed};
use neon_runtime;
use neon_runtime::raw;
use std::sync::Arc;
use context::Context;

type EventContext<'a> = crate::context::TaskContext<'a>;

struct EventHandlerInner(*mut c_void);

unsafe impl Send for EventHandlerInner {}
unsafe impl Sync for EventHandlerInner {}

impl Drop for EventHandlerInner {
    fn drop(&mut self) {
        unsafe {
            neon_runtime::handler::delete(self.0);
        }
    }
}

#[derive(Clone)]
pub struct EventHandler(Arc<EventHandlerInner>);

impl EventHandler {
    #[cfg(feature = "napi-runtime")]
    pub fn new<'a, C: Context<'a>, T: Value>(cx: &C, this: Handle<T>, callback: Handle<JsFunction>) -> Self {
        unimplemented!()
    }

    #[cfg(feature = "legacy-runtime")]
    pub fn new<'a, C: Context<'a>, T: Value>(cx: &C, this: Handle<T>, callback: Handle<JsFunction>) -> Self {
        let cb = unsafe {
            neon_runtime::handler::new(cx.env().to_raw(), this.to_raw(), callback.to_raw())
        };
        EventHandler(Arc::new(EventHandlerInner(cb)))
    }

    pub fn schedule<T, F>(&self, arg_cb: F)
        where T: Value,
              F: for<'a> FnOnce(&mut EventContext<'a>) -> Vec<Handle<'a, T>>,
              F: Send + 'static {
        self.schedule_with(move |cx, this, callback| {
            let args = arg_cb(cx);
            let _result = callback.call(cx, this, args);
        })
    }

    fn schedule_internal<F>(&self, cb: F)
        where F: FnOnce(&mut EventContext, Handle<JsValue>, Handle<JsFunction>),
              F: Send + 'static {
        let callback = Box::into_raw(Box::new(cb)) as *mut c_void;
        unsafe {
            neon_runtime::handler::schedule((*self.0).0, callback, handle_callback::<F>);
        }
    }

    pub fn schedule_with<F>(&self, arg_cb: F)
        where F: FnOnce(&mut EventContext, Handle<JsValue>, Handle<JsFunction>),
              F: Send + 'static {
        // HACK: Work around for race condition in `close`. `EventHandler` cannot be
        // dropped until all callbacks have executed.
        // NOTE: This will still leak memory if the callback is never called
        let cloned_cb = self.clone();

        self.schedule_internal(move |cx, this, cb| {
            arg_cb(cx, this, cb);
            let _ = cloned_cb;
        });
    }
}

unsafe extern "C" fn handle_callback<F>(this: raw::Local, func: raw::Local, callback: *mut c_void)
    where F: FnOnce(&mut EventContext, Handle<JsValue>, Handle<JsFunction>), F: Send + 'static {
    EventContext::with(|mut cx: EventContext| {
        let this = JsValue::new_internal(this);
        let func: Handle<JsFunction> = Handle::new_internal(JsFunction::from_raw(func));
        let callback: Box<F> = Box::from_raw(callback as *mut _);
        callback(&mut cx, this, func);
    })
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    file_format::{
        AddressPoolIndex, ByteArrayPoolIndex, Bytecode, CodeOffset, CodeUnit, FieldDefinitionIndex,
        FunctionDefinition, FunctionHandle, FunctionHandleIndex, FunctionSignature,
        FunctionSignatureIndex, LocalIndex, LocalsSignature, LocalsSignatureIndex,
        ModuleHandleIndex, StringPoolIndex, StructDefinitionIndex, TableIndex, NO_TYPE_ACTUALS,
    },
    proptest_types::signature::{FunctionSignatureGen, SignatureTokenGen},
};
use proptest::{
    collection::{vec, SizeRange},
    prelude::*,
    sample::{select, Index as PropIndex},
};

/// Represents state required to materialize final data structures for function definitions.
#[derive(Debug)]
pub struct FnDefnMaterializeState {
    pub struct_handles_len: usize,
    pub address_pool_len: usize,
    pub string_pool_len: usize,
    pub byte_array_pool_len: usize,
    pub type_signatures_len: usize,
    pub field_defs_len: usize,
    pub struct_defs_len: usize,
    pub function_defs_len: usize,
    // This is the final length of function_handles, after all the definitions add their own
    // handles.
    pub function_handles_len: usize,
    // These get mutated by `FunctionDefinitionGen`.
    pub function_signatures: Vec<FunctionSignature>,
    pub locals_signatures: Vec<LocalsSignature>,
    pub function_handles: Vec<FunctionHandle>,
}

impl FnDefnMaterializeState {
    #[inline]
    fn add_function_signature(&mut self, sig: FunctionSignature) -> FunctionSignatureIndex {
        self.function_signatures.push(sig);
        FunctionSignatureIndex::new((self.function_signatures.len() - 1) as TableIndex)
    }

    #[inline]
    fn add_locals_signature(&mut self, sig: LocalsSignature) -> LocalsSignatureIndex {
        self.locals_signatures.push(sig);
        LocalsSignatureIndex::new((self.locals_signatures.len() - 1) as TableIndex)
    }

    #[inline]
    fn add_function_handle(&mut self, handle: FunctionHandle) -> FunctionHandleIndex {
        self.function_handles.push(handle);
        FunctionHandleIndex::new((self.function_handles.len() - 1) as TableIndex)
    }
}

#[derive(Clone, Debug)]
pub struct FunctionDefinitionGen {
    name: PropIndex,
    signature: FunctionSignatureGen,
    is_public: bool,
    code: CodeUnitGen,
}

impl FunctionDefinitionGen {
    pub fn strategy(
        return_count: impl Into<SizeRange>,
        arg_count: impl Into<SizeRange>,
        kind_count: impl Into<SizeRange>,
        code_len: impl Into<SizeRange>,
    ) -> impl Strategy<Value = Self> {
        let return_count = return_count.into();
        let arg_count = arg_count.into();
        (
            any::<PropIndex>(),
            FunctionSignatureGen::strategy(
                return_count.clone(),
                arg_count.clone(),
                kind_count.into(),
            ),
            any::<bool>(),
            CodeUnitGen::strategy(arg_count, code_len),
        )
            .prop_map(|(name, signature, is_public, code)| Self {
                name,
                signature,
                is_public,
                code,
            })
    }

    pub fn materialize(self, state: &mut FnDefnMaterializeState) -> FunctionDefinition {
        let signature = self.signature.materialize(state.struct_handles_len);

        let handle = FunctionHandle {
            // 0 represents the current module
            module: ModuleHandleIndex::new(0),
            // XXX need to guarantee uniqueness of names?
            name: StringPoolIndex::new(self.name.index(state.string_pool_len) as TableIndex),
            signature: state.add_function_signature(signature),
        };
        let function_handle = state.add_function_handle(handle);

        FunctionDefinition {
            function: function_handle,
            // XXX is this even correct?
            flags: if self.is_public {
                CodeUnit::PUBLIC
            } else {
                // No qualifiers.
                0
            },
            code: self.code.materialize(state),
        }
    }
}

#[derive(Clone, Debug)]
struct CodeUnitGen {
    locals_signature: Vec<SignatureTokenGen>,
    code: Vec<BytecodeGen>,
}

impl CodeUnitGen {
    fn strategy(
        arg_count: impl Into<SizeRange>,
        code_len: impl Into<SizeRange>,
    ) -> impl Strategy<Value = Self> {
        (
            vec(SignatureTokenGen::strategy(), arg_count),
            vec(BytecodeGen::garbage_strategy(), code_len),
        )
            .prop_map(|(locals_signature, code)| Self {
                locals_signature,
                code,
            })
    }

    fn materialize(self, state: &mut FnDefnMaterializeState) -> CodeUnit {
        let locals_signature = LocalsSignature(
            self.locals_signature
                .into_iter()
                .map(|sig| sig.materialize(state.struct_handles_len))
                .collect(),
        );

        // Not all bytecodes will be successfully materialized -- count how many will.
        let code_len = self
            .code
            .iter()
            .filter(|code| code.will_materialize(state, &locals_signature))
            .count();

        let code = self
            .code
            .into_iter()
            .filter_map(|code| code.materialize(state, code_len, &locals_signature))
            .collect();

        CodeUnit {
            max_stack_size: 0,
            locals: state.add_locals_signature(locals_signature),
            // XXX actually generate code
            code,
        }
    }
}

#[derive(Clone, Debug)]
enum BytecodeGen {
    // "Simple" means this doesn't refer to any other indexes.
    Simple(Bytecode),
    // All of these refer to other indexes.
    LdAddr(PropIndex),
    LdStr(PropIndex),
    LdByteArray(PropIndex),
    BorrowField(PropIndex),
    Call(PropIndex, PropIndex),
    Pack(PropIndex, PropIndex),
    Unpack(PropIndex, PropIndex),
    Exists(PropIndex, PropIndex),
    BorrowGlobal(PropIndex, PropIndex),
    MoveFrom(PropIndex, PropIndex),
    MoveToSender(PropIndex, PropIndex),
    BrTrue(PropIndex),
    BrFalse(PropIndex),
    Branch(PropIndex),
    CopyLoc(PropIndex),
    MoveLoc(PropIndex),
    StLoc(PropIndex),
    BorrowLoc(PropIndex),
}

impl BytecodeGen {
    // This just generates nonsensical bytecodes. This will be cleaned up later as the generation
    // model is refined.
    fn garbage_strategy() -> impl Strategy<Value = Self> {
        use BytecodeGen::*;

        prop_oneof![
            Self::simple_bytecode_strategy().prop_map(Simple),
            any::<PropIndex>().prop_map(LdAddr),
            any::<PropIndex>().prop_map(LdStr),
            any::<PropIndex>().prop_map(LdByteArray),
            any::<PropIndex>().prop_map(BorrowField),
            (any::<PropIndex>(), any::<PropIndex>(),).prop_map(|(idx, types)| Call(idx, types)),
            (any::<PropIndex>(), any::<PropIndex>(),).prop_map(|(idx, types)| Pack(idx, types)),
            (any::<PropIndex>(), any::<PropIndex>(),).prop_map(|(idx, types)| Unpack(idx, types)),
            (any::<PropIndex>(), any::<PropIndex>(),).prop_map(|(idx, types)| Exists(idx, types)),
            (any::<PropIndex>(), any::<PropIndex>(),)
                .prop_map(|(idx, types)| BorrowGlobal(idx, types)),
            (any::<PropIndex>(), any::<PropIndex>(),).prop_map(|(idx, types)| MoveFrom(idx, types)),
            (any::<PropIndex>(), any::<PropIndex>(),)
                .prop_map(|(idx, types)| MoveToSender(idx, types)),
            any::<PropIndex>().prop_map(BrTrue),
            any::<PropIndex>().prop_map(BrFalse),
            any::<PropIndex>().prop_map(Branch),
            any::<PropIndex>().prop_map(CopyLoc),
            any::<PropIndex>().prop_map(MoveLoc),
            any::<PropIndex>().prop_map(StLoc),
            any::<PropIndex>().prop_map(BorrowLoc),
        ]
    }

    /// Whether this code will be materialized into a Some(bytecode).
    fn will_materialize(
        &self,
        state: &FnDefnMaterializeState,
        locals_signature: &LocalsSignature,
    ) -> bool {
        // This method should remain in sync with the `None` below.
        use BytecodeGen::*;

        match self {
            BorrowField(_) => state.field_defs_len != 0,
            CopyLoc(_) | MoveLoc(_) | StLoc(_) | BorrowLoc(_) => !locals_signature.is_empty(),
            _ => true,
        }
    }

    fn materialize(
        self,
        state: &FnDefnMaterializeState,
        code_len: usize,
        locals_signature: &LocalsSignature,
    ) -> Option<Bytecode> {
        // This method returns an Option<Bytecode> because some bytecodes cannot be represented if
        // some tables are empty.
        //
        // Once more sensible function bodies are generated this will probably have to start using
        // prop_flat_map anyway, so revisit this then.

        let bytecode = match self {
            BytecodeGen::Simple(bytecode) => bytecode,
            BytecodeGen::LdAddr(idx) => Bytecode::LdAddr(AddressPoolIndex::new(
                idx.index(state.address_pool_len) as TableIndex,
            )),
            BytecodeGen::LdStr(idx) => Bytecode::LdStr(StringPoolIndex::new(
                idx.index(state.string_pool_len) as TableIndex,
            )),
            BytecodeGen::LdByteArray(idx) => Bytecode::LdByteArray(ByteArrayPoolIndex::new(
                idx.index(state.byte_array_pool_len) as TableIndex,
            )),
            BytecodeGen::BorrowField(idx) => {
                // Again, once meaningful bytecodes are generated this won't actually be a
                // possibility since it would be impossible to load a field from a struct that
                // doesn't have any.
                if state.field_defs_len == 0 {
                    return None;
                }
                Bytecode::BorrowField(FieldDefinitionIndex::new(
                    idx.index(state.field_defs_len) as TableIndex
                ))
            }
            BytecodeGen::Call(idx, _types_idx) => Bytecode::Call(
                FunctionHandleIndex::new(idx.index(state.function_handles_len) as TableIndex),
                // TODO: generate random index to type actuals once generics is fully implemented
                NO_TYPE_ACTUALS,
            ),
            BytecodeGen::Pack(idx, _types_idx) => Bytecode::Pack(
                StructDefinitionIndex::new(idx.index(state.struct_defs_len) as TableIndex),
                // TODO: generate random index to type actuals once generics is fully implemented
                NO_TYPE_ACTUALS,
            ),
            BytecodeGen::Unpack(idx, _types_idx) => Bytecode::Unpack(
                StructDefinitionIndex::new(idx.index(state.struct_defs_len) as TableIndex),
                // TODO: generate random index to type actuals once generics is fully implemented
                NO_TYPE_ACTUALS,
            ),
            BytecodeGen::Exists(idx, _types_idx) => Bytecode::Exists(
                StructDefinitionIndex::new(idx.index(state.struct_defs_len) as TableIndex),
                // TODO: generate random index to type actuals once generics is fully implemented
                NO_TYPE_ACTUALS,
            ),
            BytecodeGen::BorrowGlobal(idx, _types_idx) => Bytecode::BorrowGlobal(
                StructDefinitionIndex::new(idx.index(state.struct_defs_len) as TableIndex),
                // TODO: generate random index to type actuals once generics is fully implemented
                NO_TYPE_ACTUALS,
            ),
            BytecodeGen::MoveFrom(idx, _types_idx) => Bytecode::MoveFrom(
                StructDefinitionIndex::new(idx.index(state.struct_defs_len) as TableIndex),
                // TODO: generate random index to type actuals once generics is fully implemented
                NO_TYPE_ACTUALS,
            ),
            BytecodeGen::MoveToSender(idx, _types_idx) => Bytecode::MoveToSender(
                StructDefinitionIndex::new(idx.index(state.struct_defs_len) as TableIndex),
                // TODO: generate random index to type actuals once generics is fully implemented
                NO_TYPE_ACTUALS,
            ),
            BytecodeGen::BrTrue(idx) => Bytecode::BrTrue(idx.index(code_len) as CodeOffset),
            BytecodeGen::BrFalse(idx) => Bytecode::BrFalse(idx.index(code_len) as CodeOffset),
            BytecodeGen::Branch(idx) => Bytecode::Branch(idx.index(code_len) as CodeOffset),
            BytecodeGen::CopyLoc(idx) => {
                if locals_signature.is_empty() {
                    return None;
                }
                Bytecode::CopyLoc(idx.index(locals_signature.len()) as LocalIndex)
            }
            BytecodeGen::MoveLoc(idx) => {
                if locals_signature.is_empty() {
                    return None;
                }
                Bytecode::MoveLoc(idx.index(locals_signature.len()) as LocalIndex)
            }
            BytecodeGen::StLoc(idx) => {
                if locals_signature.is_empty() {
                    return None;
                }
                Bytecode::StLoc(idx.index(locals_signature.len()) as LocalIndex)
            }
            BytecodeGen::BorrowLoc(idx) => {
                if locals_signature.is_empty() {
                    return None;
                }
                Bytecode::BorrowLoc(idx.index(locals_signature.len()) as LocalIndex)
            }
        };

        Some(bytecode)
    }

    fn simple_bytecode_strategy() -> impl Strategy<Value = Bytecode> {
        prop_oneof![
            // The numbers are relative weights, somewhat arbitrarily picked.
            9 => Self::just_bytecode_strategy(),
            1 => any::<u64>().prop_map(Bytecode::LdConst),
        ]
    }

    fn just_bytecode_strategy() -> impl Strategy<Value = Bytecode> {
        use Bytecode::*;

        static JUST_BYTECODES: &[Bytecode] = &[
            FreezeRef,
            ReleaseRef,
            Pop,
            Ret,
            LdTrue,
            LdFalse,
            ReadRef,
            WriteRef,
            Add,
            Sub,
            Mul,
            Mod,
            Div,
            BitOr,
            BitAnd,
            Xor,
            Or,
            And,
            Eq,
            Neq,
            Lt,
            Gt,
            Le,
            Ge,
            Abort,
            GetTxnGasUnitPrice,
            GetTxnMaxGasUnits,
            GetTxnSenderAddress,
            CreateAccount,
            EmitEvent,
            GetTxnSequenceNumber,
            GetTxnPublicKey,
        ];
        select(JUST_BYTECODES)
    }
}
<commit_msg>Ensure vectors don't overflow in function proptest<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    file_format::{
        AddressPoolIndex, ByteArrayPoolIndex, Bytecode, CodeOffset, CodeUnit, FieldDefinitionIndex,
        FunctionDefinition, FunctionHandle, FunctionHandleIndex, FunctionSignature,
        FunctionSignatureIndex, LocalIndex, LocalsSignature, LocalsSignatureIndex,
        ModuleHandleIndex, StringPoolIndex, StructDefinitionIndex, TableIndex, NO_TYPE_ACTUALS,
    },
    proptest_types::{
        signature::{FunctionSignatureGen, SignatureTokenGen},
        TableSize,
    },
};
use proptest::{
    collection::{vec, SizeRange},
    prelude::*,
    sample::{select, Index as PropIndex},
};

/// Represents state required to materialize final data structures for function definitions.
#[derive(Debug)]
pub struct FnDefnMaterializeState {
    pub struct_handles_len: usize,
    pub address_pool_len: usize,
    pub string_pool_len: usize,
    pub byte_array_pool_len: usize,
    pub type_signatures_len: usize,
    pub field_defs_len: usize,
    pub struct_defs_len: usize,
    pub function_defs_len: usize,
    // This is the final length of function_handles, after all the definitions add their own
    // handles.
    pub function_handles_len: usize,
    // These get mutated by `FunctionDefinitionGen`.
    pub function_signatures: Vec<FunctionSignature>,
    pub locals_signatures: Vec<LocalsSignature>,
    pub function_handles: Vec<FunctionHandle>,
}

impl FnDefnMaterializeState {
    #[inline]
    fn add_function_signature(&mut self, sig: FunctionSignature) -> FunctionSignatureIndex {
        precondition!(self.function_signatures.len() < TableSize::max_value() as usize);
        self.function_signatures.push(sig);
        FunctionSignatureIndex::new((self.function_signatures.len() - 1) as TableIndex)
    }

    #[inline]
    fn add_locals_signature(&mut self, sig: LocalsSignature) -> LocalsSignatureIndex {
        precondition!(self.locals_signatures.len() < TableSize::max_value() as usize);
        self.locals_signatures.push(sig);
        LocalsSignatureIndex::new((self.locals_signatures.len() - 1) as TableIndex)
    }

    #[inline]
    fn add_function_handle(&mut self, handle: FunctionHandle) -> FunctionHandleIndex {
        precondition!(self.function_handles.len() < TableSize::max_value() as usize);
        self.function_handles.push(handle);
        FunctionHandleIndex::new((self.function_handles.len() - 1) as TableIndex)
    }
}

#[derive(Clone, Debug)]
pub struct FunctionDefinitionGen {
    name: PropIndex,
    signature: FunctionSignatureGen,
    is_public: bool,
    code: CodeUnitGen,
}

impl FunctionDefinitionGen {
    pub fn strategy(
        return_count: impl Into<SizeRange>,
        arg_count: impl Into<SizeRange>,
        kind_count: impl Into<SizeRange>,
        code_len: impl Into<SizeRange>,
    ) -> impl Strategy<Value = Self> {
        let return_count = return_count.into();
        let arg_count = arg_count.into();
        (
            any::<PropIndex>(),
            FunctionSignatureGen::strategy(
                return_count.clone(),
                arg_count.clone(),
                kind_count.into(),
            ),
            any::<bool>(),
            CodeUnitGen::strategy(arg_count, code_len),
        )
            .prop_map(|(name, signature, is_public, code)| Self {
                name,
                signature,
                is_public,
                code,
            })
    }

    pub fn materialize(self, state: &mut FnDefnMaterializeState) -> FunctionDefinition {
        // This precondition should never fail because the table size cannot be greater
        // than TableSize::max_value()
        checked_precondition!(
            state.function_signatures.len() < TableSize::max_value() as usize
                && state.locals_signatures.len() < TableSize::max_value() as usize
                && state.function_handles.len() < TableSize::max_value() as usize
        );
        let signature = self.signature.materialize(state.struct_handles_len);

        let handle = FunctionHandle {
            // 0 represents the current module
            module: ModuleHandleIndex::new(0),
            // XXX need to guarantee uniqueness of names?
            name: StringPoolIndex::new(self.name.index(state.string_pool_len) as TableIndex),
            signature: state.add_function_signature(signature),
        };
        let function_handle = state.add_function_handle(handle);

        FunctionDefinition {
            function: function_handle,
            // XXX is this even correct?
            flags: if self.is_public {
                CodeUnit::PUBLIC
            } else {
                // No qualifiers.
                0
            },
            code: self.code.materialize(state),
        }
    }
}

#[derive(Clone, Debug)]
struct CodeUnitGen {
    locals_signature: Vec<SignatureTokenGen>,
    code: Vec<BytecodeGen>,
}

impl CodeUnitGen {
    fn strategy(
        arg_count: impl Into<SizeRange>,
        code_len: impl Into<SizeRange>,
    ) -> impl Strategy<Value = Self> {
        (
            vec(SignatureTokenGen::strategy(), arg_count),
            vec(BytecodeGen::garbage_strategy(), code_len),
        )
            .prop_map(|(locals_signature, code)| Self {
                locals_signature,
                code,
            })
    }

    fn materialize(self, state: &mut FnDefnMaterializeState) -> CodeUnit {
        precondition!(state.locals_signatures.len() < TableSize::max_value() as usize);
        let locals_signature = LocalsSignature(
            self.locals_signature
                .into_iter()
                .map(|sig| sig.materialize(state.struct_handles_len))
                .collect(),
        );

        // Not all bytecodes will be successfully materialized -- count how many will.
        let code_len = self
            .code
            .iter()
            .filter(|code| code.will_materialize(state, &locals_signature))
            .count();

        let code = self
            .code
            .into_iter()
            .filter_map(|code| code.materialize(state, code_len, &locals_signature))
            .collect();

        CodeUnit {
            max_stack_size: 0,
            locals: state.add_locals_signature(locals_signature),
            // XXX actually generate code
            code,
        }
    }
}

#[derive(Clone, Debug)]
enum BytecodeGen {
    // "Simple" means this doesn't refer to any other indexes.
    Simple(Bytecode),
    // All of these refer to other indexes.
    LdAddr(PropIndex),
    LdStr(PropIndex),
    LdByteArray(PropIndex),
    BorrowField(PropIndex),
    Call(PropIndex, PropIndex),
    Pack(PropIndex, PropIndex),
    Unpack(PropIndex, PropIndex),
    Exists(PropIndex, PropIndex),
    BorrowGlobal(PropIndex, PropIndex),
    MoveFrom(PropIndex, PropIndex),
    MoveToSender(PropIndex, PropIndex),
    BrTrue(PropIndex),
    BrFalse(PropIndex),
    Branch(PropIndex),
    CopyLoc(PropIndex),
    MoveLoc(PropIndex),
    StLoc(PropIndex),
    BorrowLoc(PropIndex),
}

impl BytecodeGen {
    // This just generates nonsensical bytecodes. This will be cleaned up later as the generation
    // model is refined.
    fn garbage_strategy() -> impl Strategy<Value = Self> {
        use BytecodeGen::*;

        prop_oneof![
            Self::simple_bytecode_strategy().prop_map(Simple),
            any::<PropIndex>().prop_map(LdAddr),
            any::<PropIndex>().prop_map(LdStr),
            any::<PropIndex>().prop_map(LdByteArray),
            any::<PropIndex>().prop_map(BorrowField),
            (any::<PropIndex>(), any::<PropIndex>(),).prop_map(|(idx, types)| Call(idx, types)),
            (any::<PropIndex>(), any::<PropIndex>(),).prop_map(|(idx, types)| Pack(idx, types)),
            (any::<PropIndex>(), any::<PropIndex>(),).prop_map(|(idx, types)| Unpack(idx, types)),
            (any::<PropIndex>(), any::<PropIndex>(),).prop_map(|(idx, types)| Exists(idx, types)),
            (any::<PropIndex>(), any::<PropIndex>(),)
                .prop_map(|(idx, types)| BorrowGlobal(idx, types)),
            (any::<PropIndex>(), any::<PropIndex>(),).prop_map(|(idx, types)| MoveFrom(idx, types)),
            (any::<PropIndex>(), any::<PropIndex>(),)
                .prop_map(|(idx, types)| MoveToSender(idx, types)),
            any::<PropIndex>().prop_map(BrTrue),
            any::<PropIndex>().prop_map(BrFalse),
            any::<PropIndex>().prop_map(Branch),
            any::<PropIndex>().prop_map(CopyLoc),
            any::<PropIndex>().prop_map(MoveLoc),
            any::<PropIndex>().prop_map(StLoc),
            any::<PropIndex>().prop_map(BorrowLoc),
        ]
    }

    /// Whether this code will be materialized into a Some(bytecode).
    fn will_materialize(
        &self,
        state: &FnDefnMaterializeState,
        locals_signature: &LocalsSignature,
    ) -> bool {
        // This method should remain in sync with the `None` below.
        use BytecodeGen::*;

        match self {
            BorrowField(_) => state.field_defs_len != 0,
            CopyLoc(_) | MoveLoc(_) | StLoc(_) | BorrowLoc(_) => !locals_signature.is_empty(),
            _ => true,
        }
    }

    fn materialize(
        self,
        state: &FnDefnMaterializeState,
        code_len: usize,
        locals_signature: &LocalsSignature,
    ) -> Option<Bytecode> {
        // This method returns an Option<Bytecode> because some bytecodes cannot be represented if
        // some tables are empty.
        //
        // Once more sensible function bodies are generated this will probably have to start using
        // prop_flat_map anyway, so revisit this then.

        let bytecode = match self {
            BytecodeGen::Simple(bytecode) => bytecode,
            BytecodeGen::LdAddr(idx) => Bytecode::LdAddr(AddressPoolIndex::new(
                idx.index(state.address_pool_len) as TableIndex,
            )),
            BytecodeGen::LdStr(idx) => Bytecode::LdStr(StringPoolIndex::new(
                idx.index(state.string_pool_len) as TableIndex,
            )),
            BytecodeGen::LdByteArray(idx) => Bytecode::LdByteArray(ByteArrayPoolIndex::new(
                idx.index(state.byte_array_pool_len) as TableIndex,
            )),
            BytecodeGen::BorrowField(idx) => {
                // Again, once meaningful bytecodes are generated this won't actually be a
                // possibility since it would be impossible to load a field from a struct that
                // doesn't have any.
                if state.field_defs_len == 0 {
                    return None;
                }
                Bytecode::BorrowField(FieldDefinitionIndex::new(
                    idx.index(state.field_defs_len) as TableIndex
                ))
            }
            BytecodeGen::Call(idx, _types_idx) => Bytecode::Call(
                FunctionHandleIndex::new(idx.index(state.function_handles_len) as TableIndex),
                // TODO: generate random index to type actuals once generics is fully implemented
                NO_TYPE_ACTUALS,
            ),
            BytecodeGen::Pack(idx, _types_idx) => Bytecode::Pack(
                StructDefinitionIndex::new(idx.index(state.struct_defs_len) as TableIndex),
                // TODO: generate random index to type actuals once generics is fully implemented
                NO_TYPE_ACTUALS,
            ),
            BytecodeGen::Unpack(idx, _types_idx) => Bytecode::Unpack(
                StructDefinitionIndex::new(idx.index(state.struct_defs_len) as TableIndex),
                // TODO: generate random index to type actuals once generics is fully implemented
                NO_TYPE_ACTUALS,
            ),
            BytecodeGen::Exists(idx, _types_idx) => Bytecode::Exists(
                StructDefinitionIndex::new(idx.index(state.struct_defs_len) as TableIndex),
                // TODO: generate random index to type actuals once generics is fully implemented
                NO_TYPE_ACTUALS,
            ),
            BytecodeGen::BorrowGlobal(idx, _types_idx) => Bytecode::BorrowGlobal(
                StructDefinitionIndex::new(idx.index(state.struct_defs_len) as TableIndex),
                // TODO: generate random index to type actuals once generics is fully implemented
                NO_TYPE_ACTUALS,
            ),
            BytecodeGen::MoveFrom(idx, _types_idx) => Bytecode::MoveFrom(
                StructDefinitionIndex::new(idx.index(state.struct_defs_len) as TableIndex),
                // TODO: generate random index to type actuals once generics is fully implemented
                NO_TYPE_ACTUALS,
            ),
            BytecodeGen::MoveToSender(idx, _types_idx) => Bytecode::MoveToSender(
                StructDefinitionIndex::new(idx.index(state.struct_defs_len) as TableIndex),
                // TODO: generate random index to type actuals once generics is fully implemented
                NO_TYPE_ACTUALS,
            ),
            BytecodeGen::BrTrue(idx) => Bytecode::BrTrue(idx.index(code_len) as CodeOffset),
            BytecodeGen::BrFalse(idx) => Bytecode::BrFalse(idx.index(code_len) as CodeOffset),
            BytecodeGen::Branch(idx) => Bytecode::Branch(idx.index(code_len) as CodeOffset),
            BytecodeGen::CopyLoc(idx) => {
                if locals_signature.is_empty() {
                    return None;
                }
                Bytecode::CopyLoc(idx.index(locals_signature.len()) as LocalIndex)
            }
            BytecodeGen::MoveLoc(idx) => {
                if locals_signature.is_empty() {
                    return None;
                }
                Bytecode::MoveLoc(idx.index(locals_signature.len()) as LocalIndex)
            }
            BytecodeGen::StLoc(idx) => {
                if locals_signature.is_empty() {
                    return None;
                }
                Bytecode::StLoc(idx.index(locals_signature.len()) as LocalIndex)
            }
            BytecodeGen::BorrowLoc(idx) => {
                if locals_signature.is_empty() {
                    return None;
                }
                Bytecode::BorrowLoc(idx.index(locals_signature.len()) as LocalIndex)
            }
        };

        Some(bytecode)
    }

    fn simple_bytecode_strategy() -> impl Strategy<Value = Bytecode> {
        prop_oneof![
            // The numbers are relative weights, somewhat arbitrarily picked.
            9 => Self::just_bytecode_strategy(),
            1 => any::<u64>().prop_map(Bytecode::LdConst),
        ]
    }

    fn just_bytecode_strategy() -> impl Strategy<Value = Bytecode> {
        use Bytecode::*;

        static JUST_BYTECODES: &[Bytecode] = &[
            FreezeRef,
            ReleaseRef,
            Pop,
            Ret,
            LdTrue,
            LdFalse,
            ReadRef,
            WriteRef,
            Add,
            Sub,
            Mul,
            Mod,
            Div,
            BitOr,
            BitAnd,
            Xor,
            Or,
            And,
            Eq,
            Neq,
            Lt,
            Gt,
            Le,
            Ge,
            Abort,
            GetTxnGasUnitPrice,
            GetTxnMaxGasUnits,
            GetTxnSenderAddress,
            CreateAccount,
            EmitEvent,
            GetTxnSequenceNumber,
            GetTxnPublicKey,
        ];
        select(JUST_BYTECODES)
    }
}
<|endoftext|>


<commit_before>// only-linux: Uses Linux-only APIs

#![feature(rustc_private)]
extern crate libc;

fn main() {
    let mut buf = [0u8; 5];
    unsafe {
        assert_eq!(libc::syscall(libc::SYS_getrandom, 0 as *mut libc::c_void, 0 as libc::size_t, 0 as libc::c_uint), 0);
        assert_eq!(libc::syscall(libc::SYS_getrandom, buf.as_mut_ptr() as *mut libc::c_void, 5 as libc::size_t, 0 as libc::c_uint), 5);

        assert_eq!(libc::getrandom(0 as *mut libc::c_void, 0 as libc::size_t, 0 as libc::c_uint), 0);
        assert_eq!(libc::getrandom(buf.as_mut_ptr() as *mut libc::c_void, 5 as libc::size_t, 0 as libc::c_uint), 5);
    }
}
<commit_msg>Ignore other platforms instead of using only-linux<commit_after>// Unfortunately, compiletest_rs does not support 'only-linux',
// so we need to ignore Windows and OS X instead
// ignore-macos: Uses Linux-only APIs
// ignore-windows: Uses Linux-only APIs
#![feature(rustc_private)]
extern crate libc;

fn main() {
    let mut buf = [0u8; 5];
    unsafe {
        assert_eq!(libc::syscall(libc::SYS_getrandom, 0 as *mut libc::c_void, 0 as libc::size_t, 0 as libc::c_uint), 0);
        assert_eq!(libc::syscall(libc::SYS_getrandom, buf.as_mut_ptr() as *mut libc::c_void, 5 as libc::size_t, 0 as libc::c_uint), 5);

        assert_eq!(libc::getrandom(0 as *mut libc::c_void, 0 as libc::size_t, 0 as libc::c_uint), 0);
        assert_eq!(libc::getrandom(buf.as_mut_ptr() as *mut libc::c_void, 5 as libc::size_t, 0 as libc::c_uint), 5);
    }
}
<|endoftext|>