<commit_before>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

The `ToStr` trait for converting to strings

*/

use str::OwnedStr;
use hashmap::HashMap;
use hashmap::HashSet;
use hash::Hash;
use iterator::IteratorUtil;
use cmp::Eq;
use vec::ImmutableVector;

/// A generic trait for converting a value to a string
pub trait ToStr {
    /// Converts the value of `self` to an owned string
    fn to_str(&self) -> ~str;
}

/// Trait for converting a type to a string, consuming it in the process.
pub trait ToStrConsume {
    /// Cosume and convert to a string.
    fn into_str(self) -> ~str;
}

impl ToStr for () {
    #[inline]
    fn to_str(&self) -> ~str { ~"()" }
}

impl<A:ToStr> ToStr for (A,) {
    #[inline]
    fn to_str(&self) -> ~str {
        match *self {
            (ref a,) => {
                fmt!("(%s,)", (*a).to_str())
            }
        }
    }
}

impl<A:ToStr+Hash+Eq, B:ToStr+Hash+Eq> ToStr for HashMap<A, B> {
    #[inline]
    fn to_str(&self) -> ~str {
        let mut acc = ~"{";
        let mut first = true;
        for self.iter().advance |(key, value)| {
            if first {
                first = false;
            }
            else {
                acc.push_str(", ");
            }
            acc.push_str(key.to_str());
            acc.push_str(": ");
            acc.push_str(value.to_str());
        }
        acc.push_char('}');
        acc
    }
}

impl<A:ToStr+Hash+Eq> ToStr for HashSet<A> {
    #[inline]
    fn to_str(&self) -> ~str {
        let mut acc = ~"{";
        let mut first = true;
        for self.iter().advance |element| {
            if first {
                first = false;
            }
            else {
                acc.push_str(", ");
            }
            acc.push_str(element.to_str());
        }
        acc.push_char('}');
        acc
    }
}

impl<A:ToStr,B:ToStr> ToStr for (A, B) {
    #[inline]
    fn to_str(&self) -> ~str {
        // FIXME(#4653): this causes an llvm assertion
        //let &(ref a, ref b) = self;
        match *self {
            (ref a, ref b) => {
                fmt!("(%s, %s)", (*a).to_str(), (*b).to_str())
            }
        }
    }
}

impl<A:ToStr,B:ToStr,C:ToStr> ToStr for (A, B, C) {
    #[inline]
    fn to_str(&self) -> ~str {
        // FIXME(#4653): this causes an llvm assertion
        //let &(ref a, ref b, ref c) = self;
        match *self {
            (ref a, ref b, ref c) => {
                fmt!("(%s, %s, %s)",
                    (*a).to_str(),
                    (*b).to_str(),
                    (*c).to_str()
                )
            }
        }
    }
}

impl<'self,A:ToStr> ToStr for &'self [A] {
    #[inline]
    fn to_str(&self) -> ~str {
        let mut acc = ~"[";
        let mut first = true;
        for self.iter().advance |elt| {
            if first {
                first = false;
            }
            else {
                acc.push_str(", ");
            }
            acc.push_str(elt.to_str());
        }
        acc.push_char(']');
        acc
    }
}

impl<A:ToStr> ToStr for ~[A] {
    #[inline]
    fn to_str(&self) -> ~str {
        let mut acc = ~"[";
        let mut first = true;
        for self.iter().advance |elt| {
            if first {
                first = false;
            }
            else {
                acc.push_str(", ");
            }
            acc.push_str(elt.to_str());
        }
        acc.push_char(']');
        acc
    }
}

impl<A:ToStr> ToStr for @[A] {
    #[inline]
    fn to_str(&self) -> ~str {
        let mut acc = ~"[";
        let mut first = true;
        for self.iter().advance |elt| {
            if first {
                first = false;
            }
            else {
                acc.push_str(", ");
            }
            acc.push_str(elt.to_str());
        }
        acc.push_char(']');
        acc
    }
}

#[cfg(test)]
mod tests {
    use hashmap::HashMap;
    use hashmap::HashSet;
    use container::{MutableSet, MutableMap};
    #[test]
    fn test_simple_types() {
        assert_eq!(1i.to_str(), ~"1");
        assert_eq!((-1i).to_str(), ~"-1");
        assert_eq!(200u.to_str(), ~"200");
        assert_eq!(2u8.to_str(), ~"2");
        assert_eq!(true.to_str(), ~"true");
        assert_eq!(false.to_str(), ~"false");
        assert_eq!(().to_str(), ~"()");
        assert_eq!((~"hi").to_str(), ~"hi");
        assert_eq!((@"hi").to_str(), ~"hi");
    }

    #[test]
    fn test_tuple_types() {
        assert_eq!((1, 2).to_str(), ~"(1, 2)");
        assert_eq!((~"a", ~"b", false).to_str(), ~"(a, b, false)");
        assert_eq!(((), ((), 100)).to_str(), ~"((), ((), 100))");
    }

    #[test]
    fn test_vectors() {
        let x: ~[int] = ~[];
        assert_eq!(x.to_str(), ~"[]");
        assert_eq!((~[1]).to_str(), ~"[1]");
        assert_eq!((~[1, 2, 3]).to_str(), ~"[1, 2, 3]");
        assert!((~[~[], ~[1], ~[1, 1]]).to_str() ==
               ~"[[], [1], [1, 1]]");
    }

    #[test]
    fn test_hashmap() {
        let mut table: HashMap<int, int> = HashMap::new();
        let empty: HashMap<int, int> = HashMap::new();

        table.insert(3, 4);
        table.insert(1, 2);

        let table_str = table.to_str();

        assert!(table_str == ~"{1: 2, 3: 4}" || table_str == ~"{3: 4, 1: 2}");
        assert_eq!(empty.to_str(), ~"{}");
    }

    #[test]
    fn test_hashset() {
        let mut set: HashSet<int> = HashSet::new();
        let empty_set: HashSet<int> = HashSet::new();

        set.insert(1);
        set.insert(2);

        let set_str = set.to_str();

        assert!(set_str == ~"{1, 2}" || set_str == ~"{2, 1}");
        assert_eq!(empty_set.to_str(), ~"{}");
    }
}
<commit_msg>ToStr for HashMap does not need value to implement Eq or Hash<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

The `ToStr` trait for converting to strings

*/

use str::OwnedStr;
use hashmap::HashMap;
use hashmap::HashSet;
use hash::Hash;
use iterator::IteratorUtil;
use cmp::Eq;
use vec::ImmutableVector;

/// A generic trait for converting a value to a string
pub trait ToStr {
    /// Converts the value of `self` to an owned string
    fn to_str(&self) -> ~str;
}

/// Trait for converting a type to a string, consuming it in the process.
pub trait ToStrConsume {
    /// Cosume and convert to a string.
    fn into_str(self) -> ~str;
}

impl ToStr for () {
    #[inline]
    fn to_str(&self) -> ~str { ~"()" }
}

impl<A:ToStr> ToStr for (A,) {
    #[inline]
    fn to_str(&self) -> ~str {
        match *self {
            (ref a,) => {
                fmt!("(%s,)", (*a).to_str())
            }
        }
    }
}

impl<A:ToStr+Hash+Eq, B:ToStr> ToStr for HashMap<A, B> {
    #[inline]
    fn to_str(&self) -> ~str {
        let mut acc = ~"{";
        let mut first = true;
        for self.iter().advance |(key, value)| {
            if first {
                first = false;
            }
            else {
                acc.push_str(", ");
            }
            acc.push_str(key.to_str());
            acc.push_str(": ");
            acc.push_str(value.to_str());
        }
        acc.push_char('}');
        acc
    }
}

impl<A:ToStr+Hash+Eq> ToStr for HashSet<A> {
    #[inline]
    fn to_str(&self) -> ~str {
        let mut acc = ~"{";
        let mut first = true;
        for self.iter().advance |element| {
            if first {
                first = false;
            }
            else {
                acc.push_str(", ");
            }
            acc.push_str(element.to_str());
        }
        acc.push_char('}');
        acc
    }
}

impl<A:ToStr,B:ToStr> ToStr for (A, B) {
    #[inline]
    fn to_str(&self) -> ~str {
        // FIXME(#4653): this causes an llvm assertion
        //let &(ref a, ref b) = self;
        match *self {
            (ref a, ref b) => {
                fmt!("(%s, %s)", (*a).to_str(), (*b).to_str())
            }
        }
    }
}

impl<A:ToStr,B:ToStr,C:ToStr> ToStr for (A, B, C) {
    #[inline]
    fn to_str(&self) -> ~str {
        // FIXME(#4653): this causes an llvm assertion
        //let &(ref a, ref b, ref c) = self;
        match *self {
            (ref a, ref b, ref c) => {
                fmt!("(%s, %s, %s)",
                    (*a).to_str(),
                    (*b).to_str(),
                    (*c).to_str()
                )
            }
        }
    }
}

impl<'self,A:ToStr> ToStr for &'self [A] {
    #[inline]
    fn to_str(&self) -> ~str {
        let mut acc = ~"[";
        let mut first = true;
        for self.iter().advance |elt| {
            if first {
                first = false;
            }
            else {
                acc.push_str(", ");
            }
            acc.push_str(elt.to_str());
        }
        acc.push_char(']');
        acc
    }
}

impl<A:ToStr> ToStr for ~[A] {
    #[inline]
    fn to_str(&self) -> ~str {
        let mut acc = ~"[";
        let mut first = true;
        for self.iter().advance |elt| {
            if first {
                first = false;
            }
            else {
                acc.push_str(", ");
            }
            acc.push_str(elt.to_str());
        }
        acc.push_char(']');
        acc
    }
}

impl<A:ToStr> ToStr for @[A] {
    #[inline]
    fn to_str(&self) -> ~str {
        let mut acc = ~"[";
        let mut first = true;
        for self.iter().advance |elt| {
            if first {
                first = false;
            }
            else {
                acc.push_str(", ");
            }
            acc.push_str(elt.to_str());
        }
        acc.push_char(']');
        acc
    }
}

#[cfg(test)]
mod tests {
    use hashmap::HashMap;
    use hashmap::HashSet;
    use container::{MutableSet, MutableMap};
    use super::*;

    #[test]
    fn test_simple_types() {
        assert_eq!(1i.to_str(), ~"1");
        assert_eq!((-1i).to_str(), ~"-1");
        assert_eq!(200u.to_str(), ~"200");
        assert_eq!(2u8.to_str(), ~"2");
        assert_eq!(true.to_str(), ~"true");
        assert_eq!(false.to_str(), ~"false");
        assert_eq!(().to_str(), ~"()");
        assert_eq!((~"hi").to_str(), ~"hi");
        assert_eq!((@"hi").to_str(), ~"hi");
    }

    #[test]
    fn test_tuple_types() {
        assert_eq!((1, 2).to_str(), ~"(1, 2)");
        assert_eq!((~"a", ~"b", false).to_str(), ~"(a, b, false)");
        assert_eq!(((), ((), 100)).to_str(), ~"((), ((), 100))");
    }

    #[test]
    fn test_vectors() {
        let x: ~[int] = ~[];
        assert_eq!(x.to_str(), ~"[]");
        assert_eq!((~[1]).to_str(), ~"[1]");
        assert_eq!((~[1, 2, 3]).to_str(), ~"[1, 2, 3]");
        assert!((~[~[], ~[1], ~[1, 1]]).to_str() ==
               ~"[[], [1], [1, 1]]");
    }

    struct StructWithToStrWithoutEqOrHash {
        value: int
    }

    impl ToStr for StructWithToStrWithoutEqOrHash {
        fn to_str(&self) -> ~str {
            fmt!("s%d", self.value)
        }
    }

    #[test]
    fn test_hashmap() {
        let mut table: HashMap<int, StructWithToStrWithoutEqOrHash> = HashMap::new();
        let empty: HashMap<int, StructWithToStrWithoutEqOrHash> = HashMap::new();

        table.insert(3, StructWithToStrWithoutEqOrHash { value: 4 });
        table.insert(1, StructWithToStrWithoutEqOrHash { value: 2 });

        let table_str = table.to_str();

        assert!(table_str == ~"{1: s2, 3: s4}" || table_str == ~"{3: s4, 1: s2}");
        assert_eq!(empty.to_str(), ~"{}");
    }

