<commit_before>//! The modules which contains CDRS Cassandra client.
use std::net;
use std::io;
use std::collections::HashMap;
use query::{Query, QueryParams, QueryBatch};
use frame::{Frame, Opcode, Flag};
use frame::frame_response::ResponseBody;
use IntoBytes;
use frame::parser::parse_frame;
use types::*;
use frame::events::SimpleServerEvent;

use compression::Compression;
use authenticators::Authenticator;
use error;
use transport::CDRSTransport;

use events::{Listener, EventStream, new_listener};

/// CDRS driver structure that provides a basic functionality to work with DB including
/// establishing new connection, getting supported options, preparing and executing CQL
/// queries, using compression and other.
#[derive(Eq,PartialEq,Ord,PartialOrd)]
pub struct CDRS<T: Authenticator, X: CDRSTransport> {
    compressor: Compression,
    authenticator: T,
    transport: X,
}

/// Map of options supported by Cassandra server.
pub type CassandraOptions = HashMap<String, Vec<String>>;

impl<'a, T: Authenticator + 'a, X: CDRSTransport + 'a> CDRS<T, X> {
    /// The method creates new instance of CDRS driver. At this step an instance doesn't
    /// connected to DB Server. To create new instance two parameters are needed to be
    /// provided - `addr` is IP address of DB Server, `authenticator` is a selected authenticator
    /// that is supported by particular DB Server. There are few authenticators already
    /// provided by this trait.
    pub fn new(transport: X, authenticator: T) -> CDRS<T, X> {
        return CDRS {
                   compressor: Compression::None,
                   authenticator: authenticator,
                   transport: transport,
               };
    }

    /// The method makes an Option request to DB Server. As a response the server returns
    /// a map of supported options.
    pub fn get_options(&mut self) -> error::Result<CassandraOptions> {
        let options_frame = Frame::new_req_options().into_cbytes();

        try!(self.transport.write(options_frame.as_slice()));

        return parse_frame(&mut self.transport, &self.compressor).map(|frame| {
                                                                          match frame.get_body() {
                ResponseBody::Supported(ref supported_body) => supported_body.data.clone(),
                _ => unreachable!(),
            }
                                                                      });
    }

    /// The method establishes connection to the server which address was provided on previous
    /// step. To create connection it's required to provide a compression method from a list
    /// of supported ones. In 4-th version of Cassandra protocol lz4 (`Compression::Lz4`)
    /// and snappy (`Compression::Snappy`) are supported. There is also one special compression
    /// method provided by CRDR driver, it's `Compression::None` that tells drivers that it
    /// should work without compression. If compression is provided then incomming frames
    /// will be decompressed automatically.
    pub fn start(mut self, compressor: Compression) -> error::Result<Session<T, X>> {
        self.compressor = compressor;
        let startup_frame = Frame::new_req_startup(compressor.as_str()).into_cbytes();

        try!(self.transport.write(startup_frame.as_slice()));
        let start_response = try!(parse_frame(&mut self.transport, &compressor));

        if start_response.opcode == Opcode::Ready {
            return Ok(Session::start(self));
        }

        if start_response.opcode == Opcode::Authenticate {
            let body = start_response.get_body();
            let authenticator =
                body.get_authenticator()
                    .expect("Cassandra Server did communicate that it needed password
                authentication but the  auth schema was missing in the body response");

            // This creates a new scope; avoiding a clone
            // and we check whether
            // 1. any authenticators has been passed in by client and if not send error back
            // 2. authenticator is provided by the client and `auth_scheme` presented by
            //      the server and client are same if not send error back
            // 3. if it falls through it means the preliminary conditions are true

            let auth_check = self.authenticator
                .get_cassandra_name()
                .ok_or(error::Error::General("No authenticator was provided".to_string()))
                .map(|auth| {
                    if authenticator != auth {
                        let io_err =
                            io::Error::new(io::ErrorKind::NotFound,
                                           format!("Unsupported type of authenticator. {:?} got,
                             but {} is supported.",
                                                   authenticator,
                                                   authenticator));
                        return Err(error::Error::Io(io_err));
                    }
                    Ok(())
                });

            if let Err(err) = auth_check {
                return Err(err);
            }

            let auth_token_bytes = self.authenticator.get_auth_token().into_cbytes();
            try!(self.transport
                     .write(Frame::new_req_auth_response(auth_token_bytes)
                                .into_cbytes()
                                .as_slice()));
            try!(parse_frame(&mut self.transport, &compressor));

            return Ok(Session::start(self));

        }

        unimplemented!();
    }

    fn drop_connection(&mut self) -> error::Result<()> {
        return self.transport
                   .close(net::Shutdown::Both)
                   .map_err(|err| error::Error::Io(err));
    }
}

/// The object that provides functionality for communication with Cassandra server.
pub struct Session<T: Authenticator, X: CDRSTransport> {
    started: bool,
    cdrs: CDRS<T, X>,
    compressor: Compression,
}

impl<T: Authenticator, X: CDRSTransport> Session<T, X> {
    /// Creates new session basing on CDRS instance.
    pub fn start(cdrs: CDRS<T, X>) -> Session<T, X> {
        let compressor = cdrs.compressor.clone();
        return Session {
                   cdrs: cdrs,
                   started: true,
                   compressor: compressor,
               };
    }

    /// The method overrides a compression method of current session
    pub fn compressor(&mut self, compressor: Compression) -> &mut Self {
        self.compressor = compressor;
        return self;
    }

    /// Manually ends current session.
    /// Apart of that session will be ended automatically when the instance is dropped.
    pub fn end(&mut self) {
        if self.started {
            self.started = false;
            match self.cdrs.drop_connection() {
                Ok(_) => (),
                Err(err) => {
                    println!("Error occured during dropping CDRS {:?}", err);
                }
            }
        }
    }

    /// The method makes a request to DB Server to prepare provided query.
    pub fn prepare(&mut self,
                   query: String,
                   with_tracing: bool,
                   with_warnings: bool)
                   -> error::Result<Frame> {
        let mut flags = vec![];
        if with_tracing {
            flags.push(Flag::Tracing);
        }
        if with_warnings {
            flags.push(Flag::Warning);
        }

        let options_frame = Frame::new_req_prepare(query, flags).into_cbytes();

        try!(self.cdrs.transport.write(options_frame.as_slice()));

        parse_frame(&mut self.cdrs.transport, &self.compressor)
    }

    /// The method makes a request to DB Server to execute a query with provided id
    /// using provided query parameters. `id` is an ID of a query which Server
    /// returns back to a driver as a response to `prepare` request.
    pub fn execute(&mut self,
                   id: &CBytesShort,
                   query_parameters: QueryParams,
                   with_tracing: bool,
                   with_warnings: bool)
                   -> error::Result<Frame> {

        let mut flags = vec![];
        if with_tracing {
            flags.push(Flag::Tracing);
        }
        if with_warnings {
            flags.push(Flag::Warning);
        }
        let options_frame = Frame::new_req_execute(id, query_parameters, flags).into_cbytes();

        (self.cdrs.transport.write(options_frame.as_slice()))?;
        return parse_frame(&mut self.cdrs.transport, &self.compressor);
    }

    /// The method makes a request to DB Server to execute a query provided in `query` argument.
    /// you can build the query with QueryBuilder
    /// ```
    /// let qb = QueryBuilder::new().query("select * from emp")
    /// .consistency(Consistency::One).page_size(Some(4));
    /// session.query_with_builder(qb);
    /// ```
    pub fn query(&mut self,
                 query: Query,
                 with_tracing: bool,
                 with_warnings: bool)
                 -> error::Result<Frame> {
        let mut flags = vec![];

        if with_tracing {
            flags.push(Flag::Tracing);
        }

        if with_warnings {
            flags.push(Flag::Warning);
        }

        let query_frame = Frame::new_req_query(query.query,
                                               query.consistency,
                                               query.values,
                                               query.with_names,
                                               query.page_size,
                                               query.paging_state,
                                               query.serial_consistency,
                                               query.timestamp,
                                               flags)
                .into_cbytes();

        try!(self.cdrs.transport.write(query_frame.as_slice()));
        return parse_frame(&mut self.cdrs.transport, &self.compressor);
    }

    pub fn batch(&mut self,
                 batch_query: QueryBatch,
                 with_tracing: bool,
                 with_warnings: bool)
                 -> error::Result<Frame> {
        let mut flags = vec![];

        if with_tracing {
            flags.push(Flag::Tracing);
        }

        if with_warnings {
            flags.push(Flag::Warning);
        }

        let query_frame = Frame::new_req_batch(batch_query, flags).into_cbytes();

        try!(self.cdrs.transport.write(query_frame.as_slice()));
        return parse_frame(&mut self.cdrs.transport, &self.compressor);
    }

    /// It consumes CDRS
    pub fn listen_for<'a>(mut self,
                          events: Vec<SimpleServerEvent>)
                          -> error::Result<(Listener<X>, EventStream)> {
        let query_frame = Frame::new_req_register(events).into_cbytes();
        try!(self.cdrs.transport.write(query_frame.as_slice()));
        try!(parse_frame(&mut self.cdrs.transport, &self.compressor));
        Ok(new_listener(self.cdrs.transport))
    }
}
<commit_msg>updated clippy for client.rs<commit_after>//! The modules which contains CDRS Cassandra client.
use std::net;
use std::io;
use std::collections::HashMap;
use query::{Query, QueryParams, QueryBatch};
use frame::{Frame, Opcode, Flag};
use frame::frame_response::ResponseBody;
use IntoBytes;
use frame::parser::parse_frame;
use types::*;
use frame::events::SimpleServerEvent;

