<commit_before>// This module implements the central application object.
// Copyright (c) 2014 by Shipeng Feng.
// Licensed under the BSD License, see LICENSE for more details.

use std::collections::HashMap;
use std::error::Error;
use std::io::File;

use types::{
    PencilValue,
        PenResponse,

    PencilError,
        PenHTTPError,
        PenUserError,

    UserError,
    PencilResult,
    ViewFunc,
    HTTPErrorHandler,
    UserErrorHandler,
    BeforeRequestFunc,
    AfterRequestFunc,
    TeardownRequestFunc,
};
use wrappers::{
    Request,
    Response,
};
use helpers::PathBound;
use helpers;
use config;
use logging;
use serving::run_server;
use routing::{Map, Rule};
use testing::PencilClient;
use errors::{HTTPError, NotFound, InternalServerError};

/// The pencil type.  It acts as the central application object.  Once it is created it
/// will act as a central registry for the view functions, the URL rules and much more.
#[deriving(Clone)]
pub struct Pencil {
    pub root_path: String,
    pub static_folder: String,
    pub static_url_path: String,
    pub config: config::Config,
    pub url_map: Map,
    // A dictionary of all view functions registered.
    pub view_functions: HashMap<String, ViewFunc>,
    pub before_request_funcs: Vec<BeforeRequestFunc>,
    pub after_request_funcs: Vec<AfterRequestFunc>,
    pub teardown_request_funcs: Vec<TeardownRequestFunc>,
    pub http_error_handlers: HashMap<int, HTTPErrorHandler>,
    pub user_error_handlers: HashMap<&'static str, UserErrorHandler>,
}

impl Pencil {
    /// Create a new pencil object.  It is passed the root path of your application.
    /// The root path is used to resolve resources from inside it, for more information
    /// about resource loading, see method `open_resource`.
    ///
    /// Usually you create a pencil object in your main function like this:
    ///
    /// ```rust,no_run
    /// use pencil::Pencil;
    ///
    /// fn main() {
    ///     let mut app = Pencil::new("/web/myapp");
    /// }
    /// ```
    pub fn new(root_path: &str) -> Pencil {
        Pencil {
            root_path: root_path.to_string(),
            static_folder: String::from_str("static"),
            static_url_path: String::from_str("/static"),
            config: config::Config::new(),
            url_map: Map::new(),
            view_functions: HashMap::new(),
            before_request_funcs: vec![],
            after_request_funcs: vec![],
            teardown_request_funcs: vec![],
            http_error_handlers: HashMap::new(),
            user_error_handlers: HashMap::new(),
        }
    }

    /// Set global log level based on the application's debug flag.
    pub fn set_log_level(&self) {
        logging::set_log_level(self);
    }

    /// A shortcut that is used to register a view function for a given
    /// URL rule.
    pub fn route(&mut self, rule: &'static str, methods: &[&str], endpoint: &str, view_func: ViewFunc) {
        self.add_url_rule(rule, methods, endpoint, view_func);
    }

    /// Connects a URL rule.
    fn add_url_rule(&mut self, rule: &'static str, methods: &[&str], endpoint: &str, view_func: ViewFunc) {
        let url_rule = Rule::new(rule, methods, endpoint);
        self.url_map.add(url_rule);
        self.view_functions.insert(endpoint.to_string(), view_func);
    }

    /// Registers a function to run before each request.
    pub fn before_request(&mut self, f: BeforeRequestFunc) {
        self.before_request_funcs.push(f);
    }

    /// Registers a function to run after each request.  Your function
    /// must take a response object and modify it.
    pub fn after_request(&mut self, f: AfterRequestFunc) {
        self.after_request_funcs.push(f);
    }

    /// Registers a function to run at the end of each request,
    /// regardless of whether there was an error or not.
    pub fn teardown_request(&mut self, f: TeardownRequestFunc) {
        self.teardown_request_funcs.push(f);
    }

    /// Registers a function as one http error handler.
    fn register_http_error_handler(&mut self, status_code: int, f: HTTPErrorHandler) {
        self.http_error_handlers.insert(status_code, f);
    }

    /// Registers a function as one user error handler.
    fn register_user_error_handler(&mut self, error_desc: &'static str, f: UserErrorHandler) {
        self.user_error_handlers.insert(error_desc, f);
    }

    /// Registers a function as one http error handler.  Example:
    ///
    /// ```rust,no_run
    /// use pencil::{Pencil, PencilResult, Response, PenResponse};
    /// use pencil::HTTPError;
    ///
    ///
    /// fn page_not_found(error: HTTPError) -> PencilResult {
    ///     let mut response = Response::new(String::from_str("The page does not exist"));
    ///     response.status_code = 404;
    ///     return Ok(PenResponse(response));
    /// }
    ///
    ///
    /// fn main() {
    ///     let mut app = Pencil::new("/web/demo");
    ///     app.httperrorhandler(404, page_not_found);
    /// }
    /// ```
    pub fn httperrorhandler(&mut self, status_code: int, f: HTTPErrorHandler) {
        self.register_http_error_handler(status_code, f);
    }

    /// Registers a function as one user error handler.  There are two ways to handle
    /// user errors currently, you can do it in your own view like this:
    ///
    /// ```rust,no_run
    /// use pencil::Request;
    /// use pencil::{PencilResult, PenString};
    ///
    ///
    /// struct MyErr(int);
    ///
    ///
    /// fn some_operation() -> Result<int, MyErr> {
    ///     return Err(MyErr(10));
    /// }
    ///
    ///
    /// fn my_err_handler(_: MyErr) -> PencilResult {
    ///     Ok(PenString(String::from_str("My err occurred!")))
    /// }
    ///
    ///
    /// fn hello(_: Request) -> PencilResult {
    ///     match some_operation() {
    ///         Ok(_) => Ok(PenString(String::from_str("Hello!"))),
    ///         Err(e) => my_err_handler(e),
    ///     }
    /// }
    /// ```
    ///
    /// The problem with this is that you have to do it in all of your views, it brings
    /// a lot of redundance, so pencil provides another solution, currently I still
    /// haven't got any better idea on how to store user error handlers, this feature is
    /// really just experimental, if you have any good idea, please wake me up.  Here is
    /// one simple example:
    ///
    /// ```rust,no_run
    /// use std::error::FromError;
    ///
    /// use pencil::Request;
    /// use pencil::{Pencil, PencilResult, PenString};
    /// use pencil::{PencilError, PenUserError, UserError};
    ///
    ///
    /// #[deriving(Copy)]
    /// pub struct MyErr(int);
    ///
    /// impl FromError<MyErr> for PencilError {
    ///     fn from_error(err: MyErr) -> PencilError {
    ///         let user_error = UserError::new("MyErr", None);
    ///         return PenUserError(user_error);
    ///     }
    /// }
    ///
    ///
    /// fn my_err_handler(_: UserError) -> PencilResult {
    ///     Ok(PenString(String::from_str("My err occurred!")))
    /// }
    ///
    ///
    /// fn some_operation() -> Result<String, MyErr> {
    ///     return Err(MyErr(10));
    /// }
    ///
    ///
    /// fn hello(_: Request) -> PencilResult {
    ///     let rv = try!(some_operation());
    ///     return Ok(PenString(rv));
    /// }
    ///
    ///
    /// fn main() {
    ///     let mut app = Pencil::new("/web/demo");
    ///     // Use error description as key to store handlers, really ugly...
    ///     app.usererrorhandler("MyErr", my_err_handler);
    /// }
    /// ```
    pub fn usererrorhandler(&mut self, error_desc: &'static str, f: UserErrorHandler) {
        self.register_user_error_handler(error_desc, f);
    }

    /// Creates a test client for this application, you can use it
    /// like this:
    ///
    /// ```ignore
    /// let client = app.test_client();
    /// let response = client.get('/');
    /// assert!(response.code, 200);
    /// ```
    pub fn test_client(&self) -> PencilClient {
        PencilClient::new(self)
    }

    /// Called before the actual request dispatching, you can return value
    /// from here and stop the further request handling.
    fn preprocess_request(&self, request: &Request) -> Option<PencilResult> {
        let mut result: Option<PencilResult>;
        for &func in self.before_request_funcs.iter() {
            result = func(request);
            if result.is_some() {
                return result;
            }
        }
        return None;
    }

    /// Does the request dispatching.  Matches the URL and returns the return
    /// value of the view.
    fn dispatch_request(&self, request: Request) -> PencilResult {
        if request.routing_error.is_some() {
            return Err(PenHTTPError(request.routing_error.unwrap()));
        }
        match self.view_functions.get(&request.endpoint().unwrap()) {
            Some(&view_func) => {
                return view_func(request);
            },
            None => {
                return Err(PenHTTPError(NotFound));
            }
        }
    }

    /// Converts the return value from a view function to a real
    /// response object.
    fn make_response(&self, rv: PencilValue) -> Response {
        return helpers::make_response(rv);
    }

    /// Modify the response object before it's sent to the HTTP server.
    fn process_response(&self, response: &mut Response) {
        // TODO: reverse order
        for &func in self.after_request_funcs.iter() {
            func(response);
        }
    }

    /// Called after the actual request dispatching.
    fn do_teardown_request(&self, e: Option<&PencilError>) {
        // TODO: reverse order
        for &func in self.teardown_request_funcs.iter() {
            func(e);
        }
    }

    /// This method is called whenever an error occurs that should be handled.
    fn handle_all_error(&self, e: PencilError) -> PencilResult {
        match e {
            PenHTTPError(e) => self.handle_http_error(e),
            PenUserError(e) => self.handle_user_error(e),
        }
    }

    /// Handles an User error.
    fn handle_user_error(&self, e: UserError) -> PencilResult {
        match self.user_error_handlers.get(e.description()) {
            Some(&handler) => handler(e),
            None => Err(PenUserError(e)),
        }
    }

    /// Handles an HTTP error.
    fn handle_http_error(&self, e: HTTPError) -> PencilResult {
        match self.http_error_handlers.get(&e.code()) {
            Some(&handler) => handler(e),
            None => Ok(PenResponse(e.to_response())),
        }
    }

    /// Default error handing that kicks in when an error occurs that is not
    /// handled.
    fn handle_error(&self, e: &PencilError) -> PencilValue {
        self.log_error(e);
        let internal_server_error = InternalServerError;
        match self.http_error_handlers.get(&500) {
            Some(&handler) => {
                match handler(internal_server_error) {
                    Ok(value) => value,
                    Err(_) => {
                        let e = InternalServerError;
                        PenResponse(e.to_response())
                    }
                }
            },
            None => {
                let e = InternalServerError;
                PenResponse(e.to_response())
            }
        }
    }

    /// Logs an error.
    fn log_error(&self, e: &PencilError) {
        println!("{}", e.description());
    }

    /// Dispatches the request and performs request pre and postprocessing
    /// as well as HTTP error handling.
    fn full_dispatch_request(&self, request: Request) -> Result<Response, PencilError> {
        let result = match self.preprocess_request(&request) {
            Some(result) => result,
            None => self.dispatch_request(request),
        };
        let rv = match result {
            Ok(value) => Ok(value),
            Err(e) => self.handle_all_error(e),
        };
        match rv {
            Ok(value) => {
                let mut response = self.make_response(value);
                self.process_response(&mut response);
                Ok(response)
            },
            Err(e) => Err(e),
        }
    }

