<commit_before>
/// Equivalent to a `match` expression but for routes.
///
/// Here is an example usage:
///
/// ```ignored      // FIXME:
/// # #[macro_use] extern crate rouille; fn main() {
/// # let request: rouille::Request = unsafe { std::mem::uninitialized() };
/// router!(request,
///     // first route
///     (GET) (/) => (|| {
///         12
///     }),
///
///     // ... other routes here ...
///
///     // default route
///     _ => || 5
/// )
/// # }
/// ```
///
/// The macro will take each route one by one and execute the first one that matches, similar to a
/// `match` language construct. The whole `router!` expression then returns what the closure
/// returns, therefore they must all return the same type.
///
/// You can use parameters by putting them inside `{}`:
///
/// ```ignore
/// (GET) (/{id}/foo) => (|id: u32| {
///     ...
/// }),
/// ```
///
/// If you use parameters inside `{}`, then a field with the same name must exist in the closure's
/// parameters list. The parameters do not need be in the same order.
///
/// Each parameter gets parsed through the `FromStr` trait. If the parsing fails, the route is
/// ignored.
///
/// Some other things to note:
///
/// - The right of the `=>` must have a closure-like syntax.
/// - The pattern of the URL and the closure must be inside parentheses. This is to bypass
///   limitations of Rust's macros system.
/// - The default handler (with `_`) must be present or will get a compilation error.
///
// FIXME: turn `: $pt:ident` into `ty`
// TODO: don't use a hashmap for perfs
// TODO: don't panic if parsing fails
#[macro_export]
macro_rules! router {
    ($request:expr, $(($method:ident) ($($pat:tt)+) => ($($closure:tt)+),)* _ => $def:expr) => {
        {
            use std;

            let ref request = $request;

            // ignoring the GET parameters (everything after `?`)
            let request_url = request.url();
            let request_url = {
                let pos = request_url.find('?').unwrap_or(request_url.len());
                &request_url[..pos]
            };

            let mut ret = None;

            $({
                // we use a RefCell just to avoid warnings about `values doesn't need to be mutable`
                let values = std::cell::RefCell::new(std::collections::HashMap::<&'static str, &str>::new());
                if ret.is_none() && request.method() == stringify!($method) &&
                   router!(__check_pattern values request_url $($pat)+)
                {
                    let values = values.borrow();
                    ret = router!(__parse_closure values $($closure)+);
                }
            })+

            if let Some(ret) = ret {
                ret
            } else {
                $def()
            }
        }
    };

    (__parse_closure $values:ident |$($pn:ident $(: $pt:ident)*),*| $(-> $ret:ident)* $val:expr) => (
        {
            let closure = |$($pn$(:$pt)*),*| $(-> $ret)* { $val };
            let ret;
            loop {
                ret = Some(closure(
                    $(
                        match $values.get(stringify!($pn))
                                     .expect("Closure parameter missing from route").parse()
                        {
                            Ok(val) => val,
                            Err(_) => { ret = None; break; }
                        }
                    ),*
                ));
                break;
            }
            ret
        }
    );

    (__parse_closure $values:ident || $val:expr) => (
        {
            let closure = || $val;
            assert!($values.len() == 0);
            Some(closure())
        }
    );

    (__check_pattern $values:ident $url:ident /{$p:ident} $($rest:tt)*) => (
        if !$url.starts_with('/') {
            false
        } else {
            let url = &$url[1..];
            let pat_end = url.find('/').unwrap_or(url.len());
            let rest_url = &url[pat_end..];
            if router!(__check_pattern $values rest_url $($rest)*) {
                $values.borrow_mut().insert(stringify!($p), &url[0 .. pat_end]);
                true
            } else {
                false
            }
        }
    );

    (__check_pattern $values:ident $url:ident /$p:ident $($rest:tt)*) => (
        {
            let required = concat!("/", stringify!($p));
            if $url.starts_with(required) {
                let rest_url = &$url[required.len()..];
                router!(__check_pattern $values rest_url $($rest)*)
            } else {
                false
            }
        }
    );

    (__check_pattern $values:ident $url:ident) => (
        $url.len() == 0
    );

    (__check_pattern $values:ident $url:ident /) => (
        $url == "/"
    );
}
<commit_msg>Allow non-closure expressions in router!<commit_after>
/// Equivalent to a `match` expression but for routes.
///
/// Here is an example usage:
///
/// ```ignored      // FIXME:
/// # #[macro_use] extern crate rouille; fn main() {
/// # let request: rouille::Request = unsafe { std::mem::uninitialized() };
/// router!(request,
///     // first route
///     (GET) (/) => (|| {
///         12
///     }),
///
///     // ... other routes here ...
///
///     // default route
///     _ => || 5
/// )
/// # }
/// ```
///
/// The macro will take each route one by one and execute the first one that matches, similar to a
/// `match` language construct. The whole `router!` expression then returns what the closure
/// returns, therefore they must all return the same type.
///
/// You can use parameters by putting them inside `{}`:
///
/// ```ignore
/// (GET) (/{id}/foo) => (|id: u32| {
///     ...
/// }),
/// ```
///
/// If you use parameters inside `{}`, then a field with the same name must exist in the closure's
/// parameters list. The parameters do not need be in the same order.
///
/// Each parameter gets parsed through the `FromStr` trait. If the parsing fails, the route is
/// ignored.
///
/// Some other things to note:
///
/// - The right of the `=>` must have a closure-like syntax.
/// - The pattern of the URL and the closure must be inside parentheses. This is to bypass
///   limitations of Rust's macros system.
/// - The default handler (with `_`) must be present or will get a compilation error.
///
// FIXME: turn `: $pt:ident` into `ty`
// TODO: don't use a hashmap for perfs
// TODO: don't panic if parsing fails
#[macro_export]
macro_rules! router {
    ($request:expr, $(($method:ident) ($($pat:tt)+) => ($($closure:tt)+),)* _ => $def:expr) => {
        {
            use std;

            let ref request = $request;

            // ignoring the GET parameters (everything after `?`)
            let request_url = request.url();
            let request_url = {
                let pos = request_url.find('?').unwrap_or(request_url.len());
                &request_url[..pos]
            };

            let mut ret = None;

            $({
                // we use a RefCell just to avoid warnings about `values doesn't need to be mutable`
                let values = std::cell::RefCell::new(std::collections::HashMap::<&'static str, &str>::new());
                if ret.is_none() && request.method() == stringify!($method) &&
                   router!(__check_pattern values request_url $($pat)+)
                {
                    let values = values.borrow();
                    ret = router!(__parse_closure values $($closure)+);
                }
            })+

            if let Some(ret) = ret {
                ret
            } else {
                $def()
            }
        }
    };

    (__parse_closure $values:ident |$($pn:ident $(: $pt:ident)*),*| $(-> $ret:ident)* $val:expr) => (
        {
            let closure = |$($pn$(:$pt)*),*| $(-> $ret)* { $val };
            let ret;
            loop {
                ret = Some(closure(
                    $(
                        match $values.get(stringify!($pn))
                                     .expect("Closure parameter missing from route").parse()
                        {
                            Ok(val) => val,
                            Err(_) => { ret = None; break; }
                        }
                    ),*
                ));
                break;
            }
            ret
        }
    );

    (__parse_closure $values:ident || $val:expr) => (
        {
            let closure = || $val;
            assert!($values.len() == 0);
            Some(closure())
        }
    );

    (__parse_closure $values:ident $val:expr) => (
        {
            assert!($values.len() == 0);
            Some($val)
        }
    );

    (__check_pattern $values:ident $url:ident /{$p:ident} $($rest:tt)*) => (
        if !$url.starts_with('/') {
            false
        } else {
            let url = &$url[1..];
            let pat_end = url.find('/').unwrap_or(url.len());
            let rest_url = &url[pat_end..];
            if router!(__check_pattern $values rest_url $($rest)*) {
                $values.borrow_mut().insert(stringify!($p), &url[0 .. pat_end]);
                true
            } else {
                false
            }
        }
    );

    (__check_pattern $values:ident $url:ident /$p:ident $($rest:tt)*) => (
        {
            let required = concat!("/", stringify!($p));
            if $url.starts_with(required) {
                let rest_url = &$url[required.len()..];
                router!(__check_pattern $values rest_url $($rest)*)
            } else {
                false
            }
        }
    );

    (__check_pattern $values:ident $url:ident) => (
        $url.len() == 0
    );

    (__check_pattern $values:ident $url:ident /) => (
        $url == "/"
    );
}
<|endoftext|>


<commit_before>use nain_events::{EventCategory, KeyPressedEvent};
use nain_log as log;

pub trait Application {
    fn run(&self) {
        println!("Welcome to the Nain engine!");

        let event = KeyPressedEvent::new(2, 5);
        log::trace!("{}", event);

        loop {}
    }
}
<commit_msg>Add some logs to test the key pressed event<commit_after>use nain_events::{Event, EventCategory, KeyPressedEvent};
use nain_log as log;

pub trait Application {
    fn run(&self) {
        println!("Welcome to the Nain engine!");

        let event = KeyPressedEvent::new(2, 5);

        log::trace!("{}", event);
        log::trace!("{}", event.get_name());

        if event.is_in_category(EventCategory::Keyboard) {
            log::trace!("Event category: {}", stringify!(EventCategory::Keyboard));
        }

        loop {}
    }
}
<|endoftext|>


<commit_before>// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

//! jsonrpc server over win named pipes
//!
//! ```no_run
//! extern crate jsonrpc_core;
//! extern crate json_ipc_server;
//!
//! use std::sync::Arc;
//! use jsonrpc_core::*;
//! use json_ipc_server::Server;
//!
//! struct SayHello;
//! impl SyncMethodCommand for SayHello {
//! 	fn execute(&self, _params: Params) -> Result<Value, Error> {
//! 		Ok(Value::String("hello".to_string()))
//! 	}
//! }
//!
//! fn main() {
//! 	let io = IoHandler::new();
//! 	io.add_method("say_hello", SayHello);
//! 	let server = Server::new("/tmp/json-ipc-test.ipc", &Arc::new(io)).unwrap();
//!     ::std::thread::spawn(move || server.run());
//! }
//! ```

//! Named pipes library

use miow::pipe::{NamedPipe, NamedPipeBuilder};
use std;
use std::io;
use std::io::{Read, Write};
use std::sync::atomic::*;
use std::sync::Arc;
use jsonrpc_core::IoHandler;
use validator;

pub type Result<T> = std::result::Result<T, Error>;

const MAX_REQUEST_LEN: u32 = 65536;
const REQUEST_READ_BATCH: usize = 4096;

#[derive(Debug)]
pub enum Error {
    Io(std::io::Error),
    NotStarted,
    AlreadyStopping,
    NotStopped,
    IsStopping,
}

impl std::convert::From<std::io::Error> for Error {
    fn from(io_error: std::io::Error) -> Error {
        Error::Io(io_error)
    }
}

pub struct PipeHandler {
    waiting_pipe: NamedPipe,
    io_handler: Arc<IoHandler>,
}

impl PipeHandler {
    /// start ipc rpc server (blocking)
    pub fn start(addr: &str, io_handler: &Arc<IoHandler>) -> Result<PipeHandler> {
        Ok(PipeHandler {
            waiting_pipe: try!(
                NamedPipeBuilder::new(addr)
                    .first(true)
                    .accept_remote(true)
                    .max_instances(255)
                    .inbound(true)
                    .outbound(true)
                    .out_buffer_size(MAX_REQUEST_LEN)
                    .in_buffer_size(MAX_REQUEST_LEN)
                    .create()
            ),
            io_handler: io_handler.clone(),
        })
    }

    fn handle_incoming(&mut self, addr: &str, stop: Arc<AtomicBool>) -> io::Result<()> {
        trace!(target: "ipc", "Waiting for client: [{}]", addr);
		try!(self.waiting_pipe.connect());
		trace!(target: "ipc", "Received connection to address [{}]", addr);
        if stop.load(Ordering::Relaxed) {
            trace!(target: "ipc", "Stopped listening sequence [{}]", addr);
            return Ok(())
        }

        let mut connected_pipe = std::mem::replace::<NamedPipe>(&mut self.waiting_pipe,
            try!(NamedPipeBuilder::new(addr)
                .first(false)
                .accept_remote(true)
                .inbound(true)
                .outbound(true)
                .out_buffer_size(MAX_REQUEST_LEN)
                .in_buffer_size(MAX_REQUEST_LEN)
                .create()));

        let thread_handler = self.io_handler.clone();
        std::thread::spawn(move || {
            let mut buf = vec![0u8; MAX_REQUEST_LEN as usize];
            let mut fin = REQUEST_READ_BATCH;
            loop {
                let start = fin - REQUEST_READ_BATCH;
                trace!(target: "ipc", "Reading {} - {} of the buffer", start, fin);
                match connected_pipe.read(&mut buf[start..fin]) {
                    Ok(size) => {
                        let (requests, last_index) = {
                            let effective = &buf[0..start + size];
                            fin = fin + size;
                            trace!(target: "ipc", "Received rpc data: {} bytes", effective.len());

                            validator::extract_requests(effective)
                        };
                        if requests.len() > 0 {
                            let mut response_buf = Vec::new();
                            for rpc_msg in requests  {
                                trace!(target: "ipc", "Request: {}", rpc_msg);

                                let response: Option<String> = thread_handler.handle_request(&rpc_msg);

                                if let Some(response_str) = response {
                                    trace!(target: "ipc", "Response: {}", &response_str);
                                    response_buf.extend(response_str.into_bytes());
                                }
                            }

                            if let Err(write_err) = connected_pipe.write_all(&response_buf[..]).and_then(|_| connected_pipe.flush()) {
                                trace!(target: "ipc", "Response write error: {:?}", write_err);
                            }
                            else {
                                trace!(target: "ipc", "Sent rpc response: {} bytes", response_buf.len());
                            }

                            let leftover_len = start + size - (last_index + 1);
                            if leftover_len > 0 {
                                let leftover = buf[last_index + 1..start + size].to_vec();
                                buf[0..leftover_len].copy_from_slice(&leftover[..]);
                            }
                            fin = leftover_len + REQUEST_READ_BATCH;
                        }
                        else { continue; }
                    },
                    Err(e) => {
                        // closed connection
                        trace!(target: "ipc", "Dropped connection {:?}", e);
                        break;
                    }
                }
            }
        });

        Ok(())
    }
}

pub struct Server {
    is_stopping: Arc<AtomicBool>,
    is_stopped: Arc<AtomicBool>,
    addr: String,
    io_handler: Arc<IoHandler>,
}

impl Server {
    /// New server
    pub fn new(socket_addr: &str, io_handler: &Arc<IoHandler>) -> Result<Server> {
        Ok(Server {
            io_handler: io_handler.clone(),
            is_stopping: Arc::new(AtomicBool::new(false)),
            is_stopped: Arc::new(AtomicBool::new(true)),
            addr: socket_addr.to_owned(),
        })
    }

    /// Run server (in this thread)
    pub fn run(&self) -> Result<()> {
        let mut pipe_handler = try!(PipeHandler::start(&self.addr, &self.io_handler));
        loop  {
            try!(pipe_handler.handle_incoming(&self.addr, Arc::new(AtomicBool::new(false))));
        }
    }

    /// Run server (in separate thread)
    pub fn run_async(&self) -> Result<()> {
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::IsStopping) }
        if !self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStopped) }

        trace!(target: "ipc", "Started named pipes server [{}]", self.addr);

        let thread_stopping = self.is_stopping.clone();
        let thread_stopped = self.is_stopped.clone();
        let thread_handler = self.io_handler.clone();
        let addr = self.addr.clone();
        std::thread::spawn(move || {
            let mut pipe_handler = PipeHandler::start(&addr, &thread_handler).unwrap();
            while !thread_stopping.load(Ordering::Relaxed) {
				trace!(target: "ipc", "Accepting pipe connection");
                if let Err(pipe_listener_error) = pipe_handler.handle_incoming(&addr, thread_stopping.clone()) {
                    trace!(target: "ipc", "Pipe listening error: {:?}", pipe_listener_error);
                }
            }
            thread_stopped.store(true, Ordering::Relaxed);
        });

        self.is_stopped.store(false, Ordering::Relaxed);
        Ok(())
    }

    pub fn stop_async(&self) -> Result<()> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        Ok(())
    }

    pub fn stop(&self) -> Result<()> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        while !self.is_stopped.load(Ordering::Relaxed) { std::thread::park_timeout(std::time::Duration::new(0, 50)); }
        Ok(())
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        self.stop_async().unwrap_or_else(|_| {}); // ignore error - can be stopped already
        // todo : no stable logging for windows?
        trace!(target: "ipc", "IPC Server : shutdown");
    }
}
<commit_msg>Fixing windows<commit_after>// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

