<commit_before>use command_executor::{Command, CommandContext, CommandMetadata, CommandParams, CommandGroup, CommandGroupMetadata};
use commands::*;
use utils::table::print_table;
use libindy::ErrorCode;
use libindy::wallet::Wallet;

use serde_json;
use serde_json::Value as JSONValue;
use serde_json::Map as JSONMap;

pub mod group {
    use super::*;

    command_group!(CommandGroupMetadata::new("wallet", "Wallet management commands"));
}

pub mod create_command {
    use super::*;

    command!(CommandMetadata::build("create", "Create new wallet with specified name")
                .add_main_param("name", "The name of new wallet")
                .add_param("pool_name", false, "The name of associated Indy pool")
                .add_param("key", true, "Auth key for the wallet")
                .finalize()
    );

    fn execute(ctx: &CommandContext, params: &CommandParams) -> Result<(), ()> {
        trace!("execute >> ctx {:?} params {:?}", ctx, params);

        let pool_name = get_str_param("pool_name", params).map_err(error_err!())?;
        let name = get_str_param("name", params).map_err(error_err!())?;
        let key = get_opt_str_param("key", params).map_err(error_err!())?;

        let config: Option<String> = key.map(|key| json!({ "key": key }).to_string());

        trace!("Wallet::create_wallet try: name {}, pool_name {}, config {:?}", name, pool_name, config);

        let res = Wallet::create_wallet(pool_name,
                                        name,
                                        None,
                                        config.as_ref().map(String::as_str));

        trace!("Wallet::create_wallet return: {:?}", res);

        let res = match res {
            Ok(()) => Ok(println_succ!("Wallet \"{}\" has been created", name)),
            Err(ErrorCode::WalletAlreadyExistsError) => Err(println_err!("Wallet \"{}\" already exists", name)),
            Err(err) => return Err(println_err!("Indy SDK error occurred {:?}", err)),
        };

        trace!("execute << {:?}", res);
        res
    }
}

pub mod open_command {
    use super::*;

    command_with_cleanup!(CommandMetadata::build("open", "Open wallet with specified name. Also close previously opened.")
                            .add_main_param("name", "The name of wallet")
                            .add_param("key", true, "Auth key for the wallet")
                            .add_param("rekey", true, "New auth key for the wallet (will replace previous one).")
                            .add_param("freshness_time", true, "Freshness time for entities in the wallet")
                            .finalize());

    fn execute(ctx: &CommandContext, params: &CommandParams) -> Result<(), ()> {
        trace!("execute >> ctx {:?} params {:?}", ctx, params);

        let name = get_str_param("name", params).map_err(error_err!())?;
        let key = get_opt_str_param("key", params).map_err(error_err!())?;
        let rekey = get_opt_str_param("rekey", params).map_err(error_err!())?;
        let freshness_time = get_opt_int_param::<i64>("freshness_time", params).map_err(error_err!())?;

        let config = {
            let mut json = JSONMap::new();

            update_json_map_opt_key!(json, "key", key);
            update_json_map_opt_key!(json, "rekey", rekey);
            update_json_map_opt_key!(json, "freshness_time", freshness_time);

            if !json.is_empty() {
                Some(JSONValue::from(json).to_string())
            } else {
                None
            }
        };

        let res = Ok(())
            .and_then(|_| {
                if let Some((handle, name)) = get_opened_wallet(ctx) {
                    match Wallet::close_wallet(handle) {
                        Ok(()) => {
                            set_opened_wallet(ctx, Some((handle, name.clone())));
                            Ok(println_succ!("Wallet \"{}\" has been closed", name))
                        }
                        Err(err) => Err(println_err!("Indy SDK error occurred {:?}", err)),
                    }
                } else {
                    Ok(())
                }
            })
            .and_then(|_| {
                match Wallet::open_wallet(name, config.as_ref().map(String::as_str)) {
                    Ok(handle) => {
                        set_opened_wallet(ctx, Some((handle, name.to_owned())));
                        Ok(println_succ!("Wallet \"{}\" has been opened", name))
                    }
                    Err(ErrorCode::WalletAlreadyOpenedError) => Err(println_err!("Wallet \"{}\" already opened", name)),
                    Err(ErrorCode::CommonIOError) => Err(println_err!("Wallet \"{}\" not found or unavailable", name)),
                    Err(err) => Err(println_err!("Indy SDK error occurred {:?}", err)),
                }
            });

        trace!("execute << {:?}", res);
        Ok(())
    }

    pub fn cleanup(ctx: &CommandContext) {
        trace!("cleanup >> ctx {:?}", ctx);

        if let Some((handle, name)) = get_opened_wallet(ctx) {
            match Wallet::close_wallet(handle) {
                Ok(()) => {
                    set_opened_wallet(ctx, Some((handle, name.clone())));
                    println_succ!("Wallet \"{}\" has been closed", name)
                }
                Err(err) => println_err!("Indy SDK error occurred {:?}", err),
            }
        }

        trace!("cleanup <<");
    }
}

pub mod list_command {
    use super::*;

    command!(CommandMetadata::build("list", "List existing wallets.")
                .finalize()
    );

    fn execute(ctx: &CommandContext, params: &CommandParams) -> Result<(), ()> {
        trace!("execute >> ctx {:?} params {:?}", ctx, params);

        let res = match Wallet::list_wallets() {
            Ok(wallets) => {
                let wallets: Vec<serde_json::Value> = serde_json::from_str(&wallets)
                    .map_err(|_| println_err!("Wrong data has been received"))?;

                if wallets.len() > 0 {
                    print_table(&wallets,
                                &vec![("name", "Name"),
                                      ("associated_pool_name", "Associated pool name"),
                                      ("type", "Type")]);
                } else {
                    println_succ!("There are no wallets");
                }

                if let Some((_, cur_wallet)) = get_opened_wallet(ctx) {
                    println_succ!("Current wallet \"{}\"", cur_wallet);
                }
                Ok(())
            }
            Err(ErrorCode::CommonIOError) => Err(println_succ!("There are no wallets")),
            Err(err) => Err(println_err!("Indy SDK error occurred {:?}", err)),
        };

        trace!("execute << {:?}", res);
        res
    }
}

pub mod close_command {
    use super::*;

    command!(CommandMetadata::build("close", "Close opened wallet.").finalize());

    fn execute(ctx: &CommandContext, params: &CommandParams) -> Result<(), ()> {
        trace!("execute >> ctx {:?} params {:?}", ctx, params);

        let res = Ok(())
            .and_then(|_| {
                if let Some(wallet) = get_opened_wallet(ctx) {
                    Ok(wallet)
                } else {
                    Err(println_err!("There is no opened wallet now"))
                }
            })
            .and_then(|wallet| {
                let (handle, name) = wallet;
                match Wallet::close_wallet(handle) {
                    Ok(()) => {
                        set_opened_wallet(ctx, None);
                        Ok(println_succ!("Wallet \"{}\" has been closed", name))
                    }
                    Err(err) => Err(println_err!("Indy SDK error occurred {:?}", err)),
                }
            });

        trace!("CloseCommand::execute << {:?}", res);
        res
    }
}

pub mod delete_command {
    use super::*;

    command!(CommandMetadata::build("delete", "Delete wallet with specified name")
                .add_main_param("name", "The name of deleted wallet")
                .finalize()
    );

    fn execute(ctx: &CommandContext, params: &CommandParams) -> Result<(), ()> {
        trace!("execute >> ctx: {:?} params {:?}", ctx, params);

        let name = get_str_param("name", params).map_err(error_err!())?;

        let res = match Wallet::delete_wallet(name) {
            Ok(()) => Ok(println_succ!("Wallet \"{}\" has been deleted", name)),
            Err(ErrorCode::CommonIOError) => Err(println_err!("Wallet \"{}\" not found or unavailable", name)),
            Err(err) => Err(println_err!("Indy SDK error occurred {:?}", err)),
        };

        trace!("execute << {:?}", res);
        res
    }
}

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

    mod create {
        use super::*;

        #[test]
        pub fn exec_works() {
            TestUtils::cleanup_storage();
            let cmd = create_command::new();
            cmd.metadata().help();
            let mut params = CommandParams::new();
            params.insert("name", "wallet".to_owned());
            params.insert("pool_name", "pool".to_owned());
            cmd.execute(&CommandContext::new(), &params).unwrap();
            TestUtils::cleanup_storage();
        }
    }

    mod open {
        use super::*;

        #[test]
        pub fn exec_works() {
            TestUtils::cleanup_storage();

            let cmd = open_command::new();
            let mut params = CommandParams::new();
            cmd.metadata().help();
            params.insert("name", "wallet".to_owned());

            cmd.execute(&CommandContext::new(), &params).unwrap_err(); //open not created wallet

            TestUtils::cleanup_storage();
        }

        //TODO add open_for_created_works
    }

    mod close {
        use super::*;

        #[test]
        pub fn exec_for_opened_works() {
            TestUtils::cleanup_storage();

            let ctx = CommandContext::new();

            {
                let cmd = create_command::new();
                let mut params = CommandParams::new();
                params.insert("name", "wallet".to_owned());
                params.insert("pool_name", "pool".to_owned());
                cmd.execute(&ctx, &params).unwrap();
            }

            {
                let cmd = open_command::new();
                let mut params = CommandParams::new();
                params.insert("name", "wallet".to_owned());
                cmd.execute(&ctx, &params).unwrap();
            }

            {
                let cmd = close_command::new();
                let params = CommandParams::new();
                cmd.execute(&ctx, &params).unwrap();
            }

            TestUtils::cleanup_storage();
        }
    }
}<commit_msg>[cli] Fix open wallet command ::execute.<commit_after>use command_executor::{Command, CommandContext, CommandMetadata, CommandParams, CommandGroup, CommandGroupMetadata};
use commands::*;
use utils::table::print_table;
use libindy::ErrorCode;
use libindy::wallet::Wallet;

use serde_json;
use serde_json::Value as JSONValue;
use serde_json::Map as JSONMap;

pub mod group {
    use super::*;

    command_group!(CommandGroupMetadata::new("wallet", "Wallet management commands"));
}

pub mod create_command {
    use super::*;

    command!(CommandMetadata::build("create", "Create new wallet with specified name")
                .add_main_param("name", "The name of new wallet")
                .add_param("pool_name", false, "The name of associated Indy pool")
                .add_param("key", true, "Auth key for the wallet")
                .finalize()
    );