    #[test]
    fn test_hashset() {
        let mut set: HashSet<int> = HashSet::new();
        let empty_set: HashSet<int> = HashSet::new();

        set.insert(1);
        set.insert(2);

        let set_str = set.to_str();

        assert!(set_str == ~"{1, 2}" || set_str == ~"{2, 1}");
        assert_eq!(empty_set.to_str(), ~"{}");
    }
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Loops/For

use std::collections::HashMap;

fn main() {
    // Iterate through the characters of a string
    let s = "hello, world!";
    for i in s.chars() {
        print!("{}", i);
    }
    println!("");

    // Iterate through the elements of a slice
    let array = [1, 2, 3, 4, 5];
    for i in array.iter() {
        print!("{}", i);
    }
    println!("");

    // Iterate through the elements of a hasmap
    let mut hashmap = HashMap::new();
    hashmap.insert("a", 1u8);
    hashmap.insert("b", 2);
    hashmap.insert("c", 3);
    for (c, i) in hashmap.iter() {
        println!("{}: '{}'", c, i)
    }
}
<commit_msg>disambiguate for and foreach<commit_after>// http://rosettacode.org/wiki/Loops/Foreach

use std::collections::HashMap;

fn main() {
    // Rust's for-loop already is a foreach-loop.
    let collection = vec![1, 2, 3, 4, 5];
    for elem in collection {
        println!("{}", elem);
    }

    // Do note that Rust moves values by default and doesn't copy them. A vector would be unusable
    // after looping over it like above. To preserve it, borrow it or use an Iter, to mutate values
    // do a mutable borrow or create an IterMut. To get an immutable reference omit the mut-part.

    let mut collection = vec![1, 2, 3, 4, 5];
    for mut_ref in &mut collection {
        // alternatively:
        // for mut_ref in collection.iter_mut() {
        *mut_ref *= 2;
        println!("{}", *mut_ref);
    }

    // immutable borrow
    for immut_ref in &collection {
        // alternatively:
        // for immut_ref in collection.iter() {
        println!("{}", *immut_ref);
    }

    // Iterate through the characters of a string
    let s = "hello, world!";
    for i in s.chars() {
        print!("{}", i);
    }
    println!("");

    // Iterate through the elements of a slice
    let array = [1, 2, 3, 4, 5];
    for i in array.iter() {
        print!("{}", i);
    }
    println!("");

    // Iterate through the elements of a hasmap
    let mut hashmap = HashMap::new();
    hashmap.insert("a", 1u8);
    hashmap.insert("b", 2);
    hashmap.insert("c", 3);
    for (c, i) in hashmap.iter() {
        println!("{}: '{}'", c, i)
    }
}
<|endoftext|>


<commit_before>#![no_std]
// We want to keep all mailbox constants here even if they're currently unused.
#![allow(dead_code)]
#![allow(non_snake_case)]

use kata_os_common::logger::KataLogger;
use log::{error, trace};

//------------------------------------------------------------------------------
// TODO(aappleby): Can we replace this with the register_struct! thing?

const REG_INTR_STATE: u32 = 0x000; // R/W1C
const REG_INTR_ENABLE: u32 = 0x004; // R/W
const REG_INTR_TEST: u32 = 0x008; // R/W
const REG_MBOXW: u32 = 0x00C; // W
const REG_MBOXR: u32 = 0x010; // R
const REG_STATUS: u32 = 0x014; // R
const REG_ERROR: u32 = 0x018; // R
const REG_WIRQT: u32 = 0x01C; // R/W
const REG_RIRQT: u32 = 0x020; // R/W
const REG_CTRL: u32 = 0x024; // R/W

const INTR_STATE_BIT_WTIRQ: u32 = 0b001;
const INTR_STATE_BIT_RTIRQ: u32 = 0b010;
const INTR_STATE_BIT_EIRQ: u32 = 0b100;
const INTR_STATE_MASK: u32 = 0b111;

const INTR_ENABLE_BIT_WTIRQ: u32 = 0b001;
const INTR_ENABLE_BIT_RTIRQ: u32 = 0b010;
const INTR_ENABLE_BIT_EIRQ: u32 = 0b100;
const INTR_ENABLE_MASK: u32 = 0b111;

const INTR_TEST_BIT_WTIRQ: u32 = 0b001;
const INTR_TEST_BIT_RTIRQ: u32 = 0b010;
const INTR_TEST_BIT_EIRQ: u32 = 0b100;
const INTR_TEST_MASK: u32 = 0b111;

const STATUS_BIT_EMPTY: u32 = 0b0001;
const STATUS_BIT_FULL: u32 = 0b0010;
const STATUS_BIT_WFIFOL: u32 = 0b0100;
const STATUS_BIT_RFIFOL: u32 = 0b1000;
const STATUS_MASK: u32 = 0b1111;

const ERROR_BIT_READ: u32 = 0b01;
const ERROR_BIT_WRITE: u32 = 0b10;
const ERROR_MASK: u32 = 0b11;

const FIFO_SIZE: u32 = 8;
const FIFO_MASK: u32 = FIFO_SIZE - 1;
const WIRQT_MASK: u32 = FIFO_MASK;
const RIRQT_MASK: u32 = FIFO_MASK;

const CTRL_BIT_FLUSH_WFIFO: u32 = 0b01;
const CTRL_BIT_FLUSH_RFIFO: u32 = 0b10;
const CTRL_MASK: u32 = 0b11;

// The high bit of the message header is used to distinguish between "inline"
// messages that fit in the mailbox and "long" messages that contain the
// physical address of a memory page containing the message.
const HEADER_FLAG_LONG_MESSAGE: u32 = 0x80000000;

//------------------------------------------------------------------------------

extern "C" {
    // Mailbox registers
    static mailbox_mmio: *mut u32;

    // Global mailbox lock
    fn api_mutex_lock() -> u32;
    fn api_mutex_unlock() -> u32;

    // Mailbox arrival semaphore
    fn rx_semaphore_wait() -> u32;
    fn rx_semaphore_post() -> u32;

    // Mailbox interrupts
    fn wtirq_acknowledge() -> u32;
    fn rtirq_acknowledge() -> u32;
    fn eirq_acknowledge() -> u32;
}

//------------------------------------------------------------------------------
// Directly manipulate the mailbox registers.

unsafe fn get_intr_state() -> u32 {
    mailbox_mmio.offset(0).read_volatile()
}
unsafe fn get_INTR_ENABLE() -> u32 {
    mailbox_mmio.offset(1).read_volatile()
}
unsafe fn get_INTR_TEST() -> u32 {
    mailbox_mmio.offset(2).read_volatile()
}
unsafe fn get_MBOXW() -> u32 {
    mailbox_mmio.offset(3).read_volatile()
}
unsafe fn get_MBOXR() -> u32 {
    mailbox_mmio.offset(4).read_volatile()
}
unsafe fn get_STATUS() -> u32 {
    mailbox_mmio.offset(5).read_volatile()
}
unsafe fn get_ERROR() -> u32 {
    mailbox_mmio.offset(6).read_volatile()
}
unsafe fn get_WIRQT() -> u32 {
    mailbox_mmio.offset(7).read_volatile()
}
unsafe fn get_RIRQT() -> u32 {
    mailbox_mmio.offset(8).read_volatile()
}
unsafe fn get_CTRL() -> u32 {
    mailbox_mmio.offset(9).read_volatile()
}

unsafe fn set_INTR_STATE(x: u32) {
    mailbox_mmio.offset(0).write_volatile(x);
}
unsafe fn set_INTR_ENABLE(x: u32) {
    mailbox_mmio.offset(1).write_volatile(x);
}
unsafe fn set_INTR_TEST(x: u32) {
    mailbox_mmio.offset(2).write_volatile(x);
}
unsafe fn set_MBOXW(x: u32) {
    mailbox_mmio.offset(3).write_volatile(x);
}
unsafe fn set_MBOXR(x: u32) {
    mailbox_mmio.offset(4).write_volatile(x);
}
unsafe fn set_STATUS(x: u32) {
    mailbox_mmio.offset(5).write_volatile(x);
}
unsafe fn set_ERROR(x: u32) {
    mailbox_mmio.offset(6).write_volatile(x);
}
unsafe fn set_WIRQT(x: u32) {
    mailbox_mmio.offset(7).write_volatile(x);
}
unsafe fn set_RIRQT(x: u32) {
    mailbox_mmio.offset(8).write_volatile(x);
}
unsafe fn set_CTRL(x: u32) {
    mailbox_mmio.offset(9).write_volatile(x);
}

//------------------------------------------------------------------------------
// Directly manipulate the hardware FIFOs. Synchronous and busy-waits. Not
// thread-safe, should only be used while holding the api_mutex lock.

fn enqueue_u32(x: u32) {
    unsafe {
        while (get_STATUS() & STATUS_BIT_FULL) == STATUS_BIT_FULL {}
        set_MBOXW(x);
    }
}

fn dequeue_u32() -> u32 {
    unsafe {
        while (get_STATUS() & STATUS_BIT_EMPTY) == STATUS_BIT_EMPTY {}
        return get_MBOXR();
    }
}

fn drain_read_fifo() {
    unsafe {
        while (get_STATUS() & STATUS_BIT_EMPTY) == 0 {
            let _ = get_MBOXR();
        }
    }
}

//------------------------------------------------------------------------------

#[no_mangle]
pub unsafe extern "C" fn pre_init() {
    static KATA_LOGGER: KataLogger = KataLogger;
    log::set_logger(&KATA_LOGGER).unwrap();
    log::set_max_level(log::LevelFilter::Trace);

    // We always want our receive interrupt to fire as soon as anything appears
    // in the mailbox, so set the threshold to 0.
    set_RIRQT(0);
    set_INTR_STATE(INTR_STATE_BIT_RTIRQ);
    set_INTR_ENABLE(INTR_ENABLE_BIT_RTIRQ);
}

//------------------------------------------------------------------------------

// When outbox.count > write_threshold, this interrupt fires.
#[no_mangle]
pub unsafe extern "C" fn wtirq_handle() {
    trace!("wtirq_handle()");

    // We don't have anything to do here yet, so just clear the interrupt.
    set_INTR_STATE(INTR_STATE_BIT_WTIRQ);
    wtirq_acknowledge();
}

// When inbox.count > read_threshold, this interrupt fires.
#[no_mangle]
pub unsafe extern "C" fn rtirq_handle() {
    trace!("rtirq_handle()");

    // Unblock anyone waiting for a message. api_receive() below will clear
    // the interrupt once the message has been deliverd to the client.
    rx_semaphore_post();
}

// When an error occurs, this interrupt fires. We don't handle errors yet.
#[no_mangle]
pub unsafe extern "C" fn eirq_handle() {
    error!("eirq_handle() - error flag is 0x{:X}", get_ERROR());

    // We don't have anything to do here yet, so just clear the interrupt.
    set_INTR_STATE(INTR_STATE_BIT_EIRQ);
    eirq_acknowledge();
}

//------------------------------------------------------------------------------

// Send a message to the security core. The message must be at a _physical_
// address, as the security core knows nothing about seL4's virtual memory.
#[no_mangle]
pub unsafe extern "C" fn api_send(request_paddr: u32, request_size: u32) {
    api_mutex_lock();

    let request_header = request_size | HEADER_FLAG_LONG_MESSAGE;
    enqueue_u32(request_header);
    enqueue_u32(request_paddr);

    api_mutex_unlock();
}

// Receive a message from the security core. Blocks the calling thread until a
// message arrives.
#[no_mangle]
pub unsafe extern "C" fn api_receive(response_paddr: *mut u32, response_size: *mut u32) {
    api_mutex_lock();

    // When a message arrives, the interrupt handler will raise the semaphore.
    rx_semaphore_wait();

    // Message arrived, dequeue it.
    let message_header = dequeue_u32();
    let message_paddr = dequeue_u32();
    response_paddr.write(message_paddr);
    response_size.write(message_header & !HEADER_FLAG_LONG_MESSAGE);

    // The interrupt that raised the semaphore has been handled, clear it.
    set_INTR_STATE(INTR_STATE_BIT_RTIRQ);
    rtirq_acknowledge();

    api_mutex_unlock();
}

//------------------------------------------------------------------------------
<commit_msg>MailboxDriver: clippy findings<commit_after>#![no_std]
// We want to keep all mailbox constants here even if they're currently unused.
#![allow(dead_code)]
#![allow(non_snake_case)]
#![allow(clippy::missing_safety_doc)]

use kata_os_common::logger::KataLogger;
use log::{error, trace};

//------------------------------------------------------------------------------
// TODO(aappleby): Can we replace this with the register_struct! thing?

const REG_INTR_STATE: u32 = 0x000; // R/W1C
const REG_INTR_ENABLE: u32 = 0x004; // R/W
const REG_INTR_TEST: u32 = 0x008; // R/W
const REG_MBOXW: u32 = 0x00C; // W
const REG_MBOXR: u32 = 0x010; // R
const REG_STATUS: u32 = 0x014; // R
const REG_ERROR: u32 = 0x018; // R
const REG_WIRQT: u32 = 0x01C; // R/W
const REG_RIRQT: u32 = 0x020; // R/W
const REG_CTRL: u32 = 0x024; // R/W

const INTR_STATE_BIT_WTIRQ: u32 = 0b001;
const INTR_STATE_BIT_RTIRQ: u32 = 0b010;
const INTR_STATE_BIT_EIRQ: u32 = 0b100;
const INTR_STATE_MASK: u32 = 0b111;

const INTR_ENABLE_BIT_WTIRQ: u32 = 0b001;
const INTR_ENABLE_BIT_RTIRQ: u32 = 0b010;
const INTR_ENABLE_BIT_EIRQ: u32 = 0b100;
const INTR_ENABLE_MASK: u32 = 0b111;

const INTR_TEST_BIT_WTIRQ: u32 = 0b001;
const INTR_TEST_BIT_RTIRQ: u32 = 0b010;
const INTR_TEST_BIT_EIRQ: u32 = 0b100;
const INTR_TEST_MASK: u32 = 0b111;

const STATUS_BIT_EMPTY: u32 = 0b0001;
const STATUS_BIT_FULL: u32 = 0b0010;
const STATUS_BIT_WFIFOL: u32 = 0b0100;
const STATUS_BIT_RFIFOL: u32 = 0b1000;
const STATUS_MASK: u32 = 0b1111;

const ERROR_BIT_READ: u32 = 0b01;
const ERROR_BIT_WRITE: u32 = 0b10;
const ERROR_MASK: u32 = 0b11;

const FIFO_SIZE: u32 = 8;
const FIFO_MASK: u32 = FIFO_SIZE - 1;
const WIRQT_MASK: u32 = FIFO_MASK;
const RIRQT_MASK: u32 = FIFO_MASK;

const CTRL_BIT_FLUSH_WFIFO: u32 = 0b01;
const CTRL_BIT_FLUSH_RFIFO: u32 = 0b10;
const CTRL_MASK: u32 = 0b11;

// The high bit of the message header is used to distinguish between "inline"
// messages that fit in the mailbox and "long" messages that contain the
// physical address of a memory page containing the message.
const HEADER_FLAG_LONG_MESSAGE: u32 = 0x80000000;

//------------------------------------------------------------------------------

extern "C" {
    // Mailbox registers
    static mailbox_mmio: *mut u32;

    // Global mailbox lock
    fn api_mutex_lock() -> u32;
    fn api_mutex_unlock() -> u32;

    // Mailbox arrival semaphore
    fn rx_semaphore_wait() -> u32;
    fn rx_semaphore_post() -> u32;

    // Mailbox interrupts
    fn wtirq_acknowledge() -> u32;
    fn rtirq_acknowledge() -> u32;
    fn eirq_acknowledge() -> u32;
}

//------------------------------------------------------------------------------
// Directly manipulate the mailbox registers.

unsafe fn get_intr_state() -> u32 {
    mailbox_mmio.offset(0).read_volatile()
}
unsafe fn get_INTR_ENABLE() -> u32 {
    mailbox_mmio.offset(1).read_volatile()
}
unsafe fn get_INTR_TEST() -> u32 {
    mailbox_mmio.offset(2).read_volatile()
}
unsafe fn get_MBOXW() -> u32 {
    mailbox_mmio.offset(3).read_volatile()
}
unsafe fn get_MBOXR() -> u32 {
    mailbox_mmio.offset(4).read_volatile()
}
unsafe fn get_STATUS() -> u32 {
    mailbox_mmio.offset(5).read_volatile()
}
unsafe fn get_ERROR() -> u32 {
    mailbox_mmio.offset(6).read_volatile()
}
unsafe fn get_WIRQT() -> u32 {
    mailbox_mmio.offset(7).read_volatile()
}
unsafe fn get_RIRQT() -> u32 {
    mailbox_mmio.offset(8).read_volatile()
}
unsafe fn get_CTRL() -> u32 {
    mailbox_mmio.offset(9).read_volatile()
}

unsafe fn set_INTR_STATE(x: u32) {
    mailbox_mmio.offset(0).write_volatile(x);
}
unsafe fn set_INTR_ENABLE(x: u32) {
    mailbox_mmio.offset(1).write_volatile(x);
}
unsafe fn set_INTR_TEST(x: u32) {
    mailbox_mmio.offset(2).write_volatile(x);
}
unsafe fn set_MBOXW(x: u32) {
    mailbox_mmio.offset(3).write_volatile(x);
}
unsafe fn set_MBOXR(x: u32) {
    mailbox_mmio.offset(4).write_volatile(x);
}
unsafe fn set_STATUS(x: u32) {
    mailbox_mmio.offset(5).write_volatile(x);
}
unsafe fn set_ERROR(x: u32) {
    mailbox_mmio.offset(6).write_volatile(x);
}
unsafe fn set_WIRQT(x: u32) {
    mailbox_mmio.offset(7).write_volatile(x);
}
unsafe fn set_RIRQT(x: u32) {
    mailbox_mmio.offset(8).write_volatile(x);
}
unsafe fn set_CTRL(x: u32) {
    mailbox_mmio.offset(9).write_volatile(x);
}

//------------------------------------------------------------------------------
// Directly manipulate the hardware FIFOs. Synchronous and busy-waits. Not
// thread-safe, should only be used while holding the api_mutex lock.

fn enqueue_u32(x: u32) {
    unsafe {
        while (get_STATUS() & STATUS_BIT_FULL) == STATUS_BIT_FULL {}
        set_MBOXW(x);
    }
}

fn dequeue_u32() -> u32 {
    unsafe {
        while (get_STATUS() & STATUS_BIT_EMPTY) == STATUS_BIT_EMPTY {}
        get_MBOXR()
    }
}

fn drain_read_fifo() {
    unsafe {
        while (get_STATUS() & STATUS_BIT_EMPTY) == 0 {
            let _ = get_MBOXR();
        }
    }
}

//------------------------------------------------------------------------------

#[no_mangle]
pub unsafe extern "C" fn pre_init() {
    static KATA_LOGGER: KataLogger = KataLogger;
    log::set_logger(&KATA_LOGGER).unwrap();
    log::set_max_level(log::LevelFilter::Trace);

    // We always want our receive interrupt to fire as soon as anything appears
    // in the mailbox, so set the threshold to 0.
    set_RIRQT(0);
    set_INTR_STATE(INTR_STATE_BIT_RTIRQ);
    set_INTR_ENABLE(INTR_ENABLE_BIT_RTIRQ);
}

//------------------------------------------------------------------------------

// When outbox.count > write_threshold, this interrupt fires.
#[no_mangle]
pub unsafe extern "C" fn wtirq_handle() {
    trace!("wtirq_handle()");

    // We don't have anything to do here yet, so just clear the interrupt.
    set_INTR_STATE(INTR_STATE_BIT_WTIRQ);
    wtirq_acknowledge();
}

// When inbox.count > read_threshold, this interrupt fires.
#[no_mangle]
pub unsafe extern "C" fn rtirq_handle() {
    trace!("rtirq_handle()");

    // Unblock anyone waiting for a message. api_receive() below will clear
    // the interrupt once the message has been deliverd to the client.
    rx_semaphore_post();
}

// When an error occurs, this interrupt fires. We don't handle errors yet.
#[no_mangle]
pub unsafe extern "C" fn eirq_handle() {
    error!("eirq_handle() - error flag is 0x{:X}", get_ERROR());

    // We don't have anything to do here yet, so just clear the interrupt.
    set_INTR_STATE(INTR_STATE_BIT_EIRQ);
    eirq_acknowledge();
}

//------------------------------------------------------------------------------

// Send a message to the security core. The message must be at a _physical_
// address, as the security core knows nothing about seL4's virtual memory.
#[no_mangle]
pub unsafe extern "C" fn api_send(request_paddr: u32, request_size: u32) {
    api_mutex_lock();

    let request_header = request_size | HEADER_FLAG_LONG_MESSAGE;
    enqueue_u32(request_header);
    enqueue_u32(request_paddr);

    api_mutex_unlock();
}

// Receive a message from the security core. Blocks the calling thread until a
// message arrives.
#[no_mangle]
pub unsafe extern "C" fn api_receive(response_paddr: *mut u32, response_size: *mut u32) {
    api_mutex_lock();

    // When a message arrives, the interrupt handler will raise the semaphore.
    rx_semaphore_wait();

    // Message arrived, dequeue it.
    let message_header = dequeue_u32();
    let message_paddr = dequeue_u32();
    response_paddr.write(message_paddr);
    response_size.write(message_header & !HEADER_FLAG_LONG_MESSAGE);

    // The interrupt that raised the semaphore has been handled, clear it.
    set_INTR_STATE(INTR_STATE_BIT_RTIRQ);
    rtirq_acknowledge();

    api_mutex_unlock();
}

//------------------------------------------------------------------------------
<|endoftext|>


<commit_before>use cgmath::EuclideanSpace;
use gilrs::{Axis, Button, Gilrs};
use std::{f64::consts::PI, path::PathBuf};
use structopt::StructOpt;
use winit::{
    event,
    event_loop::{ControlFlow, EventLoop},
};

#[derive(Debug, StructOpt)]
struct Opt {
    #[structopt(short, long, default_value = "8FH495PF+29")]
    plus: String,
    #[structopt(short, long, default_value = "0")]
    heading: f64,
    #[structopt(short, long, default_value = "200000")]
    elevation: f64,
    #[structopt(long)]
    generate: Option<PathBuf>,
}

fn compute_projection_matrix(width: f32, height: f32) -> cgmath::Matrix4<f32> {
    let aspect = width / height;
    let f = 1.0 / (45.0f32.to_radians() / aspect).tan();
    let near = 0.1;

    #[cfg_attr(rustfmt, rustfmt_skip)]
    cgmath::Matrix4::new(
        f/aspect,  0.0,  0.0,   0.0,
        0.0,       f,    0.0,   0.0,
        0.0,       0.0,  0.0,  -1.0,
        0.0,       0.0,  near,  0.0)
}

fn make_swapchain(
    device: &wgpu::Device,
    surface: &wgpu::Surface,
    width: u32,
    height: u32,
) -> wgpu::SwapChain {
    device.create_swap_chain(
        &surface,
        &wgpu::SwapChainDescriptor {
            usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
            format: wgpu::TextureFormat::Bgra8UnormSrgb,
            width,
            height,
            present_mode: wgpu::PresentMode::Fifo, // disable vsync by switching to Mailbox,
        },
    )
}
fn make_depth_buffer(device: &wgpu::Device, width: u32, height: u32) -> wgpu::TextureView {
    device
        .create_texture(&wgpu::TextureDescriptor {
            size: wgpu::Extent3d { width, height, depth: 1 },
            mip_level_count: 1,
            sample_count: 1,
            dimension: wgpu::TextureDimension::D2,
            format: wgpu::TextureFormat::Depth32Float,
            usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
            label: None,
        })
        .create_view(&Default::default())
}

fn main() {
    // env_logger::init();

    let runtime = tokio::runtime::Runtime::new().unwrap();

    let trace_path: Option<&std::path::Path> = if cfg!(feature = "trace") {
        std::fs::create_dir_all("trace").unwrap();
        Some(std::path::Path::new("trace"))
    } else {
        None
    };

    let event_loop = EventLoop::new();
    let monitor = event_loop
        .available_monitors()
        .find(|monitor| monitor.video_modes().any(|mode| mode.size().width == 1920));
    let window = winit::window::WindowBuilder::new()
        .with_visible(false)
        .with_fullscreen(Some(winit::window::Fullscreen::Borderless(monitor)))
        .build(&event_loop)
        .unwrap();

    let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
    let surface = unsafe { instance.create_surface(&window) };
    let adapter = runtime
        .block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
            power_preference: wgpu::PowerPreference::HighPerformance,
            compatible_surface: Some(&surface),
        }))
        .expect("Unable to create compatible wgpu adapter");

    // Terra requires support for BC texture compression.
    assert!(adapter.features().contains(wgpu::Features::TEXTURE_COMPRESSION_BC));

    let features = if !adapter.features().contains(wgpu::Features::SHADER_FLOAT64)
        || cfg!(feature = "soft-float64")
    {
        wgpu::Features::TEXTURE_COMPRESSION_BC
    } else {
        wgpu::Features::TEXTURE_COMPRESSION_BC | wgpu::Features::SHADER_FLOAT64
    };

    let (device, mut queue) = runtime
        .block_on(adapter.request_device(
            &wgpu::DeviceDescriptor { features, limits: wgpu::Limits::default(), label: None },
            trace_path,
        ))
        .expect("Unable to create compatible wgpu device");

    let mut size = window.inner_size();
    let mut swap_chain = None;
    let mut depth_buffer = None;

    #[cfg(feature = "smaa")]
    let mut smaa_target = None;

    let mut gilrs = Gilrs::new().unwrap();
    let mut current_gamepad = None;
    for (_id, gamepad) in gilrs.gamepads() {
        current_gamepad = Some(gamepad.id());
    }

    let opt = Opt::from_args();
    let plus_center =
        open_location_code::decode(&opt.plus).expect("Failed to parse plus code").center;

    let planet_radius = 6371000.0;
    let mut angle = opt.heading.to_radians();
    let mut lat = plus_center.y().to_radians();
    let mut long = plus_center.x().to_radians();
    let mut altitude = opt.elevation;

    let mut terrain = terra::Terrain::new(&device, &mut queue).unwrap();

    if let Some(dataset_directory) = opt.generate {
        let pb = indicatif::ProgressBar::new(100);
        pb.set_style(
            indicatif::ProgressStyle::default_bar()
                .template("{msg} {pos}/{len} [{wide_bar}] {percent}% {per_sec} {eta}")
                .progress_chars("=> "),
        );
        let mut last_message = None;
        let mut progress_callback = |l: &str, i: usize, total: usize| {
            if last_message.is_none() || l != last_message.as_ref().unwrap() {
                pb.set_message(l);
                pb.reset_eta();
                last_message = Some(l.to_string());
            }
            pb.set_length(total as u64);
            pb.set_position(i as u64);
        };

        runtime
            .block_on(terrain.generate_heightmaps(
                dataset_directory.join("ETOPO1_Ice_c_geotiff.zip"),
                dataset_directory.join("strm3"),
                &mut progress_callback,
            ))
            .unwrap();
        runtime
            .block_on(
                terrain
                    .generate_albedos(dataset_directory.join("bluemarble"), &mut progress_callback),
            )
            .unwrap();
        runtime.block_on(terrain.generate_roughness(&mut progress_callback)).unwrap();
    }

    {
        let r = altitude + planet_radius;
        let eye = cgmath::Point3::new(
            r * lat.cos() * long.cos(),
            r * lat.cos() * long.sin(),
            r * lat.sin(),
        );
        while terrain.poll_loading_status(&device, &mut queue, eye.into()) {
            std::thread::sleep(std::time::Duration::from_millis(10));
        }
    }

    let mut set_visible = false;
    event_loop.run(move |event, _, control_flow| {
        *control_flow = if cfg!(feature = "metal-auto-capture") {
            ControlFlow::Exit
        } else {
            ControlFlow::Poll
        };
        match event {
            event::Event::WindowEvent { event, .. } => match event {
                event::WindowEvent::CloseRequested => {
                    *control_flow = ControlFlow::Exit;
                }
                event::WindowEvent::KeyboardInput {
                    input:
                        event::KeyboardInput {
                            virtual_keycode: Some(keycode),
                            state: event::ElementState::Pressed,
                            ..
                        },
                    ..
                } => match keycode {
                    event::VirtualKeyCode::Escape => *control_flow = ControlFlow::Exit,
                    event::VirtualKeyCode::Space => altitude += 0.1 * altitude,
                    event::VirtualKeyCode::Semicolon => altitude -= 0.1 * altitude,
                    event::VirtualKeyCode::Left => {
                        lat += -angle.sin() * -(0.0000001 * altitude).min(0.01);
                        long += angle.cos() * -(0.0000001 * altitude).min(0.01);
                    }
                    event::VirtualKeyCode::Right => {
                        lat += -angle.sin() * (0.0000001 * altitude).min(0.01);
                        long += angle.cos() * (0.0000001 * altitude).min(0.01);
                    }
                    event::VirtualKeyCode::Up => {
                        lat += angle.cos() * (0.0000001 * altitude).min(0.01);
                        long += -angle.sin() * (0.0000001 * altitude).min(0.01);
                    }
                    event::VirtualKeyCode::Down => {
                        lat += angle.cos() * -(0.0000001 * altitude).min(0.01);
                        long += -angle.sin() * -(0.0000001 * altitude).min(0.01);
                    }
                    _ => {}
                },
                event::WindowEvent::Resized(new_size) => {
                    size = new_size;
                    swap_chain = None;
                    depth_buffer = None;
                    #[cfg(feature = "smaa")]
                    {
                        smaa_target = None;
                    }
                }
                _ => {}
            },
            event::Event::MainEventsCleared => {
                if swap_chain.is_none() {
                    swap_chain = Some(make_swapchain(&device, &surface, size.width, size.height));
                }
                if depth_buffer.is_none() {
                    depth_buffer = Some(make_depth_buffer(&device, size.width, size.height));
                }
                #[cfg(feature = "smaa")]
                if smaa_target.is_none() {
                    smaa_target = Some(smaa::SmaaTarget::new(
                        &device,
                        &queue,
                        size.width,
                        size.height,
                        wgpu::TextureFormat::Bgra8UnormSrgb,
                        wgpu::TextureFormat::Bgra8UnormSrgb,
                    ).unwrap());
                }

                let frame = swap_chain.as_ref().unwrap().get_current_frame();
                let frame = match frame {
                    Ok(ref f) => &f.output.view,
                    Err(_) => return,
                };

                while let Some(gilrs::Event { id, event: _event, time: _ }) = gilrs.next_event() {
                    current_gamepad = Some(id);
                }
                if let Some(gamepad) = current_gamepad.map(|id| gilrs.gamepad(id)) {
                    lat += angle.cos() * gamepad.value(Axis::LeftStickY) as f64 * 0.01
                        - angle.sin() * gamepad.value(Axis::LeftStickX) as f64 * 0.01;

                    long += -angle.sin() * gamepad.value(Axis::LeftStickY) as f64 * 0.01
                        + angle.cos() * gamepad.value(Axis::LeftStickX) as f64 * 0.01;

                    angle -= gamepad.value(Axis::RightZ) as f64 * 0.01;

                    if gamepad.is_pressed(Button::DPadUp) {
                        altitude += 0.01 * altitude;
                    }
                    if gamepad.is_pressed(Button::DPadDown) {
                        altitude -= 0.01 * altitude;
                    }
                }

                lat = lat.max(-PI).min(PI);
                if long < -PI {
                    long += PI * 2.0;
                }
                if long > PI {
                    long -= PI * 2.0;
                }

                let surface_height = terrain.get_height(lat, long) as f64;
                let r = altitude + planet_radius + surface_height + 2.0;
                let eye = cgmath::Point3::new(
                    r * lat.cos() * long.cos(),
                    r * lat.cos() * long.sin(),
                    r * lat.sin(),
                );

                let dt = (planet_radius / (planet_radius + altitude)).acos() * 0.3;
                let latc = lat + angle.cos() * dt;
                let longc = long - angle.sin() * dt;

                let center = cgmath::Point3::new(
                    planet_radius * latc.cos() * longc.cos() - eye.x,
                    planet_radius * latc.cos() * longc.sin() - eye.y,
                    planet_radius * latc.sin() - eye.z,
                );
                let up = cgmath::Vector3::new(eye.x as f32, eye.y as f32, eye.z as f32);

                let view = cgmath::Matrix4::look_at_rh(
                    cgmath::Point3::origin(),
                    cgmath::Point3::new(center.x as f32, center.y as f32, center.z as f32),
                    up,
                );

                let proj = compute_projection_matrix(size.width as f32, size.height as f32);
                let view_proj = proj * view;
                let view_proj = mint::ColumnMatrix4 {
                    x: view_proj.x.into(),
                    y: view_proj.y.into(),
                    z: view_proj.z.into(),
                    w: view_proj.w.into(),
                };

                #[cfg(feature = "smaa")]
                let color_buffer = &smaa_target.as_ref().unwrap().color_target().create_view(&Default::default());
                #[cfg(not(feature = "smaa"))]
                let color_buffer = frame;

                terrain.render(
                    &device,
                    &mut queue,
                    color_buffer,
                    depth_buffer.as_ref().unwrap(),
                    (size.width, size.height),
                    view_proj,
                    eye.into(),
                );

                #[cfg(feature = "smaa")]
                smaa_target.as_mut().unwrap().resolve(&device, &queue, &frame);

                if !set_visible {
                    window.set_visible(true);
                    set_visible = true;
                }
            }
            _ => (),
        }
    });
}
<commit_msg>Fix #14<commit_after>use cgmath::EuclideanSpace;
use gilrs::{Axis, Button, Gilrs};
use std::{f64::consts::PI, path::PathBuf};
use structopt::StructOpt;
use winit::{
    event,
    event_loop::{ControlFlow, EventLoop},
};