//! jsonrpc server over win named pipes
//!
//! ```no_run
//! extern crate jsonrpc_core;
//! extern crate json_ipc_server;
//!
//! use std::sync::Arc;
//! use jsonrpc_core::*;
//! use json_ipc_server::Server;
//!
//! struct SayHello;
//! impl SyncMethodCommand for SayHello {
//! 	fn execute(&self, _params: Params) -> Result<Value, Error> {
//! 		Ok(Value::String("hello".to_string()))
//! 	}
//! }
//!
//! fn main() {
//! 	let io = IoHandler::new();
//! 	io.add_method("say_hello", SayHello);
//! 	let server = Server::new("/tmp/json-ipc-test.ipc", &Arc::new(io)).unwrap();
//!     ::std::thread::spawn(move || server.run());
//! }
//! ```

//! Named pipes library

use miow::pipe::{NamedPipe, NamedPipeBuilder};
use std;
use std::io;
use std::io::{Read, Write};
use std::sync::atomic::*;
use std::sync::Arc;
use jsonrpc_core::IoHandler;
use validator;

pub type Result<T> = std::result::Result<T, Error>;

const MAX_REQUEST_LEN: u32 = 65536;
const REQUEST_READ_BATCH: usize = 4096;

#[derive(Debug)]
pub enum Error {
    Io(std::io::Error),
    NotStarted,
    AlreadyStopping,
    NotStopped,
    IsStopping,
}

impl std::convert::From<std::io::Error> for Error {
    fn from(io_error: std::io::Error) -> Error {
        Error::Io(io_error)
    }
}

pub struct PipeHandler {
    waiting_pipe: NamedPipe,
    io_handler: Arc<IoHandler>,
}

impl PipeHandler {
    /// start ipc rpc server (blocking)
    pub fn start(addr: &str, io_handler: &Arc<IoHandler>) -> Result<PipeHandler> {
        Ok(PipeHandler {
            waiting_pipe: try!(
                NamedPipeBuilder::new(addr)
                    .first(true)
                    .accept_remote(true)
                    .max_instances(255)
                    .inbound(true)
                    .outbound(true)
                    .out_buffer_size(MAX_REQUEST_LEN)
                    .in_buffer_size(MAX_REQUEST_LEN)
                    .create()
            ),
            io_handler: io_handler.clone(),
        })
    }

    fn handle_incoming(&mut self, addr: &str, stop: Arc<AtomicBool>) -> io::Result<()> {
        trace!(target: "ipc", "Waiting for client: [{}]", addr);
		try!(self.waiting_pipe.connect());
		trace!(target: "ipc", "Received connection to address [{}]", addr);
        if stop.load(Ordering::Relaxed) {
            trace!(target: "ipc", "Stopped listening sequence [{}]", addr);
            return Ok(())
        }

        let mut connected_pipe = std::mem::replace::<NamedPipe>(&mut self.waiting_pipe,
            try!(NamedPipeBuilder::new(addr)
                .first(false)
                .accept_remote(true)
                .inbound(true)
                .outbound(true)
                .out_buffer_size(MAX_REQUEST_LEN)
                .in_buffer_size(MAX_REQUEST_LEN)
                .create()));

        let thread_handler = self.io_handler.clone();
        std::thread::spawn(move || {
            let mut buf = vec![0u8; MAX_REQUEST_LEN as usize];
            let mut fin = REQUEST_READ_BATCH;
            loop {
                let start = fin - REQUEST_READ_BATCH;
                trace!(target: "ipc", "Reading {} - {} of the buffer", start, fin);
                match connected_pipe.read(&mut buf[start..fin]) {
                    Ok(size) => {
                        let (requests, last_index) = {
                            let effective = &buf[0..start + size];
                            fin = fin + size;
                            trace!(target: "ipc", "Received rpc data: {} bytes", effective.len());

                            validator::extract_requests(effective)
                        };
                        if requests.len() > 0 {
                            let mut response_buf = Vec::new();
                            for rpc_msg in requests  {
                                trace!(target: "ipc", "Request: {}", rpc_msg);

                                let response: Option<String> = thread_handler.handle_request_sync(&rpc_msg);

                                if let Some(response_str) = response {
                                    trace!(target: "ipc", "Response: {}", &response_str);
                                    response_buf.extend(response_str.into_bytes());
                                }
                            }

                            if let Err(write_err) = connected_pipe.write_all(&response_buf[..]).and_then(|_| connected_pipe.flush()) {
                                trace!(target: "ipc", "Response write error: {:?}", write_err);
                            }
                            else {
                                trace!(target: "ipc", "Sent rpc response: {} bytes", response_buf.len());
                            }

                            let leftover_len = start + size - (last_index + 1);
                            if leftover_len > 0 {
                                let leftover = buf[last_index + 1..start + size].to_vec();
                                buf[0..leftover_len].copy_from_slice(&leftover[..]);
                            }
                            fin = leftover_len + REQUEST_READ_BATCH;
                        }
                        else { continue; }
                    },
                    Err(e) => {
                        // closed connection
                        trace!(target: "ipc", "Dropped connection {:?}", e);
                        break;
                    }
                }
            }
        });

        Ok(())
    }
}

pub struct Server {
    is_stopping: Arc<AtomicBool>,
    is_stopped: Arc<AtomicBool>,
    addr: String,
    io_handler: Arc<IoHandler>,
}

impl Server {
    /// New server
    pub fn new(socket_addr: &str, io_handler: &Arc<IoHandler>) -> Result<Server> {
        Ok(Server {
            io_handler: io_handler.clone(),
            is_stopping: Arc::new(AtomicBool::new(false)),
            is_stopped: Arc::new(AtomicBool::new(true)),
            addr: socket_addr.to_owned(),
        })
    }

    /// Run server (in this thread)
    pub fn run(&self) -> Result<()> {
        let mut pipe_handler = try!(PipeHandler::start(&self.addr, &self.io_handler));
        loop  {
            try!(pipe_handler.handle_incoming(&self.addr, Arc::new(AtomicBool::new(false))));
        }
    }

    /// Run server (in separate thread)
    pub fn run_async(&self) -> Result<()> {
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::IsStopping) }
        if !self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStopped) }

        trace!(target: "ipc", "Started named pipes server [{}]", self.addr);

        let thread_stopping = self.is_stopping.clone();
        let thread_stopped = self.is_stopped.clone();
        let thread_handler = self.io_handler.clone();
        let addr = self.addr.clone();
        std::thread::spawn(move || {
            let mut pipe_handler = PipeHandler::start(&addr, &thread_handler).unwrap();
            while !thread_stopping.load(Ordering::Relaxed) {
				trace!(target: "ipc", "Accepting pipe connection");
                if let Err(pipe_listener_error) = pipe_handler.handle_incoming(&addr, thread_stopping.clone()) {
                    trace!(target: "ipc", "Pipe listening error: {:?}", pipe_listener_error);
                }
            }
            thread_stopped.store(true, Ordering::Relaxed);
        });

        self.is_stopped.store(false, Ordering::Relaxed);
        Ok(())
    }

    pub fn stop_async(&self) -> Result<()> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        Ok(())
    }

    pub fn stop(&self) -> Result<()> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        while !self.is_stopped.load(Ordering::Relaxed) { std::thread::park_timeout(std::time::Duration::new(0, 50)); }
        Ok(())
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        self.stop_async().unwrap_or_else(|_| {}); // ignore error - can be stopped already
        // todo : no stable logging for windows?
        trace!(target: "ipc", "IPC Server : shutdown");
    }
}
<|endoftext|>


<commit_before>#![allow(non_upper_case_globals)]

pub use self::x86_shared::*;

use core::prelude::*;
use core::mem::size_of;

mod x86_shared;

bitflags! {
	flags GdtAccess: u8 {
		const Accessed = 1 << 0,
		const Writable = 1 << 1,
		const Direction = 1 << 2,
		const Executable = 1 << 3,
		const NotTss = 1 << 4,
	}
}

#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct GdtEntry {
	limit: u16,
	base1: u16,
	base2: u8,
	access: u8,
	flags: u8,
	base3: u8,
}

#[derive(Copy, Clone)]
#[repr(C, packed)]
pub struct IdtEntry {
	offset1: u16,
	selector: u16,
	reserved: u8,
	flags: u8,
	offset2: u16
}

impl GdtEntry {
	pub fn null() -> GdtEntry {
		GdtEntry {
			base1: 0,
			base2: 0,
			base3: 0,
			access: 0,
			limit: 0,
			flags: 0
		}
	}