    fn execute(ctx: &CommandContext, params: &CommandParams) -> Result<(), ()> {
        trace!("execute >> ctx {:?} params {:?}", ctx, params);

        let pool_name = get_str_param("pool_name", params).map_err(error_err!())?;
        let name = get_str_param("name", params).map_err(error_err!())?;
        let key = get_opt_str_param("key", params).map_err(error_err!())?;

        let config: Option<String> = key.map(|key| json!({ "key": key }).to_string());

        trace!("Wallet::create_wallet try: name {}, pool_name {}, config {:?}", name, pool_name, config);

        let res = Wallet::create_wallet(pool_name,
                                        name,
                                        None,
                                        config.as_ref().map(String::as_str));

        trace!("Wallet::create_wallet return: {:?}", res);

        let res = match res {
            Ok(()) => Ok(println_succ!("Wallet \"{}\" has been created", name)),
            Err(ErrorCode::WalletAlreadyExistsError) => Err(println_err!("Wallet \"{}\" already exists", name)),
            Err(err) => return Err(println_err!("Indy SDK error occurred {:?}", err)),
        };

        trace!("execute << {:?}", res);
        res
    }
}

pub mod open_command {
    use super::*;

    command_with_cleanup!(CommandMetadata::build("open", "Open wallet with specified name. Also close previously opened.")
                            .add_main_param("name", "The name of wallet")
                            .add_param("key", true, "Auth key for the wallet")
                            .add_param("rekey", true, "New auth key for the wallet (will replace previous one).")
                            .add_param("freshness_time", true, "Freshness time for entities in the wallet")
                            .finalize());

    fn execute(ctx: &CommandContext, params: &CommandParams) -> Result<(), ()> {
        trace!("execute >> ctx {:?} params {:?}", ctx, params);

        let name = get_str_param("name", params).map_err(error_err!())?;
        let key = get_opt_str_param("key", params).map_err(error_err!())?;
        let rekey = get_opt_str_param("rekey", params).map_err(error_err!())?;
        let freshness_time = get_opt_int_param::<i64>("freshness_time", params).map_err(error_err!())?;

        let config = {
            let mut json = JSONMap::new();

            update_json_map_opt_key!(json, "key", key);
            update_json_map_opt_key!(json, "rekey", rekey);
            update_json_map_opt_key!(json, "freshness_time", freshness_time);

            if !json.is_empty() {
                Some(JSONValue::from(json).to_string())
            } else {
                None
            }
        };

        let res = Ok(())
            .and_then(|_| {
                if let Some((handle, name)) = get_opened_wallet(ctx) {
                    match Wallet::close_wallet(handle) {
                        Ok(()) => {
                            set_opened_wallet(ctx, Some((handle, name.clone())));
                            Ok(println_succ!("Wallet \"{}\" has been closed", name))
                        }
                        Err(err) => Err(println_err!("Indy SDK error occurred {:?}", err)),
                    }
                } else {
                    Ok(())
                }
            })
            .and_then(|_| {
                match Wallet::open_wallet(name, config.as_ref().map(String::as_str)) {
                    Ok(handle) => {
                        set_opened_wallet(ctx, Some((handle, name.to_owned())));
                        Ok(println_succ!("Wallet \"{}\" has been opened", name))
                    }
                    Err(ErrorCode::WalletAlreadyOpenedError) => Err(println_err!("Wallet \"{}\" already opened", name)),
                    Err(ErrorCode::CommonIOError) => Err(println_err!("Wallet \"{}\" not found or unavailable", name)),
                    Err(err) => Err(println_err!("Indy SDK error occurred {:?}", err)),
                }
            });

        trace!("execute << {:?}", res);
        res
    }

    pub fn cleanup(ctx: &CommandContext) {
        trace!("cleanup >> ctx {:?}", ctx);

        if let Some((handle, name)) = get_opened_wallet(ctx) {
            match Wallet::close_wallet(handle) {
                Ok(()) => {
                    set_opened_wallet(ctx, Some((handle, name.clone())));
                    println_succ!("Wallet \"{}\" has been closed", name)
                }
                Err(err) => println_err!("Indy SDK error occurred {:?}", err),
            }
        }

        trace!("cleanup <<");
    }
}

pub mod list_command {
    use super::*;

    command!(CommandMetadata::build("list", "List existing wallets.")
                .finalize()
    );

    fn execute(ctx: &CommandContext, params: &CommandParams) -> Result<(), ()> {
        trace!("execute >> ctx {:?} params {:?}", ctx, params);

        let res = match Wallet::list_wallets() {
            Ok(wallets) => {
                let wallets: Vec<serde_json::Value> = serde_json::from_str(&wallets)
                    .map_err(|_| println_err!("Wrong data has been received"))?;

                if wallets.len() > 0 {
                    print_table(&wallets,
                                &vec![("name", "Name"),
                                      ("associated_pool_name", "Associated pool name"),
                                      ("type", "Type")]);
                } else {
                    println_succ!("There are no wallets");
                }

                if let Some((_, cur_wallet)) = get_opened_wallet(ctx) {
                    println_succ!("Current wallet \"{}\"", cur_wallet);
                }
                Ok(())
            }
            Err(ErrorCode::CommonIOError) => Err(println_succ!("There are no wallets")),
            Err(err) => Err(println_err!("Indy SDK error occurred {:?}", err)),
        };

        trace!("execute << {:?}", res);
        res
    }
}

pub mod close_command {
    use super::*;

    command!(CommandMetadata::build("close", "Close opened wallet.").finalize());

    fn execute(ctx: &CommandContext, params: &CommandParams) -> Result<(), ()> {
        trace!("execute >> ctx {:?} params {:?}", ctx, params);

        let res = Ok(())
            .and_then(|_| {
                if let Some(wallet) = get_opened_wallet(ctx) {
                    Ok(wallet)
                } else {
                    Err(println_err!("There is no opened wallet now"))
                }
            })
            .and_then(|wallet| {
                let (handle, name) = wallet;
                match Wallet::close_wallet(handle) {
                    Ok(()) => {
                        set_opened_wallet(ctx, None);
                        Ok(println_succ!("Wallet \"{}\" has been closed", name))
                    }
                    Err(err) => Err(println_err!("Indy SDK error occurred {:?}", err)),
                }
            });

        trace!("CloseCommand::execute << {:?}", res);
        res
    }
}

pub mod delete_command {
    use super::*;

    command!(CommandMetadata::build("delete", "Delete wallet with specified name")
                .add_main_param("name", "The name of deleted wallet")
                .finalize()
    );

    fn execute(ctx: &CommandContext, params: &CommandParams) -> Result<(), ()> {
        trace!("execute >> ctx: {:?} params {:?}", ctx, params);

        let name = get_str_param("name", params).map_err(error_err!())?;

        let res = match Wallet::delete_wallet(name) {
            Ok(()) => Ok(println_succ!("Wallet \"{}\" has been deleted", name)),
            Err(ErrorCode::CommonIOError) => Err(println_err!("Wallet \"{}\" not found or unavailable", name)),
            Err(err) => Err(println_err!("Indy SDK error occurred {:?}", err)),
        };

        trace!("execute << {:?}", res);
        res
    }
}

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

    mod create {
        use super::*;

        #[test]
        pub fn exec_works() {
            TestUtils::cleanup_storage();
            let cmd = create_command::new();
            cmd.metadata().help();
            let mut params = CommandParams::new();
            params.insert("name", "wallet".to_owned());
            params.insert("pool_name", "pool".to_owned());
            cmd.execute(&CommandContext::new(), &params).unwrap();
            TestUtils::cleanup_storage();
        }
    }

    mod open {
        use super::*;

        #[test]
        pub fn exec_works() {
            TestUtils::cleanup_storage();

            let cmd = open_command::new();
            let mut params = CommandParams::new();
            cmd.metadata().help();
            params.insert("name", "wallet".to_owned());

            cmd.execute(&CommandContext::new(), &params).unwrap_err(); //open not created wallet

            TestUtils::cleanup_storage();
        }

        //TODO add open_for_created_works
    }

    mod close {
        use super::*;

        #[test]
        pub fn exec_for_opened_works() {
            TestUtils::cleanup_storage();

            let ctx = CommandContext::new();

            {
                let cmd = create_command::new();
                let mut params = CommandParams::new();
                params.insert("name", "wallet".to_owned());
                params.insert("pool_name", "pool".to_owned());
                cmd.execute(&ctx, &params).unwrap();
            }

            {
                let cmd = open_command::new();
                let mut params = CommandParams::new();
                params.insert("name", "wallet".to_owned());
                cmd.execute(&ctx, &params).unwrap();
            }

            {
                let cmd = close_command::new();
                let params = CommandParams::new();
                cmd.execute(&ctx, &params).unwrap();
            }

            TestUtils::cleanup_storage();
        }
    }
}<|endoftext|>


<commit_before>class c { //~ ERROR a class must have at least one field
    new() { }
}

fn main() {
    let a = c();
    let x = ~[a];
    let _y = x[0];
}
<commit_msg>Fix sub-breakage due to the changed error message.<commit_after>class c { //~ ERROR a struct must have at least one field
    new() { }
}

fn main() {
    let a = c();
    let x = ~[a];
    let _y = x[0];
}
<|endoftext|>


<commit_before><commit_msg>chore(Chrome binary): Update installable version<commit_after><|endoftext|>


<commit_before>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::io;
use std::mem::{align_of, size_of};
use std::slice::{from_raw_parts, from_raw_parts_mut};

/// Types for which it is safe to initialize from raw data.
///
/// A type `T` is `DataInit` if and only if it can be initialized by reading its contents from a
/// byte array.  This is generally true for all plain-old-data structs.  It is notably not true for
/// any type that includes a reference.
///
/// Implementing this trait guarantees that it is safe to instantiate the struct with random data.
pub unsafe trait DataInit: Copy + Send + Sync {
    /// Converts a slice of raw data into a reference of `Self`.
    ///
    /// The value of `data` is not copied. Instead a reference is made from the given slice. The
    /// value of `Self` will depend on the representation of the type in memory, and may change in
    /// an unstable fashion.
    ///
    /// This will return `None` if the length of data does not match the size of `Self`, or if the
    /// data is not aligned for the type of `Self`.
    fn from_slice(data: &[u8]) -> Option<&Self> {
        // Early out to avoid an unneeded `align_to` call.
        if data.len() != size_of::<Self>() {
            return None;
        }

        // Safe because the DataInit trait asserts any data is valid for this type, and we ensured
        // the size of the pointer's buffer is the correct size. The `align_to` method ensures that
        // we don't have any unaligned references. This aliases a pointer, but because the pointer
        // is from a const slice reference, there are no mutable aliases. Finally, the reference
        // returned can not outlive data because they have equal implicit lifetime constraints.
        match unsafe { data.align_to::<Self>() } {
            ([], [mid], []) => Some(mid),
            _ => None,
        }
    }