#[derive(Debug, StructOpt)]
struct Opt {
    #[structopt(short, long, default_value = "8FH495PF+29")]
    plus: String,
    #[structopt(short, long, default_value = "0")]
    heading: f64,
    #[structopt(short, long, default_value = "200000")]
    elevation: f64,
    #[structopt(long)]
    generate: Option<PathBuf>,
}

fn compute_projection_matrix(width: f32, height: f32) -> cgmath::Matrix4<f32> {
    let aspect = width / height;
    let f = 1.0 / (45.0f32.to_radians() / aspect).tan();
    let near = 0.1;

    #[cfg_attr(rustfmt, rustfmt_skip)]
    cgmath::Matrix4::new(
        f/aspect,  0.0,  0.0,   0.0,
        0.0,       f,    0.0,   0.0,
        0.0,       0.0,  0.0,  -1.0,
        0.0,       0.0,  near,  0.0)
}

fn make_swapchain(
    device: &wgpu::Device,
    surface: &wgpu::Surface,
    width: u32,
    height: u32,
) -> wgpu::SwapChain {
    device.create_swap_chain(
        &surface,
        &wgpu::SwapChainDescriptor {
            usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
            format: wgpu::TextureFormat::Bgra8UnormSrgb,
            width,
            height,
            present_mode: wgpu::PresentMode::Fifo, // disable vsync by switching to Mailbox,
        },
    )
}
fn make_depth_buffer(device: &wgpu::Device, width: u32, height: u32) -> wgpu::TextureView {
    device
        .create_texture(&wgpu::TextureDescriptor {
            size: wgpu::Extent3d { width, height, depth: 1 },
            mip_level_count: 1,
            sample_count: 1,
            dimension: wgpu::TextureDimension::D2,
            format: wgpu::TextureFormat::Depth32Float,
            usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
            label: None,
        })
        .create_view(&Default::default())
}