	pub fn new(base: *const (), limit: usize, access: GdtAccess, dpl: PrivilegeLevel) -> GdtEntry {
		let (limit, flags) = if limit < 0x100000 {
			((limit & 0xFFFF) as u16, ((limit & 0xF0000) >> 16) as u8 | 0x40u8)
		} else {
			if ((limit - 0xFFF) & 0xFFF) > 0 {
				panic!("bad segment limit for GDT entry");
			}
			(((limit & 0xFFFF000) >> 12) as u16, ((limit & 0xF0000000) >> 28) as u8 | 0xC0u8)
		};
		GdtEntry {
			base1: base as u16,
			base2: ((base as usize & 0xFF0000) >> 16) as u8,
			base3: ((base as usize & 0xFF000000) >> 24) as u8,
			access: access.bits() | ((dpl as u8) << 5) | 0x80,
			limit: limit,
			flags: flags
		}
	}
}

pub const NULL_IDT_ENTRY: IdtEntry = IdtEntry { offset1: 0, selector: 0, reserved: 0, flags: 0, offset2: 0 };

impl IdtEntry {
	pub fn new(f: unsafe extern "C" fn(), dpl: PrivilegeLevel, block: bool) -> IdtEntry {
		IdtEntry {
			offset1: f as u16,
			offset2: ((f as usize & 0xFFFF0000) >> 16) as u16,
			selector: 8,
			reserved: 0,
			flags: if block { 0x8E } else { 0x8F } | ((dpl as u8) << 5)
		}
	}
}

#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct Tss {
	pub link: u16,
	reserved0: u16,
	pub esp0: u32,
	pub ss0: u16,
	reserved1: u16,
	pub esp1: u32,
	pub ss1: u16,
	reserved2: u16,
	pub esp2: u32,
	pub ss2: u16,
	reserved3: u16,

	pub cr3: u32,
	pub eip: u32,
	pub eflags: u32,

	pub eax: u32,
	pub ecx: u32,
	pub edx: u32,
	pub ebx: u32,
	pub esp: u32,
	pub ebp: u32,
	pub esi: u32,
	pub edi: u32,

	pub es: u16,
	reserved4: u16,
	pub cs: u16,
	reserved5: u16,
	pub ss: u16,
	reserved6: u16,
	pub ds: u16,
	reserved7: u16,
	pub fs: u16,
	reserved8: u16,
	pub gs: u16,
	reserved9: u16,
	pub ldtr: u16,
	reserved10: u32,
	pub iobp_offset: u16
}

impl Tss {
	pub fn new() -> Tss {
		Tss {
			link: 0,
			reserved0: 0,
			esp0: 0,
			ss0: 0,
			reserved1: 0,
			esp1: 0,
			ss1: 0,
			reserved2: 0,
			esp2: 0,
			ss2: 0,
			reserved3: 0,
			cr3: 0,
			eip: 0,
			eflags: 0,
			eax: 0,
			ecx: 0,
			edx: 0,
			ebx: 0,
			esp: 0,
			ebp: 0,
			esi: 0,
			edi: 0,
			es: 0,
			reserved4: 0,
			cs: 0,
			reserved5: 0,
			ss: 0,
			reserved6: 0,
			ds: 0,
			reserved7: 0,
			fs: 0,
			reserved8: 0,
			gs: 0,
			reserved9: 0,
			ldtr: 0,
			reserved10: 0,
			iobp_offset: size_of::<Tss>() as u16
		}
	}
}

#[inline(always)]
pub fn get_flags() -> Flags {
	unsafe {
		let mut r: usize;
		asm!("pushfd; pop $0" : "=r"(r) ::: "intel");
		Flags::from_bits_truncate(r)
	}
}

#[inline(always)]
pub unsafe fn set_flags(val: Flags) {
	asm!("push $0; popfd" :: "r"(val.bits()) : "flags" : "volatile", "intel");
}

#[inline(always)]
pub unsafe fn set_gdt(gdt: &[GdtEntry]) {
	#[repr(C, packed)]
	struct GDTR {
		limit: u16,
		ptr: *const GdtEntry,
	}
	asm!("lgdtl $0" :: "*m"(&GDTR { ptr: gdt.as_ptr(), limit: (gdt.len()*size_of::<GdtEntry>() - 1) as u16 }) :: "volatile");
}

#[inline(always)]
pub unsafe fn set_idt(idt: &[IdtEntry]) {
	#[repr(C, packed)]
	struct IDTR {
		limit: u16,
		ptr: *const IdtEntry,
	}
	asm!("lidtl $0" :: "*m"(&IDTR { ptr: idt.as_ptr(), limit: idt.len() as u16 * 8 }) :: "volatile");
}

#[inline(always)]
pub unsafe fn stack_jmp(stack: *mut (), ip: *const ()) -> ! {
	asm!("mov esp, $0; jmp $1" :: "rg"(stack), "r"(ip) :: "volatile", "intel");
	loop { }
}
<commit_msg>Use associated const for NULL IdtEntry and GdtEntry<commit_after>#![allow(non_upper_case_globals)]

pub use self::x86_shared::*;

use core::prelude::*;
use core::mem::size_of;

mod x86_shared;

bitflags! {
	flags GdtAccess: u8 {
		const Accessed = 1 << 0,
		const Writable = 1 << 1,
		const Direction = 1 << 2,
		const Executable = 1 << 3,
		const NotTss = 1 << 4,
	}
}

#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct GdtEntry {
	limit: u16,
	base1: u16,
	base2: u8,
	access: u8,
	flags: u8,
	base3: u8,
}

#[derive(Copy, Clone)]
#[repr(C, packed)]
pub struct IdtEntry {
	offset1: u16,
	selector: u16,
	reserved: u8,
	flags: u8,
	offset2: u16
}

impl GdtEntry {
	pub const NULL: GdtEntry = GdtEntry {
		base1: 0,
		base2: 0,
		base3: 0,
		access: 0,
		limit: 0,
		flags: 0
	};

	pub fn new(base: *const (), limit: usize, access: GdtAccess, dpl: PrivilegeLevel) -> GdtEntry {
		let (limit, flags) = if limit < 0x100000 {
			((limit & 0xFFFF) as u16, ((limit & 0xF0000) >> 16) as u8 | 0x40u8)
		} else {
			if ((limit - 0xFFF) & 0xFFF) > 0 {
				panic!("bad segment limit for GDT entry");
			}
			(((limit & 0xFFFF000) >> 12) as u16, ((limit & 0xF0000000) >> 28) as u8 | 0xC0u8)
		};
		GdtEntry {
			base1: base as u16,
			base2: ((base as usize & 0xFF0000) >> 16) as u8,
			base3: ((base as usize & 0xFF000000) >> 24) as u8,
			access: access.bits() | ((dpl as u8) << 5) | 0x80,
			limit: limit,
			flags: flags
		}
	}
}

impl IdtEntry {
	pub const NULL: IdtEntry = IdtEntry {
		offset1: 0,
		selector: 0,
		reserved: 0,
		flags: 0,
		offset2: 0
	};

	pub fn new(f: unsafe extern "C" fn(), dpl: PrivilegeLevel, block: bool) -> IdtEntry {
		IdtEntry {
			offset1: f as u16,
			offset2: ((f as usize & 0xFFFF0000) >> 16) as u16,
			selector: 8,
			reserved: 0,
			flags: if block { 0x8E } else { 0x8F } | ((dpl as u8) << 5)
		}
	}
}

#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct Tss {
	pub link: u16,
	reserved0: u16,
	pub esp0: u32,
	pub ss0: u16,
	reserved1: u16,
	pub esp1: u32,
	pub ss1: u16,
	reserved2: u16,
	pub esp2: u32,
	pub ss2: u16,
	reserved3: u16,

	pub cr3: u32,
	pub eip: u32,
	pub eflags: u32,

	pub eax: u32,
	pub ecx: u32,
	pub edx: u32,
	pub ebx: u32,
	pub esp: u32,
	pub ebp: u32,
	pub esi: u32,
	pub edi: u32,

	pub es: u16,
	reserved4: u16,
	pub cs: u16,
	reserved5: u16,
	pub ss: u16,
	reserved6: u16,
	pub ds: u16,
	reserved7: u16,
	pub fs: u16,
	reserved8: u16,
	pub gs: u16,
	reserved9: u16,
	pub ldtr: u16,
	reserved10: u32,
	pub iobp_offset: u16
}

impl Tss {
	pub fn new() -> Tss {
		Tss {
			link: 0,
			reserved0: 0,
			esp0: 0,
			ss0: 0,
			reserved1: 0,
			esp1: 0,
			ss1: 0,
			reserved2: 0,
			esp2: 0,
			ss2: 0,
			reserved3: 0,
			cr3: 0,
			eip: 0,
			eflags: 0,
			eax: 0,
			ecx: 0,
			edx: 0,
			ebx: 0,
			esp: 0,
			ebp: 0,
			esi: 0,
			edi: 0,
			es: 0,
			reserved4: 0,
			cs: 0,
			reserved5: 0,
			ss: 0,
			reserved6: 0,
			ds: 0,
			reserved7: 0,
			fs: 0,
			reserved8: 0,
			gs: 0,
			reserved9: 0,
			ldtr: 0,
			reserved10: 0,
			iobp_offset: size_of::<Tss>() as u16
		}
	}
}

#[inline(always)]
pub fn get_flags() -> Flags {
	unsafe {
		let mut r: usize;
		asm!("pushfd; pop $0" : "=r"(r) ::: "intel");
		Flags::from_bits_truncate(r)
	}
}

#[inline(always)]
pub unsafe fn set_flags(val: Flags) {
	asm!("push $0; popfd" :: "r"(val.bits()) : "flags" : "volatile", "intel");
}

#[inline(always)]
pub unsafe fn set_gdt(gdt: &[GdtEntry]) {
	#[repr(C, packed)]
	struct GDTR {
		limit: u16,
		ptr: *const GdtEntry,
	}
	asm!("lgdtl $0" :: "*m"(&GDTR { ptr: gdt.as_ptr(), limit: (gdt.len()*size_of::<GdtEntry>() - 1) as u16 }) :: "volatile");
}

#[inline(always)]
pub unsafe fn set_idt(idt: &[IdtEntry]) {
	#[repr(C, packed)]
	struct IDTR {
		limit: u16,
		ptr: *const IdtEntry,
	}
	asm!("lidtl $0" :: "*m"(&IDTR { ptr: idt.as_ptr(), limit: idt.len() as u16 * 8 }) :: "volatile");
}