    /// Converts a mutable slice of raw data into a mutable reference of `Self`.
    ///
    /// Because `Self` is made from a reference to the mutable slice`, mutations to the returned
    /// reference are immediately reflected in `data`. The value of the returned `Self` will depend
    /// on the representation of the type in memory, and may change in an unstable fashion.
    ///
    /// This will return `None` if the length of data does not match the size of `Self`, or if the
    /// data is not aligned for the type of `Self`.
    fn from_mut_slice(data: &mut [u8]) -> Option<&mut Self> {
        // Early out to avoid an unneeded `align_to_mut` call.
        if data.len() != size_of::<Self>() {
            return None;
        }

        // Safe because the DataInit trait asserts any data is valid for this type, and we ensured
        // the size of the pointer's buffer is the correct size. The `align_to` method ensures that
        // we don't have any unaligned references. This aliases a pointer, but because the pointer
        // is from a mut slice reference, we borrow the passed in mutable reference. Finally, the
        // reference returned can not outlive data because they have equal implicit lifetime
        // constraints.
        match unsafe { data.align_to_mut::<Self>() } {
            ([], [mid], []) => Some(mid),
            _ => None,
        }
    }

    /// Creates an instance of `Self` by copying raw data from an io::Read stream.
    fn from_reader<R: io::Read>(mut read: R) -> io::Result<Self> {
        // Allocate a Vec<u8> with enough extra space for the worst-case alignment offset.
        let mut data = vec![0u8; size_of::<Self>() + align_of::<Self>()];

        // Get a u8 slice within data with sufficient alignment for Self.
        let align_offset = data.as_ptr().align_offset(align_of::<Self>());
        let mut aligned_data = &mut data[align_offset..align_offset + size_of::<Self>()];

        read.read_exact(&mut aligned_data)?;
        match Self::from_slice(&aligned_data) {
            Some(obj) => Ok(*obj),
            None => Err(io::Error::new(
                io::ErrorKind::InvalidData,
                "from_slice failed",
            )),
        }
    }

    /// Converts a reference to `self` into a slice of bytes.
    ///
    /// The value of `self` is not copied. Instead, the slice is made from a reference to `self`.
    /// The value of bytes in the returned slice will depend on the representation of the type in
    /// memory, and may change in an unstable fashion.
    fn as_slice(&self) -> &[u8] {
        // Safe because the entire size of self is accessible as bytes because the trait guarantees
        // it. The lifetime of the returned slice is the same as the passed reference, so that no
        // dangling pointers will result from this pointer alias.
        unsafe { from_raw_parts(self as *const Self as *const u8, size_of::<Self>()) }
    }

    /// Converts a mutable reference to `self` into a mutable slice of bytes.
    ///
    /// Because the slice is made from a reference to `self`, mutations to the returned slice are
    /// immediately reflected in `self`. The value of bytes in the returned slice will depend on
    /// the representation of the type in memory, and may change in an unstable fashion.
    fn as_mut_slice(&mut self) -> &mut [u8] {
        // Safe because the entire size of self is accessible as bytes because the trait guarantees
        // it. The trait also guarantees that any combination of bytes is valid for this type, so
        // modifying them in the form of a byte slice is valid. The lifetime of the returned slice
        // is the same as the passed reference, so that no dangling pointers will result from this
        // pointer alias. Although this does alias a mutable pointer, we do so by exclusively
        // borrowing the given mutable reference.
        unsafe { from_raw_parts_mut(self as *mut Self as *mut u8, size_of::<Self>()) }
    }
}

// All intrinsic types and arays of intrinsic types are DataInit.  They are just numbers.
macro_rules! array_data_init {
    ($T:ty, $($N:expr)+) => {
        $(
            unsafe impl DataInit for [$T; $N] {}
        )+
    }
}
macro_rules! data_init_type {
    ($($T:ident),*) => {
        $(
            unsafe impl DataInit for $T {}
            array_data_init! {
                $T,
                0  1  2  3  4  5  6  7  8  9
                10 11 12 13 14 15 16 17 18 19
                20 21 22 23 24 25 26 27 28 29
                30 31 32
            }
        )*
        #[cfg(test)]
        mod data_init_tests {
            use std::mem::{size_of, align_of};
            use crate::DataInit;

            #[test]
            fn from_slice_alignment() {
                let mut v = [0u8; 32];
                $(
                    let (pre, _, _) = unsafe { v.align_to::<$T>() };
                    let pre_len = pre.len();

                    let aligned_v = &mut v[pre_len..pre_len + size_of::<$T>()];

                    let from_aligned = $T::from_slice(aligned_v);
                    assert_eq!(from_aligned, Some(&0));

                    let from_aligned_mut = $T::from_mut_slice(aligned_v);
                    assert_eq!(from_aligned_mut, Some(&mut 0));

                    for i in 1..size_of::<$T>() {
                        let begin = pre_len + i;
                        let end = begin + size_of::<$T>();
                        let unaligned_v = &mut v[begin..end];

                        let from_unaligned = $T::from_slice(unaligned_v);
                        if align_of::<$T>() != 1 {
                            assert_eq!(from_unaligned, None);
                        }

                        let from_unaligned_mut = $T::from_mut_slice(unaligned_v);
                        if align_of::<$T>() != 1 {
                            assert_eq!(from_unaligned_mut, None);
                        }
                    }
                )*

            }
        }
    };
}
data_init_type!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);

pub mod endian;
pub use crate::endian::*;

pub mod volatile_memory;
pub use crate::volatile_memory::*;

mod flexible_array;
pub use flexible_array::{vec_with_array_field, FlexibleArray, FlexibleArrayWrapper};

mod sys;
<commit_msg>Update safety comments for DataInit.<commit_after>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::io;
use std::mem::{align_of, size_of};
use std::slice::{from_raw_parts, from_raw_parts_mut};

/// Types for which it is safe to initialize from raw data.
///
///
/// Implementing this trait guarantees that it is safe to instantiate the struct with random data.
///
/// # Safety
/// A type `T` is `DataInit` if it can be initialized by reading its contents from a byte array.
/// This is generally true for all plain-old-data structs.  It is notably not true for any type
/// that includes a reference.
///
/// It is unsafe for `T` to be `DataInit` if `T` contains implicit padding. (LLVM considers access
/// to implicit padding to be undefined behavior, which can cause UB when working with `T`.
/// For details on structure padding in Rust, see
/// https://doc.rust-lang.org/reference/type-layout.html#the-c-representation
pub unsafe trait DataInit: Copy + Send + Sync {
    /// Converts a slice of raw data into a reference of `Self`.
    ///
    /// The value of `data` is not copied. Instead a reference is made from the given slice. The
    /// value of `Self` will depend on the representation of the type in memory, and may change in
    /// an unstable fashion.
    ///
    /// This will return `None` if the length of data does not match the size of `Self`, or if the
    /// data is not aligned for the type of `Self`.
    fn from_slice(data: &[u8]) -> Option<&Self> {
        // Early out to avoid an unneeded `align_to` call.
        if data.len() != size_of::<Self>() {
            return None;
        }

        // Safe because the DataInit trait asserts any data is valid for this type, and we ensured
        // the size of the pointer's buffer is the correct size. The `align_to` method ensures that
        // we don't have any unaligned references. This aliases a pointer, but because the pointer
        // is from a const slice reference, there are no mutable aliases. Finally, the reference
        // returned can not outlive data because they have equal implicit lifetime constraints.
        match unsafe { data.align_to::<Self>() } {
            ([], [mid], []) => Some(mid),
            _ => None,
        }
    }

    /// Converts a mutable slice of raw data into a mutable reference of `Self`.
    ///
    /// Because `Self` is made from a reference to the mutable slice`, mutations to the returned
    /// reference are immediately reflected in `data`. The value of the returned `Self` will depend
    /// on the representation of the type in memory, and may change in an unstable fashion.
    ///
    /// This will return `None` if the length of data does not match the size of `Self`, or if the
    /// data is not aligned for the type of `Self`.
    fn from_mut_slice(data: &mut [u8]) -> Option<&mut Self> {
        // Early out to avoid an unneeded `align_to_mut` call.
        if data.len() != size_of::<Self>() {
            return None;
        }

        // Safe because the DataInit trait asserts any data is valid for this type, and we ensured
        // the size of the pointer's buffer is the correct size. The `align_to` method ensures that
        // we don't have any unaligned references. This aliases a pointer, but because the pointer
        // is from a mut slice reference, we borrow the passed in mutable reference. Finally, the
        // reference returned can not outlive data because they have equal implicit lifetime
        // constraints.
        match unsafe { data.align_to_mut::<Self>() } {
            ([], [mid], []) => Some(mid),
            _ => None,
        }
    }

    /// Creates an instance of `Self` by copying raw data from an io::Read stream.
    fn from_reader<R: io::Read>(mut read: R) -> io::Result<Self> {
        // Allocate a Vec<u8> with enough extra space for the worst-case alignment offset.
        let mut data = vec![0u8; size_of::<Self>() + align_of::<Self>()];

        // Get a u8 slice within data with sufficient alignment for Self.
        let align_offset = data.as_ptr().align_offset(align_of::<Self>());
        let mut aligned_data = &mut data[align_offset..align_offset + size_of::<Self>()];

        read.read_exact(&mut aligned_data)?;
        match Self::from_slice(&aligned_data) {
            Some(obj) => Ok(*obj),
            None => Err(io::Error::new(
                io::ErrorKind::InvalidData,
                "from_slice failed",
            )),
        }
    }