fn main() {
    // env_logger::init();

    let runtime = tokio::runtime::Runtime::new().unwrap();

    let trace_path: Option<&std::path::Path> = if cfg!(feature = "trace") {
        std::fs::create_dir_all("trace").unwrap();
        Some(std::path::Path::new("trace"))
    } else {
        None
    };

    let event_loop = EventLoop::new();
    let monitor = event_loop
        .available_monitors()
        .find(|monitor| monitor.video_modes().any(|mode| mode.size().width == 1920));
    let window = winit::window::WindowBuilder::new()
        .with_visible(false)
        .with_fullscreen(Some(winit::window::Fullscreen::Borderless(monitor)))
        .build(&event_loop)
        .unwrap();

    let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
    let surface = unsafe { instance.create_surface(&window) };
    let adapter = runtime
        .block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
            power_preference: wgpu::PowerPreference::HighPerformance,
            compatible_surface: Some(&surface),
        }))
        .expect("Unable to create compatible wgpu adapter");

    // Terra requires support for BC texture compression.
    assert!(adapter.features().contains(wgpu::Features::TEXTURE_COMPRESSION_BC));

    let features = if !adapter.features().contains(wgpu::Features::SHADER_FLOAT64)
        || cfg!(feature = "soft-float64")
    {
        wgpu::Features::TEXTURE_COMPRESSION_BC
    } else {
        wgpu::Features::TEXTURE_COMPRESSION_BC | wgpu::Features::SHADER_FLOAT64
    };

    let (device, mut queue) = runtime
        .block_on(adapter.request_device(
            &wgpu::DeviceDescriptor { features, limits: wgpu::Limits::default(), label: None },
            trace_path,
        ))
        .expect("Unable to create compatible wgpu device");

    let mut size = window.inner_size();
    let mut swap_chain = None;
    let mut depth_buffer = None;

    #[cfg(feature = "smaa")]
    let mut smaa_target = None;

    let mut gilrs = Gilrs::new().unwrap();
    let mut current_gamepad = None;
    for (_id, gamepad) in gilrs.gamepads() {
        current_gamepad = Some(gamepad.id());
    }

    let opt = Opt::from_args();
    let plus_center =
        open_location_code::decode(&opt.plus).expect("Failed to parse plus code").center;

    let planet_radius = 6371000.0;
    let mut angle = opt.heading.to_radians();
    let mut lat = plus_center.y().to_radians();
    let mut long = plus_center.x().to_radians();
    let mut altitude = opt.elevation;

    let mut terrain = terra::Terrain::new(&device, &mut queue).unwrap();

    if let Some(dataset_directory) = opt.generate {
        let pb = indicatif::ProgressBar::new(100);
        pb.set_style(
            indicatif::ProgressStyle::default_bar()
                .template("{msg} {pos}/{len} [{wide_bar}] {percent}% {per_sec} {eta}")
                .progress_chars("=> "),
        );
        let mut last_message = None;
        let mut progress_callback = |l: &str, i: usize, total: usize| {
            if last_message.is_none() || l != last_message.as_ref().unwrap() {
                pb.set_message(l);
                pb.reset_eta();
                last_message = Some(l.to_string());
            }
            pb.set_length(total as u64);
            pb.set_position(i as u64);
        };

        runtime
            .block_on(terrain.generate_heightmaps(
                dataset_directory.join("ETOPO1_Ice_c_geotiff.zip"),
                dataset_directory.join("strm3"),
                &mut progress_callback,
            ))
            .unwrap();
        runtime
            .block_on(
                terrain
                    .generate_albedos(dataset_directory.join("bluemarble"), &mut progress_callback),
            )
            .unwrap();
        runtime.block_on(terrain.generate_roughness(&mut progress_callback)).unwrap();
    }

    {
        let r = altitude + planet_radius;
        let eye = cgmath::Point3::new(
            r * lat.cos() * long.cos(),
            r * lat.cos() * long.sin(),
            r * lat.sin(),
        );
        while terrain.poll_loading_status(&device, &mut queue, eye.into()) {
            std::thread::sleep(std::time::Duration::from_millis(10));
        }
    }

    let mut set_visible = false;
    event_loop.run(move |event, _, control_flow| {
        *control_flow = if cfg!(feature = "metal-auto-capture") {
            ControlFlow::Exit
        } else {
            ControlFlow::Poll
        };
        match event {
            event::Event::WindowEvent { event, .. } => match event {
                event::WindowEvent::CloseRequested => {
                    *control_flow = ControlFlow::Exit;
                }
                event::WindowEvent::KeyboardInput {
                    input:
                        event::KeyboardInput {
                            virtual_keycode: Some(keycode),
                            state: event::ElementState::Pressed,
                            ..
                        },
                    ..
                } => match keycode {
                    event::VirtualKeyCode::Escape => *control_flow = ControlFlow::Exit,
                    event::VirtualKeyCode::Space => altitude += 0.1 * altitude,
                    event::VirtualKeyCode::Z | event::VirtualKeyCode::Semicolon => {
                        altitude -= 0.1 * altitude
                    }
                    event::VirtualKeyCode::Left => {
                        lat += -angle.sin() * -(0.0000001 * altitude).min(0.01);
                        long += angle.cos() * -(0.0000001 * altitude).min(0.01);
                    }
                    event::VirtualKeyCode::Right => {
                        lat += -angle.sin() * (0.0000001 * altitude).min(0.01);
                        long += angle.cos() * (0.0000001 * altitude).min(0.01);
                    }
                    event::VirtualKeyCode::Up => {
                        lat += angle.cos() * (0.0000001 * altitude).min(0.01);
                        long += -angle.sin() * (0.0000001 * altitude).min(0.01);
                    }
                    event::VirtualKeyCode::Down => {
                        lat += angle.cos() * -(0.0000001 * altitude).min(0.01);
                        long += -angle.sin() * -(0.0000001 * altitude).min(0.01);
                    }
                    _ => {}
                },
                event::WindowEvent::Resized(new_size) => {
                    size = new_size;
                    swap_chain = None;
                    depth_buffer = None;
                    #[cfg(feature = "smaa")]
                    {
                        smaa_target = None;
                    }
                }
                _ => {}
            },
            event::Event::MainEventsCleared => {
                if swap_chain.is_none() {
                    swap_chain = Some(make_swapchain(&device, &surface, size.width, size.height));
                }
                if depth_buffer.is_none() {
                    depth_buffer = Some(make_depth_buffer(&device, size.width, size.height));
                }
                #[cfg(feature = "smaa")]
                if smaa_target.is_none() {
                    smaa_target = Some(smaa::SmaaTarget::new(
                        &device,
                        &queue,
                        size.width,
                        size.height,
                        wgpu::TextureFormat::Bgra8UnormSrgb,
                        wgpu::TextureFormat::Bgra8UnormSrgb,
                    ).unwrap());
                }

                let frame = swap_chain.as_ref().unwrap().get_current_frame();
                let frame = match frame {
                    Ok(ref f) => &f.output.view,
                    Err(_) => return,
                };

                while let Some(gilrs::Event { id, event: _event, time: _ }) = gilrs.next_event() {
                    current_gamepad = Some(id);
                }
                if let Some(gamepad) = current_gamepad.map(|id| gilrs.gamepad(id)) {
                    lat += angle.cos() * gamepad.value(Axis::LeftStickY) as f64 * 0.01
                        - angle.sin() * gamepad.value(Axis::LeftStickX) as f64 * 0.01;

                    long += -angle.sin() * gamepad.value(Axis::LeftStickY) as f64 * 0.01
                        + angle.cos() * gamepad.value(Axis::LeftStickX) as f64 * 0.01;

                    angle -= gamepad.value(Axis::RightZ) as f64 * 0.01;

                    if gamepad.is_pressed(Button::DPadUp) {
                        altitude += 0.01 * altitude;
                    }
                    if gamepad.is_pressed(Button::DPadDown) {
                        altitude -= 0.01 * altitude;
                    }
                }

                lat = lat.max(-PI).min(PI);
                if long < -PI {
                    long += PI * 2.0;
                }
                if long > PI {
                    long -= PI * 2.0;
                }

                let surface_height = terrain.get_height(lat, long) as f64;
                let r = altitude + planet_radius + surface_height + 2.0;
                let eye = cgmath::Point3::new(
                    r * lat.cos() * long.cos(),
                    r * lat.cos() * long.sin(),
                    r * lat.sin(),
                );

                let dt = (planet_radius / (planet_radius + altitude)).acos() * 0.3;
                let latc = lat + angle.cos() * dt;
                let longc = long - angle.sin() * dt;

                let center = cgmath::Point3::new(
                    planet_radius * latc.cos() * longc.cos() - eye.x,
                    planet_radius * latc.cos() * longc.sin() - eye.y,
                    planet_radius * latc.sin() - eye.z,
                );
                let up = cgmath::Vector3::new(eye.x as f32, eye.y as f32, eye.z as f32);

                let view = cgmath::Matrix4::look_at_rh(
                    cgmath::Point3::origin(),
                    cgmath::Point3::new(center.x as f32, center.y as f32, center.z as f32),
                    up,
                );

                let proj = compute_projection_matrix(size.width as f32, size.height as f32);
                let view_proj = proj * view;
                let view_proj = mint::ColumnMatrix4 {
                    x: view_proj.x.into(),
                    y: view_proj.y.into(),
                    z: view_proj.z.into(),
                    w: view_proj.w.into(),
                };

                #[cfg(feature = "smaa")]
                let color_buffer = &smaa_target.as_ref().unwrap().color_target().create_view(&Default::default());
                #[cfg(not(feature = "smaa"))]
                let color_buffer = frame;

                terrain.render(
                    &device,
                    &mut queue,
                    color_buffer,
                    depth_buffer.as_ref().unwrap(),
                    (size.width, size.height),
                    view_proj,
                    eye.into(),
                );

                #[cfg(feature = "smaa")]
                smaa_target.as_mut().unwrap().resolve(&device, &queue, &frame);

                if !set_visible {
                    window.set_visible(true);
                    set_visible = true;
                }
            }
            _ => (),
        }
    });
}
<|endoftext|>