#[inline(always)]
pub unsafe fn stack_jmp(stack: *mut (), ip: *const ()) -> ! {
	asm!("mov esp, $0; jmp $1" :: "rg"(stack), "r"(ip) :: "volatile", "intel");
	loop { }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/// Configuration about types.
/// At present this is very minimal; in future we should roll
/// known_types.rs into this and possibly other things as well.
#[derive(Default, Hash, Debug)]
pub struct TypeConfig {
    pod_requests: Vec<String>,
    allowlist: Vec<String>, // not TypeName as it may be funcs not types.
    blocklist: Vec<String>, // not TypeName as it may be funcs not types.
}

impl TypeConfig {
    pub fn new() -> Self {
        Self::default()
    }

    pub(crate) fn note_pod_request(&mut self, tn: String) {
        self.pod_requests.push(tn);
    }

    pub(crate) fn add_to_allowlist(&mut self, item: String) {
        self.allowlist.push(item);
    }

    pub(crate) fn add_to_blocklist(&mut self, item: String) {
        self.blocklist.push(item);
    }

    pub fn get_pod_requests(&self) -> &[String] {
        &self.pod_requests
    }

    pub fn allowlist(&self) -> impl Iterator<Item = &String> {
        self.allowlist.iter()
    }

    pub fn allowlist_is_empty(&self) -> bool {
        self.allowlist.is_empty()
    }

    /// Whether this type is on the allowlist specified by the user.
    ///
    /// A note on the allowlist handling in general. It's used in two places:
    /// 1) As directives to bindgen
    /// 2) After bindgen has generated code, to filter the APIs which
    ///    we pass to cxx.
    /// This second pass may seem redundant. But sometimes bindgen generates
    /// unnecessary stuff.
    pub fn is_on_allowlist(&self, cpp_name: &str) -> bool {
        self.allowlist.contains(&cpp_name.to_string())
    }

    pub fn is_on_blocklist(&self, cpp_name: &str) -> bool {
        self.blocklist.contains(&cpp_name.to_string())
    }

    pub fn get_blocklist(&self) -> impl Iterator<Item = &String> {
        self.blocklist.iter()
    }
}
<commit_msg>Remove inaccurate comment.<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/// Configuration about types.
/// At present this is very minimal; in future we should roll
/// known_types.rs into this and possibly other things as well.
#[derive(Default, Hash, Debug)]
pub struct TypeConfig {
    pod_requests: Vec<String>,
    allowlist: Vec<String>,
    blocklist: Vec<String>,
}

impl TypeConfig {
    pub fn new() -> Self {
        Self::default()
    }

    pub(crate) fn note_pod_request(&mut self, tn: String) {
        self.pod_requests.push(tn);
    }

    pub(crate) fn add_to_allowlist(&mut self, item: String) {
        self.allowlist.push(item);
    }

    pub(crate) fn add_to_blocklist(&mut self, item: String) {
        self.blocklist.push(item);
    }

    pub fn get_pod_requests(&self) -> &[String] {
        &self.pod_requests
    }

    pub fn allowlist(&self) -> impl Iterator<Item = &String> {
        self.allowlist.iter()
    }

    pub fn allowlist_is_empty(&self) -> bool {
        self.allowlist.is_empty()
    }

    /// Whether this type is on the allowlist specified by the user.
    ///
    /// A note on the allowlist handling in general. It's used in two places:
    /// 1) As directives to bindgen
    /// 2) After bindgen has generated code, to filter the APIs which
    ///    we pass to cxx.
    /// This second pass may seem redundant. But sometimes bindgen generates
    /// unnecessary stuff.
    pub fn is_on_allowlist(&self, cpp_name: &str) -> bool {
        self.allowlist.contains(&cpp_name.to_string())
    }

    pub fn is_on_blocklist(&self, cpp_name: &str) -> bool {
        self.blocklist.contains(&cpp_name.to_string())
    }

    pub fn get_blocklist(&self) -> impl Iterator<Item = &String> {
        self.blocklist.iter()
    }
}
<|endoftext|>


<commit_before>use ansi_term::Colour::Blue;
use search::Search;
use ansi::Ansi;
use tty::TTY;
use fake_tty::FakeIO;
use renderer::Renderer;
use text::Text;
use std::cmp::min;

pub struct Screen <'a> {
    pub ansi: Ansi<'a>,
    pub height: usize,
    pub width: usize,
}

impl <'a> Screen <'a>{
    pub fn new() -> Screen<'a> {
        let ansi = Ansi { io: Box::new(TTY::new()) };
        let (width, height) = ansi.io.dimensions();
        Screen {
            ansi: ansi,
            height: height,
            width: width - 1,
        }
    }

    pub fn fake() -> Screen<'a> {
        Screen::fake_with_input(vec![])
    }

    pub fn fake_with_input(input: Vec<&str>) -> Screen<'a> {
        Screen {
            ansi: Ansi { io: Box::new(FakeIO::new_with_input(input)) },
            height: 20,
            width: 10,
        }
    }

    pub fn handle_keystroke(&self, search: Search<'a>, input: &str) -> Search<'a> {
        match input {
           "\u{e}" => search.down(),
           "\u{10}" => search.up(),
           "\u{7f}" => search.backspace(),
           "\n" => search.done(),
            _ => search.append_to_search(input),
        }
    }

    pub fn print(&mut self, search: &Search) {
        let renderer = Renderer;
        let result = renderer.render(search);
        self.ansi.hide_cursor();

        let start_line = self.height - search.visible_limit;

        for (idx, text) in result.iter().enumerate() {
            self.write(start_line + idx, text);
        };
        self.ansi.set_position(start_line, renderer.header(search).len());
        self.ansi.show_cursor();
    }

    pub fn write(&mut self, line: usize, text: &Text) {
        self.ansi.blank_line(line);
        self.ansi.set_position(line, 0);

        match *text {
            Text::Colored(ref matching) => {
                let (start, middle, end) = matching.parts();
                let text = format!("{}{}{}", start, Blue.paint(middle.as_ref()), end);
                let printable_length = self.printable_length(text.as_ref());
                self.ansi.print(&text[..printable_length]);
            }
            Text::Normal(ref text) => {
                let printable_length = self.printable_length(text);
                self.ansi.print(&text[..printable_length]);
            }
            Text::Highlight(ref text) => {
                let printable_length = self.printable_length(text);
                self.ansi.inverted(&text[..printable_length]);
            }
            Text::Blank => self.ansi.print("".as_ref()),
        };
    }

    pub fn clear(&mut self, lines: usize) {
        for _ in 0..lines {
            self.ansi.print("\n");
        }
    }

    pub fn reset(&mut self) {
        self.ansi.io.reset();
    }

    pub fn move_cursor_to_end(&mut self) {
        self.ansi.set_position(self.height - 1, 0);
    }

    fn printable_length(&self, text: &str) -> usize {
        min(text.len(), self.width)
    }

    pub fn run_search(&mut self, lines: Vec<String>, initial_query: Option<String>) -> Option<String> {
        let height = min(20, self.height);
        let mut search = Search::blank(&lines, initial_query, height);

        self.clear(height);

        while !search.is_done() {
            self.print(&search);
            let input = self.ansi.io.read();
            match input {
                Some(character) => {
                    search = self.handle_keystroke(search, character.as_ref());
                },
                None => break,
            };
        }
        search.selection()
    }
}
<commit_msg>Allow the Text elements to be consumed by iterator<commit_after>use ansi_term::Colour::Blue;
use search::Search;
use ansi::Ansi;
use tty::TTY;
use fake_tty::FakeIO;
use renderer::Renderer;
use text::Text;
use std::cmp::min;

pub struct Screen <'a> {
    pub ansi: Ansi<'a>,
    pub height: usize,
    pub width: usize,
}

impl <'a> Screen <'a>{
    pub fn new() -> Screen<'a> {
        let ansi = Ansi { io: Box::new(TTY::new()) };
        let (width, height) = ansi.io.dimensions();
        Screen {
            ansi: ansi,
            height: height,
            width: width - 1,
        }
    }

    pub fn fake() -> Screen<'a> {
        Screen::fake_with_input(vec![])
    }

    pub fn fake_with_input(input: Vec<&str>) -> Screen<'a> {
        Screen {
            ansi: Ansi { io: Box::new(FakeIO::new_with_input(input)) },
            height: 20,
            width: 10,
        }
    }

    pub fn handle_keystroke(&self, search: Search<'a>, input: &str) -> Search<'a> {
        match input {
           "\u{e}" => search.down(),
           "\u{10}" => search.up(),
           "\u{7f}" => search.backspace(),
           "\n" => search.done(),
            _ => search.append_to_search(input),
        }
    }

    pub fn print(&mut self, search: &Search) {
        let renderer = Renderer;
        let result = renderer.render(search);
        self.ansi.hide_cursor();

        let start_line = self.height - search.visible_limit;

        for (idx, text) in result.into_iter().enumerate() {
            self.write(start_line + idx, text);
        };
        self.ansi.set_position(start_line, renderer.header(search).len());
        self.ansi.show_cursor();
    }

    pub fn write(&mut self, line: usize, text: Text) {
        self.ansi.blank_line(line);
        self.ansi.set_position(line, 0);

        match text {
            Text::Colored(ref matching) => {
                let (start, middle, end) = matching.parts();
                let text = format!("{}{}{}", start, Blue.paint(middle.as_ref()), end);
                let printable_length = self.printable_length(text.as_ref());
                self.ansi.print(&text[..printable_length]);
            }
            Text::Normal(ref text) => {
                let printable_length = self.printable_length(text);
                self.ansi.print(&text[..printable_length]);
            }
            Text::Highlight(ref text) => {
                let printable_length = self.printable_length(text);
                self.ansi.inverted(&text[..printable_length]);
            }
            Text::Blank => self.ansi.print("".as_ref()),
        };
    }

    pub fn clear(&mut self, lines: usize) {
        for _ in 0..lines {
            self.ansi.print("\n");
        }
    }

    pub fn reset(&mut self) {
        self.ansi.io.reset();
    }

    pub fn move_cursor_to_end(&mut self) {
        self.ansi.set_position(self.height - 1, 0);
    }

    fn printable_length(&self, text: &str) -> usize {
        min(text.len(), self.width)
    }

    pub fn run_search(&mut self, lines: Vec<String>, initial_query: Option<String>) -> Option<String> {
        let height = min(20, self.height);
        let mut search = Search::blank(&lines, initial_query, height);

        self.clear(height);

        while !search.is_done() {
            self.print(&search);
            let input = self.ansi.io.read();
            match input {
                Some(character) => {
                    search = self.handle_keystroke(search, character.as_ref());
                },
                None => break,
            };
        }
        search.selection()
    }
}
<|endoftext|>


<commit_before>use std::rand::{Rng, task_rng};
use std::collections::HashMap;
use std::iter;

type Node = uint;

#[deriving(Show)]
struct NodePt {
    id: Node,
    x: f64,
    y: f64
}

#[deriving(Show, Clone)]
struct Edge {
	from: Node,
	to: Node,
	weight: f64
}

impl NodePt {
	fn new(nodeId: Node, x: f64, y: f64) -> NodePt {
		NodePt {
			id: nodeId,
			x: x,
			y: y
		}
	}

	fn distance_to(self, other: NodePt) -> f64 {
		let xx = (self.x - other.x) * (self.x - other.x);
		let yy = (self.y - other.y) * (self.y - other.y);

		(xx+yy).sqrt()
	}
}

impl PartialEq for NodePt {
	fn eq(&self, other: &NodePt) -> bool {
		self.id == other.id
	}

	fn ne(&self, other: &NodePt) -> bool {
		self.id != other.id
	}
}

impl Edge {
	fn new(a: NodePt, b: NodePt) -> Edge {
		Edge {
			from: a.id,
			to: b.id,
			weight: a.distance_to(b)
		}
	}
}

#[deriving(Show)]
struct Tour {
    nodes: Vec<Node>,
    total_weight: f64
}

impl Tour {
	fn new(nodes: Vec<Node>, weight: f64) -> Tour {
		Tour {
			nodes: nodes,
			total_weight: weight
		}
	}
}

fn make_complete_graph(nodes: Vec<NodePt>) -> Vec<Edge> {
	let mut edges: Vec<Edge> = Vec::new();

	for x in nodes.iter() {
		for y in nodes.iter() {
			if x.id != y.id {
				let e = Edge::new(*x, *y);
				edges.push(e);
			}
		}
	}

	edges
}

fn random_nodes(n: uint, x_max: f64, y_max: f64) -> Vec<NodePt> {
	let mut rng1 = task_rng();
	let mut rng2 = task_rng();
	let rngIter1 = rng1.gen_iter::<f64>();
	let rngIter2 = rng2.gen_iter::<f64>();

	rngIter1.zip(rngIter2)
		.enumerate()
		.map(|t|
			match t { (idx, (x, y)) => NodePt::new(idx, x * x_max, y * y_max) })
		.take(n)
		.collect()
}

fn make_adjacency_map(edges: Vec<Edge>, node_count: uint) -> HashMap<Node, Vec<Edge>> {
	let mut map: HashMap<Node, Vec<Edge>> = HashMap::new();

	for i in range(0, node_count) {
		let adj_edges = edges.iter()
			.map(|x| x.clone())
			.filter(|edge| edge.from == i)
			.collect();
		map.insert(i, adj_edges);
	}

	map
}

fn calc_tour_weight(tour_pts: &Vec<NodePt>) -> f64 {
	let mut sum = 0.0;
	let mut last = tour_pts.get(0);

	for point in tour_pts.iter() {
		sum += last.distance_to(*point);
		last = point;
	}
	if (tour_pts.get(0) != last) {
		sum += last.distance_to(*tour_pts.get(0));
	}

	sum
}

fn random_tour(map: &HashMap<Node, NodePt>, node_count: uint) -> Tour {
	let mut rng = task_rng();
	let mut tour_nodes: Vec<uint> = range(0, node_count).collect();
	rng.shuffle(tour_nodes.as_mut_slice());

	let mut tour_pts: Vec<NodePt> = Vec::new();
	for n in tour_nodes.iter() {
		tour_pts.push(*map.get(n));
	}

	let tour_weight = calc_tour_weight(&tour_pts);
	Tour::new(tour_nodes, tour_weight)
}

fn main() {
	let N = 12;
	let nodes = random_nodes(N, 300.0, 300.0);
	let mut map: HashMap<Node, NodePt> = HashMap::new();

	for n in nodes.iter() {
		map.insert(n.id, *n);
	}

	for i in range(0, 100000) {
		let tour = random_tour(&map, N);
	}
	// let graph = make_complete_graph(nodes);
	// let map = make_adjacency_map(graph, N);
	// let adj_edges = map.get(&2);

	//println!("{}", tour);
}<commit_msg>rewrote bunch of stuff<commit_after>extern crate time;