    /// The actual application handler.
    pub fn handle_request(&self, request: Request) -> Response {
        // let url_adapter = self.create_url_adapter(request);
        // request.url_rule, request.view_args = url_adapter.match()
        // or
        // request.routing_error = e
        match self.full_dispatch_request(request) {
            Ok(response) => {
                self.do_teardown_request(None);
                return response;
            },
            Err(e) => {
                let response = self.make_response(self.handle_error(&e));
                self.do_teardown_request(Some(&e));
                return response;
            }
        };
    }

    /// Runs the application on a local development server.
    pub fn run(self) {
        run_server(self);
    }
}

impl PathBound for Pencil {
    fn open_resource(&self, resource: &str) -> File {
        let mut path = Path::new(self.root_path.as_slice());
        path.push(resource);
        return File::open(&path).unwrap();
    }
}
<commit_msg>Use match_request<commit_after>// This module implements the central application object.
// Copyright (c) 2014 by Shipeng Feng.
// Licensed under the BSD License, see LICENSE for more details.

use std::collections::HashMap;
use std::error::Error;
use std::io::File;

use types::{
    PencilValue,
        PenResponse,

    PencilError,
        PenHTTPError,
        PenUserError,

    UserError,
    PencilResult,
    ViewFunc,
    HTTPErrorHandler,
    UserErrorHandler,
    BeforeRequestFunc,
    AfterRequestFunc,
    TeardownRequestFunc,
};
use wrappers::{
    Request,
    Response,
};
use helpers::PathBound;
use helpers;
use config;
use logging;
use serving::run_server;
use routing::{Map, Rule};
use testing::PencilClient;
use errors::{HTTPError, NotFound, InternalServerError};

/// The pencil type.  It acts as the central application object.  Once it is created it
/// will act as a central registry for the view functions, the URL rules and much more.
#[deriving(Clone)]
pub struct Pencil {
    pub root_path: String,
    pub static_folder: String,
    pub static_url_path: String,
    pub config: config::Config,
    pub url_map: Map,
    // A dictionary of all view functions registered.
    pub view_functions: HashMap<String, ViewFunc>,
    pub before_request_funcs: Vec<BeforeRequestFunc>,
    pub after_request_funcs: Vec<AfterRequestFunc>,
    pub teardown_request_funcs: Vec<TeardownRequestFunc>,
    pub http_error_handlers: HashMap<int, HTTPErrorHandler>,
    pub user_error_handlers: HashMap<&'static str, UserErrorHandler>,
}

impl Pencil {
    /// Create a new pencil object.  It is passed the root path of your application.
    /// The root path is used to resolve resources from inside it, for more information
    /// about resource loading, see method `open_resource`.
    ///
    /// Usually you create a pencil object in your main function like this:
    ///
    /// ```rust,no_run
    /// use pencil::Pencil;
    ///
    /// fn main() {
    ///     let mut app = Pencil::new("/web/myapp");
    /// }
    /// ```
    pub fn new(root_path: &str) -> Pencil {
        Pencil {
            root_path: root_path.to_string(),
            static_folder: String::from_str("static"),
            static_url_path: String::from_str("/static"),
            config: config::Config::new(),
            url_map: Map::new(),
            view_functions: HashMap::new(),
            before_request_funcs: vec![],
            after_request_funcs: vec![],
            teardown_request_funcs: vec![],
            http_error_handlers: HashMap::new(),
            user_error_handlers: HashMap::new(),
        }
    }

    /// Set global log level based on the application's debug flag.
    pub fn set_log_level(&self) {
        logging::set_log_level(self);
    }

    /// A shortcut that is used to register a view function for a given
    /// URL rule.
    pub fn route(&mut self, rule: &'static str, methods: &[&str], endpoint: &str, view_func: ViewFunc) {
        self.add_url_rule(rule, methods, endpoint, view_func);
    }

    /// Connects a URL rule.
    fn add_url_rule(&mut self, rule: &'static str, methods: &[&str], endpoint: &str, view_func: ViewFunc) {
        let url_rule = Rule::new(rule, methods, endpoint);
        self.url_map.add(url_rule);
        self.view_functions.insert(endpoint.to_string(), view_func);
    }

    /// Registers a function to run before each request.
    pub fn before_request(&mut self, f: BeforeRequestFunc) {
        self.before_request_funcs.push(f);
    }

    /// Registers a function to run after each request.  Your function
    /// must take a response object and modify it.
    pub fn after_request(&mut self, f: AfterRequestFunc) {
        self.after_request_funcs.push(f);
    }

    /// Registers a function to run at the end of each request,
    /// regardless of whether there was an error or not.
    pub fn teardown_request(&mut self, f: TeardownRequestFunc) {
        self.teardown_request_funcs.push(f);
    }

    /// Registers a function as one http error handler.
    fn register_http_error_handler(&mut self, status_code: int, f: HTTPErrorHandler) {
        self.http_error_handlers.insert(status_code, f);
    }

    /// Registers a function as one user error handler.
    fn register_user_error_handler(&mut self, error_desc: &'static str, f: UserErrorHandler) {
        self.user_error_handlers.insert(error_desc, f);
    }

    /// Registers a function as one http error handler.  Example:
    ///
    /// ```rust,no_run
    /// use pencil::{Pencil, PencilResult, Response, PenResponse};
    /// use pencil::HTTPError;
    ///
    ///
    /// fn page_not_found(error: HTTPError) -> PencilResult {
    ///     let mut response = Response::new(String::from_str("The page does not exist"));
    ///     response.status_code = 404;
    ///     return Ok(PenResponse(response));
    /// }
    ///
    ///
    /// fn main() {
    ///     let mut app = Pencil::new("/web/demo");
    ///     app.httperrorhandler(404, page_not_found);
    /// }
    /// ```
    pub fn httperrorhandler(&mut self, status_code: int, f: HTTPErrorHandler) {
        self.register_http_error_handler(status_code, f);
    }

    /// Registers a function as one user error handler.  There are two ways to handle
    /// user errors currently, you can do it in your own view like this:
    ///
    /// ```rust,no_run
    /// use pencil::Request;
    /// use pencil::{PencilResult, PenString};
    ///
    ///
    /// struct MyErr(int);
    ///
    ///
    /// fn some_operation() -> Result<int, MyErr> {
    ///     return Err(MyErr(10));
    /// }
    ///
    ///
    /// fn my_err_handler(_: MyErr) -> PencilResult {
    ///     Ok(PenString(String::from_str("My err occurred!")))
    /// }
    ///
    ///
    /// fn hello(_: Request) -> PencilResult {
    ///     match some_operation() {
    ///         Ok(_) => Ok(PenString(String::from_str("Hello!"))),
    ///         Err(e) => my_err_handler(e),
    ///     }
    /// }
    /// ```
    ///
    /// The problem with this is that you have to do it in all of your views, it brings
    /// a lot of redundance, so pencil provides another solution, currently I still
    /// haven't got any better idea on how to store user error handlers, this feature is
    /// really just experimental, if you have any good idea, please wake me up.  Here is
    /// one simple example:
    ///
    /// ```rust,no_run
    /// use std::error::FromError;
    ///
    /// use pencil::Request;
    /// use pencil::{Pencil, PencilResult, PenString};
    /// use pencil::{PencilError, PenUserError, UserError};
    ///
    ///
    /// #[deriving(Copy)]
    /// pub struct MyErr(int);
    ///
    /// impl FromError<MyErr> for PencilError {
    ///     fn from_error(err: MyErr) -> PencilError {
    ///         let user_error = UserError::new("MyErr", None);
    ///         return PenUserError(user_error);
    ///     }
    /// }
    ///
    ///
    /// fn my_err_handler(_: UserError) -> PencilResult {
    ///     Ok(PenString(String::from_str("My err occurred!")))
    /// }
    ///
    ///
    /// fn some_operation() -> Result<String, MyErr> {
    ///     return Err(MyErr(10));
    /// }
    ///
    ///
    /// fn hello(_: Request) -> PencilResult {
    ///     let rv = try!(some_operation());
    ///     return Ok(PenString(rv));
    /// }
    ///
    ///
    /// fn main() {
    ///     let mut app = Pencil::new("/web/demo");
    ///     // Use error description as key to store handlers, really ugly...
    ///     app.usererrorhandler("MyErr", my_err_handler);
    /// }
    /// ```
    pub fn usererrorhandler(&mut self, error_desc: &'static str, f: UserErrorHandler) {
        self.register_user_error_handler(error_desc, f);
    }

    /// Creates a test client for this application, you can use it
    /// like this:
    ///
    /// ```ignore
    /// let client = app.test_client();
    /// let response = client.get('/');
    /// assert!(response.code, 200);
    /// ```
    pub fn test_client(&self) -> PencilClient {
        PencilClient::new(self)
    }

    /// Called before the actual request dispatching, you can return value
    /// from here and stop the further request handling.
    fn preprocess_request(&self, request: &Request) -> Option<PencilResult> {
        let mut result: Option<PencilResult>;
        for &func in self.before_request_funcs.iter() {
            result = func(request);
            if result.is_some() {
                return result;
            }
        }
        return None;
    }

    /// Does the request dispatching.  Matches the URL and returns the return
    /// value of the view.
    fn dispatch_request(&self, request: Request) -> PencilResult {
        if request.routing_error.is_some() {
            return Err(PenHTTPError(request.routing_error.unwrap()));
        }
        match self.view_functions.get(&request.endpoint().unwrap()) {
            Some(&view_func) => {
                return view_func(request);
            },
            None => {
                return Err(PenHTTPError(NotFound));
            }
        }
    }

    /// Converts the return value from a view function to a real
    /// response object.
    fn make_response(&self, rv: PencilValue) -> Response {
        return helpers::make_response(rv);
    }

    /// Modify the response object before it's sent to the HTTP server.
    fn process_response(&self, response: &mut Response) {
        // TODO: reverse order
        for &func in self.after_request_funcs.iter() {
            func(response);
        }
    }

    /// Called after the actual request dispatching.
    fn do_teardown_request(&self, e: Option<&PencilError>) {
        // TODO: reverse order
        for &func in self.teardown_request_funcs.iter() {
            func(e);
        }
    }

    /// This method is called whenever an error occurs that should be handled.
    fn handle_all_error(&self, e: PencilError) -> PencilResult {
        match e {
            PenHTTPError(e) => self.handle_http_error(e),
            PenUserError(e) => self.handle_user_error(e),
        }
    }

    /// Handles an User error.
    fn handle_user_error(&self, e: UserError) -> PencilResult {
        match self.user_error_handlers.get(e.description()) {
            Some(&handler) => handler(e),
            None => Err(PenUserError(e)),
        }
    }