<commit_before>extern crate fs2;
extern crate regex;
extern crate toml;
#[cfg(test)] extern crate tempdir;
extern crate semver;

pub mod storeid;
pub mod content;
pub mod entry;
pub mod error;
pub mod header;
pub mod store;
mod lazyfile;

<commit_msg>Use version<commit_after>#[macro_use] extern crate version;
extern crate fs2;
extern crate regex;
extern crate toml;
#[cfg(test)] extern crate tempdir;
extern crate semver;

pub mod storeid;
pub mod content;
pub mod entry;
pub mod error;
pub mod header;
pub mod store;
mod lazyfile;

<|endoftext|>


<commit_before>

use libimagstore::storeid::StoreIdIterator;
use libimagstore::store::{FileLockEntry, Store};
use libimagstore::storeid::StoreId;
use module_path::ModuleEntryPath;
use error::{TodoError, TodoErrorKind};

use std::result::Result as RResult;

pub type Result<T> = RResult<T, TodoError>;

pub struct Read<'a> {
	 entry: FileLockEntry<'a>,
}

pub fn all_uuids(store: &Store) -> Result<ReadIterator> {
		store.retrieve_for_module("uuid")
			.map(|iter| ReadIterator::new(store, iter))
			.map_err(|e| TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e))))
}

trait FromStoreId {
    fn from_storeid<'a>(&'a Store, StoreId) -> Result<Read<'a>>;
}

impl<'a> FromStoreId for Read<'a> {

    fn from_storeid<'b>(store: &'b Store, id: StoreId) -> Result<Read<'b>> {
        match store.retrieve(id) {
        	Err(e) => Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e)))),
            Ok(c)  => Ok(Read { entry: c }),
        }
    }

}

pub struct ReadIterator<'a> {
    store: &'a Store,
    iditer: StoreIdIterator,
}

impl<'a> ReadIterator<'a> {

    pub fn new(store: &'a Store, iditer: StoreIdIterator) -> ReadIterator<'a> {
        ReadIterator {
            store: store,
            iditer: iditer,
        }
    }

}

impl<'a> Iterator for ReadIterator<'a> {
    type Item = Result<Read<'a>>;

    fn next(&mut self) -> Option<Result<Read<'a>>> {
        self.iditer
            .next()
            .map(|id| Read::from_storeid(self.store, id))
    }

}
<commit_msg>Renamed function and iterator<commit_after>
use libimagstore::storeid::{StoreIdIterator, StoreId};
use libimagstore::store::Store;
use error::{TodoError, TodoErrorKind};
use task::Task;