use std::rand::{Rng, task_rng};
use std::collections::HashMap;
use time::precise_time_ns;

pub type Node = uint;

#[deriving(Show)]
pub struct NodePt {
    id: Node,
    x: f64,
    y: f64
}

impl NodePt {
	fn new(nodeId: Node, x: f64, y: f64) -> NodePt {
		NodePt {
			id: nodeId,
			x: x,
			y: y
		}
	}

	fn distance_to(self, other: NodePt) -> f64 {
		let xx = (self.x - other.x) * (self.x - other.x);
		let yy = (self.y - other.y) * (self.y - other.y);

		(xx+yy).sqrt()
	}
}

impl PartialEq for NodePt {
	fn eq(&self, other: &NodePt) -> bool {
		self.id == other.id
	}

	fn ne(&self, other: &NodePt) -> bool {
		self.id != other.id
	}
}

#[deriving(Show, Clone)]
pub struct Edge {
	from: Node,
	to: Node,
	weight: f64
}

impl Edge {
	fn new(a: NodePt, b: NodePt) -> Edge {
		Edge {
			from: a.id,
			to: b.id,
			weight: a.distance_to(b)
		}
	}
}

#[deriving(Show)]
pub struct Tour {
    nodes: Vec<Node>,
    total_weight: f64
}

impl Tour {
	fn new(nodes: Vec<Node>, weight: f64) -> Tour {
		Tour {
			nodes: nodes,
			total_weight: weight
		}
	}

	fn calc_tour_weight(tour: &Vec<Node>, graph: &Graph) -> f64 {
		let mut tour_weight = 0.0;
		let mut last_node = tour.get(0u);
		for node in tour.iter() {
			tour_weight += graph.get(*last_node, *node);
			last_node = node;
		}

		tour_weight
	}

	fn random_tour<R: Rng>(rng: &mut R, graph: &Graph) -> Tour {
		let node_count = graph.adj_list.len();
		let mut tour_nodes: Vec<Node> = range(0, node_count).collect();
		rng.shuffle(tour_nodes.as_mut_slice());
		let tour_weight = Tour::calc_tour_weight(&tour_nodes, graph);

		Tour::new(tour_nodes, tour_weight)
	}

}

#[deriving(Show)]
pub struct Graph {
	adj_list: HashMap<Node, Vec<Edge>>
}

impl Graph {
	fn new(adj_list: HashMap<Node, Vec<Edge>>) -> Graph {
		Graph {
			adj_list: adj_list
		}
	}

	fn from_nodes(nodes: Vec<NodePt>) -> Graph {
		let mut map: HashMap<Node, Vec<Edge>> = HashMap::new();
		for i in range(0, nodes.len()) {
			let mut adj_edges: Vec<Edge> = Vec::new();

			for j in range(0, nodes.len()) {
				let a = nodes.get(i);
				let b = nodes.get(j);
				if i != j {
					adj_edges.push(Edge::new(*a, *b));
				}
			}

			map.insert(i, adj_edges);
		}

		Graph::new(map)
	}

	fn random_graph<R: Rng>(rng: &mut R, num_nodes: uint, x_max: f64, y_max: f64) -> Graph {
		let points = rng.gen_iter::<(f64, f64)>()
			.enumerate()
			.map(|t|
				match t { (idx, (x, y)) => NodePt::new(idx, x * x_max, y * y_max) })
			.take(num_nodes)
			.collect();

		Graph::from_nodes(points)
	}

	fn get(&self, n: Node, m: Node) -> f64 {
		if n == m {
			0.0
		}
		else {
			let edges = self.adj_list.get(&n);
			let mut weight = 0.0;

			for edge in edges.iter() {
				if edge.to == m {
					weight = edge.weight;
				}
			}
			weight
		}
	}

}

fn main() {
	let mut rng = task_rng();
	let node_count = 4u;
	let iters = 10000;
	let graph = Graph::random_graph(&mut rng, node_count, 200.0, 200.0);

	let t0 = time::precise_time_ns();
	for _ in range(0, iters) {
		let tour = Tour::random_tour(&mut rng, &graph);
	}
	let t1 = time::precise_time_ns();

	let dt = (t1 - t0) as f64;
	println!("{} iters: t = {} ms", iters, (dt / 1e6))
}<|endoftext|>


<commit_before>use vecmath::Matrix4;
use gfx;
use gfx::{Device, DeviceHelper, ToSlice};
use device;
use device::draw::CommandBuffer;
use render;

static VERTEX: gfx::ShaderSource<'static> = shaders! {
GLSL_120: b"
    #version 120
    uniform mat4 projection, view;

    attribute vec2 tex_coord;
    attribute vec3 color, position;

    varying vec2 v_tex_coord;
    varying vec3 v_color;

    void main() {
        v_tex_coord = tex_coord;
        v_color = color;
        gl_Position = projection * view * vec4(position, 1.0);
    }
"
GLSL_150: b"
    #version 150 core
    uniform mat4 projection, view;

    in vec2 tex_coord;
    in vec3 color, position;

    out vec2 v_tex_coord;
    out vec3 v_color;

    void main() {
        v_tex_coord = tex_coord;
        v_color = color;
        gl_Position = projection * view * vec4(position, 1.0);
    }
"
};

static FRAGMENT: gfx::ShaderSource<'static> = shaders!{
GLSL_120: b"
    #version 120

    uniform sampler2D s_texture;

    varying vec2 v_tex_coord;
    varying vec3 v_color;

    void main() {
        vec4 tex_color = texture2D(s_texture, v_tex_coord);
        if(tex_color.a == 0.0) // Discard transparent pixels.
            discard;
        gl_FragColor = tex_color * vec4(v_color, 1.0);
    }
"
GLSL_150: b"
    #version 150 core
    out vec4 out_color;

    uniform sampler2D s_texture;

    in vec2 v_tex_coord;
    in vec3 v_color;

    void main() {
        vec4 tex_color = texture(s_texture, v_tex_coord);
        if(tex_color.a == 0.0) // Discard transparent pixels.
            discard;
        out_color = tex_color * vec4(v_color, 1.0);
    }
"
};

#[shader_param(Program)]
pub struct ShaderParam {
    pub projection: [[f32, ..4], ..4],
    pub view: [[f32, ..4], ..4],
    pub s_texture: gfx::shade::TextureParam,
}

#[vertex_format]
pub struct Vertex {
    #[name="position"]
    pub xyz: [f32, ..3],
    #[name="tex_coord"]
    pub uv: [f32, ..2],
    #[name="color"]
    pub rgb: [f32, ..3],
}

impl Clone for Vertex {
    fn clone(&self) -> Vertex {
        *self
    }
}

pub struct Buffer {
    buf: gfx::BufferHandle<Vertex>,
    batch: render::batch::RefBatch<_ShaderParamLink, ShaderParam>
}

pub struct Renderer<D: Device<C>, C: CommandBuffer> {
    graphics: gfx::Graphics<D, C>,
    params: ShaderParam,
    frame: gfx::Frame,
    cd: gfx::ClearData,
    prog: device::Handle<u32, device::shade::ProgramInfo>,
    drawstate: gfx::DrawState
}

impl<D: Device<C>, C: CommandBuffer> Renderer<D, C> {
    pub fn new(mut device: D, frame: gfx::Frame, tex: gfx::TextureHandle) -> Renderer<D, C> {
        let sampler = device.create_sampler(
                gfx::tex::SamplerInfo::new(
                    gfx::tex::FilterMethod::Scale,
                    gfx::tex::WrapMode::Tile
                )
            );
        let mut graphics = gfx::Graphics::new(device);

        let params = ShaderParam {
            projection: [[0.0, ..4], ..4],
            view: [[0.0, ..4], ..4],
            s_texture: (tex, Some(sampler))
        };
        let prog = graphics.device.link_program(VERTEX.clone(), FRAGMENT.clone()).unwrap();
        let mut drawstate = gfx::DrawState::new().depth(gfx::state::Comparison::LessEqual, true);
        drawstate.primitive.front_face = gfx::state::WindingOrder::Clockwise;

        Renderer {
            graphics: graphics,
            params: params,
            frame: frame,
            cd: gfx::ClearData {
                color: [0.81, 0.8, 1.0, 1.0],
                depth: 1.0,
                stencil: 0,
            },
            prog: prog,
            drawstate: drawstate,
        }
    }

    pub fn set_projection(&mut self, proj_mat: Matrix4<f32>) {
        self.params.projection = proj_mat;
    }

    pub fn set_view(&mut self, view_mat: Matrix4<f32>) {
        self.params.view = view_mat;
    }

    pub fn clear(&mut self) {
        self.graphics.clear(self.cd, gfx::COLOR | gfx::DEPTH, &self.frame);
    }

    pub fn create_buffer(&mut self, data: &[Vertex]) -> Buffer {
        let buf = self.graphics.device.create_buffer(data.len(), gfx::UsageStatic);
        self.graphics.device.update_buffer(buf, data, 0);
        let mesh = gfx::Mesh::from_format(buf, data.len() as u32);
        Buffer {
            buf: buf,
            batch: self.graphics.make_batch(
                    &self.prog,
                    &mesh,
                    mesh.to_slice(gfx::PrimitiveType::TriangleList),
                    &self.drawstate
                ).unwrap()
        }
    }

    pub fn delete_buffer(&mut self, buf: Buffer) {
        self.graphics.device.delete_buffer(buf.buf);
    }

    pub fn render(&mut self, buffer: Buffer) {
        self.graphics.draw(&buffer.batch, &self.params, &self.frame);
    }

    pub fn end_frame(&mut self) {
        self.graphics.end_frame();
    }
}
<commit_msg>replaced gfx::BufferUsage::Static with gfx::BufferUsage::Static<commit_after>use vecmath::Matrix4;
use gfx;
use gfx::{Device, DeviceHelper, ToSlice};
use device;
use device::draw::CommandBuffer;
use render;

static VERTEX: gfx::ShaderSource<'static> = shaders! {
GLSL_120: b"
    #version 120
    uniform mat4 projection, view;

    attribute vec2 tex_coord;
    attribute vec3 color, position;

    varying vec2 v_tex_coord;
    varying vec3 v_color;

    void main() {
        v_tex_coord = tex_coord;
        v_color = color;
        gl_Position = projection * view * vec4(position, 1.0);
    }
"
GLSL_150: b"
    #version 150 core
    uniform mat4 projection, view;

    in vec2 tex_coord;
    in vec3 color, position;

    out vec2 v_tex_coord;
    out vec3 v_color;

    void main() {
        v_tex_coord = tex_coord;
        v_color = color;
        gl_Position = projection * view * vec4(position, 1.0);
    }
"
};

static FRAGMENT: gfx::ShaderSource<'static> = shaders!{
GLSL_120: b"
    #version 120

    uniform sampler2D s_texture;

    varying vec2 v_tex_coord;
    varying vec3 v_color;

    void main() {
        vec4 tex_color = texture2D(s_texture, v_tex_coord);
        if(tex_color.a == 0.0) // Discard transparent pixels.
            discard;
        gl_FragColor = tex_color * vec4(v_color, 1.0);
    }
"
GLSL_150: b"
    #version 150 core
    out vec4 out_color;

    uniform sampler2D s_texture;

    in vec2 v_tex_coord;
    in vec3 v_color;

    void main() {
        vec4 tex_color = texture(s_texture, v_tex_coord);
        if(tex_color.a == 0.0) // Discard transparent pixels.
            discard;
        out_color = tex_color * vec4(v_color, 1.0);
    }
"
};

#[shader_param(Program)]
pub struct ShaderParam {
    pub projection: [[f32, ..4], ..4],
    pub view: [[f32, ..4], ..4],
    pub s_texture: gfx::shade::TextureParam,
}

#[vertex_format]
pub struct Vertex {
    #[name="position"]
    pub xyz: [f32, ..3],
    #[name="tex_coord"]
    pub uv: [f32, ..2],
    #[name="color"]
    pub rgb: [f32, ..3],
}

impl Clone for Vertex {
    fn clone(&self) -> Vertex {
        *self
    }
}

pub struct Buffer {
    buf: gfx::BufferHandle<Vertex>,
    batch: render::batch::RefBatch<_ShaderParamLink, ShaderParam>
}