    /// Handles an HTTP error.
    fn handle_http_error(&self, e: HTTPError) -> PencilResult {
        match self.http_error_handlers.get(&e.code()) {
            Some(&handler) => handler(e),
            None => Ok(PenResponse(e.to_response())),
        }
    }

    /// Default error handing that kicks in when an error occurs that is not
    /// handled.
    fn handle_error(&self, e: &PencilError) -> PencilValue {
        self.log_error(e);
        let internal_server_error = InternalServerError;
        match self.http_error_handlers.get(&500) {
            Some(&handler) => {
                match handler(internal_server_error) {
                    Ok(value) => value,
                    Err(_) => {
                        let e = InternalServerError;
                        PenResponse(e.to_response())
                    }
                }
            },
            None => {
                let e = InternalServerError;
                PenResponse(e.to_response())
            }
        }
    }

    /// Logs an error.
    fn log_error(&self, e: &PencilError) {
        println!("{}", e.description());
    }

    /// Dispatches the request and performs request pre and postprocessing
    /// as well as HTTP error handling.
    fn full_dispatch_request(&self, request: Request) -> Result<Response, PencilError> {
        let result = match self.preprocess_request(&request) {
            Some(result) => result,
            None => self.dispatch_request(request),
        };
        let rv = match result {
            Ok(value) => Ok(value),
            Err(e) => self.handle_all_error(e),
        };
        match rv {
            Ok(value) => {
                let mut response = self.make_response(value);
                self.process_response(&mut response);
                Ok(response)
            },
            Err(e) => Err(e),
        }
    }

    /// The actual application handler.
    pub fn handle_request(&self, mut request: Request) -> Response {
        request.match_request();
        match self.full_dispatch_request(request) {
            Ok(response) => {
                self.do_teardown_request(None);
                return response;
            },
            Err(e) => {
                let response = self.make_response(self.handle_error(&e));
                self.do_teardown_request(Some(&e));
                return response;
            }
        };
    }

    /// Runs the application on a local development server.
    pub fn run(self) {
        run_server(self);
    }
}

impl PathBound for Pencil {
    fn open_resource(&self, resource: &str) -> File {
        let mut path = Path::new(self.root_path.as_slice());
        path.push(resource);
        return File::open(&path).unwrap();
    }
}
<|endoftext|>


<commit_before>use object_id::ObjectId;
use tag::Tag;
use branch::Branch;
use reference::Reference;
use pack_index::PackIndex;

pub struct Repository {
    pub path: String,
    pub wc_path: String,
    pub tags: Vec<Tag>,
    pub branches: Vec<Branch>,
    pub references: Vec<Reference>,
    pub pack_indexes: Vec<PackIndex>,
}<commit_msg>Implement a simple constructor for Repository<commit_after>use object_id::ObjectId;
use tag::Tag;
use branch::Branch;
use reference::Reference;
use pack_index::PackIndex;

pub struct Repository {
    pub path: String,
    pub wc_path: String,
    pub tags: Vec<Tag>,
    pub branches: Vec<Branch>,
    pub references: Vec<Reference>,
    pub pack_indexes: Vec<PackIndex>,
}

impl Repository {
    pub fn new(path: &str) -> Repository {
        Repository {
            path: path.to_string() + ".git/",
            wc_path: path.to_string(),
            tags: Vec::new(),
            branches: Vec::new(),
            references: Vec::new(),
            pack_indexes: Vec::new(),
        }
    }
}<|endoftext|>


<commit_before>use std::ptr::null_mut;
use std::os::unix::io::RawFd;
use libc::c_int;
use {Errno, Result};
use sys::time::TimeVal;

pub const FD_SETSIZE: RawFd = 1024;

#[cfg(any(target_os = "macos", target_os = "ios"))]
#[repr(C)]
pub struct FdSet {
    bits: [i32; FD_SETSIZE as usize / 32]
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
const BITS: usize = 32;

#[cfg(not(any(target_os = "macos", target_os = "ios")))]
#[repr(C)]
#[derive(Clone)]
pub struct FdSet {
    bits: [u64; FD_SETSIZE as usize / 64]
}

#[cfg(not(any(target_os = "macos", target_os = "ios")))]
const BITS: usize = 64;

impl FdSet {
    pub fn new() -> FdSet {
        FdSet {
            bits: [0; FD_SETSIZE as usize / BITS]
        }
    }

    pub fn insert(&mut self, fd: RawFd) {
        let fd = fd as usize;
        self.bits[fd / BITS] |= 1 << (fd % BITS);
    }

    pub fn remove(&mut self, fd: RawFd) {
        let fd = fd as usize;
        self.bits[fd / BITS] &= !(1 << (fd % BITS));
    }

    pub fn contains(&mut self, fd: RawFd) -> bool {
        let fd = fd as usize;
        self.bits[fd / BITS] & (1 << (fd % BITS)) > 0
    }

    pub fn clear(&mut self) {
        for bits in &mut self.bits {
            *bits = 0
        }
    }
}

mod ffi {
    use libc::c_int;
    use sys::time::TimeVal;
    use super::FdSet;

    extern {
        pub fn select(nfds: c_int,
                      readfds: *mut FdSet,
                      writefds: *mut FdSet,
                      errorfds: *mut FdSet,
                      timeout: *mut TimeVal) -> c_int;
    }
}

pub fn select(nfds: c_int,
              readfds: Option<&mut FdSet>,
              writefds: Option<&mut FdSet>,
              errorfds: Option<&mut FdSet>,
              timeout: Option<&mut TimeVal>) -> Result<c_int> {
    let readfds = readfds.map(|set| set as *mut FdSet).unwrap_or(null_mut());
    let writefds = writefds.map(|set| set as *mut FdSet).unwrap_or(null_mut());
    let errorfds = errorfds.map(|set| set as *mut FdSet).unwrap_or(null_mut());
    let timeout = timeout.map(|tv| tv as *mut TimeVal).unwrap_or(null_mut());

    let res = unsafe {
        ffi::select(nfds, readfds, writefds, errorfds, timeout)
    };

    Errno::result(res)
}
<commit_msg>Implement `Clone` for `FdSet` on Mac/iOS<commit_after>use std::ptr::null_mut;
use std::os::unix::io::RawFd;
use libc::c_int;
use {Errno, Result};
use sys::time::TimeVal;

pub const FD_SETSIZE: RawFd = 1024;

#[cfg(any(target_os = "macos", target_os = "ios"))]
#[repr(C)]
#[derive(Clone)]
pub struct FdSet {
    bits: [i32; FD_SETSIZE as usize / 32]
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
const BITS: usize = 32;

#[cfg(not(any(target_os = "macos", target_os = "ios")))]
#[repr(C)]
#[derive(Clone)]
pub struct FdSet {
    bits: [u64; FD_SETSIZE as usize / 64]
}

#[cfg(not(any(target_os = "macos", target_os = "ios")))]
const BITS: usize = 64;

impl FdSet {
    pub fn new() -> FdSet {
        FdSet {
            bits: [0; FD_SETSIZE as usize / BITS]
        }
    }

    pub fn insert(&mut self, fd: RawFd) {
        let fd = fd as usize;
        self.bits[fd / BITS] |= 1 << (fd % BITS);
    }

    pub fn remove(&mut self, fd: RawFd) {
        let fd = fd as usize;
        self.bits[fd / BITS] &= !(1 << (fd % BITS));
    }

    pub fn contains(&mut self, fd: RawFd) -> bool {
        let fd = fd as usize;
        self.bits[fd / BITS] & (1 << (fd % BITS)) > 0
    }

    pub fn clear(&mut self) {
        for bits in &mut self.bits {
            *bits = 0
        }
    }
}

mod ffi {
    use libc::c_int;
    use sys::time::TimeVal;
    use super::FdSet;

    extern {
        pub fn select(nfds: c_int,
                      readfds: *mut FdSet,
                      writefds: *mut FdSet,
                      errorfds: *mut FdSet,
                      timeout: *mut TimeVal) -> c_int;
    }
}

pub fn select(nfds: c_int,
              readfds: Option<&mut FdSet>,
              writefds: Option<&mut FdSet>,
              errorfds: Option<&mut FdSet>,
              timeout: Option<&mut TimeVal>) -> Result<c_int> {
    let readfds = readfds.map(|set| set as *mut FdSet).unwrap_or(null_mut());
    let writefds = writefds.map(|set| set as *mut FdSet).unwrap_or(null_mut());
    let errorfds = errorfds.map(|set| set as *mut FdSet).unwrap_or(null_mut());
    let timeout = timeout.map(|tv| tv as *mut TimeVal).unwrap_or(null_mut());

    let res = unsafe {
        ffi::select(nfds, readfds, writefds, errorfds, timeout)
    };

    Errno::result(res)
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#![crate_name = "linux_thread"]
#![crate_type = "lib"]
#![feature(plugin, no_std, optin_builtin_traits)]
#![plugin(linux_core_plugin)]
#![no_std]

#[macro_use]
extern crate linux_core as core;
extern crate linux_base as base;
extern crate linux_libc as libc;
extern crate linux_syscall as syscall;
extern crate linux_cty as cty;
extern crate linux_lock as lock;

#[prelude_import] use base::prelude::*;
use core::marker::{Leak};
use core::ops::{Drop};
use core::{mem, ptr, intrinsics};
use cty::{c_int};
use libc::{pthread_t, pthread_attr_t, PTHREAD_CREATE_DETACHED};
use lock::{LockGuard, LOCK_INIT};

mod linux { pub use base::linux::*; pub use cty; }

/// Terminates the current thread.
///
/// This is unsafe because other threads might be referencing our stack.
pub unsafe fn exit(code: c_int) -> ! {
    syscall::exit(code)
}

/// Spawns a new thread starting at the closure.
pub fn spawn<F>(f: F) -> Result
    where F: FnOnce() + Send + 'static
{
    Builder::new().chain(|b| b.spawn(f))
}

/// Spawns a new scoped thread starting at the closure.
///
/// The thread will automatically be joined when the guard's destructor runs.
pub fn scoped<'a, F>(f: F) -> Result<JoinGuard<'a>>
    where F: FnOnce() + Send + 'a
{
    Builder::new().chain(|b| b.scoped(f))
}

/// A join-guard
///
/// Note that this is `!Leak` because it allows other threads to reference objects on our
/// stack and those threads have to be joined before the end of the objects' lifetimes.
pub struct JoinGuard<'a> {
    thread: pthread_t,
    _marker: PhantomData<&'a ()>,
}

impl<'a> Drop for JoinGuard<'a> {
    fn drop(&mut self) {
        unsafe { libc::pthread_join(self.thread, 0 as *mut _); }
    }
}

impl<'a> !Leak for JoinGuard<'a> { }

/// A thread-builder
///
/// This can be used to modify properties of the thread before spawning it.
pub struct Builder {
    attr: pthread_attr_t,
}

impl Builder {
    /// Creates a new thread-builder.
    pub fn new() -> Result<Builder> {
        unsafe {
            let mut attr = mem::zeroed();
            try!(rv!(-libc::pthread_attr_init(&mut attr)));
            Ok(Builder { attr: attr })
        }
    }