use std::result::Result as RResult;

pub type Result<T> = RResult<T, TodoError>;

pub fn all_todos(store: &Store) -> Result<TaskIterator> {

    store.retrieve_for_module("uuid")
        .map(|iter| TaskIterator::new(store, iter))
        .map_err(|e| TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e))))
}

trait FromStoreId {
    fn from_storeid<'a>(&'a Store, StoreId) -> Result<Task<'a>>;
}

impl<'a> FromStoreId for Task<'a> {

    fn from_storeid<'b>(store: &'b Store, id: StoreId) -> Result<Task<'b>> {
    match store.retrieve(id) {
        Err(e) => Err(TodoError::new(TodoErrorKind::StoreError, Some(Box::new(e)))),
	    Ok(c)  => Ok(Task::new( c )),
	    }
    }
}

pub struct TaskIterator<'a> {
    store: &'a Store,
    iditer: StoreIdIterator,
}

impl<'a> TaskIterator<'a> {

    pub fn new(store: &'a Store, iditer: StoreIdIterator) -> TaskIterator<'a> {
	TaskIterator {
	    store: store,
	    iditer: iditer,
	    }
    }
}

impl<'a> Iterator for TaskIterator<'a> {
    type Item = Result<Task<'a>>;

    fn next(&mut self) -> Option<Result<Task<'a>>> {
	self.iditer
	    .next()
	    .map(|id| Task::from_storeid(self.store, id))
    }
}
<|endoftext|>


<commit_before>extern crate roboime_next;
extern crate clap;
extern crate env_logger;
extern crate log;

use std::env;
use std::sync::mpsc::channel;
use std::process::{exit, Command};
use std::error::Error;
use log::LogLevelFilter;
use env_logger::LogBuilder;
use roboime_next::prelude::*;
use roboime_next::{game, ai, grsim, Result};
use clap::{Arg, App, AppSettings};

fn main_loop() -> Result<()> {
    let matches = App::new("robime-next-cli")
        .setting(AppSettings::ColoredHelp)
        .setting(AppSettings::DeriveDisplayOrder)
        .setting(AppSettings::TrailingVarArg)
        .about("Connect an AI to a Robocup SSL game through an stdio interface (like codingame).")
        .arg(Arg::with_name("blue")
             .short("b")
             .long("blue")
             .help("Play as the blue team"))
        .arg(Arg::with_name("yellow")
             .conflicts_with("blue")
             .short("y")
             .long("yellow")
             .help("Play as the yellow team (default)"))
        .arg(Arg::with_name("v")
             .short("v")
             .multiple(true)
             .help("Sets the level of verbosity"))
        .arg(Arg::with_name("q")
             .conflicts_with("v")
             .long("quiet")
             .short("q")
             .help("Don't log warnings or errors."))
        .arg(Arg::with_name("grsim_addr")
             .long("grsim")
             .takes_value(true)
             .value_name("ADDRESS:PORT")
             .help("Set the address and port where grSim is listening for commands."))
        .arg(Arg::with_name("grsim_ip")
             .conflicts_with("gsim_addr")
             .long("grsim-addr")
             .takes_value(true)
             .value_name("ADDRESS")
             .help("Set the address where grSim is listening for commands."))
        .arg(Arg::with_name("vision_addr")
             .conflicts_with("vision_port")
             .long("vision")
             .takes_value(true)
             .value_name("ADDRESS:PORT")
             .help("Set the multicast address and port to receive the vision packets."))
        .arg(Arg::with_name("vision_port")
             .conflicts_with("vision_addr")
             .long("vision-port")
             .takes_value(true)
             .value_name("PORT")
             .help("Set the port to receive the vision packets. (Use default multicast address)"))
        .arg(Arg::with_name("AI")
             .required(true)
             .multiple(true)
             .value_name("COMMAND")
             .help("Command to start the AI, accepts arguments."))
        .get_matches();

    let mut builder = LogBuilder::new();
    builder.format(|record| {
        format!("{} [{}] {}", record.level(), record.location().module_path(), record.args())
    });
    let verbosity = matches.occurrences_of("v");
    builder.filter(Some("roboime"), match verbosity {
        0 => LogLevelFilter::Warn,
        1 => LogLevelFilter::Info,
        2 => LogLevelFilter::Debug,
        _ => LogLevelFilter::Trace,
    });
    if matches.is_present("q") {
        builder.filter(Some("roboime"), LogLevelFilter::Off);
    }
    if env::var("RUST_LOG").is_ok() {
       builder.parse(&env::var("RUST_LOG").unwrap());
    }
    try!(builder.init());

    let ai_cmd: Vec<&str> = matches.values_of("AI").unwrap().collect();
    let (ai_program, ai_args) = (ai_cmd[0], &ai_cmd[1..]);
    let mut ai_command = Command::new(ai_program);
    ai_command.args(ai_args);
    let mut ai_cfg = ai::Interface::new(ai_command);
    if matches.is_present("blue") {
        ai_cfg.is_yellow(false);
    }
    if matches.is_present("yellow") {
        ai_cfg.is_yellow(true);
    }

    let mut grsim_cfg = grsim::Interface::new();
    try!(grsim_cfg.grsim_addr(matches.value_of("grsim_addr").unwrap_or("127.0.0.1:20011")));
    try!(grsim_cfg.vision_addr(matches.value_of("vision_addr").unwrap_or("224.5.23.2:10002")));
    if matches.is_present("vision_port") {
        grsim_cfg.vision_port(try!(matches.value_of("vision_port").unwrap().parse()));
    }
    if matches.is_present("grsim_ip") {
        grsim_cfg.grsim_ip(try!(matches.value_of("grsim_ip").unwrap().parse()));
    }

    let state = game::SharedState::new();
    let (tx, rx) = channel();

    let ai = try!(ai_cfg.spawn(state.clone(), tx));
    let grsim = try!(grsim_cfg.spawn(state.clone(), rx));

    (ai, grsim).join()
}

fn dump_error(res: Result<()>) -> bool {
    if let Err(err) = res {
        println!("Error: {}.", err.description());
        while let Some(err) = err.cause() {
            println!("- caused by {}", err.description());
        }
        true
    } else {
        false
    }
}

fn main() {
    if dump_error(main_loop()) {
        exit(1);
    }
}
<commit_msg>Fix recursion bug and avoid unwrap.<commit_after>extern crate roboime_next;
extern crate clap;
extern crate env_logger;
extern crate log;

use std::env;
use std::sync::mpsc::channel;
use std::process::{exit, Command};
use std::error::Error;
use log::LogLevelFilter;
use env_logger::LogBuilder;
use roboime_next::prelude::*;
use roboime_next::{game, ai, grsim, Result};
use clap::{Arg, App, AppSettings};

fn main_loop() -> Result<()> {
    let matches = App::new("robime-next-cli")
        .setting(AppSettings::ColoredHelp)
        .setting(AppSettings::DeriveDisplayOrder)
        .setting(AppSettings::TrailingVarArg)
        .about("Connect an AI to a Robocup SSL game through an stdio interface (like codingame).")
        .arg(Arg::with_name("blue")
             .short("b")
             .long("blue")
             .help("Play as the blue team"))
        .arg(Arg::with_name("yellow")
             .conflicts_with("blue")
             .short("y")
             .long("yellow")
             .help("Play as the yellow team (default)"))
        .arg(Arg::with_name("v")
             .short("v")
             .multiple(true)
             .help("Sets the level of verbosity"))
        .arg(Arg::with_name("q")
             .conflicts_with("v")
             .long("quiet")
             .short("q")
             .help("Don't log warnings or errors."))
        .arg(Arg::with_name("grsim_addr")
             .long("grsim")
             .takes_value(true)
             .value_name("ADDRESS:PORT")
             .help("Set the address and port where grSim is listening for commands."))
        .arg(Arg::with_name("grsim_ip")
             .conflicts_with("gsim_addr")
             .long("grsim-addr")
             .takes_value(true)
             .value_name("ADDRESS")
             .help("Set the address where grSim is listening for commands."))
        .arg(Arg::with_name("vision_addr")
             .conflicts_with("vision_port")
             .long("vision")
             .takes_value(true)
             .value_name("ADDRESS:PORT")
             .help("Set the multicast address and port to receive the vision packets."))
        .arg(Arg::with_name("vision_port")
             .conflicts_with("vision_addr")
             .long("vision-port")
             .takes_value(true)
             .value_name("PORT")
             .help("Set the port to receive the vision packets. (Use default multicast address)"))
        .arg(Arg::with_name("AI")
             .required(true)
             .multiple(true)
             .value_name("COMMAND")
             .help("Command to start the AI, accepts arguments."))
        .get_matches();

    let mut builder = LogBuilder::new();
    builder.format(|record| {
        format!("{} [{}] {}", record.level(), record.location().module_path(), record.args())
    });
    let verbosity = matches.occurrences_of("v");
    builder.filter(Some("roboime"), match verbosity {
        0 => LogLevelFilter::Warn,
        1 => LogLevelFilter::Info,
        2 => LogLevelFilter::Debug,
        _ => LogLevelFilter::Trace,
    });
    if matches.is_present("q") {
        builder.filter(Some("roboime"), LogLevelFilter::Off);
    }
    if let Ok(ref log) = env::var("RUST_LOG") {
       builder.parse(log);
    }
    try!(builder.init());

    let ai_cmd: Vec<&str> = matches.values_of("AI").unwrap().collect();
    let (ai_program, ai_args) = (ai_cmd[0], &ai_cmd[1..]);
    let mut ai_command = Command::new(ai_program);
    ai_command.args(ai_args);
    let mut ai_cfg = ai::Interface::new(ai_command);
    if matches.is_present("blue") {
        ai_cfg.is_yellow(false);
    }
    if matches.is_present("yellow") {
        ai_cfg.is_yellow(true);
    }

    let mut grsim_cfg = grsim::Interface::new();
    try!(grsim_cfg.grsim_addr(matches.value_of("grsim_addr").unwrap_or("127.0.0.1:20011")));
    try!(grsim_cfg.vision_addr(matches.value_of("vision_addr").unwrap_or("224.5.23.2:10002")));
    if matches.is_present("vision_port") {
        grsim_cfg.vision_port(try!(matches.value_of("vision_port").unwrap().parse()));
    }
    if matches.is_present("grsim_ip") {
        grsim_cfg.grsim_ip(try!(matches.value_of("grsim_ip").unwrap().parse()));
    }

    let state = game::SharedState::new();
    let (tx, rx) = channel();

    let ai = try!(ai_cfg.spawn(state.clone(), tx));
    let grsim = try!(grsim_cfg.spawn(state.clone(), rx));

    (ai, grsim).join()
}