use compression::Compression;
use authenticators::Authenticator;
use error;
use transport::CDRSTransport;

use events::{Listener, EventStream, new_listener};

/// CDRS driver structure that provides a basic functionality to work with DB including
/// establishing new connection, getting supported options, preparing and executing CQL
/// queries, using compression and other.
#[derive(Eq,PartialEq,Ord,PartialOrd)]
pub struct CDRS<T: Authenticator, X: CDRSTransport> {
    compressor: Compression,
    authenticator: T,
    transport: X,
}

/// Map of options supported by Cassandra server.
pub type CassandraOptions = HashMap<String, Vec<String>>;

impl<'a, T: Authenticator + 'a, X: CDRSTransport + 'a> CDRS<T, X> {
    /// The method creates new instance of CDRS driver. At this step an instance doesn't
    /// connected to DB Server. To create new instance two parameters are needed to be
    /// provided - `addr` is IP address of DB Server, `authenticator` is a selected authenticator
    /// that is supported by particular DB Server. There are few authenticators already
    /// provided by this trait.
    pub fn new(transport: X, authenticator: T) -> CDRS<T, X> {
        return CDRS {
                   compressor: Compression::None,
                   authenticator: authenticator,
                   transport: transport,
               };
    }

    /// The method makes an Option request to DB Server. As a response the server returns
    /// a map of supported options.
    pub fn get_options(&mut self) -> error::Result<CassandraOptions> {
        let options_frame = Frame::new_req_options().into_cbytes();

        try!(self.transport.write(options_frame.as_slice()));

        parse_frame(&mut self.transport, &self.compressor)
        .map(|frame| {
                match frame.get_body() {
                ResponseBody::Supported(ref supported_body) => supported_body.data.clone(),
                _ => unreachable!(),
            }
        })
    }

    /// The method establishes connection to the server which address was provided on previous
    /// step. To create connection it's required to provide a compression method from a list
    /// of supported ones. In 4-th version of Cassandra protocol lz4 (`Compression::Lz4`)
    /// and snappy (`Compression::Snappy`) are supported. There is also one special compression
    /// method provided by CRDR driver, it's `Compression::None` that tells drivers that it
    /// should work without compression. If compression is provided then incomming frames
    /// will be decompressed automatically.
    pub fn start(mut self, compressor: Compression) -> error::Result<Session<T, X>> {
        self.compressor = compressor;
        let startup_frame = Frame::new_req_startup(compressor.as_str()).into_cbytes();

        try!(self.transport.write(startup_frame.as_slice()));
        let start_response = try!(parse_frame(&mut self.transport, &compressor));

        if start_response.opcode == Opcode::Ready {
            return Ok(Session::start(self));
        }

        if start_response.opcode == Opcode::Authenticate {
            let body = start_response.get_body();
            let authenticator =
                body.get_authenticator()
                    .expect("Cassandra Server did communicate that it needed password
                authentication but the  auth schema was missing in the body response");

            // This creates a new scope; avoiding a clone
            // and we check whether
            // 1. any authenticators has been passed in by client and if not send error back
            // 2. authenticator is provided by the client and `auth_scheme` presented by
            //      the server and client are same if not send error back
            // 3. if it falls through it means the preliminary conditions are true

            let auth_check = self.authenticator
                .get_cassandra_name()
                .ok_or(error::Error::General("No authenticator was provided".to_string()))
                .map(|auth| {
                    if authenticator != auth {
                        let io_err =
                            io::Error::new(io::ErrorKind::NotFound,
                                           format!("Unsupported type of authenticator. {:?} got,
                             but {} is supported.",
                                                   authenticator,
                                                   authenticator));
                        return Err(error::Error::Io(io_err));
                    }
                    Ok(())
                });

            if let Err(err) = auth_check {
                return Err(err);
            }

            let auth_token_bytes = self.authenticator.get_auth_token().into_cbytes();
            try!(self.transport
                     .write(Frame::new_req_auth_response(auth_token_bytes)
                                .into_cbytes()
                                .as_slice()));
            try!(parse_frame(&mut self.transport, &compressor));

            return Ok(Session::start(self));

        }

        unimplemented!();
    }

    fn drop_connection(&mut self) -> error::Result<()> {
        self.transport
            .close(net::Shutdown::Both)
            .map_err(|err| error::Error::Io(err))
    }
}

/// The object that provides functionality for communication with Cassandra server.
pub struct Session<T: Authenticator, X: CDRSTransport> {
    started: bool,
    cdrs: CDRS<T, X>,
    compressor: Compression,
}

impl<T: Authenticator, X: CDRSTransport> Session<T, X> {
    /// Creates new session basing on CDRS instance.
    pub fn start(cdrs: CDRS<T, X>) -> Session<T, X> {
        let compressor = cdrs.compressor.clone();
        Session {
            cdrs: cdrs,
            started: true,
            compressor: compressor,
        }
    }

    /// The method overrides a compression method of current session
    pub fn compressor(&mut self, compressor: Compression) -> &mut Self {
        self.compressor = compressor;
        self
    }

    /// Manually ends current session.
    /// Apart of that session will be ended automatically when the instance is dropped.
    pub fn end(&mut self) {
        if self.started {
            self.started = false;
            match self.cdrs.drop_connection() {
                Ok(_) => (),
                Err(err) => {
                    println!("Error occured during dropping CDRS {:?}", err);
                }
            }
        }
    }

    /// The method makes a request to DB Server to prepare provided query.
    pub fn prepare(&mut self,
                   query: String,
                   with_tracing: bool,
                   with_warnings: bool)
                   -> error::Result<Frame> {
        let mut flags = vec![];
        if with_tracing {
            flags.push(Flag::Tracing);
        }
        if with_warnings {
            flags.push(Flag::Warning);
        }

        let options_frame = Frame::new_req_prepare(query, flags).into_cbytes();

        try!(self.cdrs.transport.write(options_frame.as_slice()));

        parse_frame(&mut self.cdrs.transport, &self.compressor)
    }

    /// The method makes a request to DB Server to execute a query with provided id
    /// using provided query parameters. `id` is an ID of a query which Server
    /// returns back to a driver as a response to `prepare` request.
    pub fn execute(&mut self,
                   id: &CBytesShort,
                   query_parameters: QueryParams,
                   with_tracing: bool,
                   with_warnings: bool)
                   -> error::Result<Frame> {

        let mut flags = vec![];
        if with_tracing {
            flags.push(Flag::Tracing);
        }
        if with_warnings {
            flags.push(Flag::Warning);
        }
        let options_frame = Frame::new_req_execute(id, query_parameters, flags).into_cbytes();

        (self.cdrs.transport.write(options_frame.as_slice()))?;
        parse_frame(&mut self.cdrs.transport, &self.compressor)
    }

    /// The method makes a request to DB Server to execute a query provided in `query` argument.
    /// you can build the query with QueryBuilder
    /// ```
    /// let qb = QueryBuilder::new().query("select * from emp")
    /// .consistency(Consistency::One).page_size(Some(4));
    /// session.query_with_builder(qb);
    /// ```
    pub fn query(&mut self,
                 query: Query,
                 with_tracing: bool,
                 with_warnings: bool)
                 -> error::Result<Frame> {
        let mut flags = vec![];

        if with_tracing {
            flags.push(Flag::Tracing);
        }

        if with_warnings {
            flags.push(Flag::Warning);
        }

        let query_frame = Frame::new_req_query(query.query,
                                               query.consistency,
                                               query.values,
                                               query.with_names,
                                               query.page_size,
                                               query.paging_state,
                                               query.serial_consistency,
                                               query.timestamp,
                                               flags)
                .into_cbytes();

        try!(self.cdrs.transport.write(query_frame.as_slice()));
        parse_frame(&mut self.cdrs.transport, &self.compressor)
    }

    pub fn batch(&mut self,
                 batch_query: QueryBatch,
                 with_tracing: bool,
                 with_warnings: bool)
                 -> error::Result<Frame> {
        let mut flags = vec![];

        if with_tracing {
            flags.push(Flag::Tracing);
        }

        if with_warnings {
            flags.push(Flag::Warning);
        }

        let query_frame = Frame::new_req_batch(batch_query, flags).into_cbytes();

        try!(self.cdrs.transport.write(query_frame.as_slice()));
        parse_frame(&mut self.cdrs.transport, &self.compressor)
    }

    /// It consumes CDRS
    pub fn listen_for<'a>(mut self,
                          events: Vec<SimpleServerEvent>)
                          -> error::Result<(Listener<X>, EventStream)> {
        let query_frame = Frame::new_req_register(events).into_cbytes();
        try!(self.cdrs.transport.write(query_frame.as_slice()));
        try!(parse_frame(&mut self.cdrs.transport, &self.compressor));
        Ok(new_listener(self.cdrs.transport))
    }
}
<|endoftext|>


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

extern mod extra;
extern mod rustc;
extern mod rustpkg;

use extra::time;
use rustc::driver::driver::host_triple;
use rustpkg::api;
use std::from_str::{from_str};
use std::io::fs::{mkdir, File};
use std::io::buffered::BufferedReader;
use std::io;
use std::option::{Option};
use std::os;
use std::run;
use std::str;
use std::util;
use std::vec;

struct Version {
    major: uint,
    minor: uint
}