    /// Sets the size of the guard page at the end of the thread's stack.
    pub fn set_guard_size(&mut self, size: usize) -> Result {
        unsafe { rv!(-libc::pthread_attr_setguardsize(&mut self.attr, size)) }
    }

    /// Like `set_guard_size`.
    pub fn guard_size(&mut self) -> Result<usize> {
        unsafe {
            let mut size = 0;
            try!(rv!(-libc::pthread_attr_getguardsize(&self.attr, &mut size)));
            Ok(size)
        }
    }

    /// Sets the size of the thread's stack.
    pub fn set_stack_size(&mut self, size: usize) -> Result {
        unsafe { rv!(-libc::pthread_attr_setstacksize(&mut self.attr, size)) }
    }

    /// Like `set_stack_size`.
    pub fn stack_size(&mut self) -> Result<usize> {
        unsafe {
            let mut size = 0;
            try!(rv!(-libc::pthread_attr_getstacksize(&mut self.attr, &mut size)));
            Ok(size)
        }
    }

    /// See the documentation of the top-level function.
    pub fn spawn<F>(mut self, f: F) -> Result
        where F: FnOnce() + Send + 'static
    {
        unsafe {
            try!(rv!(-libc::pthread_attr_setdetachstate(&mut self.attr,
                                                        PTHREAD_CREATE_DETACHED)));
            let res = self.spawn_inner(&f).ignore_ok();
            // The other thread now has ownership of `f` if we succeeded. The API
            // currently doesn't return `f` in the failure case.
            intrinsics::forget(f);
            res
        }
    }

    /// See the documentation of the top-level function.
    pub fn scoped<'a, F>(self, f: F) -> Result<JoinGuard<'a>>
        where F: FnOnce() + Send + 'a
    {
        unsafe {
            let res = self.spawn_inner(&f);
            intrinsics::forget(f);
            res.map(|thread| JoinGuard { thread: thread, _marker: PhantomData })
        }
    }

    unsafe fn spawn_inner<F>(self, f: &F) -> Result<pthread_t>
        where F: FnOnce() + Send,
    {
        // We use the following method to get `f` onto the other thread's stack without an
        // allocation:
        //
        // - Create a lock in the shared address space and lock it.
        // - Pass a reference to the lock-guard and `f` to the other thread.
        // - Try to lock the lock again.
        // - The other thread copies everything onto its stack and then drops the lock
        //   guard.
        // - Once it drops the lock guard our lock succeeds and we know that the other
        //   thread now has its own copy of `f`.
        // - We forget our original lock guard because it has already been dropped in the
        //   other thread and forget `f` because the other thread now owns it.

        let mut thread = mem::zeroed();
        let lock = LOCK_INIT;
        let guard = lock.lock();

        // Avoid moving f around. If we move it into the structure then the compiler
        // definitely has to copy it instead of leaving it in the user's stack and only
        // passing references to our functions. This has been observed to avoid at least
        // one copy.

        let mut payload = Payload { guard: guard, f: f };
        let start_fn: unsafe extern fn(*mut u8) -> *mut u8 = mem::cast(start::<F>);
        let rv = libc::pthread_create(&mut thread, &self.attr, start_fn,
                                      &mut payload as *mut _ as *mut _);
        try!(rv!(-rv));
        lock.lock();
        mem::forget(payload.guard);
        Ok(thread)
    }
}

/// Payload to be passed to another thread.
struct Payload<'a, F>
    where F: FnOnce() + Send,
{
    guard: LockGuard<'a>,
    f: *const F,
}

/// The function that will be called by libc. The function takes ownership of the payload
/// and the `f`.
unsafe extern fn start<'a, F>(data: *mut Payload<'a, F>) -> *mut u8
    where F: FnOnce() + Send,
{
    let Payload { guard, f } = ptr::read(data);
    let f = ptr::read(f);
    drop(guard);
    f();
    0 as *mut u8
}
<commit_msg>autocommit 2015-04-24 22:04:11 CEST<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#![crate_name = "linux_thread"]
#![crate_type = "lib"]
#![feature(plugin, no_std, optin_builtin_traits)]
#![plugin(linux_core_plugin)]
#![no_std]

#[macro_use]
extern crate linux_core as core;
extern crate linux_base as base;
extern crate linux_libc as libc;
extern crate linux_syscall as syscall;
extern crate linux_cty as cty;
extern crate linux_lock as lock;

#[prelude_import] use base::prelude::*;
use core::marker::{Leak};
use core::ops::{Drop};
use core::{mem, ptr, intrinsics};
use cty::{c_int};
use libc::{pthread_t, pthread_attr_t, PTHREAD_CREATE_DETACHED};
use lock::{LockGuard, LOCK_INIT};

mod linux { pub use base::linux::*; pub use cty; }

/// Terminates the current thread.
///
/// This is unsafe because other threads might be referencing our stack.
pub unsafe fn exit(code: c_int) -> ! {
    syscall::exit(code)
}

/// Spawns a new thread starting at the closure.
pub fn spawn<F>(f: F) -> Result
    where F: FnOnce() + Send + 'static
{
    Builder::new().chain(|b| b.spawn(f))
}

/// Spawns a new scoped thread starting at the closure.
///
/// The thread will automatically be joined when the guard's destructor runs.
pub fn scoped<'a, F>(f: F) -> Result<JoinGuard<'a>>
    where F: FnOnce() + Send + 'a
{
    Builder::new().chain(|b| b.scoped(f))
}

/// A join-guard
///
/// Note that this is `!Leak` because it allows other threads to reference objects on our
/// stack and those threads have to be joined before the end of the objects' lifetimes.
pub struct JoinGuard<'a> {
    thread: pthread_t,
    _marker: PhantomData<&'a ()>,
}

impl<'a> Drop for JoinGuard<'a> {
    fn drop(&mut self) {
        unsafe { libc::pthread_join(self.thread, 0 as *mut _); }
    }
}

impl<'a> !Leak for JoinGuard<'a> { }

/// A thread-builder
///
/// This can be used to modify properties of the thread before spawning it.
pub struct Builder {
    attr: pthread_attr_t,
}

impl Builder {
    /// Creates a new thread-builder.
    pub fn new() -> Result<Builder> {
        unsafe {
            let mut attr = mem::zeroed();
            try!(rv!(-libc::pthread_attr_init(&mut attr)));
            Ok(Builder { attr: attr })
        }
    }

    /// Sets the size of the guard page at the end of the thread's stack.
    pub fn set_guard_size(&mut self, size: usize) -> Result {
        unsafe { rv!(-libc::pthread_attr_setguardsize(&mut self.attr, size)) }
    }

    /// Like `set_guard_size`.
    pub fn guard_size(&mut self) -> Result<usize> {
        unsafe {
            let mut size = 0;
            try!(rv!(-libc::pthread_attr_getguardsize(&self.attr, &mut size)));
            Ok(size)
        }
    }

    /// Sets the size of the thread's stack.
    pub fn set_stack_size(&mut self, size: usize) -> Result {
        unsafe { rv!(-libc::pthread_attr_setstacksize(&mut self.attr, size)) }
    }

    /// Like `set_stack_size`.
    pub fn stack_size(&mut self) -> Result<usize> {
        unsafe {
            let mut size = 0;
            try!(rv!(-libc::pthread_attr_getstacksize(&mut self.attr, &mut size)));
            Ok(size)
        }
    }

    /// See the documentation of the top-level function.
    pub fn spawn<F>(mut self, f: F) -> Result
        where F: FnOnce() + Send + 'static
    {
        unsafe {
            try!(rv!(-libc::pthread_attr_setdetachstate(&mut self.attr,
                                                        PTHREAD_CREATE_DETACHED)));
            match self.spawn_inner(&f) {
                Ok(_) => {
                    intrinsics::forget(f);
                    Ok(())
                },
                Err(e) => Err(e),
            }
        }
    }

    /// See the documentation of the top-level function.
    pub fn scoped<'a, F>(self, f: F) -> Result<JoinGuard<'a>>
        where F: FnOnce() + Send + 'a
    {
        unsafe {
            match self.spawn_inner(&f) {
                Ok(thread) => {
                    intrinsics::forget(f);
                    Ok(JoinGuard { thread: thread, _marker: PhantomData })
                },
                Err(e) => Err(e),
            }
        }
    }

    unsafe fn spawn_inner<F>(self, f: &F) -> Result<pthread_t>
        where F: FnOnce() + Send,
    {
        // We use the following method to get `f` onto the other thread's stack without an
        // allocation:
        //
        // - Create a lock in the shared address space and lock it.
        // - Pass a reference to the lock-guard and `f` to the other thread.
        // - Try to lock the lock again.
        // - The other thread copies everything onto its stack and then drops the lock
        //   guard.
        // - Once it drops the lock guard our lock succeeds and we know that the other
        //   thread now has its own copy of `f`.
        // - We forget our original lock guard because it has already been dropped in the
        //   other thread and forget `f` because the other thread now owns it.

        let mut thread = mem::zeroed();
        let lock = LOCK_INIT;
        let guard = lock.lock();

        // Avoid moving f around. If we move it into the structure then the compiler
        // definitely has to copy it instead of leaving it in the user's stack and only
        // passing references to our functions. This has been observed to avoid at least
        // one copy.

        let mut payload = Payload { guard: guard, f: f };
        let start_fn: unsafe extern fn(*mut u8) -> *mut u8 = mem::cast(start::<F>);
        let rv = libc::pthread_create(&mut thread, &self.attr, start_fn,
                                      &mut payload as *mut _ as *mut _);
        try!(rv!(-rv));
        lock.lock();
        mem::forget(payload.guard);
        Ok(thread)
    }
}

/// Payload to be passed to another thread.
struct Payload<'a, F>
    where F: FnOnce() + Send,
{
    guard: LockGuard<'a>,
    f: *const F,
}

/// The function that will be called by libc. The function takes ownership of the payload
/// and the `f`.
unsafe extern fn start<'a, F>(data: *mut Payload<'a, F>) -> *mut u8
    where F: FnOnce() + Send,
{
    let Payload { guard, f } = ptr::read(data);
    let f = ptr::read(f);
    drop(guard);
    f();
    0 as *mut u8
}
<|endoftext|>


<commit_before>use crate::cxx_string::CxxString;
use std::ffi::c_void;
use std::fmt::{self, Debug, Display};
use std::marker::PhantomData;
use std::mem;
use std::ptr;

/// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
#[repr(C)]
pub struct UniquePtr<T>
where
    T: UniquePtrTarget,
{
    repr: *mut c_void,
    ty: PhantomData<T>,
}