fn main() {
    if let Err(err) = main_loop() {
        println!("Error: {}.", err.description());

        let mut err: &Error = &err;
        while let Some(cause) = err.cause() {
            println!("- caused by: {}", cause.description());
            err = cause;
        }

        exit(1);
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Google Inc.
//
// 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.

use std::{
  fs::{self, File},
  io::Write,
  path::{Path, PathBuf},
};

use anyhow::Result;

use docopt::Docopt;

use cargo_raze::{
  metadata::{CargoMetadataFetcher, CargoWorkspaceFiles, MetadataFetcher},
  planning::{BuildPlanner, BuildPlannerImpl},
  rendering::{bazel::BazelRenderer, BuildRenderer, FileOutputs, RenderDetails},
  settings::{load_settings, GenMode},
  util::{find_bazel_workspace_root, PlatformDetails},
};

use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct Options {
  arg_buildprefix: Option<String>,
  flag_verbose: u32,
  flag_quiet: Option<bool>,
  flag_host: Option<String>,
  flag_color: Option<String>,
  flag_target: Option<String>,
  flag_dryrun: Option<bool>,
  flag_cargo_bin_path: Option<String>,
  flag_output: String,
}

const USAGE: &str = r#"
Generate BUILD files for your pre-vendored Cargo dependencies.

Usage:
    cargo raze (-h | --help)
    cargo raze [--verbose] [--quiet] [--color=<WHEN>] [--dryrun] [--cargo-bin-path=<PATH>] [--output=<PATH>]
    cargo raze <buildprefix> [--verbose] [--quiet] [--color=<WHEN>] [--dryrun] [--cargo-bin-path=<PATH>]
                             [--output=<PATH>]

Options:
    -h, --help                         Print this message
    -v, --verbose                      Use verbose output
    -q, --quiet                        No output printed to stdout
    --color=<WHEN>                     Coloring: auto, always, never
    -d, --dryrun                       Do not emit any files
    --cargo-bin-path=<PATH>            Path to the cargo binary to be used for loading workspace metadata
    --output=<PATH>                    Path to output the generated into.
"#;

fn main() -> Result<()> {
  let options: Options = Docopt::new(USAGE)
    .and_then(|d| d.deserialize())
    .unwrap_or_else(|e| e.exit());

  let settings = load_settings("Cargo.toml")?;
  if options.flag_verbose > 0 {
    println!("Loaded override settings: {:#?}", settings);
  }

  let mut metadata_fetcher: Box<dyn MetadataFetcher> = match options.flag_cargo_bin_path {
    Some(ref p) => Box::new(CargoMetadataFetcher::new(p, /*use_tempdir: */ true)),
    None => Box::new(CargoMetadataFetcher::default()),
  };
  let mut planner = BuildPlannerImpl::new(&mut *metadata_fetcher);

  let toml_path = PathBuf::from("./Cargo.toml");
  let lock_path_opt = fs::metadata("./Cargo.lock")
    .ok()
    .map(|_| PathBuf::from("./Cargo.lock"));
  let files = CargoWorkspaceFiles {
    toml_path,
    lock_path_opt,
  };

  let platform_details = match &settings.target {
    Some(target) => Some(PlatformDetails::new_using_rustc(target)?),
    None => None,
  };

  let prefix_path = calculate_workspace_root(
    &settings.workspace_path,
    match !options.flag_output.is_empty() {
      true => Some(&options.flag_output),
      false => None,
    },
    settings.incompatible_relative_workspace_path,
  )?;

  let planned_build = planner.plan_build(&settings, &prefix_path, files, platform_details)?;
  let mut bazel_renderer = BazelRenderer::new();

  let render_details = RenderDetails {
    path_prefix: prefix_path,
    buildfile_suffix: settings.output_buildfile_suffix,
  };

  let dry_run = options.flag_dryrun.unwrap_or(false);
  if !dry_run {
    fs::create_dir_all(&render_details.path_prefix)?;
  }

  let bazel_file_outputs = match settings.genmode {
    GenMode::Vendored => bazel_renderer.render_planned_build(&render_details, &planned_build)?,
    GenMode::Remote => {
      if !dry_run {
        let remote_dir = render_details.path_prefix.as_path().join("remote");

        // Clean out the "remote" directory and guarantee that it exists
        if remote_dir.exists() {
          for entry in glob::glob(&format!("{}/BUILD*.bazel", &remote_dir.display().to_string()))? {
            if let Ok(path) = entry {
              fs::remove_file(path)?;
            }
          }
        } else {
          fs::create_dir_all(&remote_dir)?;
        }

        if !settings.binary_deps.is_empty() {
          fs::create_dir_all(
            render_details
              .path_prefix
              .clone()
              .as_path()
              .join("lockfiles"),
          )?;
        }
      }

      bazel_renderer.render_remote_planned_build(&render_details, &planned_build)?
    }, /* exhaustive, we control the definition */
    // There are no file outputs to produce if `genmode` is Unspecified
    GenMode::Unspecified => Vec::new(),
  };

  for FileOutputs {
    path,
    contents,
  } in bazel_file_outputs
  {
    if dry_run {
      println!("{}:\n{}", path.display(), contents);
    } else {
      write_to_file(&path, &contents, options.flag_verbose > 0)?;
    }
  }

  Ok(())
}

fn write_to_file(path: &Path, contents: &str, verbose: bool) -> Result<()> {
  File::create(&path).and_then(|mut f| f.write_all(contents.as_bytes()))?;
  if verbose {
    println!("Generated {} successfully", path.display());
  }
  Ok(())
}

fn calculate_workspace_root(
  path: &str,
  output_override: Option<&str>,
  new_behavior: bool,
) -> Result<PathBuf> {
  // Default to the current directory '.'
  let mut prefix_path: PathBuf = std::env::current_dir()?;

  // Allow the command line option to take precedence
  match output_override {
    Some(output) => {
      prefix_path.clear();
      prefix_path.push(output);
    },
    None => {
      if new_behavior {
        if let Some(workspace_root) = find_bazel_workspace_root() {
          prefix_path.clear();
          prefix_path.push(workspace_root);
          prefix_path.push(
            path
              // Remove the leading "//" from the path
              .trim_start_matches('/'),
          );
        }
      }
    },
  }

  Ok(prefix_path)
}

#[test]
fn test_calculate_workspace_root() {
  assert_eq!(
    calculate_workspace_root(&"path_a".to_string(), None, true).unwrap(),
    std::env::current_dir().unwrap()
  );

  assert_eq!(
    calculate_workspace_root(
      &"path_b".to_string(),
      Some(&"direct/path".to_string()),
      true
    )
    .unwrap(),
    std::path::Path::new("direct").join("path")
  );
}
<commit_msg>Fix verbose flag by changing to bool (#271)<commit_after>// Copyright 2018 Google Inc.
//
// 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.

use std::{
  fs::{self, File},
  io::Write,
  path::{Path, PathBuf},
};

use anyhow::Result;

use docopt::Docopt;

use cargo_raze::{
  metadata::{CargoMetadataFetcher, CargoWorkspaceFiles, MetadataFetcher},
  planning::{BuildPlanner, BuildPlannerImpl},
  rendering::{bazel::BazelRenderer, BuildRenderer, FileOutputs, RenderDetails},
  settings::{load_settings, GenMode},
  util::{find_bazel_workspace_root, PlatformDetails},
};

use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct Options {
  arg_buildprefix: Option<String>,
  flag_verbose: Option<bool>,
  flag_quiet: Option<bool>,
  flag_host: Option<String>,
  flag_color: Option<String>,
  flag_target: Option<String>,
  flag_dryrun: Option<bool>,
  flag_cargo_bin_path: Option<String>,
  flag_output: String,
}

const USAGE: &str = r#"
Generate BUILD files for your pre-vendored Cargo dependencies.

Usage:
    cargo raze (-h | --help)
    cargo raze [--verbose] [--quiet] [--color=<WHEN>] [--dryrun] [--cargo-bin-path=<PATH>] [--output=<PATH>]
    cargo raze <buildprefix> [--verbose] [--quiet] [--color=<WHEN>] [--dryrun] [--cargo-bin-path=<PATH>]
                             [--output=<PATH>]

Options:
    -h, --help                         Print this message
    -v, --verbose                      Use verbose output
    -q, --quiet                        No output printed to stdout
    --color=<WHEN>                     Coloring: auto, always, never
    -d, --dryrun                       Do not emit any files
    --cargo-bin-path=<PATH>            Path to the cargo binary to be used for loading workspace metadata
    --output=<PATH>                    Path to output the generated into.
"#;

fn main() -> Result<()> {
  let options: Options = Docopt::new(USAGE)
    .and_then(|d| d.deserialize())
    .unwrap_or_else(|e| e.exit());

  let settings = load_settings("Cargo.toml")?;
  if options.flag_verbose.unwrap_or(false) {
    println!("Loaded override settings: {:#?}", settings);
  }

  let mut metadata_fetcher: Box<dyn MetadataFetcher> = match options.flag_cargo_bin_path {
    Some(ref p) => Box::new(CargoMetadataFetcher::new(p, /*use_tempdir: */ true)),
    None => Box::new(CargoMetadataFetcher::default()),
  };
  let mut planner = BuildPlannerImpl::new(&mut *metadata_fetcher);

  let toml_path = PathBuf::from("./Cargo.toml");
  let lock_path_opt = fs::metadata("./Cargo.lock")
    .ok()
    .map(|_| PathBuf::from("./Cargo.lock"));
  let files = CargoWorkspaceFiles {
    toml_path,
    lock_path_opt,
  };

  let platform_details = match &settings.target {
    Some(target) => Some(PlatformDetails::new_using_rustc(target)?),
    None => None,
  };

  let prefix_path = calculate_workspace_root(
    &settings.workspace_path,
    match !options.flag_output.is_empty() {
      true => Some(&options.flag_output),
      false => None,
    },
    settings.incompatible_relative_workspace_path,
  )?;

  let planned_build = planner.plan_build(&settings, &prefix_path, files, platform_details)?;
  let mut bazel_renderer = BazelRenderer::new();

  let render_details = RenderDetails {
    path_prefix: prefix_path,
    buildfile_suffix: settings.output_buildfile_suffix,
  };

  let dry_run = options.flag_dryrun.unwrap_or(false);
  if !dry_run {
    fs::create_dir_all(&render_details.path_prefix)?;
  }

  let bazel_file_outputs = match settings.genmode {
    GenMode::Vendored => bazel_renderer.render_planned_build(&render_details, &planned_build)?,
    GenMode::Remote => {
      if !dry_run {
        let remote_dir = render_details.path_prefix.as_path().join("remote");

        // Clean out the "remote" directory and guarantee that it exists
        if remote_dir.exists() {
          for entry in glob::glob(&format!("{}/BUILD*.bazel", &remote_dir.display().to_string()))? {
            if let Ok(path) = entry {
              fs::remove_file(path)?;
            }
          }
        } else {
          fs::create_dir_all(&remote_dir)?;
        }

        if !settings.binary_deps.is_empty() {
          fs::create_dir_all(
            render_details
              .path_prefix
              .clone()
              .as_path()
              .join("lockfiles"),
          )?;
        }
      }

      bazel_renderer.render_remote_planned_build(&render_details, &planned_build)?
    }, /* exhaustive, we control the definition */
    // There are no file outputs to produce if `genmode` is Unspecified
    GenMode::Unspecified => Vec::new(),
  };

  for FileOutputs {
    path,
    contents,
  } in bazel_file_outputs
  {
    if dry_run {
      println!("{}:\n{}", path.display(), contents);
    } else {
      write_to_file(&path, &contents, options.flag_verbose.unwrap_or(false))?;
    }
  }

  Ok(())
}

fn write_to_file(path: &Path, contents: &str, verbose: bool) -> Result<()> {
  File::create(&path).and_then(|mut f| f.write_all(contents.as_bytes()))?;
  if verbose {
    println!("Generated {} successfully", path.display());
  }
  Ok(())
}

fn calculate_workspace_root(
  path: &str,
  output_override: Option<&str>,
  new_behavior: bool,
) -> Result<PathBuf> {
  // Default to the current directory '.'
  let mut prefix_path: PathBuf = std::env::current_dir()?;

  // Allow the command line option to take precedence
  match output_override {
    Some(output) => {
      prefix_path.clear();
      prefix_path.push(output);
    },
    None => {
      if new_behavior {
        if let Some(workspace_root) = find_bazel_workspace_root() {
          prefix_path.clear();
          prefix_path.push(workspace_root);
          prefix_path.push(
            path
              // Remove the leading "//" from the path
              .trim_start_matches('/'),
          );
        }
      }
    },
  }

  Ok(prefix_path)
}

#[test]
fn test_calculate_workspace_root() {
  assert_eq!(
    calculate_workspace_root(&"path_a".to_string(), None, true).unwrap(),
    std::env::current_dir().unwrap()
  );

  assert_eq!(
    calculate_workspace_root(
      &"path_b".to_string(),
      Some(&"direct/path".to_string()),
      true
    )
    .unwrap(),
    std::path::Path::new("direct").join("path")
  );
}
<|endoftext|>


<commit_before>use combustion::board::Board;
use combustion::moves::Move;
use combustion::piece::Color;

use std::env;
use std::process::exit;

fn main() {
    let args: Vec<String> = env::args().collect();

    if args.len() < 2 {
        println!("Error: at least one argument required. Exiting...");
        exit(1);
    }

    let mut board = if args[1] == "startpos" {
        Board::initial()
    } else {
        Board::from_fen(&args[1]).unwrap()
    };

    let mut to_move = Color::White;

    for mv_str in args.iter().skip(2) {
        // should be UCI format
        let mv = Move::from_xboard_format(mv_str, &board).unwrap();
        board = board.make_move(&mv).unwrap();
    }

    for mv in &board.legal_moves().unwrap() {
        println!("{}", mv.to_xboard_format(board.color_to_move));
    }
}
<commit_msg>lazy automatic commit message<commit_after>use combustion::board::Board;
use combustion::moves::Move;

use std::env;
use std::process::exit;

fn main() {
    let args: Vec<String> = env::args().collect();

    if args.len() < 2 {
        println!("Error: at least one argument required. Exiting...");
        exit(1);
    }

    let mut board = if args[1] == "startpos" {
        Board::initial()
    } else {
        Board::from_fen(&args[1]).unwrap()
    };

    for mv_str in args.iter().skip(2) {
        // should be UCI format
        let mv = Move::from_xboard_format(mv_str, &board).unwrap();
        board = board.make_move(&mv).unwrap();
    }

    for mv in &board.legal_moves().unwrap() {
        println!("{}", mv.to_xboard_format(board.color_to_move));
    }
}
<|endoftext|>


<commit_before>#![feature(proc_macro, conservative_impl_trait, generators)]
extern crate bytes;
extern crate futures_await as futures;
extern crate tokio_core;
extern crate tokio_io;

mod cmd;
mod ftp;
mod error;
mod codec;

use std::result;
use std::io;
use std::env;
use futures::prelude::*;
use tokio_core::reactor::Core;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use tokio_core::reactor::Handle;
use tokio_core::net::TcpListener;

use tokio_core::net::TcpStream;

use futures::{Sink, Stream};
use futures::stream::SplitSink;

use tokio_io::AsyncRead;
use tokio_io::codec::Framed;
use codec::FtpCodec;
use error::Result;
use ftp::{Answer, ResultCode};
use std::path::PathBuf;
use std::path::StripPrefixError;

use cmd::Command;
type Writer = SplitSink<Framed<TcpStream, FtpCodec>>;

struct Client {
    cwd: PathBuf,
    server_root: PathBuf,
    writer: Writer,
}

impl Client {
    fn new(writer: Writer, server_root: PathBuf) -> Client {
        Client {
            cwd: PathBuf::from("/"),
            server_root,
            writer,
        }
    }
    #[async]
    fn send(mut self, answer: Answer) -> Result<Self> {
        self.writer = await!(self.writer.send(answer))?;
        Ok(self)
    }

    fn complete_path(self, path: PathBuf) -> (Self, result::Result<PathBuf, io::Error>) {
        let directory = self.server_root.join(if path.has_root() {
                path.iter().skip(1).collect()
            } else {
                path
        });
        let dir = directory.canocalize();
        if let Ok(ref dir) = dir {
            if !dir.starts_with(&self.server_root) {
                return (self, Err(io::ErrorKind::PermissionDenied.into()));
            }
        }
        (self,dir)
    }
    fn strip_prefix(self, dir:PathBuf) -> (Self, result::Result<PathBuf, StripPrefixError>) {
        let res = dir.strip_prefix(&self.server_root).map(|p| p.to_path_buf());
        (self,res)
    }

    #[async]
    fn cwd(mut self, directory: PathBuf) -> Result<Self>{
        let path = self.cwd.join(&directory);
        let (new_self, res) = self.complete_path(path);
        self = new_self;
        if let Ok(dir) = res {
            let (new_self, res) = self.strip_prefix(dir);
            self = new_self;
            if let Ok(prefix) = res {
                self.cwd = prefix.to_path_buf();
                self = await!(self.send(Answer::new(ResultCode::Ok, &format!("Directory changed to \"{}\"", directory.display()))))?;
                return Ok(self)
            }
        }
        self = await!(self.send(Answer::new(ResultCode::FileNotFound, "No such file or directory")))?;
        Ok(self);
    }

    #[async]
    fn handle_cmd(mut self, cmd: Command) -> Result<Self> {
        println!("Received command: {:?}", cmd);
        match cmd {
            Command::Cwd(directory) => {
                self= await!(self.cwd(directory))?;
            },
            Command::User(content) => {
                if content.is_empty() {
                    self = await!(self.send(Answer::new(ResultCode::InvalidParameterOrArgument,"Invalid username")))?;
                } else {
                    self = await!(self.send(Answer::new(ResultCode::UserloggedIn,&format!("Welcome {}",content))))?;
                }
            },
            Command::Pwd => {
                let msg = format!("{}", self.cwd.to_str().unwrap_or(""));
                if !msg.is_empty() {
                    let message = format!("\"/{}\" ",msg);
                    self = await!(self.send(Answer::new(ResultCode::PATHNAMECreated, &message)))?;
                } else {
                    self = await!(self.send(Answer::new(ResultCode::FileNotFound, "No such file or directory")))?;
                }
            },
            Command::Unknown(s) => self = await!(self.send(Answer::new(ResultCode::UnknownCommand, &format!("\"{}\": Not Implemented",s))))?,
            _=>  self = await!(self.send(Answer::new(ResultCode::CommandNotImplemented, "Not implemented")))?,
        }
        return Ok(self);
    }
}

#[async]
fn client(stream: TcpStream, server_root: PathBuf) -> Result<()>{
    let (writer, reader) = stream.framed(FtpCodec).split();
    let writer = await!(writer.send(Answer::new(ResultCode::ServiceReadyForNewUser, "Welcome to this FTP Server!")))?;
    let mut client = Client::new(writer, server_root);
    #[async]
    for cmd in reader {
        client = await!(client.handle_cmd(cmd))?;
    }
    println!("Client closed");
    return Ok(());;
}

#[async]
fn handle_client(stream: TcpStream, server_root: PathBuf) -> result::Result<(), ()> {
    await!(client(stream, server_root)).map_err(|error| println!("Error handling client: {}", error))
}

#[async]
fn server(handle: Handle, server_root: PathBuf) -> io::Result<()> {
    let port = 1234;
    let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127,0,0,1)), port);
    let listener = TcpListener::bind(&addr,&handle)?;
    println!("Waiting clients on port {}...",port);
    #[async]
    for (stream, addr) in listener.incoming() {
        let address = format!("[address : {}]",addr);
        println!("New client {}", address);
        handle.spawn(handle_client(stream, server_root.clone()));
        println!("Waiting another client...");
    }
    return Ok(());
}