    /// Converts a reference to `self` into a slice of bytes.
    ///
    /// The value of `self` is not copied. Instead, the slice is made from a reference to `self`.
    /// The value of bytes in the returned slice will depend on the representation of the type in
    /// memory, and may change in an unstable fashion.
    fn as_slice(&self) -> &[u8] {
        // Safe because the entire size of self is accessible as bytes because the trait guarantees
        // it. The lifetime of the returned slice is the same as the passed reference, so that no
        // dangling pointers will result from this pointer alias.
        unsafe { from_raw_parts(self as *const Self as *const u8, size_of::<Self>()) }
    }

    /// Converts a mutable reference to `self` into a mutable slice of bytes.
    ///
    /// Because the slice is made from a reference to `self`, mutations to the returned slice are
    /// immediately reflected in `self`. The value of bytes in the returned slice will depend on
    /// the representation of the type in memory, and may change in an unstable fashion.
    fn as_mut_slice(&mut self) -> &mut [u8] {
        // Safe because the entire size of self is accessible as bytes because the trait guarantees
        // it. The trait also guarantees that any combination of bytes is valid for this type, so
        // modifying them in the form of a byte slice is valid. The lifetime of the returned slice
        // is the same as the passed reference, so that no dangling pointers will result from this
        // pointer alias. Although this does alias a mutable pointer, we do so by exclusively
        // borrowing the given mutable reference.
        unsafe { from_raw_parts_mut(self as *mut Self as *mut u8, size_of::<Self>()) }
    }
}

// All intrinsic types and arays of intrinsic types are DataInit.  They are just numbers.
macro_rules! array_data_init {
    ($T:ty, $($N:expr)+) => {
        $(
            unsafe impl DataInit for [$T; $N] {}
        )+
    }
}
macro_rules! data_init_type {
    ($($T:ident),*) => {
        $(
            unsafe impl DataInit for $T {}
            array_data_init! {
                $T,
                0  1  2  3  4  5  6  7  8  9
                10 11 12 13 14 15 16 17 18 19
                20 21 22 23 24 25 26 27 28 29
                30 31 32
            }
        )*
        #[cfg(test)]
        mod data_init_tests {
            use std::mem::{size_of, align_of};
            use crate::DataInit;

            #[test]
            fn from_slice_alignment() {
                let mut v = [0u8; 32];
                $(
                    let (pre, _, _) = unsafe { v.align_to::<$T>() };
                    let pre_len = pre.len();

                    let aligned_v = &mut v[pre_len..pre_len + size_of::<$T>()];

                    let from_aligned = $T::from_slice(aligned_v);
                    assert_eq!(from_aligned, Some(&0));

                    let from_aligned_mut = $T::from_mut_slice(aligned_v);
                    assert_eq!(from_aligned_mut, Some(&mut 0));

                    for i in 1..size_of::<$T>() {
                        let begin = pre_len + i;
                        let end = begin + size_of::<$T>();
                        let unaligned_v = &mut v[begin..end];

                        let from_unaligned = $T::from_slice(unaligned_v);
                        if align_of::<$T>() != 1 {
                            assert_eq!(from_unaligned, None);
                        }

                        let from_unaligned_mut = $T::from_mut_slice(unaligned_v);
                        if align_of::<$T>() != 1 {
                            assert_eq!(from_unaligned_mut, None);
                        }
                    }
                )*

            }
        }
    };
}
data_init_type!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);

pub mod endian;
pub use crate::endian::*;

pub mod volatile_memory;
pub use crate::volatile_memory::*;

mod flexible_array;
pub use flexible_array::{vec_with_array_field, FlexibleArray, FlexibleArrayWrapper};

mod sys;
<|endoftext|>


<commit_before>
#![feature(globs)]

extern crate shader_version;
extern crate graphics;
extern crate event;
extern crate sdl2_window;
extern crate gfx;
extern crate gfx_graphics;
extern crate sdl2;

use event::{
    EventIterator,
    EventSettings,
    Window,
    WindowSettings,
};
use gfx::{Device, DeviceHelper};
use gfx_graphics::{
    G2D,
    Texture,
};
use sdl2_window::Sdl2Window;