impl<T> UniquePtr<T>
where
    T: UniquePtrTarget,
{
    /// Makes a new UniquePtr wrapping a null pointer.
    ///
    /// Matches the behavior of default-constructing a std::unique\_ptr.
    pub fn null() -> Self {
        UniquePtr {
            repr: T::__null(),
            ty: PhantomData,
        }
    }

    /// Allocates memory on the heap and makes a UniquePtr pointing to it.
    pub fn new(value: T) -> Self {
        UniquePtr {
            repr: T::__new(value),
            ty: PhantomData,
        }
    }

    /// Checks whether the UniquePtr does not own an object.
    ///
    /// This is the opposite of [std::unique_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool).
    pub fn is_null(&self) -> bool {
        let ptr = unsafe { T::__get(self.repr) };
        ptr.is_null()
    }

    /// Returns a reference to the object owned by this UniquePtr if any,
    /// otherwise None.
    pub fn as_ref(&self) -> Option<&T> {
        unsafe { T::__get(self.repr).as_ref() }
    }

    /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
    ///
    /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
    pub fn into_raw(self) -> *mut T {
        let ptr = unsafe { T::__release(self.repr) };
        mem::forget(self);
        ptr
    }

    /// Constructs a UniquePtr retaking ownership of a pointer previously
    /// obtained from `into_raw`.
    ///
    /// # Safety
    ///
    /// This function is unsafe because improper use may lead to memory
    /// problems. For example a double-free may occur if the function is called
    /// twice on the same raw pointer.
    pub unsafe fn from_raw(raw: *mut T) -> Self {
        UniquePtr {
            repr: T::__raw(raw),
            ty: PhantomData,
        }
    }
}

unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {}

impl<T> Drop for UniquePtr<T>
where
    T: UniquePtrTarget,
{
    fn drop(&mut self) {
        unsafe { T::__drop(self.repr) }
    }
}

impl<T> Debug for UniquePtr<T>
where
    T: Debug + UniquePtrTarget,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.as_ref() {
            None => formatter.write_str("nullptr"),
            Some(value) => Debug::fmt(value, formatter),
        }
    }
}

impl<T> Display for UniquePtr<T>
where
    T: Display + UniquePtrTarget,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.as_ref() {
            None => formatter.write_str("nullptr"),
            Some(value) => Display::fmt(value, formatter),
        }
    }
}

// Methods are private; not intended to be implemented outside of cxxbridge
// codebase.
pub unsafe trait UniquePtrTarget {
    #[doc(hidden)]
    fn __null() -> *mut c_void;
    #[doc(hidden)]
    fn __new(value: Self) -> *mut c_void
    where
        Self: Sized,
    {
        // Opaque C types do not get this method because they can never exist by
        // value on the Rust side of the bridge.
        let _ = value;
        unreachable!()
    }
    #[doc(hidden)]
    unsafe fn __raw(raw: *mut Self) -> *mut c_void;
    #[doc(hidden)]
    unsafe fn __get(repr: *mut c_void) -> *const Self;
    #[doc(hidden)]
    unsafe fn __release(repr: *mut c_void) -> *mut Self;
    #[doc(hidden)]
    unsafe fn __drop(repr: *mut c_void);
}

extern "C" {
    #[link_name = "cxxbridge02$unique_ptr$std$string$null"]
    fn unique_ptr_std_string_null(this: *mut *mut c_void);
    #[link_name = "cxxbridge02$unique_ptr$std$string$raw"]
    fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
    #[link_name = "cxxbridge02$unique_ptr$std$string$get"]
    fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
    #[link_name = "cxxbridge02$unique_ptr$std$string$release"]
    fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
    #[link_name = "cxxbridge02$unique_ptr$std$string$drop"]
    fn unique_ptr_std_string_drop(this: *mut *mut c_void);
}

unsafe impl UniquePtrTarget for CxxString {
    fn __null() -> *mut c_void {
        let mut repr = ptr::null_mut::<c_void>();
        unsafe { unique_ptr_std_string_null(&mut repr) }
        repr
    }
    unsafe fn __raw(raw: *mut Self) -> *mut c_void {
        let mut repr = ptr::null_mut::<c_void>();
        unique_ptr_std_string_raw(&mut repr, raw);
        repr
    }
    unsafe fn __get(repr: *mut c_void) -> *const Self {
        unique_ptr_std_string_get(&repr)
    }
    unsafe fn __release(mut repr: *mut c_void) -> *mut Self {
        unique_ptr_std_string_release(&mut repr)
    }
    unsafe fn __drop(mut repr: *mut c_void) {
        unique_ptr_std_string_drop(&mut repr);
    }
}
<commit_msg>Provide UniquePtr::as_mut<commit_after>use crate::cxx_string::CxxString;
use std::ffi::c_void;
use std::fmt::{self, Debug, Display};
use std::marker::PhantomData;
use std::mem;
use std::ptr;

/// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
#[repr(C)]
pub struct UniquePtr<T>
where
    T: UniquePtrTarget,
{
    repr: *mut c_void,
    ty: PhantomData<T>,
}

impl<T> UniquePtr<T>
where
    T: UniquePtrTarget,
{
    /// Makes a new UniquePtr wrapping a null pointer.
    ///
    /// Matches the behavior of default-constructing a std::unique\_ptr.
    pub fn null() -> Self {
        UniquePtr {
            repr: T::__null(),
            ty: PhantomData,
        }
    }

    /// Allocates memory on the heap and makes a UniquePtr pointing to it.
    pub fn new(value: T) -> Self {
        UniquePtr {
            repr: T::__new(value),
            ty: PhantomData,
        }
    }

    /// Checks whether the UniquePtr does not own an object.
    ///
    /// This is the opposite of [std::unique_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool).
    pub fn is_null(&self) -> bool {
        let ptr = unsafe { T::__get(self.repr) };
        ptr.is_null()
    }

    /// Returns a reference to the object owned by this UniquePtr if any,
    /// otherwise None.
    pub fn as_ref(&self) -> Option<&T> {
        unsafe { T::__get(self.repr).as_ref() }
    }

    /// Returns a mutable reference to the object owned by this UniquePtr if
    /// any, otherwise None.
    pub fn as_mut(&mut self) -> Option<&mut T> {
        unsafe { (T::__get(self.repr) as *mut T).as_mut() }
    }

    /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
    ///
    /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
    pub fn into_raw(self) -> *mut T {
        let ptr = unsafe { T::__release(self.repr) };
        mem::forget(self);
        ptr
    }

    /// Constructs a UniquePtr retaking ownership of a pointer previously
    /// obtained from `into_raw`.
    ///
    /// # Safety
    ///
    /// This function is unsafe because improper use may lead to memory
    /// problems. For example a double-free may occur if the function is called
    /// twice on the same raw pointer.
    pub unsafe fn from_raw(raw: *mut T) -> Self {
        UniquePtr {
            repr: T::__raw(raw),
            ty: PhantomData,
        }
    }
}

unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {}

impl<T> Drop for UniquePtr<T>
where
    T: UniquePtrTarget,
{
    fn drop(&mut self) {
        unsafe { T::__drop(self.repr) }
    }
}

impl<T> Debug for UniquePtr<T>
where
    T: Debug + UniquePtrTarget,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.as_ref() {
            None => formatter.write_str("nullptr"),
            Some(value) => Debug::fmt(value, formatter),
        }
    }
}

impl<T> Display for UniquePtr<T>
where
    T: Display + UniquePtrTarget,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.as_ref() {
            None => formatter.write_str("nullptr"),
            Some(value) => Display::fmt(value, formatter),
        }
    }
}

// Methods are private; not intended to be implemented outside of cxxbridge
// codebase.
pub unsafe trait UniquePtrTarget {
    #[doc(hidden)]
    fn __null() -> *mut c_void;
    #[doc(hidden)]
    fn __new(value: Self) -> *mut c_void
    where
        Self: Sized,
    {
        // Opaque C types do not get this method because they can never exist by
        // value on the Rust side of the bridge.
        let _ = value;
        unreachable!()
    }
    #[doc(hidden)]
    unsafe fn __raw(raw: *mut Self) -> *mut c_void;
    #[doc(hidden)]
    unsafe fn __get(repr: *mut c_void) -> *const Self;
    #[doc(hidden)]
    unsafe fn __release(repr: *mut c_void) -> *mut Self;
    #[doc(hidden)]
    unsafe fn __drop(repr: *mut c_void);
}

extern "C" {
    #[link_name = "cxxbridge02$unique_ptr$std$string$null"]
    fn unique_ptr_std_string_null(this: *mut *mut c_void);
    #[link_name = "cxxbridge02$unique_ptr$std$string$raw"]
    fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
    #[link_name = "cxxbridge02$unique_ptr$std$string$get"]
    fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
    #[link_name = "cxxbridge02$unique_ptr$std$string$release"]
    fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
    #[link_name = "cxxbridge02$unique_ptr$std$string$drop"]
    fn unique_ptr_std_string_drop(this: *mut *mut c_void);
}

unsafe impl UniquePtrTarget for CxxString {
    fn __null() -> *mut c_void {
        let mut repr = ptr::null_mut::<c_void>();
        unsafe { unique_ptr_std_string_null(&mut repr) }
        repr
    }
    unsafe fn __raw(raw: *mut Self) -> *mut c_void {
        let mut repr = ptr::null_mut::<c_void>();
        unique_ptr_std_string_raw(&mut repr, raw);
        repr
    }
    unsafe fn __get(repr: *mut c_void) -> *const Self {
        unique_ptr_std_string_get(&repr)
    }
    unsafe fn __release(mut repr: *mut c_void) -> *mut Self {
        unique_ptr_std_string_release(&mut repr)
    }
    unsafe fn __drop(mut repr: *mut c_void) {
        unique_ptr_std_string_drop(&mut repr);
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::Read;
use cudart::Memory;
use std::path::Path;
use image;

pub struct Image<T> {
    info: T,
    width: usize,
    height: usize,
    pub data: Vec<u8>
}

const Channels:usize = 3;

impl<T> Image<T> {
    pub fn from_file(file: &mut File,
                     width: usize,
                     height: usize,
                     info: T) -> Result<Image<T>, &'static str> {
        let mut buf = vec![0u8; width * height * Channels];
        try!(match file.read(&mut buf) {
            Ok(n) if(n == width * height * Channels) => Ok(()),
            _ => Err("EOF")
        });

        Ok(Image::<T> {
            info: info,
            width: width,
            height: height,
            data: buf.to_vec()
        })
    }

    pub fn from_device(memory: Memory<f32>,
                       info: T,
                       width: usize,
                       height: usize) -> Result<Image<T>, &'static str> {
        let mut buf_f32 = vec![0f32; width * height * Channels];
        try!(memory.read(&mut buf_f32));
        let buf_u8 = buf_f32.into_iter().map(|x: f32| (x * 255.0) as u8).collect::<Vec<_>>();

        Ok(Image::<T> {
            info: info,
            width: width,
            height: height,
            data: buf_u8
        })
    }