pub struct Renderer<D: Device<C>, C: CommandBuffer> {
    graphics: gfx::Graphics<D, C>,
    params: ShaderParam,
    frame: gfx::Frame,
    cd: gfx::ClearData,
    prog: device::Handle<u32, device::shade::ProgramInfo>,
    drawstate: gfx::DrawState
}

impl<D: Device<C>, C: CommandBuffer> Renderer<D, C> {
    pub fn new(mut device: D, frame: gfx::Frame, tex: gfx::TextureHandle) -> Renderer<D, C> {
        let sampler = device.create_sampler(
                gfx::tex::SamplerInfo::new(
                    gfx::tex::FilterMethod::Scale,
                    gfx::tex::WrapMode::Tile
                )
            );
        let mut graphics = gfx::Graphics::new(device);

        let params = ShaderParam {
            projection: [[0.0, ..4], ..4],
            view: [[0.0, ..4], ..4],
            s_texture: (tex, Some(sampler))
        };
        let prog = graphics.device.link_program(VERTEX.clone(), FRAGMENT.clone()).unwrap();
        let mut drawstate = gfx::DrawState::new().depth(gfx::state::Comparison::LessEqual, true);
        drawstate.primitive.front_face = gfx::state::WindingOrder::Clockwise;

        Renderer {
            graphics: graphics,
            params: params,
            frame: frame,
            cd: gfx::ClearData {
                color: [0.81, 0.8, 1.0, 1.0],
                depth: 1.0,
                stencil: 0,
            },
            prog: prog,
            drawstate: drawstate,
        }
    }

    pub fn set_projection(&mut self, proj_mat: Matrix4<f32>) {
        self.params.projection = proj_mat;
    }

    pub fn set_view(&mut self, view_mat: Matrix4<f32>) {
        self.params.view = view_mat;
    }

    pub fn clear(&mut self) {
        self.graphics.clear(self.cd, gfx::COLOR | gfx::DEPTH, &self.frame);
    }

    pub fn create_buffer(&mut self, data: &[Vertex]) -> Buffer {
        let buf = self.graphics.device.create_buffer(data.len(), gfx::BufferUsage::Static);
        self.graphics.device.update_buffer(buf, data, 0);
        let mesh = gfx::Mesh::from_format(buf, data.len() as u32);
        Buffer {
            buf: buf,
            batch: self.graphics.make_batch(
                    &self.prog,
                    &mesh,
                    mesh.to_slice(gfx::PrimitiveType::TriangleList),
                    &self.drawstate
                ).unwrap()
        }
    }

    pub fn delete_buffer(&mut self, buf: Buffer) {
        self.graphics.device.delete_buffer(buf.buf);
    }

    pub fn render(&mut self, buffer: Buffer) {
        self.graphics.draw(&buffer.batch, &self.params, &self.frame);
    }

    pub fn end_frame(&mut self) {
        self.graphics.end_frame();
    }
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

#![deny(
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_mut,
    unused_qualifications,
    while_true,
)]

#[macro_use] extern crate log;
#[macro_use] extern crate version;
extern crate fs2;
extern crate glob;
#[macro_use] extern crate lazy_static;
extern crate regex;
extern crate toml;
#[cfg(test)] extern crate tempdir;
extern crate semver;
extern crate crossbeam;
extern crate walkdir;
extern crate itertools;
#[macro_use] extern crate is_match;
#[macro_use] extern crate serde;
#[macro_use] extern crate serde_json;
#[macro_use] extern crate serde_derive;

#[macro_use] extern crate libimagerror;
extern crate libimagutil;

#[macro_use] mod util;

pub mod storeid;
pub mod error;
pub mod store;
mod configuration;
pub mod file_abstraction;
pub mod toml_ext;

<commit_msg>Remove unneeded [macro_use]<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

#![deny(
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_mut,
    unused_qualifications,
    while_true,
)]

#[macro_use] extern crate log;
#[macro_use] extern crate version;
extern crate fs2;
extern crate glob;
#[macro_use] extern crate lazy_static;
extern crate regex;
extern crate toml;
#[cfg(test)] extern crate tempdir;
extern crate semver;
extern crate crossbeam;
extern crate walkdir;
extern crate itertools;
#[macro_use] extern crate is_match;
extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;

#[macro_use] extern crate libimagerror;
extern crate libimagutil;

#[macro_use] mod util;

pub mod storeid;
pub mod error;
pub mod store;
mod configuration;
pub mod file_abstraction;
pub mod toml_ext;

<|endoftext|>


<commit_before>// Copyright 2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! `IMPL` Low level signal support.

use libc::{c_void, c_uint, c_ulong};

use gobject_ffi::{self, GCallback};
use ffi::GQuark;
use object::{IsA, Object};
use source::CallbackGuard;
use translate::ToGlibPtr;

pub unsafe fn connect(receiver: *mut gobject_ffi::GObject, signal_name: &str, trampoline: GCallback,
                      closure: *mut Box<Fn() + 'static>) -> u64 {
    let handle = gobject_ffi::g_signal_connect_data(receiver, signal_name.to_glib_none().0,
        trampoline, closure as *mut _, Some(destroy_closure),
        gobject_ffi::GConnectFlags::empty()) as u64;
    assert!(handle > 0);
    handle
}

pub fn signal_handler_block<T: IsA<Object>>(instance: &T, handler_id: u64) {
    unsafe {
        gobject_ffi::g_signal_handler_block(instance.to_glib_none().0, handler_id as c_ulong);
    }
}

pub fn signal_handler_unblock<T: IsA<Object>>(instance: &T, handler_id: u64) {
    unsafe {
        gobject_ffi::g_signal_handler_unblock(instance.to_glib_none().0, handler_id as c_ulong);
    }
}

pub fn signal_stop_emission<T: IsA<Object>>(instance: &T, signal_id: u32, detail: GQuark) {
    unsafe {
        gobject_ffi::g_signal_stop_emission(instance.to_glib_none().0, signal_id as c_uint, detail);
    }
}

pub fn signal_stop_emission_by_name<T: IsA<Object>>(instance: &T, signal_name: &str) {
    unsafe {
        gobject_ffi::g_signal_stop_emission_by_name(instance.to_glib_none().0, signal_name.to_glib_none().0);
    }
}

unsafe extern "C" fn destroy_closure(ptr: *mut c_void, _: *mut gobject_ffi::GClosure) {
    let _guard = CallbackGuard::new();
    // destroy
    Box::<Box<Fn()>>::from_raw(ptr as *mut _);
}
<commit_msg>Add signal::Inhibit<commit_after>// Copyright 2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! `IMPL` Low level signal support.

use libc::{c_void, c_uint, c_ulong};

use gobject_ffi::{self, GCallback};
use ffi::{gboolean, GQuark};
use object::{IsA, Object};
use source::CallbackGuard;
use translate::{ToGlib, ToGlibPtr};

/// Whether to propagate the signal to the default handler.
///
/// Don't inhibit default handlers without a reason, they're usually helpful.
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct Inhibit(pub bool);

#[doc(hidden)]
impl ToGlib for Inhibit {
    type GlibType = gboolean;

    #[inline]
    fn to_glib(&self) -> gboolean {
        self.0.to_glib()
    }
}

pub unsafe fn connect(receiver: *mut gobject_ffi::GObject, signal_name: &str, trampoline: GCallback,
                      closure: *mut Box<Fn() + 'static>) -> u64 {
    let handle = gobject_ffi::g_signal_connect_data(receiver, signal_name.to_glib_none().0,
        trampoline, closure as *mut _, Some(destroy_closure),
        gobject_ffi::GConnectFlags::empty()) as u64;
    assert!(handle > 0);
    handle
}

pub fn signal_handler_block<T: IsA<Object>>(instance: &T, handler_id: u64) {
    unsafe {
        gobject_ffi::g_signal_handler_block(instance.to_glib_none().0, handler_id as c_ulong);
    }
}

pub fn signal_handler_unblock<T: IsA<Object>>(instance: &T, handler_id: u64) {
    unsafe {
        gobject_ffi::g_signal_handler_unblock(instance.to_glib_none().0, handler_id as c_ulong);
    }
}

pub fn signal_stop_emission<T: IsA<Object>>(instance: &T, signal_id: u32, detail: GQuark) {
    unsafe {
        gobject_ffi::g_signal_stop_emission(instance.to_glib_none().0, signal_id as c_uint, detail);
    }
}

pub fn signal_stop_emission_by_name<T: IsA<Object>>(instance: &T, signal_name: &str) {
    unsafe {
        gobject_ffi::g_signal_stop_emission_by_name(instance.to_glib_none().0, signal_name.to_glib_none().0);
    }
}

unsafe extern "C" fn destroy_closure(ptr: *mut c_void, _: *mut gobject_ffi::GClosure) {
    let _guard = CallbackGuard::new();
    // destroy
    Box::<Box<Fn()>>::from_raw(ptr as *mut _);
}
<|endoftext|>


<commit_before>// Copyright (c) 2019 DDN. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

pub mod error;

use errno;
use error::LiblustreError;
use libc;
use liblustreapi_sys as sys;
use log;
use std::{
    convert::From,
    ffi::{CStr, CString},
    fmt,
    num::ParseIntError,
    path::PathBuf,
    str::FromStr,
};

const PATH_BYTES: usize = 4096;

// FID

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Fid {
    pub seq: u64,
    pub oid: u32,
    pub ver: u32,
}
impl fmt::Display for Fid {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[0x{:x}:0x{:x}:0x{:x}]", self.seq, self.oid, self.ver)
    }
}
impl FromStr for Fid {
    type Err = ParseIntError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let fidstr = s.trim_matches(|c| c == '[' || c == ']');
        let arr: Vec<&str> = fidstr
            .split(':')
            .map(|num| num.trim_start_matches("0x"))
            .collect();
        Ok(Self {
            seq: u64::from_str_radix(arr[0], 16)?,
            oid: u32::from_str_radix(arr[1], 16)?,
            ver: u32::from_str_radix(arr[2], 16)?,
        })
    }
}
impl From<[u8; 40_usize]> for Fid {
    fn from(fidstr: [u8; 40_usize]) -> Self {
        String::from_utf8_lossy(&fidstr)
            .into_owned()
            .parse::<Self>()
            .unwrap()
    }
}
impl From<sys::lu_fid> for Fid {
    fn from(fid: sys::lu_fid) -> Self {
        Self {
            seq: fid.f_seq,
            oid: fid.f_oid,
            ver: fid.f_ver,
        }
    }
}

fn buf2string(mut buf: Vec<u8>) -> Result<String, LiblustreError> {
    unsafe {
        let s = CStr::from_ptr(buf.as_ptr() as *const i8);
        let len = s.to_bytes().len();
        buf.set_len(len);
    };

    Ok(CString::new(buf)?.into_string()?)
}

pub fn fid2path(device: &str, fidstr: &str) -> Result<String, LiblustreError> {
    if !fidstr.starts_with('[') {
        return Err(LiblustreError::invalid_input(format!(
            "FID is invalid format {}",
            fidstr
        )));
    }

    let mut buf: Vec<u8> = vec![0; std::mem::size_of::<u8>() * PATH_BYTES];
    let ptr = buf.as_mut_ptr() as *mut libc::c_char;

    let devptr = CString::new(device)?.into_raw();
    let fidptr = CString::new(fidstr)?.into_raw();

    let rc = unsafe {
        let mut recno: i64 = -1;
        let mut linkno: i32 = 0;
        let rc = sys::llapi_fid2path(
            devptr,
            fidptr,
            ptr,
            buf.len() as i32,
            &mut recno as *mut std::os::raw::c_longlong,
            &mut linkno as *mut std::os::raw::c_int,
        );
        // Ensure CStrings are freed
        let _ = CString::from_raw(devptr);
        let _ = CString::from_raw(fidptr);
        rc
    };

    if rc != 0 {
        return Err(LiblustreError::os_error(rc.abs()));
    }

    buf2string(buf)
}

pub fn search_rootpath(fsname: &str) -> Result<String, LiblustreError> {
    // @TODO this should do more validation
    if fsname.starts_with('/') {
        return Ok(fsname.to_string());
    }
    let fsc = CString::new(fsname.as_bytes())?;

    let mut page: Vec<u8> = vec![0; std::mem::size_of::<u8>() * PATH_BYTES];
    let ptr = page.as_mut_ptr() as *mut libc::c_char;

    let rc = unsafe { sys::llapi_search_rootpath(ptr, fsc.as_ptr()) };

    if rc != 0 {
        log::error!(
            "Error: llapi_search_rootpath({}) => {}",
            fsc.into_string()?,
            rc
        );
        return Err(LiblustreError::os_error(rc.abs()));
    }

    buf2string(page)
}