fn main() {
    let opengl = shader_version::opengl::OpenGL_3_2;
    let mut window = Sdl2Window::new(
        opengl,
        WindowSettings {
            title: "gfx_graphics: imagetest".to_string(),
            size: [300, 300],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    let mut device = gfx::GlDevice::new(|s| unsafe {
        std::mem::transmute(sdl2::video::gl_get_proc_address(s))
    });
    let (w, h) = window.get_size();
    let frame = gfx::Frame::new(w as u16, h as u16);
    let mut renderer = device.create_renderer();

    let image = Texture::from_path(&mut device,
        &Path::new("rust.png")).unwrap();
    let event_settings = EventSettings {
            updates_per_second: 120,
            max_frames_per_second: 60,
        };
    let mut g2d = G2D::new(&mut device);
    for e in EventIterator::new(&mut window, &event_settings) {
        use event::RenderEvent;
        e.render(|_| {
            g2d.draw(&mut renderer, &frame, |c, g| {
                use graphics::*;
                c.rgb(1.0, 1.0, 1.0).draw(g);
                c.rect(0.0, 0.0, 100.0, 100.0).rgb(1.0, 0.0, 0.0).draw(g);
                c.rect(50.0, 50.0, 100.0, 100.0).rgba(0.0, 1.0, 0.0, 0.3).draw(g);
                c.trans(100.0, 100.0).image(&image).draw(g);
            });

            device.submit(renderer.as_buffer());
            renderer.reset();
       });
    }
}
<commit_msg>Upgraded to latest piston-event<commit_after>
#![feature(globs)]

extern crate shader_version;
extern crate graphics;
extern crate event;
extern crate sdl2_window;
extern crate gfx;
extern crate gfx_graphics;
extern crate sdl2;

use std::cell::RefCell;
use event::{
    Events,
    Window,
    WindowSettings,
};
use gfx::{Device, DeviceHelper};
use gfx_graphics::{
    G2D,
    Texture,
};
use sdl2_window::Sdl2Window;

fn main() {
    let opengl = shader_version::opengl::OpenGL_3_2;
    let window = Sdl2Window::new(
        opengl,
        WindowSettings {
            title: "gfx_graphics: imagetest".to_string(),
            size: [300, 300],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    let mut device = gfx::GlDevice::new(|s| unsafe {
        std::mem::transmute(sdl2::video::gl_get_proc_address(s))
    });
    let (w, h) = window.get_size();
    let frame = gfx::Frame::new(w as u16, h as u16);
    let mut renderer = device.create_renderer();

    let image = Texture::from_path(&mut device,
        &Path::new("rust.png")).unwrap();
    let mut g2d = G2D::new(&mut device);
    let window = RefCell::new(window);
    for e in Events::new(&window) {
        use event::RenderEvent;
        e.render(|_| {
            g2d.draw(&mut renderer, &frame, |c, g| {
                use graphics::*;
                c.rgb(1.0, 1.0, 1.0).draw(g);
                c.rect(0.0, 0.0, 100.0, 100.0).rgb(1.0, 0.0, 0.0).draw(g);
                c.rect(50.0, 50.0, 100.0, 100.0).rgba(0.0, 1.0, 0.0, 0.3).draw(g);
                c.trans(100.0, 100.0).image(&image).draw(g);
            });

            device.submit(renderer.as_buffer());
            renderer.reset();
       });
    }
}
<|endoftext|>


<commit_before>// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers
//
// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc.
// and the party accessing this file ("Licensee") apply to Licensee's use of
// the Software until such time that the Software is made available under an
// open source license such as the Apache 2.0 License.

#[macro_use]
extern crate habitat_sup as sup;
extern crate habitat_core as hcore;
extern crate rustc_serialize;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate ansi_term;
extern crate libc;
#[macro_use]
extern crate clap;

use std::process;
use std::result;
use std::str::FromStr;

use ansi_term::Colour::Yellow;
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
use hcore::env as henv;
use hcore::fs;
use hcore::crypto::{default_cache_key_path, SymKey};
use hcore::crypto::init as crypto_init;
use hcore::package::PackageIdent;
use hcore::url::{DEFAULT_DEPOT_URL, DEPOT_URL_ENVVAR};

use sup::config::{Command, Config, UpdateStrategy};
use sup::error::{Error, Result, SupError};
use sup::command::*;
use sup::topology::Topology;
use sup::util::parse_ip_port_with_defaults;
use sup::util::sys::ip;

/// Our output key
static LOGKEY: &'static str = "MN";

/// The version number
const VERSION: &'static str = include_str!(concat!(env!("OUT_DIR"), "/VERSION"));

/// CLI defaults
static DEFAULT_GROUP: &'static str = "default";
static DEFAULT_SIDECAR_LISTEN_IP_PORT: &'static str = "0.0.0.0:9631";

const DEFAULT_GOSSIP_LISTEN_PORT: u16 = 9634;

static RING_ENVVAR: &'static str = "HAB_RING";
static RING_KEY_ENVVAR: &'static str = "HAB_RING_KEY";

/// Creates a [Config](config/struct.Config.html) from global args
/// and subcommand args.
fn config_from_args(args: &ArgMatches, subcommand: &str, sub_args: &ArgMatches) -> Result<Config> {
    let mut config = Config::new();
    let command = try!(Command::from_str(subcommand));
    config.set_command(command);
    if let Some(ref strategy) = sub_args.value_of("strategy") {
        config.set_update_strategy(UpdateStrategy::from_str(strategy));
    }
    if let Some(ref archive) = sub_args.value_of("archive") {
        config.set_archive(archive.to_string());
    }
    if let Some(ref package) = sub_args.value_of("package") {
        let ident = try!(PackageIdent::from_str(package));
        config.set_package(ident);
    }
    if let Some(key) = sub_args.value_of("key") {
        config.set_key(key.to_string());
    }
    if let Some(email) = sub_args.value_of("email") {
        config.set_email(email.to_string());
    }
    if let Some(user) = sub_args.value_of("user") {
        config.set_user_key(user.to_string());
    }
    if let Some(service) = sub_args.value_of("service") {
        config.set_service_key(service.to_string());
    }
    if let Some(infile) = sub_args.value_of("infile") {
        config.set_infile(infile.to_string());
    }
    if let Some(outfile) = sub_args.value_of("outfile") {
        config.set_outfile(outfile.to_string());
    }
    if let Some(topology) = sub_args.value_of("topology") {
        match topology.as_ref() {
            "standalone" => {
                config.set_topology(Topology::Standalone);
            }
            "leader" => {
                config.set_topology(Topology::Leader);
            }
            "initializer" => {
                config.set_topology(Topology::Initializer);
            }
            t => return Err(sup_error!(Error::UnknownTopology(String::from(t)))),
        }
    }
    if sub_args.value_of("expire-days").is_some() {
        let ed = value_t!(sub_args.value_of("expire-days"), u16).unwrap_or_else(|e| e.exit());
        config.set_expire_days(ed);
    }
    let env_or_default = henv::var(DEPOT_URL_ENVVAR).unwrap_or(DEFAULT_DEPOT_URL.to_string());
    let url = sub_args.value_of("url").unwrap_or(&env_or_default);
    config.set_url(url.to_string());
    config.set_group(sub_args.value_of("group").unwrap_or(DEFAULT_GROUP).to_string());
    let bindings = match sub_args.values_of("bind") {
        Some(bind) => bind.map(|s| s.to_string()).collect(),
        None => vec![],
    };
    config.set_bind(bindings);
    config.set_path(sub_args.value_of("path")
                            .unwrap_or(fs::svc_path(sup::PROGRAM_NAME.as_str())
                                           .join("data")
                                           .to_string_lossy()
                                           .as_ref())
                            .to_string());

    let default_gossip_ip = try!(ip());
    let (gossip_ip, gossip_port) = try!(parse_ip_port_with_defaults(
                                        sub_args.value_of("listen-peer"),
                                        &default_gossip_ip,
                                        DEFAULT_GOSSIP_LISTEN_PORT));

    debug!("Gossip IP = {}", &gossip_ip);
    debug!("Gossip Port = {}", &gossip_port);
    config.set_gossip_listen_ip(gossip_ip);
    config.set_gossip_listen_port(gossip_port);
    config.set_sidecar_listen(sub_args.value_of("listen-sidecar")
                                      .unwrap_or(DEFAULT_SIDECAR_LISTEN_IP_PORT)
                                      .to_string());
    let gossip_peers = match sub_args.values_of("peer") {
        Some(gp) => gp.map(|s| s.to_string()).collect(),
        None => vec![],
    };
    config.set_gossip_peer(gossip_peers);
    if sub_args.value_of("permanent-peer").is_some() {
        config.set_gossip_permanent(true);
    }
    if let Some(sg) = sub_args.value_of("service-group") {
        config.set_service_group(sg.to_string());
    }
    if let Some(fp) = sub_args.value_of("file-path") {
        config.set_file_path(fp.to_string());
    }
    config.set_version_number(value_t!(sub_args, "version-number", u64).unwrap_or(0));
    let ring = match sub_args.value_of("ring") {
        Some(val) => Some(try!(SymKey::get_latest_pair_for(&val, &default_cache_key_path(None)))),
        None => {
            match henv::var(RING_KEY_ENVVAR) {
                Ok(val) => {
                    Some(try!(SymKey::write_file_from_str(&val, &default_cache_key_path(None))))
                }
                Err(_) => {
                    match henv::var(RING_ENVVAR) {
                        Ok(val) => {
                            Some(try!(SymKey::get_latest_pair_for(&val,
                                                                  &default_cache_key_path(None))))
                        }
                        Err(_) => None,
                    }
                }
            }
        }
    };
    if let Some(ring) = ring {
        config.set_ring(ring.name_with_rev());
    }
    if args.value_of("verbose").is_some() {
        sup::output::set_verbose(true);
    }
    if args.value_of("no-color").is_some() {
        sup::output::set_no_color(true);
    }

    if let Some(org) = sub_args.value_of("organization") {
        config.set_organization(org.to_string());
    }
    debug!("Config:\n{:?}", config);
    Ok(config)
}

type Handler = fn(&Config) -> result::Result<(), sup::error::SupError>;

/// The entrypoint for the Supervisor.
///
/// * Set up the logger
/// * Pull in the arguments from the Command Line, push through clap
/// * Dispatch to a function that handles that action called
/// * Exit cleanly, or if we return an `Error`, call `exit_with(E, 1)`
#[allow(dead_code)]
fn main() {
    env_logger::init().unwrap();
    crypto_init();

    let arg_url = || {
        Arg::with_name("url")
            .short("u")
            .long("url")
            .takes_value(true)
            .help("Use the specified package depot url")
    };
    let arg_group = || {
        Arg::with_name("group")
            .long("group")
            .takes_value(true)
            .help("The service group; shared config and topology [default: default].")
    };

    let arg_org = || {
        Arg::with_name("organization")
            .long("org")
            .takes_value(true)
            .help("The organization that a service is part of")
    };

    let arg_strategy = || {
        Arg::with_name("strategy")
            .long("strategy")
            .short("s")
            .takes_value(true)
            .possible_values(&["none", "at-once"])
            .help("The update strategy; [default: none].")
    };

    let sub_start = SubCommand::with_name("start")
                        .about("Start a Habitat-supervised service from a package")
                        .arg(Arg::with_name("package")
                                 .index(1)
                                 .required(true)
                                 .help("Name of package to start"))
                        .arg(arg_url())
                        .arg(arg_group())
                        .arg(arg_org())
                        .arg(arg_strategy())
                        .arg(Arg::with_name("topology")
                                 .short("t")
                                 .long("topology")
                                 .value_name("topology")
                                 .help("Service topology"))
                        .arg(Arg::with_name("bind")
                                 .long("bind")
                                 .value_name("bind")
                                 .multiple(true)
                                 .help("One or more service groups to bind to a configuration"))
                        .arg(Arg::with_name("ring")
                                 .short("r")
                                 .long("ring")
                                 .value_name("ring")
                                 .help("Ring key name"))
                        .arg(Arg::with_name("peer")
                                 .long("peer")
                                 .value_name("ip:port")
                                 .multiple(true)
                                 .help("The listen address of an initial peer"))
                        .arg(Arg::with_name("listen-peer")
                                 .long("listen-peer")
                                 .value_name("ip:port")
                                 .help("The listen address [default: ip_with_default_route:9634]"))
                        .arg(Arg::with_name("listen-sidecar")
                                 .long("listen-sidecar")
                                 .value_name("ip:port")
                                 .help("The sidecar listen address [default: 0.0.0.0:9631]"))
                        .arg(Arg::with_name("permanent-peer")
                                 .short("I")
                                 .long("permanent-peer")
                                 .help("If this service is a permanent peer"));
    let sub_bash = SubCommand::with_name("bash").about("Start an interactive shell (bash)");
    let sub_sh = SubCommand::with_name("sh").about("Start an interactive shell (sh)");
    let sub_config = SubCommand::with_name("config")
                         .about("Print the default.toml for a given package")
                         .arg(Arg::with_name("package")
                                  .index(1)
                                  .required(true)
                                  .help("Name of package"));
    let args = App::new(sup::PROGRAM_NAME.as_str())
                   .version(VERSION)
                   .setting(AppSettings::VersionlessSubcommands)
                   .setting(AppSettings::SubcommandRequiredElseHelp)
                   .arg(Arg::with_name("verbose")
                            .short("v")
                            .global(true)
                            .help("Verbose output; shows line numbers"))
                   .arg(Arg::with_name("no-color")
                            .long("no-color")
                            .global(true)
                            .help("Turn ANSI color off :("))
                   .subcommand(sub_start)
                   .subcommand(sub_bash)
                   .subcommand(sub_sh)
                   .subcommand(sub_config);
    let matches = args.get_matches();

    debug!("clap matches {:?}", matches);

    let subcommand_name = matches.subcommand_name().unwrap();
    let subcommand_matches = matches.subcommand_matches(subcommand_name).unwrap();

    let config = match config_from_args(&matches, subcommand_name, &subcommand_matches) {
        Ok(config) => config,
        Err(e) => return exit_with(e, 1),
    };

    let result = match config.command() {
        Command::ShellBash => shell_bash(&config),
        Command::ShellSh => shell_sh(&config),
        Command::Config => configure(&config),
        Command::Start => start(&config),
    };

    match result {
        Ok(_) => std::process::exit(0),
        Err(e) => exit_with(e, 1),
    }
}

/// Exit with an error message and the right status code
#[allow(dead_code)]
fn exit_with(e: SupError, code: i32) {
    println!("{}", e);
    process::exit(code)
}

/// Start a sh shell
#[allow(dead_code)]
fn shell_sh(_config: &Config) -> Result<()> {
    shell::sh()
}

/// Start a bash shell
#[allow(dead_code)]
fn shell_bash(_config: &Config) -> Result<()> {
    shell::bash()
}

/// Show the configuration options for a service
#[allow(dead_code)]
fn configure(config: &Config) -> Result<()> {
    try!(configure::display(config));
    Ok(())
}

/// Start a service
#[allow(dead_code)]
fn start(config: &Config) -> Result<()> {
    outputln!("Starting {}",
              Yellow.bold().paint(config.package().to_string()));
    try!(start::package(config));
    outputln!("Finished with {}",
              Yellow.bold().paint(config.package().to_string()));
    Ok(())
}
<commit_msg>[sup] Fix Supervisor CLI compilation.<commit_after>// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers
//
// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc.
// and the party accessing this file ("Licensee") apply to Licensee's use of
// the Software until such time that the Software is made available under an
// open source license such as the Apache 2.0 License.

#[macro_use]
extern crate habitat_sup as sup;
extern crate habitat_core as hcore;
extern crate rustc_serialize;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate ansi_term;
extern crate libc;
#[macro_use]
extern crate clap;

use std::process;
use std::result;
use std::str::FromStr;

use ansi_term::Colour::Yellow;
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
use hcore::env as henv;
use hcore::fs;
use hcore::crypto::{default_cache_key_path, SymKey};
use hcore::crypto::init as crypto_init;
use hcore::package::PackageIdent;
use hcore::url::{DEFAULT_DEPOT_URL, DEPOT_URL_ENVVAR};

use sup::config::{Command, Config, UpdateStrategy};
use sup::error::{Error, Result, SupError};
use sup::command::*;
use sup::topology::Topology;
use sup::util::parse_ip_port_with_defaults;
use sup::util::sys::ip;

/// Our output key
static LOGKEY: &'static str = "MN";

/// The version number
const VERSION: &'static str = include_str!(concat!(env!("OUT_DIR"), "/VERSION"));

/// CLI defaults
static DEFAULT_GROUP: &'static str = "default";
static DEFAULT_SIDECAR_LISTEN_IP_PORT: &'static str = "0.0.0.0:9631";

const DEFAULT_GOSSIP_LISTEN_PORT: u16 = 9634;

static RING_ENVVAR: &'static str = "HAB_RING";
static RING_KEY_ENVVAR: &'static str = "HAB_RING_KEY";

/// Creates a [Config](config/struct.Config.html) from global args
/// and subcommand args.
fn config_from_args(args: &ArgMatches, subcommand: &str, sub_args: &ArgMatches) -> Result<Config> {
    let mut config = Config::new();
    let command = try!(Command::from_str(subcommand));
    config.set_command(command);
    if let Some(ref strategy) = sub_args.value_of("strategy") {
        config.set_update_strategy(UpdateStrategy::from_str(strategy));
    }
    if let Some(ref archive) = sub_args.value_of("archive") {
        config.set_archive(archive.to_string());
    }
    if let Some(ref package) = sub_args.value_of("package") {
        let ident = try!(PackageIdent::from_str(package));
        config.set_package(ident);
    }
    if let Some(key) = sub_args.value_of("key") {
        config.set_key(key.to_string());
    }
    if let Some(email) = sub_args.value_of("email") {
        config.set_email(email.to_string());
    }
    if let Some(user) = sub_args.value_of("user") {
        config.set_user_key(user.to_string());
    }
    if let Some(service) = sub_args.value_of("service") {
        config.set_service_key(service.to_string());
    }
    if let Some(infile) = sub_args.value_of("infile") {
        config.set_infile(infile.to_string());
    }
    if let Some(outfile) = sub_args.value_of("outfile") {
        config.set_outfile(outfile.to_string());
    }
    if let Some(topology) = sub_args.value_of("topology") {
        match topology.as_ref() {
            "standalone" => {
                config.set_topology(Topology::Standalone);
            }
            "leader" => {
                config.set_topology(Topology::Leader);
            }
            "initializer" => {
                config.set_topology(Topology::Initializer);
            }
            t => return Err(sup_error!(Error::UnknownTopology(String::from(t)))),
        }
    }
    if sub_args.value_of("expire-days").is_some() {
        let ed = value_t!(sub_args.value_of("expire-days"), u16).unwrap_or_else(|e| e.exit());
        config.set_expire_days(ed);
    }
    let env_or_default = henv::var(DEPOT_URL_ENVVAR).unwrap_or(DEFAULT_DEPOT_URL.to_string());
    let url = sub_args.value_of("url").unwrap_or(&env_or_default);
    config.set_url(url.to_string());
    config.set_group(sub_args.value_of("group").unwrap_or(DEFAULT_GROUP).to_string());
    let bindings = match sub_args.values_of("bind") {
        Some(bind) => bind.map(|s| s.to_string()).collect(),
        None => vec![],
    };
    config.set_bind(bindings);
    config.set_path(sub_args.value_of("path")
                            .unwrap_or(fs::svc_path(sup::PROGRAM_NAME.as_str())
                                           .join("data")
                                           .to_string_lossy()
                                           .as_ref())
                            .to_string());

    let default_gossip_ip = try!(ip());
    let (gossip_ip, gossip_port) = try!(parse_ip_port_with_defaults(
                                        sub_args.value_of("listen-peer"),
                                        &default_gossip_ip,
                                        DEFAULT_GOSSIP_LISTEN_PORT));

    debug!("Gossip IP = {}", &gossip_ip);
    debug!("Gossip Port = {}", &gossip_port);
    config.set_gossip_listen_ip(gossip_ip);
    config.set_gossip_listen_port(gossip_port);
    config.set_sidecar_listen(sub_args.value_of("listen-sidecar")
                                      .unwrap_or(DEFAULT_SIDECAR_LISTEN_IP_PORT)
                                      .to_string());
    let gossip_peers = match sub_args.values_of("peer") {
        Some(gp) => gp.map(|s| s.to_string()).collect(),
        None => vec![],
    };
    config.set_gossip_peer(gossip_peers);
    if sub_args.value_of("permanent-peer").is_some() {
        config.set_gossip_permanent(true);
    }
    if let Some(sg) = sub_args.value_of("service-group") {
        config.set_service_group(sg.to_string());
    }
    if let Some(fp) = sub_args.value_of("file-path") {
        config.set_file_path(fp.to_string());
    }
    config.set_version_number(value_t!(sub_args, "version-number", u64).unwrap_or(0));
    let ring = match sub_args.value_of("ring") {
        Some(val) => Some(try!(SymKey::get_latest_pair_for(&val, &default_cache_key_path(None)))),
        None => {
            match henv::var(RING_KEY_ENVVAR) {
                Ok(val) => {
                    let (key, _) = try!(SymKey::write_file_from_str(&val,
                                                                    &default_cache_key_path(None)));
                    Some(key)
                }
                Err(_) => {
                    match henv::var(RING_ENVVAR) {
                        Ok(val) => {
                            Some(try!(SymKey::get_latest_pair_for(&val,
                                                                  &default_cache_key_path(None))))
                        }
                        Err(_) => None,
                    }
                }
            }
        }
    };
    if let Some(ring) = ring {
        config.set_ring(ring.name_with_rev());
    }
    if args.value_of("verbose").is_some() {
        sup::output::set_verbose(true);
    }
    if args.value_of("no-color").is_some() {
        sup::output::set_no_color(true);
    }

    if let Some(org) = sub_args.value_of("organization") {
        config.set_organization(org.to_string());
    }
    debug!("Config:\n{:?}", config);
    Ok(config)
}

type Handler = fn(&Config) -> result::Result<(), sup::error::SupError>;

/// The entrypoint for the Supervisor.
///
/// * Set up the logger
/// * Pull in the arguments from the Command Line, push through clap
/// * Dispatch to a function that handles that action called
/// * Exit cleanly, or if we return an `Error`, call `exit_with(E, 1)`
#[allow(dead_code)]
fn main() {
    env_logger::init().unwrap();
    crypto_init();

    let arg_url = || {
        Arg::with_name("url")
            .short("u")
            .long("url")
            .takes_value(true)
            .help("Use the specified package depot url")
    };
    let arg_group = || {
        Arg::with_name("group")
            .long("group")
            .takes_value(true)
            .help("The service group; shared config and topology [default: default].")
    };

    let arg_org = || {
        Arg::with_name("organization")
            .long("org")
            .takes_value(true)
            .help("The organization that a service is part of")
    };

    let arg_strategy = || {
        Arg::with_name("strategy")
            .long("strategy")
            .short("s")
            .takes_value(true)
            .possible_values(&["none", "at-once"])
            .help("The update strategy; [default: none].")
    };

    let sub_start = SubCommand::with_name("start")
                        .about("Start a Habitat-supervised service from a package")
                        .arg(Arg::with_name("package")
                                 .index(1)
                                 .required(true)
                                 .help("Name of package to start"))
                        .arg(arg_url())
                        .arg(arg_group())
                        .arg(arg_org())
                        .arg(arg_strategy())
                        .arg(Arg::with_name("topology")
                                 .short("t")
                                 .long("topology")
                                 .value_name("topology")
                                 .help("Service topology"))
                        .arg(Arg::with_name("bind")
                                 .long("bind")
                                 .value_name("bind")
                                 .multiple(true)
                                 .help("One or more service groups to bind to a configuration"))
                        .arg(Arg::with_name("ring")
                                 .short("r")
                                 .long("ring")
                                 .value_name("ring")
                                 .help("Ring key name"))
                        .arg(Arg::with_name("peer")
                                 .long("peer")
                                 .value_name("ip:port")
                                 .multiple(true)
                                 .help("The listen address of an initial peer"))
                        .arg(Arg::with_name("listen-peer")
                                 .long("listen-peer")
                                 .value_name("ip:port")
                                 .help("The listen address [default: ip_with_default_route:9634]"))
                        .arg(Arg::with_name("listen-sidecar")
                                 .long("listen-sidecar")
                                 .value_name("ip:port")
                                 .help("The sidecar listen address [default: 0.0.0.0:9631]"))
                        .arg(Arg::with_name("permanent-peer")
                                 .short("I")
                                 .long("permanent-peer")
                                 .help("If this service is a permanent peer"));
    let sub_bash = SubCommand::with_name("bash").about("Start an interactive shell (bash)");
    let sub_sh = SubCommand::with_name("sh").about("Start an interactive shell (sh)");
    let sub_config = SubCommand::with_name("config")
                         .about("Print the default.toml for a given package")
                         .arg(Arg::with_name("package")
                                  .index(1)
                                  .required(true)
                                  .help("Name of package"));
    let args = App::new(sup::PROGRAM_NAME.as_str())
                   .version(VERSION)
                   .setting(AppSettings::VersionlessSubcommands)
                   .setting(AppSettings::SubcommandRequiredElseHelp)
                   .arg(Arg::with_name("verbose")
                            .short("v")
                            .global(true)
                            .help("Verbose output; shows line numbers"))
                   .arg(Arg::with_name("no-color")
                            .long("no-color")
                            .global(true)
                            .help("Turn ANSI color off :("))
                   .subcommand(sub_start)
                   .subcommand(sub_bash)
                   .subcommand(sub_sh)
                   .subcommand(sub_config);
    let matches = args.get_matches();

    debug!("clap matches {:?}", matches);

    let subcommand_name = matches.subcommand_name().unwrap();
    let subcommand_matches = matches.subcommand_matches(subcommand_name).unwrap();

    let config = match config_from_args(&matches, subcommand_name, &subcommand_matches) {
        Ok(config) => config,
        Err(e) => return exit_with(e, 1),
    };

    let result = match config.command() {
        Command::ShellBash => shell_bash(&config),
        Command::ShellSh => shell_sh(&config),
        Command::Config => configure(&config),
        Command::Start => start(&config),
    };

    match result {
        Ok(_) => std::process::exit(0),
        Err(e) => exit_with(e, 1),
    }
}

/// Exit with an error message and the right status code
#[allow(dead_code)]
fn exit_with(e: SupError, code: i32) {
    println!("{}", e);
    process::exit(code)
}

/// Start a sh shell
#[allow(dead_code)]
fn shell_sh(_config: &Config) -> Result<()> {
    shell::sh()
}

/// Start a bash shell
#[allow(dead_code)]
fn shell_bash(_config: &Config) -> Result<()> {
    shell::bash()
}

/// Show the configuration options for a service
#[allow(dead_code)]
fn configure(config: &Config) -> Result<()> {
    try!(configure::display(config));
    Ok(())
}

/// Start a service
#[allow(dead_code)]
fn start(config: &Config) -> Result<()> {
    outputln!("Starting {}",
              Yellow.bold().paint(config.package().to_string()));
    try!(start::package(config));
    outputln!("Finished with {}",
              Yellow.bold().paint(config.package().to_string()));
    Ok(())
}
<|endoftext|>


<commit_before>#![doc(html_favicon_url = "https://www.ruma.io/favicon.ico")]
#![doc(html_logo_url = "https://www.ruma.io/images/logo.png")]
//! Types and traits for working with the [Matrix](https://matrix.org) protocol.
//!
//! This crate re-exports things from all of the other ruma crates so you don't
//! have to manually keep all the versions in sync.
//!
//! Which crates are re-exported can be configured through cargo features.
//!
//! > ⚠ Some details might be missing because rustdoc has trouble with re-exports so you may need
//!   to refer to other crates' documentations.
//!
//! # API features
//!
//! Depending on which parts of Matrix are relevant to you, activate the following features:
//!
//! * `appservice-api` -- Application Service API.
//! * `client-api` -- Client-Server API.
//! * `federation-api` -- Server-Server (Federation) API.
//! * `identity-service-api` -- Identity Service API.
//! * `push-gateway-api` -- Push Gateway API.
//!
//! These features have `client`- and `server`-optimized variants that are enabled respectively
//! with the `-c` and `-s` suffixes. For example:
//!   * `client-api-c` -- The Client-Server API optimized for the client side.
//!   * `client-api-s` -- The Client-Server API optimized for the server side.
//!
//! # Compatibility feature
//!
//! * `compat` increases compatibility with other parts of the Matrix ecosystem, at the expense of
//! deviating from the specification.
//!
//! # Convenience features
//!
//! These features are only useful if you want to use a method that requires it:
//!
//! * `either`
//! * `rand`
//! * `markdown`
//!
//! # Unstable features
//!
//! By using these features, you opt out of all semver guarantees Ruma otherwise provides:
//!
//! * `unstable-exhaustive-types` -- Most types in Ruma are marked as non-exhaustive to avoid
//!   breaking changes when new fields are added in the specification. This feature compiles all
//!   types as exhaustive.
//! * `unstable-mscXXXX`, where `XXXX` is the MSC number -- Upcoming Matrix features that may be
//!   subject to change or removal.
//! * `unstable-pre-spec` -- Undocumented Matrix features that may be subject to change or removal.
//!
//! # Common features
//!
//! These submodules are usually activated by the API features when needed:
//!
//! * `api`
//! * `events`
//! * `signatures`
//!
//! # `ruma-client` features
//!
//! The `client` feature activates [`ruma::client`][client], and `client-ext-client-api` activates
//! `ruma-client`s `client-api` feature. All other `client-*` features activate the same feature
//! without the `client-` prefix on `ruma-client`. See the crate's documentation for the effect of
//! these features.
//!
//! If you are viewing this on `docs.rs`, you can have a look at the feature dependencies by
//! clicking **Feature flags** in the toolbar at the top.

#![warn(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

#[doc(inline)]
pub use ruma_common as common;
#[doc(inline)]
pub use ruma_common::serde;

#[cfg(feature = "client")]
#[doc(inline)]
pub use ruma_client as client;
#[cfg(feature = "events")]
#[doc(inline)]
pub use ruma_common::events;
#[cfg(feature = "signatures")]
#[doc(inline)]
pub use ruma_signatures as signatures;
#[cfg(feature = "state-res")]
#[doc(inline)]
pub use ruma_state_res as state_res;

/// (De)serializable types for various [Matrix APIs][apis] requests and responses and abstractions
/// for them.
///
/// [apis]: https://spec.matrix.org/v1.2/#matrix-apis
#[cfg(feature = "api")]
pub mod api {
    pub use ruma_common::api::*;

    #[cfg(feature = "ruma-appservice-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "appservice-api",
            feature = "appservice-api-c",
            feature = "appservice-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_appservice_api as appservice;
    #[cfg(feature = "ruma-client-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "client-api",
            feature = "client-api-c",
            feature = "client-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_client_api as client;
    #[cfg(feature = "ruma-federation-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "federation-api",
            feature = "federation-api-c",
            feature = "federation-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_federation_api as federation;
    #[cfg(feature = "ruma-identity-service-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "identity-service-api",
            feature = "identity-service-api-c",
            feature = "identity-service-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_identity_service_api as identity_service;
    #[cfg(feature = "ruma-push-gateway-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "push-gateway-api",
            feature = "push-gateway-api-c",
            feature = "push-gateway-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_push_gateway_api as push_gateway;
}

#[doc(no_inline)]
pub use assign::assign;
#[doc(no_inline)]
pub use js_int::{int, uint, Int, UInt};
#[cfg(feature = "client-ext-client-api")]
pub use ruma_client::Client;
pub use ruma_common::{
    authentication, device_id, device_key_id, directory, encryption, event_id, matrix_uri, mxc_uri,
    power_levels, presence, push, receipt, room, room_alias_id, room_id, room_version_id,
    serde::Incoming, server_name, server_signing_key_id, thirdparty, to_device, user_id,
    ClientSecret, DeviceId, DeviceKeyAlgorithm, DeviceKeyId, DeviceSignatures, DeviceSigningKeyId,
    EntitySignatures, EventEncryptionAlgorithm, EventId, KeyId, KeyName, MatrixToUri,
    MilliSecondsSinceUnixEpoch, MxcUri, PrivOwnedStr, RoomAliasId, RoomId, RoomOrAliasId,
    RoomVersionId, SecondsSinceUnixEpoch, ServerName, ServerSignatures, ServerSigningKeyId,
    SessionId, Signatures, SigningKeyAlgorithm, TransactionId, UserId,
};
<commit_msg>Re-export macro exports module from ruma<commit_after>#![doc(html_favicon_url = "https://www.ruma.io/favicon.ico")]
#![doc(html_logo_url = "https://www.ruma.io/images/logo.png")]
//! Types and traits for working with the [Matrix](https://matrix.org) protocol.
//!
//! This crate re-exports things from all of the other ruma crates so you don't
//! have to manually keep all the versions in sync.
//!
//! Which crates are re-exported can be configured through cargo features.
//!
//! > ⚠ Some details might be missing because rustdoc has trouble with re-exports so you may need
//!   to refer to other crates' documentations.
//!
//! # API features
//!
//! Depending on which parts of Matrix are relevant to you, activate the following features:
//!
//! * `appservice-api` -- Application Service API.
//! * `client-api` -- Client-Server API.
//! * `federation-api` -- Server-Server (Federation) API.
//! * `identity-service-api` -- Identity Service API.
//! * `push-gateway-api` -- Push Gateway API.
//!
//! These features have `client`- and `server`-optimized variants that are enabled respectively
//! with the `-c` and `-s` suffixes. For example:
//!   * `client-api-c` -- The Client-Server API optimized for the client side.
//!   * `client-api-s` -- The Client-Server API optimized for the server side.
//!
//! # Compatibility feature
//!
//! * `compat` increases compatibility with other parts of the Matrix ecosystem, at the expense of
//! deviating from the specification.
//!
//! # Convenience features
//!
//! These features are only useful if you want to use a method that requires it:
//!
//! * `either`
//! * `rand`
//! * `markdown`
//!
//! # Unstable features
//!
//! By using these features, you opt out of all semver guarantees Ruma otherwise provides:
//!
//! * `unstable-exhaustive-types` -- Most types in Ruma are marked as non-exhaustive to avoid
//!   breaking changes when new fields are added in the specification. This feature compiles all
//!   types as exhaustive.
//! * `unstable-mscXXXX`, where `XXXX` is the MSC number -- Upcoming Matrix features that may be
//!   subject to change or removal.
//! * `unstable-pre-spec` -- Undocumented Matrix features that may be subject to change or removal.
//!
//! # Common features
//!
//! These submodules are usually activated by the API features when needed:
//!
//! * `api`
//! * `events`
//! * `signatures`
//!
//! # `ruma-client` features
//!
//! The `client` feature activates [`ruma::client`][client], and `client-ext-client-api` activates
//! `ruma-client`s `client-api` feature. All other `client-*` features activate the same feature
//! without the `client-` prefix on `ruma-client`. See the crate's documentation for the effect of
//! these features.
//!
//! If you are viewing this on `docs.rs`, you can have a look at the feature dependencies by
//! clicking **Feature flags** in the toolbar at the top.

#![warn(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

#[doc(inline)]
pub use ruma_common as common;
#[doc(inline)]
pub use ruma_common::serde;

#[cfg(feature = "client")]
#[doc(inline)]
pub use ruma_client as client;
#[cfg(feature = "events")]
#[doc(inline)]
pub use ruma_common::events;
#[cfg(feature = "signatures")]
#[doc(inline)]
pub use ruma_signatures as signatures;
#[cfg(feature = "state-res")]
#[doc(inline)]
pub use ruma_state_res as state_res;

/// (De)serializable types for various [Matrix APIs][apis] requests and responses and abstractions
/// for them.
///
/// [apis]: https://spec.matrix.org/v1.2/#matrix-apis
#[cfg(feature = "api")]
pub mod api {
    pub use ruma_common::api::*;

    #[cfg(feature = "ruma-appservice-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "appservice-api",
            feature = "appservice-api-c",
            feature = "appservice-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_appservice_api as appservice;
    #[cfg(feature = "ruma-client-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "client-api",
            feature = "client-api-c",
            feature = "client-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_client_api as client;
    #[cfg(feature = "ruma-federation-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "federation-api",
            feature = "federation-api-c",
            feature = "federation-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_federation_api as federation;
    #[cfg(feature = "ruma-identity-service-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "identity-service-api",
            feature = "identity-service-api-c",
            feature = "identity-service-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_identity_service_api as identity_service;
    #[cfg(feature = "ruma-push-gateway-api")]
    #[cfg_attr(
        docsrs,
        doc(cfg(any(
            feature = "push-gateway-api",
            feature = "push-gateway-api-c",
            feature = "push-gateway-api-s"
        )))
    )]
    #[doc(inline)]
    pub use ruma_push_gateway_api as push_gateway;
}

#[doc(no_inline)]
pub use assign::assign;
#[doc(no_inline)]
pub use js_int::{int, uint, Int, UInt};
#[cfg(feature = "client-ext-client-api")]
pub use ruma_client::Client;
pub use ruma_common::{
    authentication, device_id, device_key_id, directory, encryption, event_id, exports, matrix_uri,
    mxc_uri, power_levels, presence, push, receipt, room, room_alias_id, room_id, room_version_id,
    serde::Incoming, server_name, server_signing_key_id, thirdparty, to_device, user_id,
    ClientSecret, DeviceId, DeviceKeyAlgorithm, DeviceKeyId, DeviceSignatures, DeviceSigningKeyId,
    EntitySignatures, EventEncryptionAlgorithm, EventId, KeyId, KeyName, MatrixToUri,
    MilliSecondsSinceUnixEpoch, MxcUri, PrivOwnedStr, RoomAliasId, RoomId, RoomOrAliasId,
    RoomVersionId, SecondsSinceUnixEpoch, ServerName, ServerSignatures, ServerSigningKeyId,
    SessionId, Signatures, SigningKeyAlgorithm, TransactionId, UserId,
};
<|endoftext|>


<commit_before>use core::ptr::Unique;

use memory::{allocate_frame, deallocate_frame, Frame};

use super::{Page, PAGE_SIZE, PhysicalAddress, VirtualAddress};
use super::entry::{self, EntryFlags};
use super::table::{self, Table, Level4};

pub struct Mapper {
    p4: Unique<Table<Level4>>,
}

impl Mapper {
    /// Create a new page table
    pub unsafe fn new() -> Mapper {
        Mapper {
            p4: Unique::new(table::P4),
        }
    }

    pub fn p4(&self) -> &Table<Level4> {
        unsafe { self.p4.get() }
    }

    pub fn p4_mut(&mut self) -> &mut Table<Level4> {
        unsafe { self.p4.get_mut() }
    }

    /// Map a page to a frame
    pub fn map_to(&mut self, page: Page, frame: Frame, flags: EntryFlags) {
        let mut p3 = self.p4_mut().next_table_create(page.p4_index());
        let mut p2 = p3.next_table_create(page.p3_index());
        let mut p1 = p2.next_table_create(page.p2_index());

        assert!(p1[page.p1_index()].is_unused(),
            "{:X}: Set to {:X}: {:?}, requesting {:X}: {:?}",
            page.start_address().get(),
            p1[page.p1_index()].address().get(), p1[page.p1_index()].flags(),
            frame.start_address().get(), flags);
        p1[page.p1_index()].set(frame, flags | entry::PRESENT);
    }

    /// Map a page to the next free frame
    pub fn map(&mut self, page: Page, flags: EntryFlags) {
        let frame = allocate_frame().expect("out of memory");
        self.map_to(page, frame, flags)
    }

    /// Update flags for a page
    pub fn remap(&mut self, page: Page, flags: EntryFlags) {
        let mut p3 = self.p4_mut().next_table_mut(page.p4_index()).expect("failed to remap: no p3");
        let mut p2 = p3.next_table_mut(page.p3_index()).expect("failed to remap: no p2");
        let mut p1 = p2.next_table_mut(page.p2_index()).expect("failed to remap: no p1");
        let frame = p1[page.p1_index()].pointed_frame().expect("failed to remap: not mapped");
        p1[page.p1_index()].set(frame, flags | entry::PRESENT);
    }

    /// Identity map a frame
    pub fn identity_map(&mut self, frame: Frame, flags: EntryFlags) {
        let page = Page::containing_address(VirtualAddress::new(frame.start_address().get()));
        self.map_to(page, frame, flags)
    }

    /// Unmap a page
    pub fn unmap(&mut self, page: Page) {
        let p1 = self.p4_mut()
                     .next_table_mut(page.p4_index())
                     .and_then(|p3| p3.next_table_mut(page.p3_index()))
                     .and_then(|p2| p2.next_table_mut(page.p2_index()))
                     .expect("mapping code does not support huge pages");
        let frame = p1[page.p1_index()].pointed_frame().unwrap();
        p1[page.p1_index()].set_unused();
        // TODO free p(1,2,3) table if empty
        deallocate_frame(frame);
    }

    /// Unmap a page, return frame without free
    pub fn unmap_return(&mut self, page: Page) -> Frame {
        let p1 = self.p4_mut()
                     .next_table_mut(page.p4_index())
                     .and_then(|p3| p3.next_table_mut(page.p3_index()))
                     .and_then(|p2| p2.next_table_mut(page.p2_index()))
                     .expect("mapping code does not support huge pages");
        let frame = p1[page.p1_index()].pointed_frame().unwrap();
        p1[page.p1_index()].set_unused();
        frame
    }

    pub fn translate_page(&self, page: Page) -> Option<Frame> {
        self.p4().next_table(page.p4_index())
            .and_then(|p3| p3.next_table(page.p3_index()))
            .and_then(|p2| p2.next_table(page.p2_index()))
            .and_then(|p1| p1[page.p1_index()].pointed_frame())
    }

    /// Translate a virtual address to a physical one
    pub fn translate(&self, virtual_address: VirtualAddress) -> Option<PhysicalAddress> {
        let offset = virtual_address.get() % PAGE_SIZE;
        self.translate_page(Page::containing_address(virtual_address))
            .map(|frame| PhysicalAddress::new(frame.start_address().get() + offset))
    }
}
<commit_msg>Add function for getting mapped page flags<commit_after>use core::ptr::Unique;

use memory::{allocate_frame, deallocate_frame, Frame};

use super::{Page, PAGE_SIZE, PhysicalAddress, VirtualAddress};
use super::entry::{self, EntryFlags};
use super::table::{self, Table, Level4};

pub struct Mapper {
    p4: Unique<Table<Level4>>,
}

impl Mapper {
    /// Create a new page table
    pub unsafe fn new() -> Mapper {
        Mapper {
            p4: Unique::new(table::P4),
        }
    }

    pub fn p4(&self) -> &Table<Level4> {
        unsafe { self.p4.get() }
    }

    pub fn p4_mut(&mut self) -> &mut Table<Level4> {
        unsafe { self.p4.get_mut() }
    }

    /// Map a page to a frame
    pub fn map_to(&mut self, page: Page, frame: Frame, flags: EntryFlags) {
        let mut p3 = self.p4_mut().next_table_create(page.p4_index());
        let mut p2 = p3.next_table_create(page.p3_index());
        let mut p1 = p2.next_table_create(page.p2_index());

        assert!(p1[page.p1_index()].is_unused(),
            "{:X}: Set to {:X}: {:?}, requesting {:X}: {:?}",
            page.start_address().get(),
            p1[page.p1_index()].address().get(), p1[page.p1_index()].flags(),
            frame.start_address().get(), flags);
        p1[page.p1_index()].set(frame, flags | entry::PRESENT);
    }

    /// Map a page to the next free frame
    pub fn map(&mut self, page: Page, flags: EntryFlags) {
        let frame = allocate_frame().expect("out of memory");
        self.map_to(page, frame, flags)
    }

    /// Update flags for a page
    pub fn remap(&mut self, page: Page, flags: EntryFlags) {
        let mut p3 = self.p4_mut().next_table_mut(page.p4_index()).expect("failed to remap: no p3");
        let mut p2 = p3.next_table_mut(page.p3_index()).expect("failed to remap: no p2");
        let mut p1 = p2.next_table_mut(page.p2_index()).expect("failed to remap: no p1");
        let frame = p1[page.p1_index()].pointed_frame().expect("failed to remap: not mapped");
        p1[page.p1_index()].set(frame, flags | entry::PRESENT);
    }

    /// Identity map a frame
    pub fn identity_map(&mut self, frame: Frame, flags: EntryFlags) {
        let page = Page::containing_address(VirtualAddress::new(frame.start_address().get()));
        self.map_to(page, frame, flags)
    }

    /// Unmap a page
    pub fn unmap(&mut self, page: Page) {
        let p1 = self.p4_mut()
                     .next_table_mut(page.p4_index())
                     .and_then(|p3| p3.next_table_mut(page.p3_index()))
                     .and_then(|p2| p2.next_table_mut(page.p2_index()))
                     .expect("mapping code does not support huge pages");
        let frame = p1[page.p1_index()].pointed_frame().unwrap();
        p1[page.p1_index()].set_unused();
        // TODO free p(1,2,3) table if empty
        deallocate_frame(frame);
    }

    /// Unmap a page, return frame without free
    pub fn unmap_return(&mut self, page: Page) -> Frame {
        let p1 = self.p4_mut()
                     .next_table_mut(page.p4_index())
                     .and_then(|p3| p3.next_table_mut(page.p3_index()))
                     .and_then(|p2| p2.next_table_mut(page.p2_index()))
                     .expect("mapping code does not support huge pages");
        let frame = p1[page.p1_index()].pointed_frame().unwrap();
        p1[page.p1_index()].set_unused();
        frame
    }

    pub fn translate_page(&self, page: Page) -> Option<Frame> {
        self.p4().next_table(page.p4_index())
            .and_then(|p3| p3.next_table(page.p3_index()))
            .and_then(|p2| p2.next_table(page.p2_index()))
            .and_then(|p1| p1[page.p1_index()].pointed_frame())
    }

    pub fn translate_page_flags(&self, page: Page) -> Option<EntryFlags> {
        self.p4().next_table(page.p4_index())
            .and_then(|p3| p3.next_table(page.p3_index()))
            .and_then(|p2| p2.next_table(page.p2_index()))
            .and_then(|p1| Some(p1[page.p1_index()].flags()))
    }

    /// Translate a virtual address to a physical one
    pub fn translate(&self, virtual_address: VirtualAddress) -> Option<PhysicalAddress> {
        let offset = virtual_address.get() % PAGE_SIZE;
        self.translate_page(Page::containing_address(virtual_address))
            .map(|frame| PhysicalAddress::new(frame.start_address().get() + offset))
    }
}
<|endoftext|>