    pub fn save(self, path: &str) -> Result<(), &'static str> {
        match image::save_buffer(&Path::new(&path),
                                 &self.data_whc(),
                                 self.width as u32,
                                 self.height as u32,
                                 image::RGB(8)) {
            Ok(()) => Ok(()),
            Err(_) => Err("Failed to save the result image file.")
        }
    }

    pub fn to_device(&self) -> Result<Memory<f32>, &'static str> {
        let buf = self.data.clone().into_iter().map(|x: u8| (x as f32) / 255.0).collect::<Vec<_>>();
        let mut mem = try!(Memory::new(self.size()));
        try!(mem.write(&buf));
        Ok(mem)
    }

    pub fn size(&self) -> usize {
        self.width * self.height * Channels
    }

    pub fn data_whc(&self) -> Vec<u8> {
        let mut res = vec![0u8; self.size()];
        for i in 0..res.len() {
            res[i] = self.data[(i % 3) * (32 * 32) + (i / 3)];
        }
        res
    }
}
<commit_msg>bugfix: must accept mutable size<commit_after>use std::fs::File;
use std::io::Read;
use cudart::Memory;
use std::path::Path;
use image;

pub struct Image<T> {
    info: T,
    width: usize,
    height: usize,
    pub data: Vec<u8>
}

const Channels:usize = 3;

impl<T> Image<T> {
    pub fn from_file(file: &mut File,
                     width: usize,
                     height: usize,
                     info: T) -> Result<Image<T>, &'static str> {
        let mut buf = vec![0u8; width * height * Channels];
        try!(match file.read(&mut buf) {
            Ok(n) if(n == width * height * Channels) => Ok(()),
            _ => Err("EOF")
        });

        Ok(Image::<T> {
            info: info,
            width: width,
            height: height,
            data: buf.to_vec()
        })
    }

    pub fn from_device(memory: Memory<f32>,
                       info: T,
                       width: usize,
                       height: usize) -> Result<Image<T>, &'static str> {
        let mut buf_f32 = vec![0f32; width * height * Channels];
        try!(memory.read(&mut buf_f32));
        let buf_u8 = buf_f32.into_iter().map(|x: f32| (x * 255.0) as u8).collect::<Vec<_>>();

        Ok(Image::<T> {
            info: info,
            width: width,
            height: height,
            data: buf_u8
        })
    }

    pub fn save(self, path: &str) -> Result<(), &'static str> {
        match image::save_buffer(&Path::new(&path),
                                 &self.data_whc(),
                                 self.width as u32,
                                 self.height as u32,
                                 image::RGB(8)) {
            Ok(()) => Ok(()),
            Err(_) => Err("Failed to save the result image file.")
        }
    }

    pub fn to_device(&self) -> Result<Memory<f32>, &'static str> {
        let buf = self.data.clone().into_iter().map(|x: u8| (x as f32) / 255.0).collect::<Vec<_>>();
        let mut mem = try!(Memory::new(self.size()));
        try!(mem.write(&buf));
        Ok(mem)
    }

    pub fn size(&self) -> usize {
        self.width * self.height * Channels
    }

    pub fn data_whc(&self) -> Vec<u8> {
        let mut res = vec![0u8; self.size()];
        for i in 0..res.len() {
            res[i] = self.data[(i % 3) * (self.width * self.height) + (i / 3)];
        }
        res
    }
}
<|endoftext|>