pub fn mdc_stat(path: &PathBuf) -> Result<sys::lstat_t, LiblustreError> {
    let file_name = path
        .file_name()
        .ok_or_else(|| LiblustreError::not_found(format!("File Not Found: {:?}", path)))?
        .to_str()
        .ok_or_else(|| LiblustreError::not_found(format!("No string for File: {:?}", path)))?;

    let file_namec = CString::new(file_name)?;

    let dirstr = path
        .parent()
        .ok_or_else(|| LiblustreError::not_found(format!("No Parent directory: {:?}", path)))?
        .to_str()
        .ok_or_else(|| LiblustreError::not_found(format!("No string for Parent: {:?}", path)))?;

    let dircstr = CString::new(dirstr)?;

    let page = Vec::with_capacity(PATH_BYTES);

    unsafe {
        libc::memcpy(
            page.as_ptr() as *mut libc::c_void,
            file_namec.as_ptr() as *const libc::c_void,
            file_namec.as_bytes_with_nul().len(),
        );
    }

    let dirhandle = unsafe { libc::opendir(dircstr.as_ptr() as *const i8) };

    if dirhandle.is_null() {
        let e = errno::errno();
        log::error!("Failed top opendir({:?}) -> {}", dircstr, e);
        return Err(LiblustreError::os_error(e.into()));
    }

    let fd = unsafe { libc::dirfd(dirhandle) };

    if fd < 0 {
        let e = errno::errno();
        log::error!("Failed dirfd({:?}) => {}", dirhandle, e);
        return Err(LiblustreError::os_error(e.into()));
    }

    let rc = unsafe {
        libc::ioctl(
            fd,
            sys::IOC_MDC_GETFILEINFO as u64,
            page.as_ptr() as *mut sys::lov_user_mds_data_v1,
        )
    };

    if rc < 0 {
        let e = errno::errno();
        log::error!("Failed ioctl({:?}) => {}", path, e);
        return Err(LiblustreError::os_error(e.into()));
    }

    let rc = unsafe { libc::closedir(dirhandle) };

    if rc < 0 {
        let e = errno::errno();
        log::error!("Failed closedir({:?}) => {}", dirhandle, e);
        return Err(LiblustreError::os_error(e.into()));
    }

    let statptr: *const sys::lstat_t = page.as_ptr();
    let stat: sys::lstat_t = unsafe { *statptr };

    Ok(stat)
}

pub fn rmfid(mntpt: &str, fidstr: &str) -> Result<(), LiblustreError> {
    use std::fs; // @TODO replace with sys::llapi_rmfid once LU-12090 lands

    let path = fid2path(mntpt, &fidstr)?;
    let pb: std::path::PathBuf = [mntpt, &path].iter().collect();
    if let Err(e) = fs::remove_file(pb) {
        log::error!("Failed to remove {}: {:?}", fidstr, e);
    }

    Ok(())
}

pub fn rmfids(
    mntpt: &str,
    fidlist: impl IntoIterator<Item = String>,
) -> Result<(), LiblustreError> {
    // @TODO replace with sys::llapi_rmfid once LU-12090 lands
    for fidstr in fidlist {
        rmfid(&mntpt, &fidstr)?;
    }

    Ok(())
}

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

    #[test]
    fn fid_display() {
        let fid = Fid {
            ver: 1,
            oid: 2,
            seq: 64,
        };
        assert_eq!("[0x40:0x2:0x1]", format!("{}", fid))
    }

    #[test]
    fn lu_fid2fid() {
        let fid = sys::lu_fid {
            f_ver: 1,
            f_oid: 4,
            f_seq: 64,
        };
        assert_eq!("[0x40:0x4:0x1]", format!("{}", Fid::from(fid)))
    }

    #[test]
    fn string2fid() {
        let fid = Fid {
            seq: 0x404,
            oid: 0x40,
            ver: 0x10,
        };
        assert_eq!(Ok(fid), Fid::from_str("[0x404:0x40:0x10]"))
    }
}
<commit_msg>Fix fid error (#1011)<commit_after>// Copyright (c) 2019 DDN. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

pub mod error;

use errno;
use error::LiblustreError;
use libc;
use liblustreapi_sys as sys;
use log;
use std::{
    convert::From,
    ffi::{CStr, CString},
    fmt,
    num::ParseIntError,
    path::PathBuf,
    str::FromStr,
};

const PATH_BYTES: usize = 4096;

// FID

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Fid {
    pub seq: u64,
    pub oid: u32,
    pub ver: u32,
}
impl fmt::Display for Fid {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[0x{:x}:0x{:x}:0x{:x}]", self.seq, self.oid, self.ver)
    }
}
impl FromStr for Fid {
    type Err = ParseIntError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let fidstr = s.trim_matches(|c| c == '[' || c == ']');
        let arr: Vec<&str> = fidstr
            .split(':')
            .map(|num| num.trim_start_matches("0x"))
            .collect();
        Ok(Self {
            seq: u64::from_str_radix(arr[0], 16)?,
            oid: u32::from_str_radix(arr[1], 16)?,
            ver: u32::from_str_radix(arr[2], 16)?,
        })
    }
}
impl From<[u8; 40_usize]> for Fid {
    fn from(fidstr: [u8; 40_usize]) -> Self {
        String::from_utf8_lossy(&fidstr)
            .into_owned()
            .parse::<Self>()
            .unwrap()
    }
}
impl From<sys::lu_fid> for Fid {
    fn from(fid: sys::lu_fid) -> Self {
        Self {
            seq: fid.f_seq,
            oid: fid.f_oid,
            ver: fid.f_ver,
        }
    }
}

fn buf2string(mut buf: Vec<u8>) -> Result<String, LiblustreError> {
    unsafe {
        let s = CStr::from_ptr(buf.as_ptr() as *const i8);
        let len = s.to_bytes().len();
        buf.set_len(len);
    };

    Ok(CString::new(buf)?.into_string()?)
}

pub fn fid2path(device: &str, fidstr: &str) -> Result<String, LiblustreError> {
    if !fidstr.starts_with('[') {
        return Err(LiblustreError::invalid_input(format!(
            "FID is invalid format {}",
            fidstr
        )));
    }

    let mut buf: Vec<u8> = vec![0; std::mem::size_of::<u8>() * PATH_BYTES];
    let ptr = buf.as_mut_ptr() as *mut libc::c_char;

    let devptr = CString::new(device)?.into_raw();
    let fidptr = CString::new(fidstr)?.into_raw();

    let rc = unsafe {
        let mut recno: i64 = -1;
        let mut linkno: i32 = 0;
        let rc = sys::llapi_fid2path(
            devptr,
            fidptr,
            ptr,
            buf.len() as i32,
            &mut recno as *mut std::os::raw::c_longlong,
            &mut linkno as *mut std::os::raw::c_int,
        );
        // Ensure CStrings are freed
        let _ = CString::from_raw(devptr);
        let _ = CString::from_raw(fidptr);
        rc
    };

    if rc != 0 {
        return Err(LiblustreError::os_error(rc.abs()));
    }

    buf2string(buf)
}

pub fn search_rootpath(fsname: &str) -> Result<String, LiblustreError> {
    // @TODO this should do more validation
    if fsname.starts_with('/') {
        return Ok(fsname.to_string());
    }
    let fsc = CString::new(fsname.as_bytes())?;

    let mut page: Vec<u8> = vec![0; std::mem::size_of::<u8>() * PATH_BYTES];
    let ptr = page.as_mut_ptr() as *mut libc::c_char;

    let rc = unsafe { sys::llapi_search_rootpath(ptr, fsc.as_ptr()) };

    if rc != 0 {
        log::error!(
            "Error: llapi_search_rootpath({}) => {}",
            fsc.into_string()?,
            rc
        );
        return Err(LiblustreError::os_error(rc.abs()));
    }

    buf2string(page)
}

pub fn mdc_stat(path: &PathBuf) -> Result<sys::lstat_t, LiblustreError> {
    let file_name = path
        .file_name()
        .ok_or_else(|| LiblustreError::not_found(format!("File Not Found: {:?}", path)))?
        .to_str()
        .ok_or_else(|| LiblustreError::not_found(format!("No string for File: {:?}", path)))?;

    let file_namec = CString::new(file_name)?;

    let dirstr = path
        .parent()
        .ok_or_else(|| LiblustreError::not_found(format!("No Parent directory: {:?}", path)))?
        .to_str()
        .ok_or_else(|| LiblustreError::not_found(format!("No string for Parent: {:?}", path)))?;

    let dircstr = CString::new(dirstr)?;

    let page = Vec::with_capacity(PATH_BYTES);

    unsafe {
        libc::memcpy(
            page.as_ptr() as *mut libc::c_void,
            file_namec.as_ptr() as *const libc::c_void,
            file_namec.as_bytes_with_nul().len(),
        );
    }

    let dirhandle = unsafe { libc::opendir(dircstr.as_ptr() as *const i8) };

    if dirhandle.is_null() {
        let e = errno::errno();
        log::error!("Failed top opendir({:?}) -> {}", dircstr, e);
        return Err(LiblustreError::os_error(e.into()));
    }

    let fd = unsafe { libc::dirfd(dirhandle) };

    if fd < 0 {
        let e = errno::errno();
        log::error!("Failed dirfd({:?}) => {}", dirhandle, e);
        return Err(LiblustreError::os_error(e.into()));
    }

    let rc = unsafe {
        libc::ioctl(
            fd,
            sys::IOC_MDC_GETFILEINFO as u64,
            page.as_ptr() as *mut sys::lov_user_mds_data_v1,
        )
    };

    if rc < 0 {
        let e = errno::errno();
        log::error!("Failed ioctl({:?}) => {}", path, e);
        return Err(LiblustreError::os_error(e.into()));
    }

    let rc = unsafe { libc::closedir(dirhandle) };

    if rc < 0 {
        let e = errno::errno();
        log::error!("Failed closedir({:?}) => {}", dirhandle, e);
        return Err(LiblustreError::os_error(e.into()));
    }

    let statptr: *const sys::lstat_t = page.as_ptr();
    let stat: sys::lstat_t = unsafe { *statptr };

    Ok(stat)
}

pub fn rmfid(mntpt: &str, fidstr: &str) -> Result<(), LiblustreError> {
    use std::fs; // @TODO replace with sys::llapi_rmfid once LU-12090 lands

    let path = fid2path(mntpt, &fidstr)?;
    let pb: std::path::PathBuf = [mntpt, &path].iter().collect();
    if let Err(e) = fs::remove_file(pb) {
        log::error!("Failed to remove {}: {:?}", fidstr, e);
    }

    Ok(())
}