impl Version {
    pub fn parse(version_str: &str) -> Option<Version> {
        let mut it = version_str.split('.');
        match (it.next().and_then(from_str::<uint>), it.next().and_then(from_str::<uint>)) {
            (Some(major), Some(minor)) => Some(Version { major: major, minor: minor }),
            _                          => None
        }
    }
}

impl ToStr for Version {
    fn to_str(&self) -> ~str {
        format!("{:u}.{:u}", self.major, self.minor)
    }
}

impl Ord for Version {
    fn lt(&self, other: &Version) -> bool {
        self.major < other.major || (self.major == other.major && self.minor < other.minor)
    }
}

fn cd(path: &Path) {
    if !os::change_dir(path) {
        fail!("Package script error: Failed to `cd` into `{}`", path.display());
    }
}

fn do_install(args: ~[~str]) {
    let sysroot_arg = args[1].clone();
    let sysroot_path = from_str(sysroot_arg).unwrap();

    let pcre_libs = match os::getenv("PCRE_LIBS") {
        None            => {
            let pcre_config_output = run::process_output("pcre-config", [~"--libs"]);
            if !pcre_config_output.status.success() {
                fail!("Package script error: `pcre-config` failed");
            }
            let output_ptr = vec::raw::to_ptr(pcre_config_output.output);
            let output_len = pcre_config_output.output.len();
            let libs_str = unsafe { str::raw::from_buf_len(output_ptr, output_len) };
            os::setenv("PCRE_LIBS", libs_str);
            libs_str
        },
        Some(pcre_libs) => pcre_libs
    };
    // `pcre-config` adds a newline to the end, which we need to trim away because newlines
    // in link_args cause build issues.
    let trimmed_pcre_libs = pcre_libs.trim();
    debug!("PCRE_LIBS=\"{:s}\"", trimmed_pcre_libs);

    let workspace_path = os::getcwd();

    // Check the version
    let target_build_path = workspace_path.join("build").join(host_triple());
    if !target_build_path.exists() {
        if !io::result(|| mkdir(&target_build_path, 0x1FF)).is_ok() {
            fail!("Package script error: Failed to create target build directory `{}`", target_build_path.display());
        }
    }
    let out_path = target_build_path.join("pcre");
    if !out_path.exists() {
        if !io::result(|| mkdir(&out_path, 0x1FF)).is_ok() {
            fail!("Package script error: Failed to create output directory `{}`", out_path.display());
        }
    }

    let versioncheck_rs_path = out_path.join("versioncheck.rs");
    {
        let mut w = match File::create(&versioncheck_rs_path) {
            None    => fail!("Package script error: Failed to open `{}` for writing", versioncheck_rs_path.display()),
            Some(w) => w
        };
        write!(&mut w as &mut Writer, "\
\\#[feature(globs)];
use std::c_str::\\{CString\\};
use std::libc::*;
use std::ptr;
use std::vec;

type options = c_int;
struct pcre;
struct pcre_extra;

\\#[link_args = \"{:s}\"]
extern \\{
    static pcre_free: extern \"C\" fn(ptr: *c_void);

    fn pcre_compile(pattern: *c_char, options: options, errptr: *mut *c_char, erroffset: *mut c_int, tableptr: *c_uchar) -> *pcre;
    fn pcre_exec(code: *pcre, extra: *pcre_extra, subject: *c_char, length: c_int, startoffset: c_int, options: options, ovector: *mut c_int, ovecsize: c_int) -> c_int;
    fn pcre_version() -> *c_char;
\\}

fn main () \\{
    unsafe \\{
        let version_cstring = CString::new(pcre_version(), false);
        let version_str = version_cstring.as_str().unwrap().to_owned();

        let pattern = \"^\\\\\\\\d+\\\\\\\\.\\\\\\\\d+\";
        pattern.with_c_str(|pattern_c_str| \\{
            let mut err: *c_char = ptr::null();
            let mut erroffset: c_int = 0;
            let code = pcre_compile(pattern_c_str, 0, &mut err, &mut erroffset, ptr::null());
            if ptr::is_null(code) \\{
                if ptr::is_null(code) \\{
                    let err_cstring = CString::new(err, false);
                    match err_cstring.as_str() \\{
                        None          => fail!(\"pcre_compile() failed at offset \\{\\}\", erroffset as uint),
                        Some(err_str) => fail!(\"pcre_compile() failed at offset \\{\\}: \\{\\}\", erroffset as uint, err_str)
                    \\}
                \\}
            \\}
            assert!(ptr::is_not_null(code));

            let ovecsize = 1 * 3;
            let mut ovector: ~[c_int] = vec::from_elem(ovecsize, 0 as c_int);
            version_str.with_c_str_unchecked(|version_c_str| \\{
                let rc = pcre_exec(code, ptr::null(), version_c_str, version_str.len() as c_int, 0, 0, vec::raw::to_mut_ptr(ovector), ovecsize as c_int);
                if rc < 0 \\{
                    fail!(\"pcre_exec() failed\");
                \\}

                print(version_str.slice_to(ovector[1] as uint));
            \\});

            pcre_free(code as *c_void);
        \\});
    \\}
\\}
", trimmed_pcre_libs);
    }

    // Compile and run `versioncheck.rs`
    cd(&out_path);
    let rustc_run_output = run::process_output("rustc", [~"versioncheck.rs"]);
    if !rustc_run_output.status.success() {
        println(str::from_utf8(rustc_run_output.output));
        println(str::from_utf8(rustc_run_output.error));
        fail!("Package script error: `rustc versioncheck.rs` failed: {}", rustc_run_output.status);
    }
    let version_check_output = run::process_output("./versioncheck", []);
    if !version_check_output.status.success() {
        println(str::from_utf8(version_check_output.output));
        println(str::from_utf8(version_check_output.error));
        fail!("versioncheck error: {}", version_check_output.status);
    }
    cd(&workspace_path);

    let output_ptr = vec::raw::to_ptr(version_check_output.output);
    let output_len = version_check_output.output.len();
    let output_str = unsafe { str::raw::from_buf_len(output_ptr, output_len) };

    // The "no debug symbols in executable" warning may be present in the output.
    // https://github.com/mozilla/rust/issues/3495
    let mut output_rsplit_iter = output_str.rsplit('\n');
    let version_str: ~str = match output_rsplit_iter.next() {
        None              => output_str.clone(),
        Some(version_str) => version_str.to_owned()
    };

    debug!("libpcre version {:s}", version_str);

    let min_required_version = Version::parse("8.20").unwrap();
    let pcre_version = match Version::parse(version_str) {
        None               => fail!("Package script error: Failed to parse version string '{}'", version_str),
        Some(pcre_version) => pcre_version
    };

    if pcre_version < min_required_version {
        fail!("Package script error: Found libpcre version {}, but at least version {} is required", version_str, min_required_version.to_str());
    }

    let src_path = workspace_path.join("src");

    // Output `src/pcre/detail/native.rs`
    let detail_src_path = src_path.join("pcre").join("detail");
    if !detail_src_path.exists() {
        fail!("Package script error: Source directory `{}` does not exist.", detail_src_path.display());
    }
    let native_rs_path = detail_src_path.join("native.rs");
    let native_rs_in_path = detail_src_path.join("native.rs.in");
    if !native_rs_in_path.exists() {
        fail!("Package script error: Source file `{}` does not exist.", native_rs_in_path.display());
    }
    {
        let r = match File::open(&native_rs_in_path) {
            None    => fail!("Package script error: Failed to open `{}` for reading", native_rs_in_path.display()),
            Some(r) => r
        };
        let mut w = match File::create(&native_rs_path) {
            None    => fail!("Package script error: Failed to open `{}` for writing", native_rs_path.display()),
            Some(w) => w
        };
        write!(&mut w as &mut Writer, "// -*- buffer-read-only: t -*-\n");
        write!(&mut w as &mut Writer, "// Generated by {:s} on {:s}\n", args[0], time::now().rfc822());

        let mut buffered_reader = BufferedReader::new(r);
        while !buffered_reader.eof() {
            let line = buffered_reader.read_line();
            if line.is_some() {
                let substituted_line = str::replace(line.unwrap(), "@PCRE_LIBS@", trimmed_pcre_libs);
                write!(&mut w as &mut Writer, "{:s}", substituted_line);
            }
        }
    }

    api::build_lib(sysroot_path, workspace_path, ~"pcre", rustpkg::version::ExactRevision(~"0.1"), from_str("mod.rs").unwrap());
}

fn do_configs(args: ~[~str]) {
    drop(args);
}

fn main() {
    let args = os::args();
    let args_len = args.len();

    if args_len < 2 {
        fail!("Package script requires a directory where rustc libraries live as the first argument");
    } else if args_len < 3 {
        fail!("Package script requires a command as the second argument");
    }

    if args[2] == ~"install" {
        do_install(args);
    } else if args[2] == ~"configs" {
        do_configs(args);
    } else {
        fail!("Package script error: Unsupported command `{}`", args[2]);
    }
}
<commit_msg>Remove unused import `std::util`<commit_after>// Copyright 2013 The rust-pcre authors.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern mod extra;
extern mod rustc;
extern mod rustpkg;

use extra::time;
use rustc::driver::driver::host_triple;
use rustpkg::api;
use std::from_str::{from_str};
use std::io::fs::{mkdir, File};
use std::io::buffered::BufferedReader;
use std::io;
use std::option::{Option};
use std::os;
use std::run;
use std::str;
use std::vec;

struct Version {
    major: uint,
    minor: uint
}

impl Version {
    pub fn parse(version_str: &str) -> Option<Version> {
        let mut it = version_str.split('.');
        match (it.next().and_then(from_str::<uint>), it.next().and_then(from_str::<uint>)) {
            (Some(major), Some(minor)) => Some(Version { major: major, minor: minor }),
            _                          => None
        }
    }
}

impl ToStr for Version {
    fn to_str(&self) -> ~str {
        format!("{:u}.{:u}", self.major, self.minor)
    }
}

impl Ord for Version {
    fn lt(&self, other: &Version) -> bool {
        self.major < other.major || (self.major == other.major && self.minor < other.minor)
    }
}

fn cd(path: &Path) {
    if !os::change_dir(path) {
        fail!("Package script error: Failed to `cd` into `{}`", path.display());
    }
}

fn do_install(args: ~[~str]) {
    let sysroot_arg = args[1].clone();
    let sysroot_path = from_str(sysroot_arg).unwrap();

    let pcre_libs = match os::getenv("PCRE_LIBS") {
        None            => {
            let pcre_config_output = run::process_output("pcre-config", [~"--libs"]);
            if !pcre_config_output.status.success() {
                fail!("Package script error: `pcre-config` failed");
            }
            let output_ptr = vec::raw::to_ptr(pcre_config_output.output);
            let output_len = pcre_config_output.output.len();
            let libs_str = unsafe { str::raw::from_buf_len(output_ptr, output_len) };
            os::setenv("PCRE_LIBS", libs_str);
            libs_str
        },
        Some(pcre_libs) => pcre_libs
    };
    // `pcre-config` adds a newline to the end, which we need to trim away because newlines
    // in link_args cause build issues.
    let trimmed_pcre_libs = pcre_libs.trim();
    debug!("PCRE_LIBS=\"{:s}\"", trimmed_pcre_libs);

    let workspace_path = os::getcwd();

    // Check the version
    let target_build_path = workspace_path.join("build").join(host_triple());
    if !target_build_path.exists() {
        if !io::result(|| mkdir(&target_build_path, 0x1FF)).is_ok() {
            fail!("Package script error: Failed to create target build directory `{}`", target_build_path.display());
        }
    }
    let out_path = target_build_path.join("pcre");
    if !out_path.exists() {
        if !io::result(|| mkdir(&out_path, 0x1FF)).is_ok() {
            fail!("Package script error: Failed to create output directory `{}`", out_path.display());
        }
    }

    let versioncheck_rs_path = out_path.join("versioncheck.rs");
    {
        let mut w = match File::create(&versioncheck_rs_path) {
            None    => fail!("Package script error: Failed to open `{}` for writing", versioncheck_rs_path.display()),
            Some(w) => w
        };
        write!(&mut w as &mut Writer, "\
\\#[feature(globs)];
use std::c_str::\\{CString\\};
use std::libc::*;
use std::ptr;
use std::vec;

type options = c_int;
struct pcre;
struct pcre_extra;

\\#[link_args = \"{:s}\"]
extern \\{
    static pcre_free: extern \"C\" fn(ptr: *c_void);

    fn pcre_compile(pattern: *c_char, options: options, errptr: *mut *c_char, erroffset: *mut c_int, tableptr: *c_uchar) -> *pcre;
    fn pcre_exec(code: *pcre, extra: *pcre_extra, subject: *c_char, length: c_int, startoffset: c_int, options: options, ovector: *mut c_int, ovecsize: c_int) -> c_int;
    fn pcre_version() -> *c_char;
\\}

fn main () \\{
    unsafe \\{
        let version_cstring = CString::new(pcre_version(), false);
        let version_str = version_cstring.as_str().unwrap().to_owned();

        let pattern = \"^\\\\\\\\d+\\\\\\\\.\\\\\\\\d+\";
        pattern.with_c_str(|pattern_c_str| \\{
            let mut err: *c_char = ptr::null();
            let mut erroffset: c_int = 0;
            let code = pcre_compile(pattern_c_str, 0, &mut err, &mut erroffset, ptr::null());
            if ptr::is_null(code) \\{
                if ptr::is_null(code) \\{
                    let err_cstring = CString::new(err, false);
                    match err_cstring.as_str() \\{
                        None          => fail!(\"pcre_compile() failed at offset \\{\\}\", erroffset as uint),
                        Some(err_str) => fail!(\"pcre_compile() failed at offset \\{\\}: \\{\\}\", erroffset as uint, err_str)
                    \\}
                \\}
            \\}
            assert!(ptr::is_not_null(code));

            let ovecsize = 1 * 3;
            let mut ovector: ~[c_int] = vec::from_elem(ovecsize, 0 as c_int);
            version_str.with_c_str_unchecked(|version_c_str| \\{
                let rc = pcre_exec(code, ptr::null(), version_c_str, version_str.len() as c_int, 0, 0, vec::raw::to_mut_ptr(ovector), ovecsize as c_int);
                if rc < 0 \\{
                    fail!(\"pcre_exec() failed\");
                \\}

                print(version_str.slice_to(ovector[1] as uint));
            \\});

            pcre_free(code as *c_void);
        \\});
    \\}
\\}
", trimmed_pcre_libs);
    }

    // Compile and run `versioncheck.rs`
    cd(&out_path);
    let rustc_run_output = run::process_output("rustc", [~"versioncheck.rs"]);
    if !rustc_run_output.status.success() {
        println(str::from_utf8(rustc_run_output.output));
        println(str::from_utf8(rustc_run_output.error));
        fail!("Package script error: `rustc versioncheck.rs` failed: {}", rustc_run_output.status);
    }
    let version_check_output = run::process_output("./versioncheck", []);
    if !version_check_output.status.success() {
        println(str::from_utf8(version_check_output.output));
        println(str::from_utf8(version_check_output.error));
        fail!("versioncheck error: {}", version_check_output.status);
    }
    cd(&workspace_path);

    let output_ptr = vec::raw::to_ptr(version_check_output.output);
    let output_len = version_check_output.output.len();
    let output_str = unsafe { str::raw::from_buf_len(output_ptr, output_len) };

    // The "no debug symbols in executable" warning may be present in the output.
    // https://github.com/mozilla/rust/issues/3495
    let mut output_rsplit_iter = output_str.rsplit('\n');
    let version_str: ~str = match output_rsplit_iter.next() {
        None              => output_str.clone(),
        Some(version_str) => version_str.to_owned()
    };

    debug!("libpcre version {:s}", version_str);

    let min_required_version = Version::parse("8.20").unwrap();
    let pcre_version = match Version::parse(version_str) {
        None               => fail!("Package script error: Failed to parse version string '{}'", version_str),
        Some(pcre_version) => pcre_version
    };

    if pcre_version < min_required_version {
        fail!("Package script error: Found libpcre version {}, but at least version {} is required", version_str, min_required_version.to_str());
    }

    let src_path = workspace_path.join("src");

    // Output `src/pcre/detail/native.rs`
    let detail_src_path = src_path.join("pcre").join("detail");
    if !detail_src_path.exists() {
        fail!("Package script error: Source directory `{}` does not exist.", detail_src_path.display());
    }
    let native_rs_path = detail_src_path.join("native.rs");
    let native_rs_in_path = detail_src_path.join("native.rs.in");
    if !native_rs_in_path.exists() {
        fail!("Package script error: Source file `{}` does not exist.", native_rs_in_path.display());
    }
    {
        let r = match File::open(&native_rs_in_path) {
            None    => fail!("Package script error: Failed to open `{}` for reading", native_rs_in_path.display()),
            Some(r) => r
        };
        let mut w = match File::create(&native_rs_path) {
            None    => fail!("Package script error: Failed to open `{}` for writing", native_rs_path.display()),
            Some(w) => w
        };
        write!(&mut w as &mut Writer, "// -*- buffer-read-only: t -*-\n");
        write!(&mut w as &mut Writer, "// Generated by {:s} on {:s}\n", args[0], time::now().rfc822());

        let mut buffered_reader = BufferedReader::new(r);
        while !buffered_reader.eof() {
            let line = buffered_reader.read_line();
            if line.is_some() {
                let substituted_line = str::replace(line.unwrap(), "@PCRE_LIBS@", trimmed_pcre_libs);
                write!(&mut w as &mut Writer, "{:s}", substituted_line);
            }
        }
    }

    api::build_lib(sysroot_path, workspace_path, ~"pcre", rustpkg::version::ExactRevision(~"0.1"), from_str("mod.rs").unwrap());
}

fn do_configs(args: ~[~str]) {
    drop(args);
}

fn main() {
    let args = os::args();
    let args_len = args.len();

    if args_len < 2 {
        fail!("Package script requires a directory where rustc libraries live as the first argument");
    } else if args_len < 3 {
        fail!("Package script requires a command as the second argument");
    }

    if args[2] == ~"install" {
        do_install(args);
    } else if args[2] == ~"configs" {
        do_configs(args);
    } else {
        fail!("Package script error: Unsupported command `{}`", args[2]);
    }
}
<|endoftext|>


<commit_before>use std::default::Default;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::prelude::*;
use getopts::{Options};
use toml::{self, Value};
use calx::backend::{CanvasMagnify};
use calx::vorud::{Vorud, FromVorud};
use super::app_data_path;

thread_local!(pub static _CONFIG: Config = Default::default());

#[derive(Copy, Clone, Debug)]
pub struct Config {
    /// The player will move to the side when bumping against a wall.
    pub wall_sliding: bool,
    /// How to scale the graphics when making the window larger.
    pub magnify_mode: CanvasMagnify,
    /// Fixed world random number generator seed.
    pub rng_seed: Option<u32>,
}

impl Default for Config {
    fn default() -> Config {
        Config {
            wall_sliding: true,
            magnify_mode: CanvasMagnify::PixelPerfect,
            rng_seed: None,
        }
    }
}

impl Config {
    /// Parse command line options and apply them to the config object. Return
    /// an error containing a usage string if the parsing fails.
    ///
    /// Returning a string with Ok indicates that the string should be printed
    /// and the program should then exit.
    pub fn parse_args<T: Iterator<Item=String>>(&mut self, args: T) -> Result<Option<String>, String> {
        let mut opts = Options::new();
        opts.optflag("", "no-wall-sliding", "Don't move diagonally along obstacles when walking into them");
        opts.optflag("h", "help", "Display this message");
        opts.optflag("V", "version", "Print version info and exit");
        opts.optopt("", "magnify-mode", "How to filter magnified graphics. MODE = pixel | nearest | smooth", "MODE");
        opts.optopt("", "seed", "World generation seed", "VORUD");

        let args: Vec<String> = args.collect();

        let parse = match opts.parse(&args[1..]) {
            Ok(m) => m,
            Err(f) => {
                return Err(usage_error(f.to_string(), &opts));
            }
        };

        if parse.opt_present("help") {
            return Ok(Some(format!("{}", opts.usage("Usage: magog [options]"))));
        }

        if parse.opt_present("version") {
            return Ok(Some(format!("Magog v{} built with {}",
                                ::version(), ::compiler_version())));
        }

        if parse.opt_present("no-wall-sliding") {
            self.wall_sliding = false;
        }

        if let Some(x) = parse.opt_str("magnify-mode") {
            match &x[..] {
                "pixel" => { self.magnify_mode = CanvasMagnify::PixelPerfect; }
                "nearest" => { self.magnify_mode = CanvasMagnify::Nearest; }
                "smooth" => { self.magnify_mode = CanvasMagnify::Smooth; }
                err => {
                    return Err(usage_error(format!("Unknown magnify mode '{}'", err), &opts));
                }
            }
        }

        if let Some(seed) = parse.opt_str("seed") {
            // XXX: Could this be written to use the try! macro?
            let err = Err(usage_error(format!("Invalid seed value '{}'", seed), &opts));
            if let Ok(vorud) = Vorud::new(seed.clone()) {
                if let Ok(val) = FromVorud::from_vorud(&vorud) {
                    self.rng_seed = Some(val);
                } else {
                    return err;
                }
            } else {
                return err;
            }
        }

        return Ok(None);

        fn usage_error(msg: String, opts: &Options) -> String {
            format!("{}\n{}",
                    msg, opts.usage("Usage:\n    magog [options]"))
        }
    }

    pub fn file_path(&self) -> PathBuf {
        let mut ret = app_data_path();
        ret.push("config.toml");
        ret
    }

    /// Output the default config file.
    pub fn default_file(&self) -> String {
        // TODO: Make this data-driven, have option metadata that specifies
        // the help string and what to print out.
        format!(
r#"# Move diagonally along obstacles when walking into them
wall-sliding = true

# How to filter magnified graphics. pixel | nearest | smooth
magnify-mode = "pixel"
"#)
    }

    pub fn load<P: AsRef<Path>>(&mut self, path: P) -> Result<(), String> {
        // TODO: Error handling.

        // TODO: This should be data-driven somehow from a common config
        // metadata object instead of relying on the error-prone retyped
        // schema in the match segment.
        let mut file = File::open(path).unwrap();
        let mut toml = String::new();
        file.read_to_string(&mut toml).unwrap();

        let mut parser = toml::Parser::new(&toml);

        let settings = parser.parse();

        if settings.is_none() {
            let mut err = String::new();
            for e in parser.errors.iter() {
                err.push_str(&format!("{}", e));
            }
            return Err(err);
        }

        let settings = settings.unwrap();

        // TODO: Error message instead of silent no-op if the type of the
        // value isn't what we expect.
        if let Some(&Value::Boolean(b)) = settings.get("wall-sliding") {
            self.wall_sliding = b;
        }

        if let Some(&Value::String(ref mag)) = settings.get("magnify-mode") {
            match &mag[..] {
                "pixel" => { self.magnify_mode = CanvasMagnify::PixelPerfect; }
                "nearest" => { self.magnify_mode = CanvasMagnify::Nearest; }
                "smooth" => { self.magnify_mode = CanvasMagnify::Smooth; }
                _ => { return Err(format!("Bad magnify mode '{}'", mag)); }
            };
        }

        Ok(())
    }
}
<commit_msg>Fullscreen mode option<commit_after>use std::default::Default;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::prelude::*;
use getopts::{Options};
use toml::{self, Value};
use calx::backend::{CanvasMagnify};
use calx::vorud::{Vorud, FromVorud};
use super::app_data_path;

thread_local!(pub static _CONFIG: Config = Default::default());

#[derive(Copy, Clone, Debug)]
pub struct Config {
    /// The player will move to the side when bumping against a wall.
    pub wall_sliding: bool,
    /// How to scale the graphics when making the window larger.
    pub magnify_mode: CanvasMagnify,
    /// Fixed world random number generator seed.
    pub rng_seed: Option<u32>,
    /// Start in fullscreen mode
    pub fullscreen: bool,
}

impl Default for Config {
    fn default() -> Config {
        Config {
            wall_sliding: true,
            magnify_mode: CanvasMagnify::PixelPerfect,
            rng_seed: None,
            fullscreen: false,
        }
    }
}

impl Config {
    /// Parse command line options and apply them to the config object. Return
    /// an error containing a usage string if the parsing fails.
    ///
    /// Returning a string with Ok indicates that the string should be printed
    /// and the program should then exit.
    pub fn parse_args<T: Iterator<Item=String>>(&mut self, args: T) -> Result<Option<String>, String> {
        let mut opts = Options::new();
        opts.optflag("", "no-wall-sliding", "Don't move diagonally along obstacles when walking into them");
        opts.optflag("h", "help", "Display this message");
        opts.optflag("V", "version", "Print version info and exit");
        opts.optopt("", "magnify-mode", "How to filter magnified graphics. MODE = pixel | nearest | smooth", "MODE");
        opts.optopt("", "seed", "World generation seed", "VORUD");
        opts.optflag("", "fullscreen", "Run in fullscreen mode");

        let args: Vec<String> = args.collect();

        let parse = match opts.parse(&args[1..]) {
            Ok(m) => m,
            Err(f) => {
                return Err(usage_error(f.to_string(), &opts));
            }
        };

        if parse.opt_present("help") {
            return Ok(Some(format!("{}", opts.usage("Usage: magog [options]"))));
        }

        if parse.opt_present("version") {
            return Ok(Some(format!("Magog v{} built with {}",
                                ::version(), ::compiler_version())));
        }

        if parse.opt_present("no-wall-sliding") {
            self.wall_sliding = false;
        }

        if parse.opt_present("fullscreen") {
            self.fullscreen = true;
        }

        if let Some(x) = parse.opt_str("magnify-mode") {
            match &x[..] {
                "pixel" => { self.magnify_mode = CanvasMagnify::PixelPerfect; }
                "nearest" => { self.magnify_mode = CanvasMagnify::Nearest; }
                "smooth" => { self.magnify_mode = CanvasMagnify::Smooth; }
                err => {
                    return Err(usage_error(format!("Unknown magnify mode '{}'", err), &opts));
                }
            }
        }

        if let Some(seed) = parse.opt_str("seed") {
            // XXX: Could this be written to use the try! macro?
            let err = Err(usage_error(format!("Invalid seed value '{}'", seed), &opts));
            if let Ok(vorud) = Vorud::new(seed.clone()) {
                if let Ok(val) = FromVorud::from_vorud(&vorud) {
                    self.rng_seed = Some(val);
                } else {
                    return err;
                }
            } else {
                return err;
            }
        }

        return Ok(None);

        fn usage_error(msg: String, opts: &Options) -> String {
            format!("{}\n{}",
                    msg, opts.usage("Usage:\n    magog [options]"))
        }
    }

    pub fn file_path(&self) -> PathBuf {
        let mut ret = app_data_path();
        ret.push("config.toml");
        ret
    }

    /// Output the default config file.
    pub fn default_file(&self) -> String {
        // TODO: Make this data-driven, have option metadata that specifies
        // the help string and what to print out.
        format!(
r#"# Move diagonally along obstacles when walking into them
wall-sliding = true

# How to filter magnified graphics. pixel | nearest | smooth
magnify-mode = "pixel"

# Start the game in fullscreen instead of windowed mode
fullscreen = false
"#)
    }

    pub fn load<P: AsRef<Path>>(&mut self, path: P) -> Result<(), String> {
        // TODO: Error handling.

        // TODO: This should be data-driven somehow from a common config
        // metadata object instead of relying on the error-prone retyped
        // schema in the match segment.
        let mut file = File::open(path).unwrap();
        let mut toml = String::new();
        file.read_to_string(&mut toml).unwrap();

        let mut parser = toml::Parser::new(&toml);

        let settings = parser.parse();

        if settings.is_none() {
            let mut err = String::new();
            for e in parser.errors.iter() {
                err.push_str(&format!("{}", e));
            }
            return Err(err);
        }

        let settings = settings.unwrap();

        // TODO: Error message instead of silent no-op if the type of the
        // value isn't what we expect.
        if let Some(&Value::Boolean(b)) = settings.get("wall-sliding") {
            self.wall_sliding = b;
        }

        if let Some(&Value::String(ref mag)) = settings.get("magnify-mode") {
            match &mag[..] {
                "pixel" => { self.magnify_mode = CanvasMagnify::PixelPerfect; }
                "nearest" => { self.magnify_mode = CanvasMagnify::Nearest; }
                "smooth" => { self.magnify_mode = CanvasMagnify::Smooth; }
                _ => { return Err(format!("Bad magnify mode '{}'", mag)); }
            };
        }

        if let Some(&Value::Boolean(b)) = settings.get("fullscreen") {
            self.fullscreen = b;
        }

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


<commit_before>/// Common configuration options for the window manager.
pub struct Config {
    /// Whether focus follows mouse movements or
    /// only click events and keyboard movements.
    pub focus_follows_mouse: bool,
    /// Border color for focused windows.
    pub focus_border_color: uint,
    /// Border color for unfocused windows.
    pub border_color: uint,
    /// Border width. This is the same for both, focused and unfocused.
    pub border_width: uint,
    /// Default spacing between windows
    pub spacing: uint,
    /// Default terminal to start
    pub terminal: (String, String),
    /// Path to the logfile
    pub logfile: String,
    /// Default tags for workspaces
    pub tags: Vec<String>
}

impl Config {
    /// Create the default configuration.
    pub fn default() -> Config {
        Config {
            focus_follows_mouse: true,
            focus_border_color:  0x00B6FFB0,
            border_color:        0x00FFB6B0,
            border_width:        2,
            spacing:             10,
            terminal:            (String::from_str("xterm"), String::from_str("-fg White -bg Black")),
            logfile:             String::from_str("/home/wollwage/wtftw.log"),
            tags:                vec!(
                                     String::from_str("1: term"),
                                     String::from_str("2: web"),
                                     String::from_str("3: code"),
                                     String::from_str("4 media"))

        }
    }
}
<commit_msg>updated default logfile path<commit_after>use std::os::homedir;

/// Common configuration options for the window manager.
pub struct Config {
    /// Whether focus follows mouse movements or
    /// only click events and keyboard movements.
    pub focus_follows_mouse: bool,
    /// Border color for focused windows.
    pub focus_border_color: uint,
    /// Border color for unfocused windows.
    pub border_color: uint,
    /// Border width. This is the same for both, focused and unfocused.
    pub border_width: uint,
    /// Default spacing between windows
    pub spacing: uint,
    /// Default terminal to start
    pub terminal: (String, String),
    /// Path to the logfile
    pub logfile: String,
    /// Default tags for workspaces
    pub tags: Vec<String>
}

impl Config {
    /// Create the default configuration.
    pub fn default() -> Config {
        Config {
            focus_follows_mouse: true,
            focus_border_color:  0x00B6FFB0,
            border_color:        0x00FFB6B0,
            border_width:        2,
            spacing:             10,
            terminal:            (String::from_str("xterm"), String::from_str("-fg White -bg Black")),
            logfile:             format!("{}/.wtftw.log", homedir().unwrap().to_c_str()),
            tags:                vec!(
                                     String::from_str("1: term"),
                                     String::from_str("2: web"),
                                     String::from_str("3: code"),
                                     String::from_str("4 media"))

        }
    }
}
<|endoftext|>


<commit_before>use std::io::{File};
use std::str::{FromStr};
use std::slice::{SliceExt};
use std::collections::{HashMap, BTreeMap};
use toml::{Parser, Value, Table};

use sprite::{SpriteRect};

const DEFAULT_TILE_SIZE: i64 = 16;

type Coords = (i32, i32);

pub struct TomlConfig;

impl TomlConfig {

    /// override the default value if the given table location exists.
    fn defaults(what: &Table, attribute: &str, default: i64) -> i64 {
        let wrapped_default = Value::Integer(default);
        let attr = what.get(attribute).unwrap_or(&wrapped_default);
        attr.as_integer().expect(format!("`{}` must be an integer", attribute).as_slice())
    }

    /// helper function to obtain sprite coordinates
    fn get_coord(name: &String, values: &[Value]) -> Coords {
        if values.len() != 2 {
            panic!("attribute {:?} has too many values.", name);
        }
        let x = values[0].as_integer().expect("`x` must be an integer") as i32;
        let y = values[1].as_integer().expect("`y` must be an integer") as i32;
        (x, y)
    }

    fn get_coords(name: &String, table: &Table) -> Vec<Coords> {
        let mut coords = vec![];
        for (name, value) in table.iter() {
            match value.type_str() {
                "array" => {
                    let values = value.as_slice().unwrap();
                    let (x, y) = TomlConfig::get_coord(name, values);
                    coords.push((x, y));
                }
                _ => {} // ignore
            }
        }
        coords
    }

    /// given a TOML configuration file, extract the relevant
    /// spritesheet information. returns a hashmap of `Sprite`s.
    pub fn process_spritesheet(toml_path: &Path) -> HashMap<String, Vec<SpriteRect>> {
        let mut toml_file = File::open(toml_path);
        match toml_file.read_to_string() {
            Err(why) => panic!("Could not read configuration file {}: {}", toml_path.display(), why),
            Ok(contents) => {
                let value = Parser::new(contents.as_slice()).parse().expect("Configuration file is not valid TOML.");
                let sprites = value.get("sprites").expect("Configuration file does not have `sprites` entry.");
                let sprites_table = sprites.as_table().expect("`sprites` entry is not a TOML table.");
                let tile_width = TomlConfig::defaults(sprites_table, "tile_width", DEFAULT_TILE_SIZE);
                let tile_height = TomlConfig::defaults(sprites_table, "tile_height", DEFAULT_TILE_SIZE);
                let mut sprites = HashMap::new();
                for (name, value) in sprites_table.iter() {
                    match value.type_str() {
                        "array" => {
                            let values = value.as_slice().unwrap();
                            let (x, y) = TomlConfig::get_coord(name, values);
                            let rect = SpriteRect::new(x, y, tile_width as i32, tile_height as i32);
                            sprites.insert(name.clone(), vec![rect]);
                        }
                        "table" => {
                            let table = value.as_table().unwrap();
                            // look for a local tile_width or tile_height
                            let tile_width = TomlConfig::defaults(table, "tile_width", tile_width);
                            let tile_height = TomlConfig::defaults(table, "tile_height", tile_height);
                            let coords = TomlConfig::get_coords(name, table);
                            let rects = coords.iter().map(|&(x, y)| {
                                SpriteRect::new(x, y, tile_width as i32, tile_height as i32)
                            }).collect();
                            sprites.insert(name.clone(), rects);
                        }
                        _ => panic!("unknown TOML type {:?}", name)
                    }
                }
                sprites
            }
        }
    }
}
<commit_msg>Allow known TOML variables to slip through.<commit_after>use std::io::{File};
use std::str::{FromStr};
use std::slice::{SliceExt};
use std::collections::{HashMap, BTreeMap};
use toml::{Parser, Value, Table};

use sprite::{SpriteRect};

const DEFAULT_TILE_SIZE: i64 = 16;

type Coords = (i32, i32);

pub struct TomlConfig;

impl TomlConfig {

    /// override the default value if the given table location exists.
    fn defaults(what: &Table, attribute: &str, default: i64) -> i64 {
        let wrapped_default = Value::Integer(default);
        let attr = what.get(attribute).unwrap_or(&wrapped_default);
        attr.as_integer().expect(format!("`{}` must be an integer", attribute).as_slice())
    }

    /// helper function to obtain sprite coordinates
    fn get_coord(name: &String, values: &[Value]) -> Coords {
        if values.len() != 2 {
            panic!("attribute {:?} has too many values.", name);
        }
        let x = values[0].as_integer().expect("`x` must be an integer") as i32;
        let y = values[1].as_integer().expect("`y` must be an integer") as i32;
        (x, y)
    }

    fn get_coords(name: &String, table: &Table) -> Vec<Coords> {
        let mut coords = vec![];
        for (name, value) in table.iter() {
            match value.type_str() {
                "array" => {
                    let values = value.as_slice().unwrap();
                    let (x, y) = TomlConfig::get_coord(name, values);
                    coords.push((x, y));
                }
                _ => {
                    match name.as_slice() {
                        "tile_width" | "tile_height" => {} // ignore
                        _ => panic!("unknown TOML type {:?}", name)
                    }
                }
            }
        }
        coords
    }

    /// given a TOML configuration file, extract the relevant
    /// spritesheet information. returns a hashmap of `Sprite`s.
    pub fn process_spritesheet(toml_path: &Path) -> HashMap<String, Vec<SpriteRect>> {
        let mut toml_file = File::open(toml_path);
        match toml_file.read_to_string() {
            Err(why) => panic!("Could not read configuration file {}: {}", toml_path.display(), why),
            Ok(contents) => {
                let value = Parser::new(contents.as_slice()).parse().expect("Configuration file is not valid TOML.");
                let sprites = value.get("sprites").expect("Configuration file does not have `sprites` entry.");
                let sprites_table = sprites.as_table().expect("`sprites` entry is not a TOML table.");
                let tile_width = TomlConfig::defaults(sprites_table, "tile_width", DEFAULT_TILE_SIZE);
                let tile_height = TomlConfig::defaults(sprites_table, "tile_height", DEFAULT_TILE_SIZE);
                let mut sprites = HashMap::new();
                for (name, value) in sprites_table.iter() {
                    match value.type_str() {
                        "array" => {
                            let values = value.as_slice().unwrap();
                            let (x, y) = TomlConfig::get_coord(name, values);
                            let rect = SpriteRect::new(x, y, tile_width as i32, tile_height as i32);
                            sprites.insert(name.clone(), vec![rect]);
                        }
                        "table" => {
                            let table = value.as_table().unwrap();
                            // look for a local tile_width or tile_height
                            let tile_width = TomlConfig::defaults(table, "tile_width", tile_width);
                            let tile_height = TomlConfig::defaults(table, "tile_height", tile_height);
                            let coords = TomlConfig::get_coords(name, table);
                            let rects = coords.iter().map(|&(x, y)| {
                                SpriteRect::new(x, y, tile_width as i32, tile_height as i32)
                            }).collect();
                            sprites.insert(name.clone(), rects);
                        }
                        _ => {
                            match name.as_slice() {
                                "tile_width" | "tile_height" => {} // ignore
                                _ => panic!("unknown TOML type {:?}", name)
                            }
                        }
                    }
                }
                sprites
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Database operations

pub use self::add_package::add_package_into_database;
pub use self::add_package::add_build_into_database;
pub use self::file::add_path_into_database;

use postgres::{Connection, SslMode};
use postgres::error::{Error, ConnectError};
use std::env;
use r2d2;
use r2d2_postgres;

mod add_package;
mod file;

/// Connects to database
pub fn connect_db() -> Result<Connection, ConnectError> {
    // FIXME: unwrap might not be the best here
    let db_url = env::var("CRATESFYI_DATABASE_URL")
        .expect("CRATESFYI_DATABASE_URL environment variable is not exists");
    Connection::connect(&db_url[..], SslMode::None)
}

pub fn create_pool() -> r2d2::Pool<r2d2_postgres::PostgresConnectionManager> {
    let db_url = env::var("CRATESFYI_DATABASE_URL")
        .expect("CRATESFYI_DATABASE_URL environment variable is not exists");
    let config = r2d2::Config::default();
    let manager = r2d2_postgres::PostgresConnectionManager::new(&db_url[..],
                                                                r2d2_postgres::SslMode::None)
        .expect("Failed to create PostgresConnectionManager");
    r2d2::Pool::new(config, manager).expect("Failed to create r2d2 pool")
}

/// Updates content column in crates table.
///
/// This column will be used for searches and always contains `tsvector` of:
///
///   * crate name (rank A-weight)
///   * latest release description (rank B-weight)
///   * latest release keywords (rank B-weight)
///   * latest release readme (rank C-weight)
///   * latest release root rustdoc (rank C-weight)
pub fn update_search_index(conn: &Connection) -> Result<u64, Error> {
    conn.execute("
        WITH doc as (
            SELECT DISTINCT ON(releases.crate_id)
                   releases.id,
                   releases.crate_id,
                   setweight(to_tsvector(crates.name), 'A')                                   ||
                   setweight(to_tsvector(coalesce(releases.description, '')), 'B')            ||
                   setweight(to_tsvector(coalesce((
                                SELECT string_agg(value, ' ')
                                FROM json_array_elements_text(releases.keywords)), '')), 'B') ||
                   setweight(to_tsvector(coalesce(releases.readme, '')), 'C')                 ||
                   setweight(to_tsvector(coalesce(releases.description_long, '')), 'C') as content
            FROM releases
            INNER JOIN crates ON crates.id = releases.crate_id
            ORDER BY releases.crate_id, releases.release_time DESC
        )
        UPDATE crates
        SET latest_version_id = doc.id,
            content = doc.content
        FROM doc
        WHERE crates.id = doc.crate_id AND
            (crates.latest_version_id = 0 OR crates.latest_version_id != doc.id);", &[])
}

/// Creates database tables
pub fn create_tables(conn: &Connection) -> Result<(), Error> {
    let queries = [
        "CREATE TABLE crates ( \
            id SERIAL PRIMARY KEY, \
            name VARCHAR(255) UNIQUE NOT NULL, \
            latest_version_id INT DEFAULT 0, \
            versions JSON DEFAULT '[]', \
            downloads_total INT DEFAULT 0, \
            github_description VARCHAR(1024), \
            github_stars INT DEFAULT 0, \
            github_forks INT DEFAULT 0, \
            github_issues INT DEFAULT 0, \
            github_last_commit TIMESTAMP, \
            github_last_update TIMESTAMP, \
            content tsvector, \
        )",
        "CREATE TABLE releases ( \
            id SERIAL PRIMARY KEY, \
            crate_id INT NOT NULL REFERENCES crates(id), \
            version VARCHAR(100), \
            release_time TIMESTAMP, \
            dependencies JSON, \
            target_name VARCHAR(255), \
            yanked BOOL DEFAULT FALSE, \
            build_status BOOL DEFAULT FALSE, \
            rustdoc_status BOOL DEFAULT FALSE, \
            test_status BOOL DEFAULT FALSE, \
            license VARCHAR(100), \
            repository_url VARCHAR(255), \
            homepage_url VARCHAR(255), \
            description VARCHAR(1024), \
            description_long VARCHAR(51200), \
            readme VARCHAR(51200), \
            authors JSON, \
            keywords JSON, \
            have_examples BOOL DEFAULT FALSE, \
            downloads INT DEFAULT 0, \
            files JSON, \
            UNIQUE (crate_id, version) \
        )",
        "CREATE TABLE authors ( \
            id SERIAL PRIMARY KEY, \
            name VARCHAR(255), \
            email VARCHAR(255), \
            slug VARCHAR(255) UNIQUE NOT NULL \
        )",
        "CREATE TABLE author_rels ( \
            rid INT REFERENCES releases(id), \
            aid INT REFERENCES authors(id), \
            UNIQUE(rid, aid) \
        )",
        "CREATE TABLE keywords ( \
            id SERIAL PRIMARY KEY, \
            name VARCHAR(255), \
            slug VARCHAR(255) NOT NULL UNIQUE \
        )",
        "CREATE TABLE keyword_rels ( \
            rid INT REFERENCES releases(id), \
            kid INT REFERENCES keywords(id), \
            UNIQUE(rid, kid) \
        )",
        "CREATE TABLE owners ( \
            id SERIAL PRIMARY KEY, \
            login VARCHAR(255) NOT NULL UNIQUE, \
            avatar VARCHAR(255), \
            name VARCHAR(255), \
            email VARCHAR(255) \
        )",
        "CREATE TABLE owner_rels ( \
            cid INT REFERENCES releases(id), \
            oid INT REFERENCES owners(id), \
            UNIQUE(cid, oid) \
        )",
        "CREATE TABLE builds ( \
            id SERIAL, \
            rid INT NOT NULL REFERENCES releases(id), \
            rustc_version VARCHAR(100) NOT NULL, \
            cratesfyi_version VARCHAR(100) NOT NULL, \
            build_status BOOL NOT NULL, \
            build_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, \
            output TEXT \
        )",
        "CREATE TABLE queue ( \
            id SERIAL, \
            name VARCHAR(255), \
            version VARCHAR(100), \
            UNIQUE(name, version) \
        )",
        "CREATE TABLE files ( \
            path VARCHAR(4096) NOT NULL PRIMARY KEY, \
            mime VARCHAR(100) NOT NULL, \
            date_added TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, \
            date_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, \
            content BYTEA \
        )",
        "CREATE INDEX content_idx ON crates USING gin(content)",
    ];

    for query in queries.into_iter() {
        try!(conn.execute(query, &[]));
    }

    Ok(())
}

#[cfg(test)]
mod test {
    extern crate env_logger;
    use super::*;

    #[test]
    #[ignore]
    fn test_connect_db() {
        let conn = connect_db();
        assert!(conn.is_ok());
    }

    #[test]
    #[ignore]
    fn test_create_tables() {
        let _ = env_logger::init();
        let conn = connect_db();
        assert!(conn.is_ok());

        // FIXME: As expected this test always fails if database is already created
        let res = create_tables(&conn.unwrap());
        info!("RES: {:#?}", res);
        assert!(res.is_ok());
    }
}
<commit_msg>Fix query<commit_after>//! Database operations

pub use self::add_package::add_package_into_database;
pub use self::add_package::add_build_into_database;
pub use self::file::add_path_into_database;

use postgres::{Connection, SslMode};
use postgres::error::{Error, ConnectError};
use std::env;
use r2d2;
use r2d2_postgres;

mod add_package;
mod file;

/// Connects to database
pub fn connect_db() -> Result<Connection, ConnectError> {
    // FIXME: unwrap might not be the best here
    let db_url = env::var("CRATESFYI_DATABASE_URL")
        .expect("CRATESFYI_DATABASE_URL environment variable is not exists");
    Connection::connect(&db_url[..], SslMode::None)
}

pub fn create_pool() -> r2d2::Pool<r2d2_postgres::PostgresConnectionManager> {
    let db_url = env::var("CRATESFYI_DATABASE_URL")
        .expect("CRATESFYI_DATABASE_URL environment variable is not exists");
    let config = r2d2::Config::default();
    let manager = r2d2_postgres::PostgresConnectionManager::new(&db_url[..],
                                                                r2d2_postgres::SslMode::None)
        .expect("Failed to create PostgresConnectionManager");
    r2d2::Pool::new(config, manager).expect("Failed to create r2d2 pool")
}

/// Updates content column in crates table.
///
/// This column will be used for searches and always contains `tsvector` of:
///
///   * crate name (rank A-weight)
///   * latest release description (rank B-weight)
///   * latest release keywords (rank B-weight)
///   * latest release readme (rank C-weight)
///   * latest release root rustdoc (rank C-weight)
pub fn update_search_index(conn: &Connection) -> Result<u64, Error> {
    conn.execute("
        WITH doc as (
            SELECT DISTINCT ON(releases.crate_id)
                   releases.id,
                   releases.crate_id,
                   setweight(to_tsvector(crates.name), 'A')                                   ||
                   setweight(to_tsvector(coalesce(releases.description, '')), 'B')            ||
                   setweight(to_tsvector(coalesce((
                                SELECT string_agg(value, ' ')
                                FROM json_array_elements_text(releases.keywords)), '')), 'B') ||
                   setweight(to_tsvector(coalesce(releases.readme, '')), 'C')                 ||
                   setweight(to_tsvector(coalesce(releases.description_long, '')), 'C') as content
            FROM releases
            INNER JOIN crates ON crates.id = releases.crate_id
            ORDER BY releases.crate_id, releases.release_time DESC
        )
        UPDATE crates
        SET latest_version_id = doc.id,
            content = doc.content
        FROM doc
        WHERE crates.id = doc.crate_id AND
            (crates.latest_version_id = 0 OR crates.latest_version_id != doc.id);", &[])
}

/// Creates database tables
pub fn create_tables(conn: &Connection) -> Result<(), Error> {
    let queries = [
        "CREATE TABLE crates ( \
            id SERIAL PRIMARY KEY, \
            name VARCHAR(255) UNIQUE NOT NULL, \
            latest_version_id INT DEFAULT 0, \
            versions JSON DEFAULT '[]', \
            downloads_total INT DEFAULT 0, \
            github_description VARCHAR(1024), \
            github_stars INT DEFAULT 0, \
            github_forks INT DEFAULT 0, \
            github_issues INT DEFAULT 0, \
            github_last_commit TIMESTAMP, \
            github_last_update TIMESTAMP, \
            content tsvector \
        )",
        "CREATE TABLE releases ( \
            id SERIAL PRIMARY KEY, \
            crate_id INT NOT NULL REFERENCES crates(id), \
            version VARCHAR(100), \
            release_time TIMESTAMP, \
            dependencies JSON, \
            target_name VARCHAR(255), \
            yanked BOOL DEFAULT FALSE, \
            build_status BOOL DEFAULT FALSE, \
            rustdoc_status BOOL DEFAULT FALSE, \
            test_status BOOL DEFAULT FALSE, \
            license VARCHAR(100), \
            repository_url VARCHAR(255), \
            homepage_url VARCHAR(255), \
            description VARCHAR(1024), \
            description_long VARCHAR(51200), \
            readme VARCHAR(51200), \
            authors JSON, \
            keywords JSON, \
            have_examples BOOL DEFAULT FALSE, \
            downloads INT DEFAULT 0, \
            files JSON, \
            UNIQUE (crate_id, version) \
        )",
        "CREATE TABLE authors ( \
            id SERIAL PRIMARY KEY, \
            name VARCHAR(255), \
            email VARCHAR(255), \
            slug VARCHAR(255) UNIQUE NOT NULL \
        )",
        "CREATE TABLE author_rels ( \
            rid INT REFERENCES releases(id), \
            aid INT REFERENCES authors(id), \
            UNIQUE(rid, aid) \
        )",
        "CREATE TABLE keywords ( \
            id SERIAL PRIMARY KEY, \
            name VARCHAR(255), \
            slug VARCHAR(255) NOT NULL UNIQUE \
        )",
        "CREATE TABLE keyword_rels ( \
            rid INT REFERENCES releases(id), \
            kid INT REFERENCES keywords(id), \
            UNIQUE(rid, kid) \
        )",
        "CREATE TABLE owners ( \
            id SERIAL PRIMARY KEY, \
            login VARCHAR(255) NOT NULL UNIQUE, \
            avatar VARCHAR(255), \
            name VARCHAR(255), \
            email VARCHAR(255) \
        )",
        "CREATE TABLE owner_rels ( \
            cid INT REFERENCES releases(id), \
            oid INT REFERENCES owners(id), \
            UNIQUE(cid, oid) \
        )",
        "CREATE TABLE builds ( \
            id SERIAL, \
            rid INT NOT NULL REFERENCES releases(id), \
            rustc_version VARCHAR(100) NOT NULL, \
            cratesfyi_version VARCHAR(100) NOT NULL, \
            build_status BOOL NOT NULL, \
            build_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, \
            output TEXT \
        )",
        "CREATE TABLE queue ( \
            id SERIAL, \
            name VARCHAR(255), \
            version VARCHAR(100), \
            UNIQUE(name, version) \
        )",
        "CREATE TABLE files ( \
            path VARCHAR(4096) NOT NULL PRIMARY KEY, \
            mime VARCHAR(100) NOT NULL, \
            date_added TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, \
            date_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, \
            content BYTEA \
        )",
        "CREATE INDEX content_idx ON crates USING gin(content)",
    ];

    for query in queries.into_iter() {
        try!(conn.execute(query, &[]));
    }

    Ok(())
}

#[cfg(test)]
mod test {
    extern crate env_logger;
    use super::*;

    #[test]
    #[ignore]
    fn test_connect_db() {
        let conn = connect_db();
        assert!(conn.is_ok());
    }

    #[test]
    #[ignore]
    fn test_create_tables() {
        let _ = env_logger::init();
        let conn = connect_db();
        assert!(conn.is_ok());

        // FIXME: As expected this test always fails if database is already created
        let res = create_tables(&conn.unwrap());
        info!("RES: {:#?}", res);
        assert!(res.is_ok());
    }
}
<|endoftext|>


<commit_before>use cpu::CPU;
use keypad::KeypadKey;
use std::io::prelude::*;

pub struct Device
{
    cpu: CPU<'static>,
}

fn stdoutprinter(v: u8) -> u8
{
    print!("{}", v as char);
    let _ = ::std::io::stdout().flush();
    0
}

impl Device
{
    pub fn new(romname: &str) -> ::StrResult<Device>
    {
        CPU::new(romname, None).map(|cpu| Device { cpu: cpu })
    }

    pub fn new_cgb(romname: &str) -> ::StrResult<Device>
    {
        CPU::new_cgb(romname, None).map(|cpu| Device { cpu: cpu })
    }

    pub fn do_cycle(&mut self) -> u32
    {
        self.cpu.do_cycle()
    }

    pub fn set_stdout(&mut self, output: bool)
    {
        if output {
            self.cpu.mmu.serial.set_callback(Box::new(stdoutprinter));
        } else {
            self.cpu.mmu.serial.unset_callback();
        }
    }

    pub fn check_and_reset_gpu_updated(&mut self) -> bool
    {
        let result = self.cpu.mmu.gpu.updated;
        self.cpu.mmu.gpu.updated = false;
        result
    }

    pub fn get_gpu_data<'a>(&'a self) -> &'a [u8]
    {
        &self.cpu.mmu.gpu.data
    }

    pub fn enable_audio(&mut self) {
        self.cpu.mmu.sound = ::sound::Sound::new();
    }

    pub fn sync_audio(&mut self) {
        if let Some(ref mut sound) = self.cpu.mmu.sound {
            sound.sync();
        }
    }

    pub fn keyup(&mut self, key: KeypadKey)
    {
        self.cpu.mmu.keypad.keyup(key);
    }

    pub fn keydown(&mut self, key: KeypadKey)
    {
        self.cpu.mmu.keypad.keydown(key);
    }
}
<commit_msg>Update style of device.rs<commit_after>use cpu::CPU;
use keypad::KeypadKey;

pub struct Device {
    cpu: CPU<'static>,
}

fn stdoutprinter(v: u8) -> u8 {
    use std::io::Write;

    print!("{}", v as char);
    let _ = ::std::io::stdout().flush();
    0
}

impl Device {
    pub fn new(romname: &str) -> ::StrResult<Device> {
        CPU::new(romname, None).map(|cpu| Device { cpu: cpu })
    }

    pub fn new_cgb(romname: &str) -> ::StrResult<Device> {
        CPU::new_cgb(romname, None).map(|cpu| Device { cpu: cpu })
    }

    pub fn do_cycle(&mut self) -> u32 {
        self.cpu.do_cycle()
    }

    pub fn set_stdout(&mut self, output: bool) {
        if output {
            self.cpu.mmu.serial.set_callback(Box::new(stdoutprinter));
        }
        else {
            self.cpu.mmu.serial.unset_callback();
        }
    }

    pub fn check_and_reset_gpu_updated(&mut self) -> bool {
        let result = self.cpu.mmu.gpu.updated;
        self.cpu.mmu.gpu.updated = false;
        result
    }

    pub fn get_gpu_data(&self) -> &[u8] {
        &self.cpu.mmu.gpu.data
    }

    pub fn enable_audio(&mut self) {
        self.cpu.mmu.sound = ::sound::Sound::new();
    }

    pub fn sync_audio(&mut self) {
        if let Some(ref mut sound) = self.cpu.mmu.sound {
            sound.sync();
        }
    }

    pub fn keyup(&mut self, key: KeypadKey) {
        self.cpu.mmu.keypad.keyup(key);
    }

    pub fn keydown(&mut self, key: KeypadKey) {
        self.cpu.mmu.keypad.keydown(key);
    }
}
<|endoftext|>