<commit_before>pub trait Vector<C>
    where Self: Sized
{
    fn add<'a, V: 'a>(&mut self, rhs: &'a V) -> &mut Self where Self: From<&'a V>;
    fn add_into<'a, V: 'a>(&self, rhs: &'a V, dest: &mut Self) where Self: From<&'a V>;
    fn angle<'a, V: 'a>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn angle_cos<'a, V: 'a>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn distance<'a, V: 'a>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn distance_sq<'a, V: 'a>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn dot<'a, V: 'a>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn fma<'a, V: 'a>(&mut self, a: &'a V, b: &'a V) -> &mut Self where Self: From<&'a V>;
    fn fma_into<'a, V: 'a>(&self, a: &'a V, b: &'a V, dest: &mut Self) where Self: From<&'a V>;
    fn length(&self) -> C;
    fn length_squared(&self) -> C;
    fn lerp<'a, V: 'a>(&mut self, other: &'a V, t: C) -> &mut Self where Self: From<&'a V>;
    fn lerp_into<'a, V: 'a>(&self, other: &'a V, t: C, dest: &mut Self) where Self: From<&'a V>;
    fn mul<'a, V: 'a>(&mut self, rhs: &'a V) -> &mut Self where Self: From<&'a V>;
    fn mul_into<'a, V: 'a>(&self, rhs: &'a V, dest: &mut Self) where Self: From<&'a V>;
    fn negate(&mut self) -> &mut Self;
    fn negate_into(&self, dest: &mut Self);
    fn normalize(&mut self) -> &mut Self;
    fn normalize_into(&self, dest: &mut Self);
    fn set<'a, V: 'a>(&mut self, rhs: &'a V) -> &mut Self where Self: From<&'a V>;
    fn sub<'a, V: 'a>(&mut self, rhs: &'a V) -> &mut Self where Self: From<&'a V>;
    fn sub_into<'a, V: 'a>(&self, rhs: &'a V, dest: &mut Self) where Self: From<&'a V>;
    fn zero(&mut self) -> &mut Self;
}

pub trait Vector2<C>: Vector<C> {
    fn new(x: C, y: C) -> Self;
}

pub trait Vector3<C>: Vector<C> {
    fn new(x: C, y: C, z: C) -> Self;
    fn cross<'a, V: 'a>(&mut self, v: &'a V) -> &mut Self where Self: From<&'a V>;
    fn cross_into<'a, V: 'a>(&self, v: &'a V, dest: &mut Self) where Self: From<&'a V>;
}

pub trait Vector4<C>: Vector<C> {
    fn new(x: C, y: C, z: C, w: C) -> Self;
}

pub mod vector2f;
pub mod vector3f;
pub mod vector4f;
<commit_msg>add todo for possible API improvements<commit_after>// todo:
// for _into methods, add two more generic types `D` and `T`.
// `D` will be specific to just those functions
// `T` will be generic across the whole Vector<C>
//
// change to: pub trait Vector<C, T> {}
// and it will be impl'd like this:
// impl Vector<f32, Vector2> for Vector2f {}
//
// then add getters/setters to Vector2
// (if needed) make Vector2 not a Sub-Trait of Vector
//
// then the trait bound on `D` can be `where D: T`
// this allows us to just call setters on D no matter what type it is.
// need to evaluate performance of this concept.
//

pub trait Vector<C>
    where Self: Sized
{
    fn add<'a, V: 'a>(&mut self, rhs: &'a V) -> &mut Self where Self: From<&'a V>;
    fn add_into<'a, V: 'a>(&self, rhs: &'a V, dest: &mut Self) where Self: From<&'a V>;
    fn angle<'a, V: 'a>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn angle_cos<'a, V: 'a>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn distance<'a, V: 'a>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn distance_sq<'a, V: 'a>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn dot<'a, V: 'a>(&self, rhs: &'a V) -> C where Self: From<&'a V>;
    fn fma<'a, V: 'a>(&mut self, a: &'a V, b: &'a V) -> &mut Self where Self: From<&'a V>;
    fn fma_into<'a, V: 'a>(&self, a: &'a V, b: &'a V, dest: &mut Self) where Self: From<&'a V>;
    fn length(&self) -> C;
    fn length_squared(&self) -> C;
    fn lerp<'a, V: 'a>(&mut self, other: &'a V, t: C) -> &mut Self where Self: From<&'a V>;
    fn lerp_into<'a, V: 'a>(&self, other: &'a V, t: C, dest: &mut Self) where Self: From<&'a V>;
    fn mul<'a, V: 'a>(&mut self, rhs: &'a V) -> &mut Self where Self: From<&'a V>;
    fn mul_into<'a, V: 'a>(&self, rhs: &'a V, dest: &mut Self) where Self: From<&'a V>;
    fn negate(&mut self) -> &mut Self;
    fn negate_into(&self, dest: &mut Self);
    fn normalize(&mut self) -> &mut Self;
    fn normalize_into(&self, dest: &mut Self);
    fn set<'a, V: 'a>(&mut self, rhs: &'a V) -> &mut Self where Self: From<&'a V>;
    fn sub<'a, V: 'a>(&mut self, rhs: &'a V) -> &mut Self where Self: From<&'a V>;
    fn sub_into<'a, V: 'a>(&self, rhs: &'a V, dest: &mut Self) where Self: From<&'a V>;
    fn zero(&mut self) -> &mut Self;
}

pub trait Vector2<C>: Vector<C> {
    fn new(x: C, y: C) -> Self;
}

pub trait Vector3<C>: Vector<C> {
    fn new(x: C, y: C, z: C) -> Self;
    fn cross<'a, V: 'a>(&mut self, v: &'a V) -> &mut Self where Self: From<&'a V>;
    fn cross_into<'a, V: 'a>(&self, v: &'a V, dest: &mut Self) where Self: From<&'a V>;
}

pub trait Vector4<C>: Vector<C> {
    fn new(x: C, y: C, z: C, w: C) -> Self;
}

pub mod vector2f;
pub mod vector3f;
pub mod vector4f;
<|endoftext|>


<commit_before>//
// Copyright 2019 The Project Oak Authors
//
// 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
//
//     http://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.
//

//! Helper library for accessing Oak storage services.

use crate::grpc;
use crate::proto::grpc_encap::{GrpcRequest, GrpcResponse};
use crate::proto::storage_channel::{
    StorageChannelDeleteRequest, StorageChannelDeleteResponse, StorageChannelReadRequest,
    StorageChannelReadResponse, StorageChannelWriteRequest, StorageChannelWriteResponse,
};
use log::{info, warn};
use protobuf::Message;

/// Default name for predefined node config that corresponds to a storage
/// pseudo-Node.
pub const DEFAULT_CONFIG_NAME: &str = "storage";

/// Local representation of the connection to an external storage service.
pub struct Storage {
    write_channel: crate::WriteHandle,
}

impl Storage {
    /// Create a default `Storage` instance assuming the default pre-defined
    /// name (`"storage"`) identifying storage node config.
    pub fn default() -> Option<Storage> {
        Storage::new(DEFAULT_CONFIG_NAME)
    }

    /// Create a `Storage` instance using the given name identifying storage
    /// node configuration.
    pub fn new(config: &str) -> Option<Storage> {
        // Create a channel and pass the read half to a fresh storage Node.
        let (write_channel, read_channel) = match crate::channel_create() {
            Ok(x) => x,
            Err(_e) => return None,
        };
        if crate::node_create(config, "oak_main", read_channel).is_err() {
            if let Err(status) = crate::channel_close(write_channel.handle) {
                warn!("could not close write channel: {:?}", status);
            };
            if let Err(status) = crate::channel_close(read_channel.handle) {
                warn!("could not close read channel: {:?}", status);
            };
            return None;
        }

        if let Err(status) = crate::channel_close(read_channel.handle) {
            warn!("could not close read channel: {:?}", status);
        };
        Some(Storage { write_channel })
    }

    fn execute_operation<Req, Res>(
        &mut self,
        grpc_method_name: &str,
        operation_request: &Req,
    ) -> grpc::Result<Res>
    where
        Req: protobuf::Message,
        Res: protobuf::Message,
    {
        info!(
            "StorageChannelRequest: {}",
            protobuf::text_format::print_to_string(operation_request)
        );

        let mut request_any = protobuf::well_known_types::Any::new();
        // TODO: rust-protobuf does not provide pack_from/unpack_to functions.
        // https://github.com/stepancheg/rust-protobuf/issues/455
        request_any.set_type_url(
            String::from("type.googleapis.com/") + operation_request.descriptor().full_name(),
        );
        operation_request
            .write_to_writer(&mut request_any.value)
            .expect("could not convert operation request to `Any` value");
        let mut grpc_request = GrpcRequest::new();
        grpc_request.method_name = grpc_method_name.to_owned();
        grpc_request.set_req_msg(request_any);
        let mut grpc_data = Vec::new();
        grpc_request
            .write_to_writer(&mut grpc_data)
            .expect("could not convert gRPC request to bytes");

        // Create an ephemeral channel for the response.
        let (rsp_out, rsp_in) = match crate::channel_create() {
            Ok(x) => x,
            Err(status) => {
                return Err(grpc::build_status(
                    grpc::Code::INTERNAL,
                    &format!("failed to create storage response channel: {:?}", status),
                ));
            }
        };

        crate::channel_write(self.write_channel, &grpc_data, &[rsp_out.handle])
            .expect("could not write to channel");
        crate::channel_close(rsp_out.handle).expect("could not close channel");

        // Block until there is a response available.
        loop {
            let wait_result = crate::wait_on_channels(&[rsp_in]).unwrap();
            if wait_result[0] == crate::ChannelReadStatus::ReadReady {
                break;
            }
        }

        let mut buffer = Vec::<u8>::with_capacity(256);
        let mut handles = Vec::<crate::Handle>::with_capacity(1);
        crate::channel_read(rsp_in, &mut buffer, &mut handles)
            .expect("could not read from channel");
        if !handles.is_empty() {
            panic!("unexpected handles received alongside storage request")
        }
        let mut grpc_response: GrpcResponse = protobuf::parse_from_reader(&mut &buffer[..])
            .expect("could not parse gRPC response from bytes");
        info!(
            "StorageChannelResponse: {}",
            protobuf::text_format::print_to_string(&grpc_response)
        );
        crate::channel_close(rsp_in.handle).expect("could not close channel");

        let status = grpc_response.take_status();
        if status.code != 0 {
            Err(status)
        } else {
            let response = protobuf::parse_from_bytes(grpc_response.get_rsp_msg().value.as_slice())
                .expect("could not parse gRPC response message from `Any` value");
            Ok(response)
        }
    }

    /// Read the value associated with the given `name` from the storage
    /// instance identified by `name`.
    pub fn read(&mut self, storage_name: &[u8], name: &[u8]) -> grpc::Result<Vec<u8>> {
        let mut read_request = StorageChannelReadRequest::new();
        read_request.storage_name = storage_name.to_owned();
        read_request.mut_item().set_name(name.to_owned());

        // TODO: Automatically generate boilerplate from the proto definition.
        self.execute_operation::<StorageChannelReadRequest, StorageChannelReadResponse>(
            "/oak.StorageNode/Read",
            &read_request,
        )
        .map(|r| r.get_item().get_value().to_vec())
    }

    /// Set the value associated with the given `name` from the storage instance
    /// identified by `name`.
    pub fn write(&mut self, storage_name: &[u8], name: &[u8], value: &[u8]) -> grpc::Result<()> {
        let mut write_request = StorageChannelWriteRequest::new();
        // TODO: Set policy for item.
        write_request.storage_name = storage_name.to_owned();
        write_request.mut_item().set_name(name.to_owned());
        write_request.mut_item().set_value(value.to_owned());

        // TODO: Automatically generate boilerplate from the proto definition.
        self.execute_operation::<StorageChannelWriteRequest, StorageChannelWriteResponse>(
            "/oak.StorageNode/Write",
            &write_request,
        )
        .map(|_| ())
    }

    /// Delete the value associated with the given `name` from the storage
    /// instance identified by `name`.
    pub fn delete(&mut self, storage_name: &[u8], name: &[u8]) -> grpc::Result<()> {
        let mut delete_request = StorageChannelDeleteRequest::new();
        delete_request.storage_name = storage_name.to_owned();
        delete_request.mut_item().set_name(name.to_owned());

        // TODO: Automatically generate boilerplate from the proto definition.
        self.execute_operation::<StorageChannelDeleteRequest, StorageChannelDeleteResponse>(
            "/oak.StorageNode/Delete",
            &delete_request,
        )
        .map(|_| ())
    }
}
<commit_msg>sdk/storage: use defaults for message building<commit_after>//
// Copyright 2019 The Project Oak Authors
//
// 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
//
//     http://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.
//

//! Helper library for accessing Oak storage services.

use crate::grpc;
use crate::proto::grpc_encap::{GrpcRequest, GrpcResponse};
use crate::proto::storage_channel::{
    StorageChannelDeleteRequest, StorageChannelDeleteResponse, StorageChannelReadRequest,
    StorageChannelReadResponse, StorageChannelWriteRequest, StorageChannelWriteResponse,
    StorageItem,
};
use log::{info, warn};
use protobuf::Message;

/// Default name for predefined node config that corresponds to a storage
/// pseudo-Node.
pub const DEFAULT_CONFIG_NAME: &str = "storage";

/// Local representation of the connection to an external storage service.
pub struct Storage {
    write_channel: crate::WriteHandle,
}

impl Storage {
    /// Create a default `Storage` instance assuming the default pre-defined
    /// name (`"storage"`) identifying storage node config.
    pub fn default() -> Option<Storage> {
        Storage::new(DEFAULT_CONFIG_NAME)
    }

    /// Create a `Storage` instance using the given name identifying storage
    /// node configuration.
    pub fn new(config: &str) -> Option<Storage> {
        // Create a channel and pass the read half to a fresh storage Node.
        let (write_channel, read_channel) = match crate::channel_create() {
            Ok(x) => x,
            Err(_e) => return None,
        };
        if crate::node_create(config, "oak_main", read_channel).is_err() {
            if let Err(status) = crate::channel_close(write_channel.handle) {
                warn!("could not close write channel: {:?}", status);
            };
            if let Err(status) = crate::channel_close(read_channel.handle) {
                warn!("could not close read channel: {:?}", status);
            };
            return None;
        }

        if let Err(status) = crate::channel_close(read_channel.handle) {
            warn!("could not close read channel: {:?}", status);
        };
        Some(Storage { write_channel })
    }

    fn execute_operation<Req, Res>(
        &mut self,
        grpc_method_name: &str,
        operation_request: &Req,
    ) -> grpc::Result<Res>
    where
        Req: protobuf::Message,
        Res: protobuf::Message,
    {
        info!(
            "StorageChannelRequest: {}",
            protobuf::text_format::print_to_string(operation_request)
        );

        let mut request_any = protobuf::well_known_types::Any::new();
        // TODO: rust-protobuf does not provide pack_from/unpack_to functions.
        // https://github.com/stepancheg/rust-protobuf/issues/455
        request_any.set_type_url(
            String::from("type.googleapis.com/") + operation_request.descriptor().full_name(),
        );
        operation_request
            .write_to_writer(&mut request_any.value)
            .expect("could not convert operation request to `Any` value");
        let mut grpc_request = GrpcRequest::new();
        grpc_request.method_name = grpc_method_name.to_owned();
        grpc_request.set_req_msg(request_any);
        let mut grpc_data = Vec::new();
        grpc_request
            .write_to_writer(&mut grpc_data)
            .expect("could not convert gRPC request to bytes");

        // Create an ephemeral channel for the response.
        let (rsp_out, rsp_in) = match crate::channel_create() {
            Ok(x) => x,
            Err(status) => {
                return Err(grpc::build_status(
                    grpc::Code::INTERNAL,
                    &format!("failed to create storage response channel: {:?}", status),
                ));
            }
        };

        crate::channel_write(self.write_channel, &grpc_data, &[rsp_out.handle])
            .expect("could not write to channel");
        crate::channel_close(rsp_out.handle).expect("could not close channel");

        // Block until there is a response available.
        loop {
            let wait_result = crate::wait_on_channels(&[rsp_in]).unwrap();
            if wait_result[0] == crate::ChannelReadStatus::ReadReady {
                break;
            }
        }

        let mut buffer = Vec::<u8>::with_capacity(256);
        let mut handles = Vec::<crate::Handle>::with_capacity(1);
        crate::channel_read(rsp_in, &mut buffer, &mut handles)
            .expect("could not read from channel");
        if !handles.is_empty() {
            panic!("unexpected handles received alongside storage request")
        }
        let mut grpc_response: GrpcResponse = protobuf::parse_from_reader(&mut &buffer[..])
            .expect("could not parse gRPC response from bytes");
        info!(
            "StorageChannelResponse: {}",
            protobuf::text_format::print_to_string(&grpc_response)
        );
        crate::channel_close(rsp_in.handle).expect("could not close channel");

        let status = grpc_response.take_status();
        if status.code != 0 {
            Err(status)
        } else {
            let response = protobuf::parse_from_bytes(grpc_response.get_rsp_msg().value.as_slice())
                .expect("could not parse gRPC response message from `Any` value");
            Ok(response)
        }
    }

    /// Read the value associated with the given `name` from the storage
    /// instance identified by `name`.
    pub fn read(&mut self, storage_name: &[u8], name: &[u8]) -> grpc::Result<Vec<u8>> {
        let read_request = StorageChannelReadRequest {
            storage_name: storage_name.to_owned(),
            item: protobuf::SingularPtrField::some(StorageItem {
                name: name.to_owned(),
                ..Default::default()
            }),
            ..Default::default()
        };

        // TODO: Automatically generate boilerplate from the proto definition.
        self.execute_operation::<StorageChannelReadRequest, StorageChannelReadResponse>(
            "/oak.StorageNode/Read",
            &read_request,
        )
        .map(|r| r.get_item().get_value().to_vec())
    }

    /// Set the value associated with the given `name` from the storage instance
    /// identified by `name`.
    pub fn write(&mut self, storage_name: &[u8], name: &[u8], value: &[u8]) -> grpc::Result<()> {
        // TODO: Set policy for item.
        let write_request = StorageChannelWriteRequest {
            storage_name: storage_name.to_owned(),
            item: protobuf::SingularPtrField::some(StorageItem {
                name: name.to_owned(),
                value: value.to_owned(),
                ..Default::default()
            }),
            ..Default::default()
        };

        // TODO: Automatically generate boilerplate from the proto definition.
        self.execute_operation::<StorageChannelWriteRequest, StorageChannelWriteResponse>(
            "/oak.StorageNode/Write",
            &write_request,
        )
        .map(|_| ())
    }

    /// Delete the value associated with the given `name` from the storage
    /// instance identified by `name`.
    pub fn delete(&mut self, storage_name: &[u8], name: &[u8]) -> grpc::Result<()> {
        let delete_request = StorageChannelDeleteRequest {
            storage_name: storage_name.to_owned(),
            item: protobuf::SingularPtrField::some(StorageItem {
                name: name.to_owned(),
                ..Default::default()
            }),
            ..Default::default()
        };

        // TODO: Automatically generate boilerplate from the proto definition.
        self.execute_operation::<StorageChannelDeleteRequest, StorageChannelDeleteResponse>(
            "/oak.StorageNode/Delete",
            &delete_request,
        )
        .map(|_| ())
    }
}
<|endoftext|>


<commit_before>use cw::{BLOCK, CVec};
use std::cmp;
use std::collections::HashMap;

#[derive(Hash, Eq, PartialEq)]
enum WordConstraint {
    Length(usize),
    CharAt(char, usize, usize),
    BigramAt([char; 2], usize, usize),
    TrigramAt([char; 3], usize, usize),
    NGramAt(CVec, usize, usize),
}

impl WordConstraint {
    fn with_ngram(ngram: &[char], pos: usize, len: usize) -> WordConstraint {
        match ngram.len() {
            0 => WordConstraint::Length(len),
            1 => WordConstraint::CharAt(ngram[0], pos, len),
            2 => WordConstraint::BigramAt([ngram[0], ngram[1]], pos, len),
            3 => WordConstraint::TrigramAt([ngram[0], ngram[1], ngram[2]], pos, len),
            _ => WordConstraint::NGramAt(ngram.to_vec(), pos, len),
        }
    }
}

pub struct WordStats {
    freq: HashMap<WordConstraint, usize>,
    max_n: usize,
}

impl WordStats {
    pub fn new(max_n: usize) -> WordStats {
        WordStats {
            freq: HashMap::new(),
            max_n: max_n,
        }
    }

    pub fn add_words<'a, T: Iterator<Item = &'a CVec>>(&mut self, words: T) {
        for word in words {
            self.add_word(word);
        }
    }

    fn get(&self, wc: &WordConstraint) -> usize { *self.freq.get(wc).unwrap_or(&0) }

    fn get_total(&self, len: usize) -> usize { self.get(&WordConstraint::Length(len)) }

    fn get_freq(&self, ngram: &[char], pos: usize, len: usize) -> usize {
        self.get(&WordConstraint::with_ngram(ngram, pos, len))
    }

    fn increase(&mut self, wc: WordConstraint) {
        let prev_freq = self.get(&wc);
        self.freq.insert(wc, prev_freq + 1);
    }

    pub fn add_word(&mut self, word: &CVec) {
        self.increase(WordConstraint::Length(word.len()));
        for n in 1..(self.max_n + 1) {
            for (pos, ngram) in word.windows(n).enumerate() {
                self.increase(WordConstraint::with_ngram(ngram, pos, word.len()));
            }
        }
    }

    fn get_estimate(&self, subword: &[char], pos: usize, len: usize) -> f32 {
        let n = cmp::min(self.max_n, subword.len());
        let mut estimate = self.get_freq(&subword[0..n], pos, len) as f32;
        if estimate == 0_f32 {
            return 0_f32;
        }
        for dp in 1..(subword.len() - n) {
            let next_est = self.get_freq(&subword[dp..(dp + n)], pos + dp, len) as f32;
            if next_est == 0_f32 {
                return 0_f32;
            }
            estimate *= next_est;
            if n > 1 {
                estimate /= self.get_freq(&subword[dp..(dp + n - 1)], pos + dp, len) as f32;
            }
        }
        estimate
    }

    pub fn estimate_matches(&self, pattern: &CVec) -> f32 {
        let len = pattern.len();
        let total = self.get_total(len) as f32;
        if total == 0_f32 {
            return 0_f32;
        }
        let mut probability = 1_f32;
        let mut pos = 0;
        for i in pattern.iter().enumerate()
                .filter(|&(_, ch)| ch == &BLOCK)
                .map(|(i, _)| i)
                .chain(Some(len).into_iter()) {
            if i > pos {
                probability *= self.get_estimate(&pattern[pos..i], pos, len) / total;
                if probability == 0_f32 {
                    return 0_f32;
                }
            }
            pos = i + 1;
        }
        probability * total
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use cw::CVec;
    use std::collections::HashSet;

    #[test]
    fn test() {
        let mut words: HashSet<CVec> = HashSet::new();
        words.insert("ABCD".chars().collect());
        words.insert("AXYZ".chars().collect());
        let mut ws = WordStats::new(2);
        ws.add_words(words.iter());
        assert_eq!(1_f32, ws.estimate_matches(&"AB##".chars().collect()));
        assert_eq!(1_f32, ws.estimate_matches(&"#B##".chars().collect()));
        assert_eq!(0_f32, ws.estimate_matches(&"#AB#".chars().collect()));
        assert_eq!(0_f32, ws.estimate_matches(&"###A".chars().collect()));
        assert_eq!(0_f32, ws.estimate_matches(&"##".chars().collect()));
        assert_eq!(0_f32, ws.estimate_matches(&"#####".chars().collect()));
        assert_eq!(2_f32, ws.estimate_matches(&"A###".chars().collect()));
        assert_eq!(1_f32, ws.estimate_matches(&"#B##".chars().collect()));
        assert_eq!(1_f32, ws.estimate_matches(&"ABC#".chars().collect()));
        assert_eq!(0_f32, ws.estimate_matches(&"#C##".chars().collect()));
    }
}
<commit_msg>WordConstraint iterators<commit_after>use cw::{BLOCK, CVec};
use std::cmp;
use std::collections::HashMap;
use std::iter;
use std::slice;
use std::ops;

#[derive(Hash, Eq, PartialEq)]
enum WordConstraint {
    Length(usize),
    CharAt(char, usize, usize),
    BigramAt([char; 2], usize, usize),
    TrigramAt([char; 3], usize, usize),
    NGramAt(CVec, usize, usize),
}

type NgramIter<'a> = iter::Map<
            iter::Zip<slice::Windows<'a, char>, iter::Enumerate<iter::Repeat<usize>>>,
            fn((&[char], (usize, usize))) -> WordConstraint>;

impl WordConstraint {
    fn with_ngram(ngram: &[char], pos: usize, len: usize) -> WordConstraint {
        match ngram.len() {
            0 => WordConstraint::Length(len),
            1 => WordConstraint::CharAt(ngram[0], pos, len),
            2 => WordConstraint::BigramAt([ngram[0], ngram[1]], pos, len),
            3 => WordConstraint::TrigramAt([ngram[0], ngram[1], ngram[2]], pos, len),
            _ => WordConstraint::NGramAt(ngram.to_vec(), pos, len),
        }
    }

    fn ngram_constraints<'a>(word: &'a CVec, n: usize) -> NgramIter<'a> {
        fn to_constraint((ngram, (pos, len)): (&[char], (usize, usize))) -> WordConstraint {
            WordConstraint::with_ngram(ngram, pos, len)
        };
        word.windows(n).zip(iter::repeat(word.len()).enumerate()).map(to_constraint)
    }

    fn all_constraints<'a>(word: &'a CVec, max_n: usize) -> iter::FlatMap<
            iter::Zip<iter::Repeat<&'a CVec>, ops::Range<usize>>,
            NgramIter<'a>,
            fn((&'a Vec<char>, usize)) -> NgramIter<'a>> {
        fn to_iter<'a>((word, n): (&'a CVec, usize)) -> NgramIter<'a> {
            WordConstraint::ngram_constraints(word, n)
        };
        iter::repeat(word).zip(1..(max_n + 1)).flat_map(to_iter)
    }
}

pub struct WordStats {
    freq: HashMap<WordConstraint, usize>,
    max_n: usize,
}

impl WordStats {
    pub fn new(max_n: usize) -> WordStats {
        WordStats {
            freq: HashMap::new(),
            max_n: max_n,
        }
    }

    pub fn add_words<'a, T: Iterator<Item = &'a CVec>>(&mut self, words: T) {
        for word in words {
            self.add_word(word);
        }
    }

    fn get(&self, wc: &WordConstraint) -> usize { *self.freq.get(wc).unwrap_or(&0) }

    fn get_total(&self, len: usize) -> usize { self.get(&WordConstraint::Length(len)) }

    fn get_freq(&self, ngram: &[char], pos: usize, len: usize) -> usize {
        self.get(&WordConstraint::with_ngram(ngram, pos, len))
    }

    fn increase(&mut self, wc: WordConstraint) {
        let prev_freq = self.get(&wc);
        self.freq.insert(wc, prev_freq + 1);
    }

    pub fn add_word(&mut self, word: &CVec) {
        self.increase(WordConstraint::Length(word.len()));
        for wc in WordConstraint::all_constraints(word, self.max_n) {
            self.increase(wc);
        }
    }

    fn get_estimate(&self, subword: &[char], pos: usize, len: usize) -> f32 {
        let n = cmp::min(self.max_n, subword.len());
        let mut estimate = self.get_freq(&subword[0..n], pos, len) as f32;
        if estimate == 0_f32 {
            return 0_f32;
        }
        for dp in 1..(subword.len() - n) {
            let next_est = self.get_freq(&subword[dp..(dp + n)], pos + dp, len) as f32;
            if next_est == 0_f32 {
                return 0_f32;
            }
            estimate *= next_est;
            if n > 1 {
                estimate /= self.get_freq(&subword[dp..(dp + n - 1)], pos + dp, len) as f32;
            }
        }
        estimate
    }

    pub fn estimate_matches(&self, pattern: &CVec) -> f32 {
        let len = pattern.len();
        let total = self.get_total(len) as f32;
        if total == 0_f32 {
            return 0_f32;
        }
        let mut probability = 1_f32;
        let mut pos = 0;
        for i in pattern.iter().enumerate()
                .filter(|&(_, ch)| ch == &BLOCK)
                .map(|(i, _)| i)
                .chain(Some(len).into_iter()) {
            if i > pos {
                probability *= self.get_estimate(&pattern[pos..i], pos, len) / total;
                if probability == 0_f32 {
                    return 0_f32;
                }
            }
            pos = i + 1;
        }
        probability * total
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use cw::CVec;
    use std::collections::HashSet;

    #[test]
    fn test() {
        let mut words: HashSet<CVec> = HashSet::new();
        words.insert("ABCD".chars().collect());
        words.insert("AXYZ".chars().collect());
        let mut ws = WordStats::new(2);
        ws.add_words(words.iter());
        assert_eq!(1_f32, ws.estimate_matches(&"AB##".chars().collect()));
        assert_eq!(1_f32, ws.estimate_matches(&"#B##".chars().collect()));
        assert_eq!(0_f32, ws.estimate_matches(&"#AB#".chars().collect()));
        assert_eq!(0_f32, ws.estimate_matches(&"###A".chars().collect()));
        assert_eq!(0_f32, ws.estimate_matches(&"##".chars().collect()));
        assert_eq!(0_f32, ws.estimate_matches(&"#####".chars().collect()));
        assert_eq!(2_f32, ws.estimate_matches(&"A###".chars().collect()));
        assert_eq!(1_f32, ws.estimate_matches(&"#B##".chars().collect()));
        assert_eq!(1_f32, ws.estimate_matches(&"ABC#".chars().collect()));
        assert_eq!(0_f32, ws.estimate_matches(&"#C##".chars().collect()));
    }
}
<|endoftext|>