pub fn rmfids(
    mntpt: &str,
    fidlist: impl IntoIterator<Item = String>,
) -> Result<(), LiblustreError> {
    // @TODO replace with sys::llapi_rmfid once LU-12090 lands
    for fidstr in fidlist {
        rmfid(&mntpt, &fidstr).unwrap_or_else(|x| {
            log::error!(
                "Couldn't remove fid {} with mountpoint {}: {}.",
                fidstr,
                mntpt,
                x
            )
        });
    }

    Ok(())
}

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

    #[test]
    fn fid_display() {
        let fid = Fid {
            ver: 1,
            oid: 2,
            seq: 64,
        };
        assert_eq!("[0x40:0x2:0x1]", format!("{}", fid))
    }

    #[test]
    fn lu_fid2fid() {
        let fid = sys::lu_fid {
            f_ver: 1,
            f_oid: 4,
            f_seq: 64,
        };
        assert_eq!("[0x40:0x4:0x1]", format!("{}", Fid::from(fid)))
    }

    #[test]
    fn string2fid() {
        let fid = Fid {
            seq: 0x404,
            oid: 0x40,
            ver: 0x10,
        };
        assert_eq!(Ok(fid), Fid::from_str("[0x404:0x40:0x10]"))
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use libc::{c_int, c_void};
use std::mem;

#[repr(C)]
pub struct nl_sock;
#[repr(C)]
pub struct nl_cb;

#[link(name="nl-3")]
extern "C" {
	// Exposed socket functions
	fn nl_socket_alloc() -> *const nl_sock;
	fn nl_socket_free(socket: *const nl_sock);
	fn nl_socket_get_fd(socket: *const nl_sock) -> i32;
	fn nl_socket_set_buffer_size(socket: *const nl_sock, rxbuf: c_int, txbuf: c_int) -> i32;

	fn nl_socket_set_cb(socket: *const nl_sock, cb: *const nl_cb);
	fn nl_socket_get_cb(socket: *const nl_sock) -> nl_cb;

	fn nl_socket_set_local_port(socket: *const nl_sock, port: u32);
	fn nl_socket_get_local_port(socket: *const nl_sock) -> u32;

	fn nl_connect(socket: *const nl_sock, protocol: u32) -> i32;
	fn nl_close(socket: *const nl_sock);

	// Exposed socket transceivers
	fn nl_send_simple(socket: *const nl_sock, msg_type: c_int, flags: c_int, buf: *const c_void, size: c_int) -> i32;
    fn nl_sendto(socket: *const nl_sock, buf: *const c_void, size: c_int) -> i32;
    fn nl_send(socket: *const nl_sock, msg: *const ::message::nl_msg) -> i32;
    fn nl_send_auto(socket: *const nl_sock, msg: *const ::message::nl_msg) -> i32;
    fn nl_sendmsg(socket: *const nl_sock, msg: *const ::message::nl_msg, hdr: *const ::message::nlmsghdr) -> i32;
}

pub struct NetlinkSocket {
    pub ptr: *const nl_sock,
}

pub fn alloc() -> NetlinkSocket {
    NetlinkSocket {
        ptr: unsafe { nl_socket_alloc() },
    }
}

pub fn free(sock: NetlinkSocket) {
    unsafe { nl_socket_free(sock.ptr); }
}

pub fn set_buffer_size(sock: &mut NetlinkSocket, rxbuf: i32, txbuf: i32) -> i32 {
    unsafe { nl_socket_set_buffer_size(sock.ptr, rxbuf, txbuf) }
}

pub fn connect(sock: &mut NetlinkSocket, protocol: u32) -> i32 {
    unsafe { nl_connect(sock.ptr, protocol) }
}

pub fn close(sock: &mut NetlinkSocket) {
    unsafe{ nl_close(sock.ptr) }
}

pub fn get_local_port(sock: &NetlinkSocket) -> u32 {
    unsafe { nl_socket_get_local_port(sock.ptr) }
}

pub fn set_local_port(sock: &mut NetlinkSocket, port: u32) {
    unsafe { nl_socket_set_local_port(sock.ptr, port) }
}

pub fn get_fd(sock: &NetlinkSocket) -> i32 {
    unsafe { nl_socket_get_fd(sock.ptr) }
}

pub fn send_simple<T>(sock: &NetlinkSocket, msg_type: i32, flags: i32, buf: &T, size: i32) -> i32 {
    unsafe {
        let vptr: *const c_void = mem::transmute(buf);
        nl_send_simple(sock.ptr, msg_type, flags, vptr, size) as i32
    }
}

pub fn sendto<T>(sock: &NetlinkSocket, buf: &T, size: u32) -> i32 {
    unsafe {
        let vptr: *const c_void = mem::transmute(buf);
        nl_sendto(sock.ptr, vptr, size as c_int)
    }
}

pub fn send(sock: &NetlinkSocket, mut msg: ::message::NetlinkMessage) -> i32 {
    unsafe { nl_send(sock.ptr, ::message::expose::nl_msg_ptr(&mut msg)) }
}

pub fn send_auto(sock: &NetlinkSocket, mut msg: ::message::NetlinkMessage) -> i32 {
    unsafe { nl_send_auto(sock.ptr, ::message::expose::nl_msg_ptr(&mut msg)) }
}

pub fn sendmsg(sock: &NetlinkSocket, mut msg: ::message::NetlinkMessage) -> i32 {
    let hdr = match ::message::expose::nlmsghdr_ptr(&mut msg) {
        Some(hdr) => hdr,
        _ => return -22
    };

    unsafe { nl_sendmsg(sock.ptr, ::message::expose::nl_msg_ptr(&mut msg), hdr) }
}

pub mod expose {
    pub fn nl_sock_ptr(sock: &mut ::socket::NetlinkSocket) -> *const ::socket::nl_sock {
        sock.ptr
    }

}
<commit_msg>Change exposure function to normal borrow<commit_after>extern crate libc;

use libc::{c_int, c_void};
use std::mem;

#[repr(C)]
pub struct nl_sock;
#[repr(C)]
pub struct nl_cb;

#[link(name="nl-3")]
extern "C" {
	// Exposed socket functions
	fn nl_socket_alloc() -> *const nl_sock;
	fn nl_socket_free(socket: *const nl_sock);
	fn nl_socket_get_fd(socket: *const nl_sock) -> i32;
	fn nl_socket_set_buffer_size(socket: *const nl_sock, rxbuf: c_int, txbuf: c_int) -> i32;

	fn nl_socket_set_cb(socket: *const nl_sock, cb: *const nl_cb);
	fn nl_socket_get_cb(socket: *const nl_sock) -> nl_cb;

	fn nl_socket_set_local_port(socket: *const nl_sock, port: u32);
	fn nl_socket_get_local_port(socket: *const nl_sock) -> u32;

	fn nl_connect(socket: *const nl_sock, protocol: u32) -> i32;
	fn nl_close(socket: *const nl_sock);

	// Exposed socket transceivers
	fn nl_send_simple(socket: *const nl_sock, msg_type: c_int, flags: c_int, buf: *const c_void, size: c_int) -> i32;
    fn nl_sendto(socket: *const nl_sock, buf: *const c_void, size: c_int) -> i32;
    fn nl_send(socket: *const nl_sock, msg: *const ::message::nl_msg) -> i32;
    fn nl_send_auto(socket: *const nl_sock, msg: *const ::message::nl_msg) -> i32;
    fn nl_sendmsg(socket: *const nl_sock, msg: *const ::message::nl_msg, hdr: *const ::message::nlmsghdr) -> i32;
}

pub struct NetlinkSocket {
    pub ptr: *const nl_sock,
}

pub fn alloc() -> NetlinkSocket {
    NetlinkSocket {
        ptr: unsafe { nl_socket_alloc() },
    }
}

pub fn free(sock: NetlinkSocket) {
    unsafe { nl_socket_free(sock.ptr); }
}

pub fn set_buffer_size(sock: &mut NetlinkSocket, rxbuf: i32, txbuf: i32) -> i32 {
    unsafe { nl_socket_set_buffer_size(sock.ptr, rxbuf, txbuf) }
}

pub fn connect(sock: &mut NetlinkSocket, protocol: u32) -> i32 {
    unsafe { nl_connect(sock.ptr, protocol) }
}

pub fn close(sock: &mut NetlinkSocket) {
    unsafe{ nl_close(sock.ptr) }
}

pub fn get_local_port(sock: &NetlinkSocket) -> u32 {
    unsafe { nl_socket_get_local_port(sock.ptr) }
}

pub fn set_local_port(sock: &mut NetlinkSocket, port: u32) {
    unsafe { nl_socket_set_local_port(sock.ptr, port) }
}

pub fn get_fd(sock: &NetlinkSocket) -> i32 {
    unsafe { nl_socket_get_fd(sock.ptr) }
}

pub fn send_simple<T>(sock: &NetlinkSocket, msg_type: i32, flags: i32, buf: &T, size: i32) -> i32 {
    unsafe {
        let vptr: *const c_void = mem::transmute(buf);
        nl_send_simple(sock.ptr, msg_type, flags, vptr, size) as i32
    }
}

pub fn sendto<T>(sock: &NetlinkSocket, buf: &T, size: u32) -> i32 {
    unsafe {
        let vptr: *const c_void = mem::transmute(buf);
        nl_sendto(sock.ptr, vptr, size as c_int)
    }
}

pub fn send(sock: &NetlinkSocket, mut msg: ::message::NetlinkMessage) -> i32 {
    unsafe { nl_send(sock.ptr, ::message::expose::nl_msg_ptr(&mut msg)) }
}

pub fn send_auto(sock: &NetlinkSocket, mut msg: ::message::NetlinkMessage) -> i32 {
    unsafe { nl_send_auto(sock.ptr, ::message::expose::nl_msg_ptr(&mut msg)) }
}

pub fn sendmsg(sock: &NetlinkSocket, mut msg: ::message::NetlinkMessage) -> i32 {
    let hdr = match ::message::expose::nlmsghdr_ptr(&mut msg) {
        Some(hdr) => hdr,
        _ => return -22
    };

    unsafe { nl_sendmsg(sock.ptr, ::message::expose::nl_msg_ptr(&mut msg), hdr) }
}

pub fn recvmsg(sock: &NetlinkSocket, fptr: fn()->i32) -> i32 {
    4
}

pub mod expose {
    pub fn nl_sock_ptr(sock: &::socket::NetlinkSocket) -> *const ::socket::nl_sock {
        sock.ptr
    }

}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate serde_json;

use request;

pub use types::{Account, CreateAccountResponse};

impl Account {
    pub fn new(short_name: &str, author_name: &str, author_url: &str) -> Account {
        Account {
            short_name: short_name.to_string(),
            author_name: author_name.to_string(),
            author_url: author_url.to_string(),
            access_token: "".to_string(),
            auth_url: "".to_string(),
            page_count: 0,
        }
    }

    pub fn set_short_name(&mut self, short_name: &str) -> &mut Account {
        self.short_name = short_name.to_string();
        self
    }

    pub fn set_author_name(&mut self, author_name: &str) -> &mut Account {
        self.author_name = author_name.to_string();
        self
    }

    pub fn set_author_url(&mut self, author_url: &str) -> &mut Account {
        self.author_url = author_url.to_string();
        self
    }

    pub fn set_auth_url(&mut self, auth_url: &str) -> &mut Account {
        self.auth_url = auth_url.to_string();
        self
    }

    pub fn set_access_token(&mut self, access_token: &str) -> &mut Account {
        self.access_token = access_token.to_string();
        self
    }

    pub fn create_account(&mut self) -> Account {
        let req_url = format!(
            "https://api.telegra.ph/createAccount?short_name={}&author_name={}",
            self.short_name,
            self.author_name
        );
        let res_json = request::get(&req_url);

        let decoded: CreateAccountResponse = serde_json::from_str(&res_json).unwrap();

        println!("{:?}", decoded);

        self.set_access_token(&decoded.result.access_token)
            .set_auth_url(&decoded.result.auth_url);

        decoded.result
    }
}
<commit_msg>added edit_account_info method<commit_after>extern crate hyper;
extern crate serde_json;

use request;

pub use types::{Account, CreateAccountResponse};

impl Account {
    pub fn new(short_name: &str, author_name: &str, author_url: &str) -> Account {
        Account {
            short_name: short_name.to_string(),
            author_name: author_name.to_string(),
            author_url: author_url.to_string(),
            access_token: "".to_string(),
            auth_url: "".to_string(),
            page_count: 0,
        }
    }

    pub fn set_short_name(&mut self, short_name: &str) -> &mut Account {
        self.short_name = short_name.to_string();
        self
    }

    pub fn set_author_name(&mut self, author_name: &str) -> &mut Account {
        self.author_name = author_name.to_string();
        self
    }

    pub fn set_author_url(&mut self, author_url: &str) -> &mut Account {
        self.author_url = author_url.to_string();
        self
    }

    pub fn set_auth_url(&mut self, auth_url: &str) -> &mut Account {
        self.auth_url = auth_url.to_string();
        self
    }

    pub fn set_access_token(&mut self, access_token: &str) -> &mut Account {
        self.access_token = access_token.to_string();
        self
    }

    pub fn create_account(&mut self) -> String {
        let req_url = format!(
            "https://api.telegra.ph/createAccount?short_name={}&author_name={}",
            self.short_name,
            self.author_name
        );
        let res_json = request::get(&req_url);
        let decoded: CreateAccountResponse = serde_json::from_str(&res_json).unwrap();

        self.set_access_token(&decoded.result.access_token)
            .set_auth_url(&decoded.result.auth_url);

        res_json
    }

    pub fn edit_accout_info(&self, acc: Account) -> String {
        let url = String::from("https://api.telegra.ph/editAccountInfo?");
        let mut params: Vec<String> = vec![];

        let access_token = "access_token=".to_string() + &if acc.access_token.len() == 0 {
                self.access_token.clone()
            } else {
                acc.access_token
            };
        params.push(access_token);

        if acc.short_name.len() > 0 {
            let short_name = "short_name=".to_string() + &acc.short_name;
            params.push(short_name);
        }
        if acc.author_url.len() > 0 {
            let author_url = "author_url=".to_string() + &acc.author_url;
            params.push(author_url);
        }
        if acc.author_name.len() > 0 {
            let author_name = "author_name=".to_string() + &acc.author_name;
            params.push(author_name);
        }
        if acc.auth_url.len() > 0 {
            let auth_url = "auth_url=".to_string() + &acc.auth_url;
            params.push(auth_url);
        }

        let url = url + &params.join("&");

        request::get(&url)
    }

}
<|endoftext|>