fn main() {
    let mut core = Core::new().expect("Cannot create tokio Core");
    let handle = core.handle();
    match env::current_dir() {
        Ok(server_root) => {
            if let Err(error) = core.run(server(handle, server_root)) {
                println!("Error running the server: {}", error);
            }
        },
        Err(e) => println!("Could not start server: {:?}",e),

    }

}
<commit_msg>Fixed error in main.rs<commit_after>#![feature(proc_macro, conservative_impl_trait, generators)]
extern crate bytes;
extern crate futures_await as futures;
extern crate tokio_core;
extern crate tokio_io;

mod cmd;
mod ftp;
mod error;
mod codec;

use std::result;
use std::io;
use std::env;
use futures::prelude::*;
use tokio_core::reactor::Core;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use tokio_core::reactor::Handle;
use tokio_core::net::TcpListener;

use tokio_core::net::TcpStream;

use futures::{Sink, Stream};
use futures::stream::SplitSink;

use tokio_io::AsyncRead;
use tokio_io::codec::Framed;
use codec::FtpCodec;
use error::Result;
use ftp::{Answer, ResultCode};
use std::path::PathBuf;
use std::path::StripPrefixError;

use cmd::Command;
type Writer = SplitSink<Framed<TcpStream, FtpCodec>>;

struct Client {
    cwd: PathBuf,
    server_root: PathBuf,
    writer: Writer,
}

impl Client {
    fn new(writer: Writer, server_root: PathBuf) -> Client {
        Client {
            cwd: PathBuf::from("/"),
            server_root,
            writer,
        }
    }
    #[async]
    fn send(mut self, answer: Answer) -> Result<Self> {
        self.writer = await!(self.writer.send(answer))?;
        Ok(self)
    }

    fn complete_path(self, path: PathBuf) -> (Self, result::Result<PathBuf, io::Error>) {
        let directory = self.server_root.join(if path.has_root() {
                path.iter().skip(1).collect()
            } else {
                path
        });
        let dir = directory.canonicalize();
        if let Ok(ref dir) = dir {
            if !dir.starts_with(&self.server_root) {
                return (self, Err(io::ErrorKind::PermissionDenied.into()));
            }
        }
        (self,dir)
    }
    fn strip_prefix(self, dir:PathBuf) -> (Self, result::Result<PathBuf, StripPrefixError>) {
        let res = dir.strip_prefix(&self.server_root).map(|p| p.to_path_buf());
        (self,res)
    }

    #[async]
    fn cwd(mut self, directory: PathBuf) -> Result<Self>{
        let path = self.cwd.join(&directory);
        let (new_self, res) = self.complete_path(path);
        self = new_self;
        if let Ok(dir) = res {
            let (new_self, res) = self.strip_prefix(dir);
            self = new_self;
            if let Ok(prefix) = res {
                self.cwd = prefix.to_path_buf();
                self = await!(self.send(Answer::new(ResultCode::Ok, &format!("Directory changed to \"{}\"", directory.display()))))?;
                return Ok(self)
            }
        }
        self = await!(self.send(Answer::new(ResultCode::FileNotFound, "No such file or directory")))?;
        return Ok(self);
    }

    #[async]
    fn handle_cmd(mut self, cmd: Command) -> Result<Self> {
        println!("Received command: {:?}", cmd);
        match cmd {
            Command::Cwd(directory) => {
                self= await!(self.cwd(directory))?;
            },
            Command::User(content) => {
                if content.is_empty() {
                    self = await!(self.send(Answer::new(ResultCode::InvalidParameterOrArgument,"Invalid username")))?;
                } else {
                    self = await!(self.send(Answer::new(ResultCode::UserloggedIn,&format!("Welcome {}",content))))?;
                }
            },
            Command::Pwd => {
                let msg = format!("{}", self.cwd.to_str().unwrap_or(""));
                if !msg.is_empty() {
                    let message = format!("\"/{}\" ",msg);
                    self = await!(self.send(Answer::new(ResultCode::PATHNAMECreated, &message)))?;
                } else {
                    self = await!(self.send(Answer::new(ResultCode::FileNotFound, "No such file or directory")))?;
                }
            },
            Command::Unknown(s) => self = await!(self.send(Answer::new(ResultCode::UnknownCommand, &format!("\"{}\": Not Implemented",s))))?,
            _=>  self = await!(self.send(Answer::new(ResultCode::CommandNotImplemented, "Not implemented")))?,
        }
        return Ok(self);
    }
}

#[async]
fn client(stream: TcpStream, server_root: PathBuf) -> Result<()>{
    let (writer, reader) = stream.framed(FtpCodec).split();
    let writer = await!(writer.send(Answer::new(ResultCode::ServiceReadyForNewUser, "Welcome to this FTP Server!")))?;
    let mut client = Client::new(writer, server_root);
    #[async]
    for cmd in reader {
        client = await!(client.handle_cmd(cmd))?;
    }
    println!("Client closed");
    return Ok(());;
}

#[async]
fn handle_client(stream: TcpStream, server_root: PathBuf) -> result::Result<(), ()> {
    await!(client(stream, server_root)).map_err(|error| println!("Error handling client: {}", error))
}

#[async]
fn server(handle: Handle, server_root: PathBuf) -> io::Result<()> {
    let port = 1234;
    let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127,0,0,1)), port);
    let listener = TcpListener::bind(&addr,&handle)?;
    println!("Waiting clients on port {}...",port);
    #[async]
    for (stream, addr) in listener.incoming() {
        let address = format!("[address : {}]",addr);
        println!("New client {}", address);
        handle.spawn(handle_client(stream, server_root.clone()));
        println!("Waiting another client...");
    }
    return Ok(());
}

fn main() {
    let mut core = Core::new().expect("Cannot create tokio Core");
    let handle = core.handle();
    match env::current_dir() {
        Ok(server_root) => {
            if let Err(error) = core.run(server(handle, server_root)) {
                println!("Error running the server: {}", error);
            }
        },
        Err(e) => println!("Could not start server: {:?}",e),

    }

}
<|endoftext|>