<commit_before>//! DHT implementation based on Kademlia.
//!
//! See [original paper](http://pdos.csail.mit.edu/%7Epetar/papers/maymounkov-kademlia-lncs.pdf)
//! for details. The most essential difference is that when k-bucket is full,
//! no RPC call is done. It is up to upper-level code to ensure proper clean up
//! using `pop_oldest` call.

use std::num::Zero;
use num::BigUint;

use super::GenericNodeTable;
use super::Node;

// TODO(divius): make public?
static BUCKET_SIZE: uint = 1024;
static HASH_SIZE: uint = 160;

/// Kademlia node table.
///
/// Keeps nodes in a number of k-buckets (equal to bit size of ID in a system,
/// usually 160), where N-th k-bucket contains nodes with distance
/// from 2^N to 2^(N+1) from our node.
#[unstable]
pub struct NodeTable {
    own_id: BigUint,
    // TODO(divius): convert to more appropriate data structure
    buckets: Vec<KBucket>,
}

/// K-bucket - structure for keeping last nodes in Kademlia.
struct KBucket {
    data: Vec<Node>,
    size: uint
}

#[unstable]
impl NodeTable {
    /// Create a new node table.
    ///
    /// `own_id` -- ID of the current node (used to calculate metrics).
    pub fn new(own_id: BigUint) -> NodeTable {
        NodeTable::with_details(own_id, BUCKET_SIZE, HASH_SIZE)
    }

    // TODO(divius): make public
    fn with_details(own_id: BigUint, bucket_size: uint,
                    hash_size: uint) -> NodeTable {
        NodeTable {
            own_id: own_id,
            buckets: Vec::from_fn(hash_size,
                                  |_| KBucket::new(bucket_size)),
        }
    }

    #[inline]
    fn distance(id1: &BigUint, id2: &BigUint) -> BigUint {
        id1.bitxor(id2)
    }

    fn bucket_number(&self, id: &BigUint) -> uint {
        let diff = NodeTable::distance(&self.own_id, id);
        debug_assert!(!diff.is_zero());
        let res = diff.bits() - 1;
        debug!("ID {} relative to own ID {} falls into bucket {}",
               id, self.own_id, res);
        res
    }
}

#[unstable]
impl GenericNodeTable for NodeTable {
    fn update(&mut self, node: &Node) -> bool {
        assert!(node.id != self.own_id);
        let bucket = self.bucket_number(&node.id);
        self.buckets.get_mut(bucket).update(node)
    }

    fn find(&self, id: &BigUint, count: uint) -> Vec<Node> {
        debug_assert!(count > 0);
        assert!(*id != self.own_id)
        let bucket = self.bucket_number(id);
        self.buckets[bucket].find(id, count)
    }
}

impl KBucket {
    pub fn new(k: uint) -> KBucket {
        assert!(k > 0)
        KBucket {
            data: Vec::new(),
            size: k
        }
    }

    pub fn update(&mut self, node: &Node) -> bool {
        if self.data.iter().any(|x| x.id == node.id) {
            self.update_position(node);
            debug!("Promoted node {} to the top of kbucket", node);
            true
        }
        else if self.data.len() == self.size {
            debug!("Not adding new node {} to kbucket - no space left", node);
            false
        }
        else {
            self.data.push(node.clone());
            debug!("Added new node {} to kbucket", node);
            true
        }
    }

    pub fn find(&self, id: &BigUint, count: uint) -> Vec<Node> {
        let sort_fn = |a: &Node, b: &Node| {
            NodeTable::distance(id, &a.id).cmp(&NodeTable::distance(id, &b.id))
        };
        let mut data_copy = self.data.clone();
        data_copy.sort_by(sort_fn);
        Vec::from_slice(data_copy.slice(0, count))
    }

    fn update_position(&mut self, node: &Node) {
        // TODO(divius): 1. optimize, 2. make it less ugly
        let mut new_data = Vec::with_capacity(self.data.len());
        new_data.extend(self.data.iter()
                        .filter(|x| x.id != node.id)
                        .map(|x| x.clone()));
        new_data.push(node.clone());
        self.data = new_data;
    }
}

#[cfg(test)]
mod test {
    use std::from_str::FromStr;
    use std::num::FromPrimitive;
    use num::BigUint;
    use super::super::GenericNodeTable;
    use super::super::Node;
    use super::HASH_SIZE;
    use super::KBucket;
    use super::NodeTable;

    static ADDR: &'static str = "127.0.0.1:80";

    fn new_node(id: uint) -> Node {
        Node {
            id: FromPrimitive::from_uint(id).unwrap(),
            address: FromStr::from_str(ADDR).unwrap()
        }
    }

    fn prepare(count: uint) -> KBucket {
        KBucket {
            data: Vec::from_fn(count, |i| new_node(i)),
            size: 3,
        }
    }

    fn assert_node_list_eq(expected: &[&Node], actual: &Vec<Node>) {
        let act: Vec<BigUint> = actual.iter().map(|x| x.id.clone()).collect();
        let exp: Vec<BigUint> = expected.iter().map(|x| x.id.clone()).collect();
        assert_eq!(exp, act);
    }

    #[test]
    fn test_nodetable_new() {
        let n = NodeTable::new(FromPrimitive::from_uint(42).unwrap());
        assert_eq!(HASH_SIZE, n.buckets.len());
    }

    #[test]
    fn test_nodetable_bucket_number() {
        let n = NodeTable::new(FromPrimitive::from_uint(42).unwrap());
        let id = FromPrimitive::from_uint(41).unwrap();
        // 42 xor 41 == 3
        assert_eq!(1, n.bucket_number(&id));
    }

    #[test]
    fn test_nodetable_update() {
        let mut n = NodeTable::with_details(
            FromPrimitive::from_uint(42).unwrap(), 1, HASH_SIZE);
        let node = new_node(41);
        n.update(&node);
        assert_eq!(1, n.buckets[1].data.len());
        n.update(&node);
        assert_eq!(1, n.buckets[1].data.len());
    }

    #[test]
    fn test_nodetable_find() {
        let n = NodeTable {
            buckets: vec![prepare(1), prepare(3), prepare(1)],
            own_id: FromPrimitive::from_uint(0).unwrap()
        };
        // 0 xor 3 = 3, 1 xor 3 = 2, 2 xor 3 = 1
        let id = FromPrimitive::from_uint(3).unwrap();
        assert_node_list_eq([&n.buckets[1].data[2]],
                            &n.find(&id, 1));
    }

    #[test]
    fn test_kbucket_new() {
        let b = KBucket::new(3);
        assert_eq!(0, b.data.len());
        assert_eq!(3, b.size);
    }

    #[test]
    fn test_kbucket_update_unknown() {
        let mut b = prepare(1);
        let node = new_node(42);
        assert!(b.update(&node))
        assert_eq!(2, b.data.len());
        assert_eq!(node.id, b.data.get(1).id);
    }

    #[test]
    fn test_kbucket_update_known() {
        let mut b = prepare(2);
        let node = new_node(0);
        assert!(b.update(&node))
        assert_eq!(2, b.data.len());
        assert_eq!(node.id, b.data.get(1).id);
    }

    #[test]
    fn test_kbucket_update_conflict() {
        let mut b = prepare(3);  // 3 is size
        let node = new_node(42);
        assert!(!b.update(&node))
    }

    #[test]
    fn test_kbucket_find() {
        let b = prepare(3);
        // Nodes with ID's 0, 1, 2; assume our ID is also 2 (impossible IRL)
        let id = FromPrimitive::from_uint(2).unwrap();
        // 0 xor 2 = 2, 1 xor 2 = 3, 2 xor 2 = 0
        assert_node_list_eq([&b.data[2]], &b.find(&id, 1));
        assert_node_list_eq([&b.data[2], &b.data[0]], &b.find(&id, 2));
    }
}
<commit_msg>Fix latest deprecations<commit_after>//! DHT implementation based on Kademlia.
//!
//! See [original paper](http://pdos.csail.mit.edu/%7Epetar/papers/maymounkov-kademlia-lncs.pdf)
//! for details. The most essential difference is that when k-bucket is full,
//! no RPC call is done. It is up to upper-level code to ensure proper clean up
//! using `pop_oldest` call.

use std::num::Zero;
use num::BigUint;

use super::GenericNodeTable;
use super::Node;

// TODO(divius): make public?
static BUCKET_SIZE: uint = 1024;
static HASH_SIZE: uint = 160;

/// Kademlia node table.
///
/// Keeps nodes in a number of k-buckets (equal to bit size of ID in a system,
/// usually 160), where N-th k-bucket contains nodes with distance
/// from 2^N to 2^(N+1) from our node.
#[unstable]
pub struct NodeTable {
    own_id: BigUint,
    // TODO(divius): convert to more appropriate data structure
    buckets: Vec<KBucket>,
}

/// K-bucket - structure for keeping last nodes in Kademlia.
struct KBucket {
    data: Vec<Node>,
    size: uint
}

#[unstable]
impl NodeTable {
    /// Create a new node table.
    ///
    /// `own_id` -- ID of the current node (used to calculate metrics).
    pub fn new(own_id: BigUint) -> NodeTable {
        NodeTable::with_details(own_id, BUCKET_SIZE, HASH_SIZE)
    }

    // TODO(divius): make public
    fn with_details(own_id: BigUint, bucket_size: uint,
                    hash_size: uint) -> NodeTable {
        NodeTable {
            own_id: own_id,
            buckets: Vec::from_fn(hash_size,
                                  |_| KBucket::new(bucket_size)),
        }
    }

    #[inline]
    fn distance(id1: &BigUint, id2: &BigUint) -> BigUint {
        id1.bitxor(id2)
    }

    fn bucket_number(&self, id: &BigUint) -> uint {
        let diff = NodeTable::distance(&self.own_id, id);
        debug_assert!(!diff.is_zero());
        let res = diff.bits() - 1;
        debug!("ID {} relative to own ID {} falls into bucket {}",
               id, self.own_id, res);
        res
    }
}

#[unstable]
impl GenericNodeTable for NodeTable {
    fn update(&mut self, node: &Node) -> bool {
        assert!(node.id != self.own_id);
        let bucket = self.bucket_number(&node.id);
        self.buckets.get_mut(bucket).update(node)
    }

    fn find(&self, id: &BigUint, count: uint) -> Vec<Node> {
        debug_assert!(count > 0);
        assert!(*id != self.own_id)
        let bucket = self.bucket_number(id);
        self.buckets[bucket].find(id, count)
    }
}

impl KBucket {
    pub fn new(k: uint) -> KBucket {
        assert!(k > 0)
        KBucket {
            data: Vec::new(),
            size: k
        }
    }

    pub fn update(&mut self, node: &Node) -> bool {
        if self.data.iter().any(|x| x.id == node.id) {
            self.update_position(node);
            debug!("Promoted node {} to the top of kbucket", node);
            true
        }
        else if self.data.len() == self.size {
            debug!("Not adding new node {} to kbucket - no space left", node);
            false
        }
        else {
            self.data.push(node.clone());
            debug!("Added new node {} to kbucket", node);
            true
        }
    }

    pub fn find(&self, id: &BigUint, count: uint) -> Vec<Node> {
        let sort_fn = |a: &Node, b: &Node| {
            NodeTable::distance(id, &a.id).cmp(&NodeTable::distance(id, &b.id))
        };
        let mut data_copy = self.data.clone();
        data_copy.sort_by(sort_fn);
        data_copy.slice(0, count).to_vec()
    }

    fn update_position(&mut self, node: &Node) {
        // TODO(divius): 1. optimize, 2. make it less ugly
        let mut new_data = Vec::with_capacity(self.data.len());
        new_data.extend(self.data.iter()
                        .filter(|x| x.id != node.id)
                        .map(|x| x.clone()));
        new_data.push(node.clone());
        self.data = new_data;
    }
}

#[cfg(test)]
mod test {
    use std::from_str::FromStr;
    use std::num::FromPrimitive;
    use num::BigUint;
    use super::super::GenericNodeTable;
    use super::super::Node;
    use super::HASH_SIZE;
    use super::KBucket;
    use super::NodeTable;

    static ADDR: &'static str = "127.0.0.1:80";

    fn new_node(id: uint) -> Node {
        Node {
            id: FromPrimitive::from_uint(id).unwrap(),
            address: FromStr::from_str(ADDR).unwrap()
        }
    }

    fn prepare(count: uint) -> KBucket {
        KBucket {
            data: Vec::from_fn(count, |i| new_node(i)),
            size: 3,
        }
    }

    fn assert_node_list_eq(expected: &[&Node], actual: &Vec<Node>) {
        let act: Vec<BigUint> = actual.iter().map(|x| x.id.clone()).collect();
        let exp: Vec<BigUint> = expected.iter().map(|x| x.id.clone()).collect();
        assert_eq!(exp, act);
    }

    #[test]
    fn test_nodetable_new() {
        let n = NodeTable::new(FromPrimitive::from_uint(42).unwrap());
        assert_eq!(HASH_SIZE, n.buckets.len());
    }

    #[test]
    fn test_nodetable_bucket_number() {
        let n = NodeTable::new(FromPrimitive::from_uint(42).unwrap());
        let id = FromPrimitive::from_uint(41).unwrap();
        // 42 xor 41 == 3
        assert_eq!(1, n.bucket_number(&id));
    }

    #[test]
    fn test_nodetable_update() {
        let mut n = NodeTable::with_details(
            FromPrimitive::from_uint(42).unwrap(), 1, HASH_SIZE);
        let node = new_node(41);
        n.update(&node);
        assert_eq!(1, n.buckets[1].data.len());
        n.update(&node);
        assert_eq!(1, n.buckets[1].data.len());
    }

    #[test]
    fn test_nodetable_find() {
        let n = NodeTable {
            buckets: vec![prepare(1), prepare(3), prepare(1)],
            own_id: FromPrimitive::from_uint(0).unwrap()
        };
        // 0 xor 3 = 3, 1 xor 3 = 2, 2 xor 3 = 1
        let id = FromPrimitive::from_uint(3).unwrap();
        assert_node_list_eq([&n.buckets[1].data[2]],
                            &n.find(&id, 1));
    }

    #[test]
    fn test_kbucket_new() {
        let b = KBucket::new(3);
        assert_eq!(0, b.data.len());
        assert_eq!(3, b.size);
    }

    #[test]
    fn test_kbucket_update_unknown() {
        let mut b = prepare(1);
        let node = new_node(42);
        assert!(b.update(&node))
        assert_eq!(2, b.data.len());
        assert_eq!(node.id, b.data[1].id);
    }

    #[test]
    fn test_kbucket_update_known() {
        let mut b = prepare(2);
        let node = new_node(0);
        assert!(b.update(&node))
        assert_eq!(2, b.data.len());
        assert_eq!(node.id, b.data[1].id);
    }

    #[test]
    fn test_kbucket_update_conflict() {
        let mut b = prepare(3);  // 3 is size
        let node = new_node(42);
        assert!(!b.update(&node))
    }

    #[test]
    fn test_kbucket_find() {
        let b = prepare(3);
        // Nodes with ID's 0, 1, 2; assume our ID is also 2 (impossible IRL)
        let id = FromPrimitive::from_uint(2).unwrap();
        // 0 xor 2 = 2, 1 xor 2 = 3, 2 xor 2 = 0
        assert_node_list_eq([&b.data[2]], &b.find(&id, 1));
        assert_node_list_eq([&b.data[2], &b.data[0]], &b.find(&id, 2));
    }
}
<|endoftext|>


<commit_before>use super::ease::Easing;

pub struct Circ;

impl Easing for Circ {
    fn ease_in(t: f32, b: f32, c: f32, d: f32) -> f32 {
        let inner_t = t / d;
        -c * ((1.0 - inner_t * inner_t).sqrt() - 1.0) + b
    }

    fn ease_out(t: f32, b: f32, c: f32, d: f32) -> f32 {
        let inner_t = t / d - 1.0;
        c * (1.0 - inner_t * inner_t).sqrt() + b
    }

    fn ease_in_out(t: f32, b: f32, c: f32, d: f32) -> f32 {
        let mut inner_t = t / (d / 2.0);
        if inner_t < 1.0 {
            return -c / 2.0 * ((1.0 - inner_t * inner_t).sqrt() - 1.0) + b;
        }

        inner_t -= 2.0;
        return c / 2.0 * ((1.0 - inner_t * inner_t).sqrt() + 1.0) + b;
    }
}

mod test {
    use functions::ease::Easing;
    #[test]
    fn ease_in() {
        assert_relative_eq!(super::Circ::ease_in(1.0, 2.0, 3.0, 4.0), 2.0952625);
    }

    #[test]
    fn ease_out() {
        assert_relative_eq!(super::Circ::ease_out(1.0, 2.0, 3.0, 4.0), 3.9843135);
    }

    #[test]
    fn ease_in_out() {
        assert_relative_eq!(super::Circ::ease_in_out(1.0, 2.0, 3.0, 4.0), 2.200962);
    }
}
<commit_msg>circ function test added<commit_after>use super::ease::Easing;

pub struct Circ;

impl Easing for Circ {
    fn ease_in(t: f32, b: f32, c: f32, d: f32) -> f32 {
        let inner_t = t / d;
        -c * ((1.0 - inner_t * inner_t).sqrt() - 1.0) + b
    }

    fn ease_out(t: f32, b: f32, c: f32, d: f32) -> f32 {
        let inner_t = t / d - 1.0;
        c * (1.0 - inner_t * inner_t).sqrt() + b
    }

    fn ease_in_out(t: f32, b: f32, c: f32, d: f32) -> f32 {
        let mut inner_t = t / (d / 2.0);
        if inner_t < 1.0 {
            return -c / 2.0 * ((1.0 - inner_t * inner_t).sqrt() - 1.0) + b;
        }

        inner_t -= 2.0;
        return c / 2.0 * ((1.0 - inner_t * inner_t).sqrt() + 1.0) + b;
    }
}

mod test {
    use functions::ease::Easing;
    #[test]
    fn ease_in() {
        assert_relative_eq!(super::Circ::ease_in(1.0, 2.0, 3.0, 4.0), 2.0952625);
    }

    #[test]
    fn ease_out() {
        assert_relative_eq!(super::Circ::ease_out(1.0, 2.0, 3.0, 4.0), 3.9843135);
    }

    #[test]
    fn ease_in_out() {
        assert_relative_eq!(super::Circ::ease_in_out(1.0, 2.0, 3.0, 4.0), 2.200962);
        assert_relative_eq!(super::Circ::ease_in_out(51.0, 1.0, 100.0, 100.0), 60.949871);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2018 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use std::fmt;
use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use std::os::unix::io::AsRawFd;
use std::thread;
use std::time::{Duration, Instant};

use gpio::epoll::{epoll_event, Epoll, EventFd, EPOLLERR, EPOLLET, EPOLLIN, EPOLLPRI};
use gpio::sysfs;
use gpio::{Error, Level, Result, Trigger};

#[derive(Debug)]
struct Interrupt {
    pin: u8,
    trigger: Trigger,
    sysfs_value: File,
}

impl Interrupt {
    fn new(pin: u8, trigger: Trigger) -> Result<Interrupt> {
        // Export the GPIO pin so we can configure it through sysfs, set its mode to
        // input, and set the trigger type.
        sysfs::export(pin)?;
        sysfs::set_direction(pin, sysfs::Direction::In)?;
        sysfs::set_edge(pin, trigger)?;

        Ok(Interrupt {
            pin,
            trigger,
            sysfs_value: sysfs::open_value(pin)?,
        })
    }

    fn trigger(&self) -> Trigger {
        self.trigger
    }

    fn fd(&self) -> i32 {
        self.sysfs_value.as_raw_fd()
    }

    fn set_trigger(&mut self, trigger: Trigger) -> Result<()> {
        self.trigger = trigger;
        sysfs::set_edge(self.pin, trigger)?;

        Ok(())
    }

    fn level(&mut self) -> Result<Level> {
        let mut buffer = [0; 1];
        self.sysfs_value.read_exact(&mut buffer)?;
        self.sysfs_value.seek(SeekFrom::Start(0))?;

        match &buffer {
            b"0" => Ok(Level::Low),
            _ => Ok(Level::High),
        }
    }
}

impl Drop for Interrupt {
    fn drop(&mut self) {
        sysfs::unexport(self.pin).ok();
    }
}

#[derive(Debug)]
struct TriggerStatus {
    interrupt: Option<Interrupt>,
    triggered: bool,
    level: Level,
}

pub struct EventLoop {
    poll: Epoll,
    events: Vec<epoll_event>,
    trigger_status: Vec<TriggerStatus>,
}

impl fmt::Debug for EventLoop {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("EventLoop")
            .field("poll", &self.poll)
            .field("events", &format_args!("{{ .. }}"))
            .field("trigger_status", &format_args!("{{ .. }}"))
            .finish()
    }
}

impl EventLoop {
    pub fn new(capacity: usize) -> Result<EventLoop> {
        let mut trigger_status = Vec::with_capacity(capacity);

        // Initialize trigger_status while circumventing the Copy/Clone requirement
        for _ in 0..trigger_status.capacity() {
            trigger_status.push(TriggerStatus {
                interrupt: None,
                triggered: false,
                level: Level::Low,
            });
        }

        Ok(EventLoop {
            poll: Epoll::new()?,
            events: vec![epoll_event { events: 0, u64: 0 }; capacity],
            trigger_status,
        })
    }

    pub fn poll(
        &mut self,
        pins: &[u8],
        reset: bool,
        timeout: Option<Duration>,
    ) -> Result<Option<(u8, Level)>> {
        for pin in pins {
            if *pin as usize >= self.trigger_status.capacity() {
                return Err(Error::InvalidPin(*pin));
            }

            // Did we cache any trigger events during the previous poll?
            if self.trigger_status[*pin as usize].triggered {
                self.trigger_status[*pin as usize].triggered = false;

                if !reset {
                    return Ok(Some((*pin, self.trigger_status[*pin as usize].level)));
                }
            }

            // Read the logic level to reset any pending trigger events
            if let Some(ref mut interrupt) = self.trigger_status[*pin as usize].interrupt {
                if reset {
                    interrupt.level()?;
                }
            }
        }

        // Loop until we get any of the events we're waiting for, or a timeout occurs
        let now = Instant::now();
        loop {
            let num_events = self.poll.wait(&mut self.events, timeout)?;

            // No events means a timeout occurred
            if num_events == 0 {
                return Ok(None);
            }

            for idx in 0..num_events {
                let pin = self.events[idx].u64 as usize;
                if pin < self.trigger_status.capacity() {
                    self.trigger_status[pin].triggered = true;
                    self.trigger_status[pin].level =
                        if let Some(ref mut interrupt) = self.trigger_status[pin].interrupt {
                            interrupt.level()?
                        } else {
                            Level::Low
                        };
                }
            }

            // Were any interrupts triggered? If so, return one. The rest
            // will be saved for the next poll.
            for pin in pins {
                if self.trigger_status[*pin as usize].triggered {
                    self.trigger_status[*pin as usize].triggered = false;
                    return Ok(Some((*pin, self.trigger_status[*pin as usize].level)));
                }
            }

            // It's possible a pin we're not waiting for continuously triggers
            // an interrupt, causing repeated loops with calls to poll() using a
            // reset timeout value. Make sure we haven't been looping longer than
            // the requested timeout.
            if let Some(t) = timeout {
                if now.elapsed() > t {
                    return Ok(None);
                }
            }
        }
    }

    pub fn set_interrupt(&mut self, pin: u8, trigger: Trigger) -> Result<()> {
        self.trigger_status[pin as usize].triggered = false;

        // Interrupt already exists. We just need to change the trigger.
        if let Some(ref mut interrupt) = self.trigger_status[pin as usize].interrupt {
            if interrupt.trigger != trigger {
                interrupt.set_trigger(trigger)?;
            }

            return Ok(());
        }

        // Register a new interrupt
        let mut base = Interrupt::new(pin, trigger)?;
        base.level()?;
        self.poll
            .add(base.fd(), u64::from(pin), EPOLLERR | EPOLLET | EPOLLPRI)?;
        self.trigger_status[pin as usize].interrupt = Some(base);

        Ok(())
    }

    pub fn clear_interrupt(&mut self, pin: u8) -> Result<()> {
        self.trigger_status[pin as usize].triggered = false;

        if let Some(interrupt) = self.trigger_status[pin as usize].interrupt.take() {
            self.poll.delete(interrupt.fd())?;
        }

        Ok(())
    }
}

pub struct AsyncInterrupt {
    pin: u8,
    poll_thread: Option<thread::JoinHandle<Result<()>>>,
    tx: EventFd,
}

impl AsyncInterrupt {
    pub fn new<C>(pin: u8, trigger: Trigger, mut callback: C) -> Result<AsyncInterrupt>
    where
        C: FnMut(Level) + Send + 'static,
    {
        let tx = EventFd::new()?;
        let rx = tx.fd();

        let poll_thread = thread::spawn(move || -> Result<()> {
            let poll = Epoll::new()?;

            // rx becomes readable when the main thread calls notify()
            poll.add(rx, rx as u64, EPOLLERR | EPOLLET | EPOLLIN)?;

            // Triggering an interrupt sets error and priority
            let mut base = Interrupt::new(pin, trigger)?;
            let base_fd = base.fd();
            base.level()?;
            poll.add(base_fd, base_fd as u64, EPOLLERR | EPOLLET | EPOLLPRI)?;

            let mut events = [epoll_event { events: 0, u64: 0 }; 2];
            loop {
                let num_events = poll.wait(&mut events, None)?;
                if num_events > 0 {
                    for event in &events[0..num_events] {
                        if event.u64 == rx as u64 {
                            return Ok(()); // The main thread asked us to stop
                        } else if event.u64 == base.fd() as u64 {
                            callback(base.level()?);
                        }
                    }
                }
            }
        });

        Ok(AsyncInterrupt {
            pin,
            poll_thread: Some(poll_thread),
            tx,
        })
    }

    pub fn stop(&mut self) -> Result<()> {
        self.tx.notify()?;

        if let Some(poll_thread) = self.poll_thread.take() {
            match poll_thread.join() {
                Ok(r) => return r,
                Err(_) => return Err(Error::ThreadPanic),
            }
        }

        Ok(())
    }
}

impl Drop for AsyncInterrupt {
    fn drop(&mut self) {
        // Unexport the pin here, because we can't rely on the thread
        // living long enough to unexport it.
        sysfs::unexport(self.pin).ok();
    }
}

impl fmt::Debug for AsyncInterrupt {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("AsyncInterrupt")
            .field("pin", &self.pin)
            .field("poll_thread", &self.poll_thread)
            .field("tx", &self.tx)
            .finish()
    }
}
<commit_msg>Cleanup epoll code<commit_after>// Copyright (c) 2017-2018 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use std::fmt;
use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use std::os::unix::io::AsRawFd;
use std::thread;
use std::time::{Duration, Instant};

use gpio::epoll::{epoll_event, Epoll, EventFd, EPOLLERR, EPOLLET, EPOLLIN, EPOLLPRI};
use gpio::sysfs;
use gpio::{Error, Level, Result, Trigger};

#[derive(Debug)]
struct Interrupt {
    pin: u8,
    trigger: Trigger,
    sysfs_value: File,
}

impl Interrupt {
    fn new(pin: u8, trigger: Trigger) -> Result<Interrupt> {
        // Export the GPIO pin so we can configure it through sysfs, set its mode to
        // input, and set the trigger type.
        sysfs::export(pin)?;
        sysfs::set_direction(pin, sysfs::Direction::In)?;
        sysfs::set_edge(pin, trigger)?;

        Ok(Interrupt {
            pin,
            trigger,
            sysfs_value: sysfs::open_value(pin)?,
        })
    }

    fn trigger(&self) -> Trigger {
        self.trigger
    }

    fn fd(&self) -> i32 {
        self.sysfs_value.as_raw_fd()
    }

    fn set_trigger(&mut self, trigger: Trigger) -> Result<()> {
        self.trigger = trigger;
        sysfs::set_edge(self.pin, trigger)?;

        Ok(())
    }

    fn level(&mut self) -> Result<Level> {
        let mut buffer = [0; 1];
        self.sysfs_value.read_exact(&mut buffer)?;
        self.sysfs_value.seek(SeekFrom::Start(0))?;

        match &buffer {
            b"0" => Ok(Level::Low),
            _ => Ok(Level::High),
        }
    }
}

impl Drop for Interrupt {
    fn drop(&mut self) {
        sysfs::unexport(self.pin).ok();
    }
}

#[derive(Debug)]
struct TriggerStatus {
    interrupt: Option<Interrupt>,
    triggered: bool,
    level: Level,
}

pub struct EventLoop {
    poll: Epoll,
    events: Vec<epoll_event>,
    trigger_status: Vec<TriggerStatus>,
}

impl fmt::Debug for EventLoop {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("EventLoop")
            .field("poll", &self.poll)
            .field("events", &format_args!("{{ .. }}"))
            .field("trigger_status", &format_args!("{{ .. }}"))
            .finish()
    }
}

impl EventLoop {
    pub fn new(capacity: usize) -> Result<EventLoop> {
        let mut trigger_status = Vec::with_capacity(capacity);

        // Initialize trigger_status while circumventing the Copy/Clone requirement
        for _ in 0..trigger_status.capacity() {
            trigger_status.push(TriggerStatus {
                interrupt: None,
                triggered: false,
                level: Level::Low,
            });
        }

        Ok(EventLoop {
            poll: Epoll::new()?,
            events: vec![epoll_event { events: 0, u64: 0 }; capacity],
            trigger_status,
        })
    }

    pub fn poll(
        &mut self,
        pins: &[u8],
        reset: bool,
        timeout: Option<Duration>,
    ) -> Result<Option<(u8, Level)>> {
        for pin in pins {
            if *pin as usize >= self.trigger_status.capacity() {
                return Err(Error::InvalidPin(*pin));
            }

            // Did we cache any trigger events during the previous poll?
            if self.trigger_status[*pin as usize].triggered {
                self.trigger_status[*pin as usize].triggered = false;

                if !reset {
                    return Ok(Some((*pin, self.trigger_status[*pin as usize].level)));
                }
            }

            // Read the logic level to reset any pending trigger events
            if let Some(ref mut interrupt) = self.trigger_status[*pin as usize].interrupt {
                if reset {
                    interrupt.level()?;
                }
            }
        }

        // Loop until we get any of the events we're waiting for, or a timeout occurs
        let now = Instant::now();
        loop {
            let num_events = self.poll.wait(&mut self.events, timeout)?;

            // No events means a timeout occurred
            if num_events == 0 {
                return Ok(None);
            }

            for event in &self.events[0..num_events] {
                let pin = event.u64 as usize;
                if pin < self.trigger_status.capacity() {
                    self.trigger_status[pin].triggered = true;
                    self.trigger_status[pin].level =
                        if let Some(ref mut interrupt) = self.trigger_status[pin].interrupt {
                            interrupt.level()?
                        } else {
                            Level::Low
                        };
                }
            }

            // Were any interrupts triggered? If so, return one. The rest
            // will be saved for the next poll.
            for pin in pins {
                if self.trigger_status[*pin as usize].triggered {
                    self.trigger_status[*pin as usize].triggered = false;
                    return Ok(Some((*pin, self.trigger_status[*pin as usize].level)));
                }
            }

            // It's possible a pin we're not waiting for continuously triggers
            // an interrupt, causing repeated loops with calls to poll() using a
            // reset timeout value. Make sure we haven't been looping longer than
            // the requested timeout.
            if let Some(t) = timeout {
                if now.elapsed() > t {
                    return Ok(None);
                }
            }
        }
    }

    pub fn set_interrupt(&mut self, pin: u8, trigger: Trigger) -> Result<()> {
        self.trigger_status[pin as usize].triggered = false;

        // Interrupt already exists. We just need to change the trigger.
        if let Some(ref mut interrupt) = self.trigger_status[pin as usize].interrupt {
            if interrupt.trigger != trigger {
                interrupt.set_trigger(trigger)?;
            }

            return Ok(());
        }

        // Register a new interrupt
        let mut base = Interrupt::new(pin, trigger)?;
        base.level()?;
        self.poll
            .add(base.fd(), u64::from(pin), EPOLLERR | EPOLLET | EPOLLPRI)?;
        self.trigger_status[pin as usize].interrupt = Some(base);

        Ok(())
    }

    pub fn clear_interrupt(&mut self, pin: u8) -> Result<()> {
        self.trigger_status[pin as usize].triggered = false;

        if let Some(interrupt) = self.trigger_status[pin as usize].interrupt.take() {
            self.poll.delete(interrupt.fd())?;
        }

        Ok(())
    }
}

pub struct AsyncInterrupt {
    pin: u8,
    poll_thread: Option<thread::JoinHandle<Result<()>>>,
    tx: EventFd,
}

impl AsyncInterrupt {
    pub fn new<C>(pin: u8, trigger: Trigger, mut callback: C) -> Result<AsyncInterrupt>
    where
        C: FnMut(Level) + Send + 'static,
    {
        let tx = EventFd::new()?;
        let rx = tx.fd();

        let poll_thread = thread::spawn(move || -> Result<()> {
            let poll = Epoll::new()?;

            // rx becomes readable when the main thread calls notify()
            poll.add(rx, rx as u64, EPOLLERR | EPOLLET | EPOLLIN)?;

            // Triggering an interrupt sets error and priority
            let mut base = Interrupt::new(pin, trigger)?;
            let base_fd = base.fd();
            base.level()?;
            poll.add(base_fd, base_fd as u64, EPOLLERR | EPOLLET | EPOLLPRI)?;

            let mut events = [epoll_event { events: 0, u64: 0 }; 2];
            loop {
                let num_events = poll.wait(&mut events, None)?;
                if num_events > 0 {
                    for event in &events[0..num_events] {
                        let fd = event.u64 as i32;
                        if fd == rx {
                            return Ok(()); // The main thread asked us to stop
                        } else if fd == base.fd() {
                            callback(base.level()?);
                        }
                    }
                }
            }
        });

        Ok(AsyncInterrupt {
            pin,
            poll_thread: Some(poll_thread),
            tx,
        })
    }

    pub fn stop(&mut self) -> Result<()> {
        self.tx.notify()?;

        if let Some(poll_thread) = self.poll_thread.take() {
            match poll_thread.join() {
                Ok(r) => return r,
                Err(_) => return Err(Error::ThreadPanic),
            }
        }

        Ok(())
    }
}

impl Drop for AsyncInterrupt {
    fn drop(&mut self) {
        // Unexport the pin here, because we can't rely on the thread
        // living long enough to unexport it.
        sysfs::unexport(self.pin).ok();
    }
}

impl fmt::Debug for AsyncInterrupt {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("AsyncInterrupt")
            .field("pin", &self.pin)
            .field("poll_thread", &self.poll_thread)
            .field("tx", &self.tx)
            .finish()
    }
}
<|endoftext|>


<commit_before>mod moore;
mod von_neumann;

pub use self::moore::MooreNhood;
pub use self::von_neumann::VonNeumannNhood;
<commit_msg>Note about nhood module.<commit_after>//! Module contains several implemented neighborhoods.

mod moore;
mod von_neumann;

pub use self::moore::MooreNhood;
pub use self::von_neumann::VonNeumannNhood;
<|endoftext|>


<commit_before>use lisp::cell::Cell;

// Produces a vector of Strings, with no empty ones
pub fn tokenize(input : &str) -> Vec<String> {
    let formatted = format_braces(input);
    let mut tokens : Vec<String> = Vec::new();

    for token in formatted.split(' ') {
        let t = token.trim();
        // push only tokens with text
        if t != "" {
            tokens.push(t.to_string());
        }
    }

    tokens
}

// Puts spaces befor and after braces
fn format_braces(input : &str) -> String {
    input.replace("(", " ( ").replace(")", " ) ").trim().to_string()
}

// Consumes a vector of Strings, returning data to be used with eval
pub fn parse_tree_from_tokens(tokens : &mut Vec<String>) -> Option<Cell> {
    let mut result : Option<Cell> = None;

    if !tokens.is_empty() {
        let curr_token = tokens.remove(0);

        match curr_token.as_ref() {
            "(" => {
                    // build a list
                    let mut l : Vec<Cell> = Vec::new();

                    while &tokens[0] != ")" {
                        l.push(parse_tree_from_tokens(tokens).unwrap());
                    }

                    tokens.remove(0);
                    result = Some(Cell::List(l));
                },
            ")" => panic!("Unbalanced )"),
            s => {
                // parse the single atom
                result = Some(parse_atom(s));
            }
        }

    }

    result
}

// Parses an atomic value (number/string)
fn parse_atom(input : &str) -> Cell {
    // try parsing as i32
    let n_int = input.parse::<i32>();
    if n_int.is_err() {
        // try parsing as f32
        let n_f = input.parse::<f32>();
        if n_f.is_err() {
            return Cell::Symbol(input.to_string());
        }
        return Cell::Number(n_f.unwrap());
    }
    Cell::Number(n_int.unwrap() as f32)
}

#[test]
fn test_parse_atom() {

    let atom = "123";
    let token = match parse_atom(atom) {
        Cell::Number(n) => n,
        _ => 0.0
    };

    assert_eq!(token, 123.0);

    let atom = "12.3";
    let token = match parse_atom(atom) {
        Cell::Number(n) => n,
        _ => 0.0
    };

    assert_eq!(token, 12.3);

    let atom = "12g.3";
    let token = match parse_atom(atom) {
        Cell::Symbol(n) => n,
        _ => "wat".to_string()
    };

    assert_eq!(&token, atom);
}
<commit_msg>parsing of boolean values and nil<commit_after>use lisp::cell::Cell;

// Produces a vector of Strings, with no empty ones
pub fn tokenize(input : &str) -> Vec<String> {
    let formatted = format_braces(input);
    let mut tokens : Vec<String> = Vec::new();

    for token in formatted.split(' ') {
        let t = token.trim();
        // push only tokens with text
        if t != "" {
            tokens.push(t.to_string());
        }
    }

    tokens
}

// Puts spaces befor and after braces
fn format_braces(input : &str) -> String {
    input.replace("(", " ( ").replace(")", " ) ").trim().to_string()
}

// Consumes a vector of Strings, returning data to be used with eval
pub fn parse_tree_from_tokens(tokens : &mut Vec<String>) -> Option<Cell> {
    let mut result : Option<Cell> = None;

    if !tokens.is_empty() {
        let curr_token = tokens.remove(0);

        match curr_token.as_ref() {
            "(" => {
                    // build a list
                    let mut l : Vec<Cell> = Vec::new();

                    while &tokens[0] != ")" {
                        l.push(parse_tree_from_tokens(tokens).unwrap());
                    }

                    tokens.remove(0);
                    result = Some(Cell::List(l));
                },
            ")" => panic!("Unbalanced )"),
            s => {
                // parse the single atom
                result = Some(parse_atom(s));
            }
        }

    }

    result
}

// Parses an atomic value (number/string)
fn parse_atom(input : &str) -> Cell {
    let n_f = input.parse::<f32>();

    if n_f.is_err() {
        match input {
            "#t" => Cell::True,
            "#f" => Cell::False,
            "nil" => Cell::Nil,
            _ => Cell::Symbol(input.to_string())
        }
    } else {
        Cell::Number(n_f.unwrap())
    }
}

#[test]
fn test_parse_atom() {

    let atom = "123";
    let token = match parse_atom(atom) {
        Cell::Number(n) => n,
        _ => 0.0
    };

    assert_eq!(token, 123.0);

    let atom = "12.3";
    let token = match parse_atom(atom) {
        Cell::Number(n) => n,
        _ => 0.0
    };

    assert_eq!(token, 12.3);

    let atom = "12g.3";
    let token = match parse_atom(atom) {
        Cell::Symbol(n) => n,
        _ => "wat".to_string()
    };

    assert_eq!(&token, atom);
}
<|endoftext|>


<commit_before>use std::collections::{BTreeMap, HashMap};
use std::io::{self, Read, Write};
use std::env;
use std::error::Error;
use std::fs::{self, File};
use std::path::Path;
use std::process;

use toml::{self, Table, Value};
use tempdir::TempDir;

use deps::RawDep;
use deps::Dep;
use error::{CliError, CliResult};
use config::Config;
use fmt::Format;

pub struct Lockfile {
    pub deps: HashMap<String, RawDep>,
    toml: Box<Table>,
}

impl Lockfile {
    pub fn from_config(cfg: &Config) -> CliResult<Self> {
        debugln!("Lockfile:from_config");
        Lockfile::from_file(&cfg.lockfile)
    }

    pub fn from_file<P: AsRef<Path>>(p: P) -> CliResult<Self> {
        debugln!("Lockfile:from_file:file={:?}", p.as_ref());
        let mut f = match File::open(p.as_ref()) {
            Ok(f) => f,
            Err(e) => return Err(CliError::FileOpen(e.description().to_owned())),
        };

        let mut s = String::new();
        if let Err(e) = f.read_to_string(&mut s) {
            return Err(CliError::Generic(format!("Couldn't read the contents of the lockfile with error: {}",
                                                 e.description())));
        }

        let mut parser = toml::Parser::new(&s);
        if let Some(toml) = parser.parse() {
            return Ok(Lockfile {
                deps: HashMap::new(),
                toml: Box::new(toml),
            });
        }

        // On err
        let mut error_str = String::from("could not parse input as TOML\n");
        for error in parser.errors.iter() {
            let (loline, locol) = parser.to_linecol(error.lo);
            let (hiline, hicol) = parser.to_linecol(error.hi);
            error_str.push_str(&format!("{:?}:{}:{}{} {}\n",
                                        f,
                                        loline + 1,
                                        locol + 1,
                                        if loline != hiline || locol != hicol {
                                            format!("-{}:{}", hiline + 1, hicol + 1)
                                        } else {
                                            "".to_owned()
                                        },
                                        error.desc));
        }
        Err(CliError::Generic(error_str))
    }

    #[cfg_attr(feature = "lints", allow(cyclomatic_complexity))]
    pub fn get_updates(&mut self, cfg: &Config) -> CliResult<Option<BTreeMap<String, Dep>>> {
        debugln!("Lockfile:get_updates");
        try!(self.parse_deps_to_depth(cfg.depth));

        // try!(self.get_non_root_deps(self.toml));
        let tmp = match TempDir::new("cargo-outdated") {
            Ok(t) => t,
            Err(e) => return Err(CliError::Generic(e.description().to_owned())),
        };

        verbose!(cfg, "Setting up temp space...");
        let tmp_manifest = tmp.path().join(&cfg.manifest.file_name().unwrap());
        let tmp_lockfile = tmp.path().join(&cfg.lockfile.file_name().unwrap());

        let mut mf = match File::create(&tmp_manifest) {
            Ok(f) => f,
            Err(e) => {
                debugln!("Lockfile:get_updates:creating temp manifest failed: {}", e);
                return Err(CliError::Generic(e.description().to_owned()));
            }
        };

        debugln!("Lockfile:get_updates:temp manifest created");
        try!(self.write_semver_manifest(&mut mf));
        verboseln!(cfg, "{}", Format::Good("Done"));

        match fs::copy(&cfg.lockfile, &tmp_lockfile) {
            Ok(..) => (),
            Err(e) => {
                debugln!("temp Cargo.lock failed with error: {}", e);
                return Err(CliError::Generic(e.description().to_owned()));
            }
        }

        debugln!("\n{}\n", {
            let mut f = File::open(&tmp_lockfile)
                .unwrap_or_else(|e| panic!("cannot open file: {}", e));

            let mut s = String::new();
            f.read_to_string(&mut s).ok();
            s
        });

        let cwd = env::current_dir()
            .unwrap_or_else(|e| panic!("current working dir opening error: {}", e));
        debugln!("executing; cargo update");
        env::set_current_dir(tmp.path())
            .unwrap_or_else(|e| panic!("cannot set current dir: {}", e));
        print!("Checking for SemVer compatible updates...");
        let mut out = io::stdout();
        out.flush().unwrap_or_else(|e| panic!("failed to flush stdout: {}", e));
        if let Err(e) = process::Command::new("cargo")
            .arg("update")
            .arg("--manifest-path")
            .arg(tmp_manifest.to_str()
                .expect("failed to convert temp Cargo.toml path to string"))
            .output()
            .and_then(|v| {
                if v.status.success() {
                    Ok(v)
                } else {
                    Err(io::Error::new(io::ErrorKind::Other, "did not exit successfully"))
                }
            }) {

            return Err(CliError::Generic(format!("Failed to run 'cargo update' with error '{}'",
                                                 e.description())));
        }
        println!("{}", Format::Good("Done"));

        verbose!(cfg, "Parsing the results...");
        debugln!("creating new lockfile from tmp results");
        let mut updated_lf = try!(Lockfile::from_file(&tmp_lockfile));
        try!(updated_lf.parse_deps_to_depth(0));
        let mut res = BTreeMap::new();
        debugln!("parsing semver results");
        for (d_name, d) in self.deps.iter() {
            debugln!("iter; name={}; ver={}", d_name, d.ver);
            if let Some(semver_dep) = updated_lf.deps.get(&d.name) {
                if semver_dep.ver != d.ver {
                    res.insert(d_name.to_owned(),
                               Dep {
                                   name: d_name.to_owned(),
                                   source: d.source.clone(),
                                   project_ver: d.ver.clone(),
                                   semver_ver: Some(semver_dep.ver.clone()),
                                   latest_ver: None,
                               });
                }
            }
        }
        verboseln!(cfg, "{}", Format::Good("Done"));

        verbose!(cfg, "Creating temp space for latest versions...");
        let mut mf = match File::create(&tmp_manifest) {
            Ok(f) => f,
            Err(e) => {
                debugln!("temp Cargo.toml failed with error: {}", e);
                return Err(CliError::Generic(e.description().to_owned()));
            }
        };

        try!(self.write_latest_manifest(&mut mf));

        match fs::copy(&cfg.lockfile, &tmp_lockfile) {
            Ok(..) => (),
            Err(e) => {
                debugln!("temp Cargo.lock failed with error: {}", e);
                return Err(CliError::Generic(e.description().to_owned()));
            }
        }
        verboseln!(cfg, "{}", Format::Good("Done"));

        print!("Checking for the latest updates...");
        out.flush().expect("failed to flush stdout");
        if let Err(e) = process::Command::new("cargo")
            .arg("update")
            .arg("--manifest-path")
            .arg(tmp_manifest.to_str()
                .expect("failed to convert temp Cargo.toml path to string"))
            .output()
            .and_then(|v| {
                if v.status.success() {
                    Ok(v)
                } else {
                    Err(io::Error::new(io::ErrorKind::Other, "did not exit successfully"))
                }
            }) {

            return Err(CliError::Generic(format!("Failed to run 'cargo update' with error '{}'",
                                                 e.description())));
        }
        println!("{}", Format::Good("Done"));

        verbose!(cfg, "Parsing the results...");
        let mut updated_lf = try!(Lockfile::from_file(&tmp_lockfile));
        try!(updated_lf.parse_deps_to_depth(0));
        for (d_name, d) in self.deps.iter() {
            debugln!("iter; name={}", d_name);
            if let Some(latest_dep) = updated_lf.deps.get(&d.name) {
                if latest_dep.ver != d.ver {
                    let exists = if let Some(d) = res.get_mut(d_name) {
                        d.latest_ver = Some(latest_dep.ver.clone());
                        true
                    } else {
                        false
                    };

                    if !exists {
                        res.insert(d_name.to_owned(),
                                   Dep {
                                       name: d_name.to_owned(),
                                       source: d.source.clone(),
                                       project_ver: d.ver.clone(),
                                       semver_ver: None,
                                       latest_ver: Some(latest_dep.ver.clone()),
                                   });
                    }
                }
            }
        }
        verboseln!(cfg, "{}", Format::Good("Done"));

        env::set_current_dir(&cwd).unwrap_or_else(|e| panic!("cannot set current dir: {}", e));

        if res.is_empty() {
            debugln!("returning; res=Ok(None)");
            Ok(None)
        } else {
            if let Some(ref dep_v) = cfg.to_update {
                let mut safe = vec![];
                for dep in dep_v {
                    if res.contains_key(dep.to_owned()) {
                        safe.push(dep);
                    }
                }
                let mut ret = BTreeMap::new();
                for dep in safe.into_iter() {
                    ret.insert((*dep).to_owned(),
                               res.remove(&**dep)
                                   .expect("failed to get dependency from results set"));
                }
                return Ok(Some(ret));
            }
            debugln!("returning; res={:#?}", res);
            Ok(Some(res))
        }
    }

    fn parse_deps_to_depth(&mut self, mut depth: u32) -> CliResult<()> {
        debugln!("executing; parse_deps_to_depth; depth={}", depth);
        let mut all_deps = depth == 0;

        try!(self.parse_root_deps());

        while depth > 1 || all_deps {
            debugln!("iter; depth={};", depth);
            match self.toml.get("package") {
                Some(&Value::Array(ref tables)) => {
                    for table in tables {
                        let name = table.lookup("name")
                            .expect("no 'name' field in Cargo.lock [package] table")
                            .as_str()
                            .expect("'name' field of [package] table in Cargo.lock was \
                                             not a valid string");
                        if !self.deps.contains_key(name) {
                            continue;
                        }
                        let ver = table.lookup("version")
                            .expect("no 'version' field in Cargo.lock [package] table")
                            .as_str()
                            .expect("'version' field of [package] table in Cargo.lock \
                                                was not a valid string");
                        let mut next_level = vec![];
                        if let Some(existing_dep) = self.deps.get_mut(name) {
                            if existing_dep.ver != ver {
                                // probably a child of another dep...skip!
                                continue;
                            }
                            match table.lookup("dependencies") {
                                Some(&Value::Array(ref deps)) => {
                                    let mut children = vec![];
                                    for d in deps {
                                        let dep_str = d.as_str().unwrap_or("");
                                        let mut child: RawDep = match dep_str.parse() {
                                            Ok(val) => val,
                                            Err(e) => return Err(CliError::Generic(e)),
                                        };
                                        child.parent = Some(name.to_owned());
                                        children.push(child.name.clone());
                                        if all_deps || depth > 1 {
                                            debugln!("adding sub dep {}->{}", name, child.name);
                                            next_level.push(child);
                                        }
                                    }
                                    existing_dep.children = Some(children);
                                }
                                Some(..) => unreachable!(),
                                None => (),
                            }
                        }
                        for child in next_level.into_iter() {
                            self.deps
                                .insert(format!("{}->{}",
                                                child.parent
                                                    .as_ref()
                                                    .expect("child dependency has no parent node")
                                                    .clone(),
                                                child.name.clone()),
                                        child);
                        }
                    }
                    depth = if depth > 0 { depth - 1 } else { break; };
                    if depth == 1 {
                        all_deps = false;
                    }
                }
                Some(_) => unreachable!(),
                None => return Err(CliError::NoNonRootDeps),
            }
        }

        debugln!("All deps: {:#?}", self.deps);
        Ok(())
    }

    fn parse_root_deps(&mut self) -> CliResult<()> {
        debugln!("executing; parse_root_deps;");
        let root_table = match self.toml.get("root") {
            Some(table) => table,
            None => return Err(CliError::TomlTableRoot),
        };
        match root_table.lookup("dependencies") {
            Some(&Value::Array(ref val)) => {
                debugln!("found root deps table");

                for v in val {
                    let val_str = v.as_str().unwrap_or("");
                    debugln!("adding root dep {}", val_str);
                    let raw_dep: RawDep = match val_str.parse() {
                        Ok(val) => val,
                        Err(e) => return Err(CliError::Generic(e)),
                    };
                    self.deps.insert(raw_dep.name.clone(), raw_dep);
                }
            }
            Some(_) => unreachable!(),
            None => return Err(CliError::NoRootDeps),
        }

        debugln!("Root deps: {:#?}", self.deps);
        Ok(())
    }

    fn write_manifest_pretext<W>(&self, w: &mut W) -> CliResult<()>
        where W: Write
    {
        write!(w,
               "[package]\n\
                      name = \"temp\"\n\
                      version = \"1.0.0\"\n\
                      [[bin]]\n\
                      name = \"test\"\n\
                      [dependencies]\n")
            .unwrap();

        Ok(())
    }

    fn unique_deps(&self) -> HashMap<String, RawDep> {
        self.deps.iter().map(|(_, ref dep)| (dep.name.clone(), (**dep).clone())).collect()
    }

    pub fn write_semver_manifest<W>(&self, w: &mut W) -> CliResult<()>
        where W: Write
    {
        debugln!("executing; write_semver_manifest;");
        try!(self.write_manifest_pretext(w));

        for dep in self.unique_deps().values() {
            if !dep.source.starts_with("(registry+") {
                continue;
            }
            debugln!("iter; name={}; ver=~{}", dep.name, dep.ver);
            if let Err(e) = write!(w, "{} = \"~{}\"\n", dep.name, dep.ver) {
                return Err(CliError::Generic(format!("Failed to write Cargo.toml with error '{}'",
                                                     e.description())));
            }
        }

        Ok(())
    }
    pub fn write_latest_manifest<W>(&self, w: &mut W) -> CliResult<()>
        where W: Write
    {
        debugln!("write_latest_manifest;");
        try!(self.write_manifest_pretext(w));

        for dep in self.unique_deps().values() {
            if !dep.source.starts_with("(registry+") {
                continue;
            }
            debugln!("write_latest_manifest:iter:ver=*,name={}", dep.name);
            if let Err(e) = write!(w, "{} = \"*\"\n", dep.name) {
                return Err(CliError::Generic(format!("Failed to write manifest with error: '{}'",
                                                     e.description())));
            }
        }

        Ok(())
    }
}
<commit_msg>Use default (caret) requirement, fixes #31<commit_after>use std::collections::{BTreeMap, HashMap};
use std::io::{self, Read, Write};
use std::env;
use std::error::Error;
use std::fs::{self, File};
use std::path::Path;
use std::process;

use toml::{self, Table, Value};
use tempdir::TempDir;

use deps::RawDep;
use deps::Dep;
use error::{CliError, CliResult};
use config::Config;
use fmt::Format;

pub struct Lockfile {
    pub deps: HashMap<String, RawDep>,
    toml: Box<Table>,
}

impl Lockfile {
    pub fn from_config(cfg: &Config) -> CliResult<Self> {
        debugln!("Lockfile:from_config");
        Lockfile::from_file(&cfg.lockfile)
    }

    pub fn from_file<P: AsRef<Path>>(p: P) -> CliResult<Self> {
        debugln!("Lockfile:from_file:file={:?}", p.as_ref());
        let mut f = match File::open(p.as_ref()) {
            Ok(f) => f,
            Err(e) => return Err(CliError::FileOpen(e.description().to_owned())),
        };

        let mut s = String::new();
        if let Err(e) = f.read_to_string(&mut s) {
            return Err(CliError::Generic(format!("Couldn't read the contents of the lockfile with error: {}",
                                                 e.description())));
        }

        let mut parser = toml::Parser::new(&s);
        if let Some(toml) = parser.parse() {
            return Ok(Lockfile {
                deps: HashMap::new(),
                toml: Box::new(toml),
            });
        }

        // On err
        let mut error_str = String::from("could not parse input as TOML\n");
        for error in parser.errors.iter() {
            let (loline, locol) = parser.to_linecol(error.lo);
            let (hiline, hicol) = parser.to_linecol(error.hi);
            error_str.push_str(&format!("{:?}:{}:{}{} {}\n",
                                        f,
                                        loline + 1,
                                        locol + 1,
                                        if loline != hiline || locol != hicol {
                                            format!("-{}:{}", hiline + 1, hicol + 1)
                                        } else {
                                            "".to_owned()
                                        },
                                        error.desc));
        }
        Err(CliError::Generic(error_str))
    }

    #[cfg_attr(feature = "lints", allow(cyclomatic_complexity))]
    pub fn get_updates(&mut self, cfg: &Config) -> CliResult<Option<BTreeMap<String, Dep>>> {
        debugln!("Lockfile:get_updates");
        try!(self.parse_deps_to_depth(cfg.depth));

        // try!(self.get_non_root_deps(self.toml));
        let tmp = match TempDir::new("cargo-outdated") {
            Ok(t) => t,
            Err(e) => return Err(CliError::Generic(e.description().to_owned())),
        };

        verbose!(cfg, "Setting up temp space...");
        let tmp_manifest = tmp.path().join(&cfg.manifest.file_name().unwrap());
        let tmp_lockfile = tmp.path().join(&cfg.lockfile.file_name().unwrap());

        let mut mf = match File::create(&tmp_manifest) {
            Ok(f) => f,
            Err(e) => {
                debugln!("Lockfile:get_updates:creating temp manifest failed: {}", e);
                return Err(CliError::Generic(e.description().to_owned()));
            }
        };

        debugln!("Lockfile:get_updates:temp manifest created");
        try!(self.write_semver_manifest(&mut mf));
        verboseln!(cfg, "{}", Format::Good("Done"));

        match fs::copy(&cfg.lockfile, &tmp_lockfile) {
            Ok(..) => (),
            Err(e) => {
                debugln!("temp Cargo.lock failed with error: {}", e);
                return Err(CliError::Generic(e.description().to_owned()));
            }
        }

        debugln!("\n{}\n", {
            let mut f = File::open(&tmp_lockfile)
                .unwrap_or_else(|e| panic!("cannot open file: {}", e));

            let mut s = String::new();
            f.read_to_string(&mut s).ok();
            s
        });

        let cwd = env::current_dir()
            .unwrap_or_else(|e| panic!("current working dir opening error: {}", e));
        debugln!("executing; cargo update");
        env::set_current_dir(tmp.path())
            .unwrap_or_else(|e| panic!("cannot set current dir: {}", e));
        print!("Checking for SemVer compatible updates...");
        let mut out = io::stdout();
        out.flush().unwrap_or_else(|e| panic!("failed to flush stdout: {}", e));
        if let Err(e) = process::Command::new("cargo")
            .arg("update")
            .arg("--manifest-path")
            .arg(tmp_manifest.to_str()
                .expect("failed to convert temp Cargo.toml path to string"))
            .output()
            .and_then(|v| {
                if v.status.success() {
                    Ok(v)
                } else {
                    Err(io::Error::new(io::ErrorKind::Other, "did not exit successfully"))
                }
            }) {

            return Err(CliError::Generic(format!("Failed to run 'cargo update' with error '{}'",
                                                 e.description())));
        }
        println!("{}", Format::Good("Done"));

        verbose!(cfg, "Parsing the results...");
        debugln!("creating new lockfile from tmp results");
        let mut updated_lf = try!(Lockfile::from_file(&tmp_lockfile));
        try!(updated_lf.parse_deps_to_depth(0));
        let mut res = BTreeMap::new();
        debugln!("parsing semver results");
        for (d_name, d) in self.deps.iter() {
            debugln!("iter; name={}; ver={}", d_name, d.ver);
            if let Some(semver_dep) = updated_lf.deps.get(&d.name) {
                if semver_dep.ver != d.ver {
                    res.insert(d_name.to_owned(),
                               Dep {
                                   name: d_name.to_owned(),
                                   source: d.source.clone(),
                                   project_ver: d.ver.clone(),
                                   semver_ver: Some(semver_dep.ver.clone()),
                                   latest_ver: None,
                               });
                }
            }
        }
        verboseln!(cfg, "{}", Format::Good("Done"));

        verbose!(cfg, "Creating temp space for latest versions...");
        let mut mf = match File::create(&tmp_manifest) {
            Ok(f) => f,
            Err(e) => {
                debugln!("temp Cargo.toml failed with error: {}", e);
                return Err(CliError::Generic(e.description().to_owned()));
            }
        };

        try!(self.write_latest_manifest(&mut mf));

        match fs::copy(&cfg.lockfile, &tmp_lockfile) {
            Ok(..) => (),
            Err(e) => {
                debugln!("temp Cargo.lock failed with error: {}", e);
                return Err(CliError::Generic(e.description().to_owned()));
            }
        }
        verboseln!(cfg, "{}", Format::Good("Done"));

        print!("Checking for the latest updates...");
        out.flush().expect("failed to flush stdout");
        if let Err(e) = process::Command::new("cargo")
            .arg("update")
            .arg("--manifest-path")
            .arg(tmp_manifest.to_str()
                .expect("failed to convert temp Cargo.toml path to string"))
            .output()
            .and_then(|v| {
                if v.status.success() {
                    Ok(v)
                } else {
                    Err(io::Error::new(io::ErrorKind::Other, "did not exit successfully"))
                }
            }) {

            return Err(CliError::Generic(format!("Failed to run 'cargo update' with error '{}'",
                                                 e.description())));
        }
        println!("{}", Format::Good("Done"));

        verbose!(cfg, "Parsing the results...");
        let mut updated_lf = try!(Lockfile::from_file(&tmp_lockfile));
        try!(updated_lf.parse_deps_to_depth(0));
        for (d_name, d) in self.deps.iter() {
            debugln!("iter; name={}", d_name);
            if let Some(latest_dep) = updated_lf.deps.get(&d.name) {
                if latest_dep.ver != d.ver {
                    let exists = if let Some(d) = res.get_mut(d_name) {
                        d.latest_ver = Some(latest_dep.ver.clone());
                        true
                    } else {
                        false
                    };

                    if !exists {
                        res.insert(d_name.to_owned(),
                                   Dep {
                                       name: d_name.to_owned(),
                                       source: d.source.clone(),
                                       project_ver: d.ver.clone(),
                                       semver_ver: None,
                                       latest_ver: Some(latest_dep.ver.clone()),
                                   });
                    }
                }
            }
        }
        verboseln!(cfg, "{}", Format::Good("Done"));

        env::set_current_dir(&cwd).unwrap_or_else(|e| panic!("cannot set current dir: {}", e));

        if res.is_empty() {
            debugln!("returning; res=Ok(None)");
            Ok(None)
        } else {
            if let Some(ref dep_v) = cfg.to_update {
                let mut safe = vec![];
                for dep in dep_v {
                    if res.contains_key(dep.to_owned()) {
                        safe.push(dep);
                    }
                }
                let mut ret = BTreeMap::new();
                for dep in safe.into_iter() {
                    ret.insert((*dep).to_owned(),
                               res.remove(&**dep)
                                   .expect("failed to get dependency from results set"));
                }
                return Ok(Some(ret));
            }
            debugln!("returning; res={:#?}", res);
            Ok(Some(res))
        }
    }

    fn parse_deps_to_depth(&mut self, mut depth: u32) -> CliResult<()> {
        debugln!("executing; parse_deps_to_depth; depth={}", depth);
        let mut all_deps = depth == 0;

        try!(self.parse_root_deps());

        while depth > 1 || all_deps {
            debugln!("iter; depth={};", depth);
            match self.toml.get("package") {
                Some(&Value::Array(ref tables)) => {
                    for table in tables {
                        let name = table.lookup("name")
                            .expect("no 'name' field in Cargo.lock [package] table")
                            .as_str()
                            .expect("'name' field of [package] table in Cargo.lock was \
                                             not a valid string");
                        if !self.deps.contains_key(name) {
                            continue;
                        }
                        let ver = table.lookup("version")
                            .expect("no 'version' field in Cargo.lock [package] table")
                            .as_str()
                            .expect("'version' field of [package] table in Cargo.lock \
                                                was not a valid string");
                        let mut next_level = vec![];
                        if let Some(existing_dep) = self.deps.get_mut(name) {
                            if existing_dep.ver != ver {
                                // probably a child of another dep...skip!
                                continue;
                            }
                            match table.lookup("dependencies") {
                                Some(&Value::Array(ref deps)) => {
                                    let mut children = vec![];
                                    for d in deps {
                                        let dep_str = d.as_str().unwrap_or("");
                                        let mut child: RawDep = match dep_str.parse() {
                                            Ok(val) => val,
                                            Err(e) => return Err(CliError::Generic(e)),
                                        };
                                        child.parent = Some(name.to_owned());
                                        children.push(child.name.clone());
                                        if all_deps || depth > 1 {
                                            debugln!("adding sub dep {}->{}", name, child.name);
                                            next_level.push(child);
                                        }
                                    }
                                    existing_dep.children = Some(children);
                                }
                                Some(..) => unreachable!(),
                                None => (),
                            }
                        }
                        for child in next_level.into_iter() {
                            self.deps
                                .insert(format!("{}->{}",
                                                child.parent
                                                    .as_ref()
                                                    .expect("child dependency has no parent node")
                                                    .clone(),
                                                child.name.clone()),
                                        child);
                        }
                    }
                    depth = if depth > 0 { depth - 1 } else { break; };
                    if depth == 1 {
                        all_deps = false;
                    }
                }
                Some(_) => unreachable!(),
                None => return Err(CliError::NoNonRootDeps),
            }
        }

        debugln!("All deps: {:#?}", self.deps);
        Ok(())
    }

    fn parse_root_deps(&mut self) -> CliResult<()> {
        debugln!("executing; parse_root_deps;");
        let root_table = match self.toml.get("root") {
            Some(table) => table,
            None => return Err(CliError::TomlTableRoot),
        };
        match root_table.lookup("dependencies") {
            Some(&Value::Array(ref val)) => {
                debugln!("found root deps table");

                for v in val {
                    let val_str = v.as_str().unwrap_or("");
                    debugln!("adding root dep {}", val_str);
                    let raw_dep: RawDep = match val_str.parse() {
                        Ok(val) => val,
                        Err(e) => return Err(CliError::Generic(e)),
                    };
                    self.deps.insert(raw_dep.name.clone(), raw_dep);
                }
            }
            Some(_) => unreachable!(),
            None => return Err(CliError::NoRootDeps),
        }

        debugln!("Root deps: {:#?}", self.deps);
        Ok(())
    }

    fn write_manifest_pretext<W>(&self, w: &mut W) -> CliResult<()>
        where W: Write
    {
        write!(w,
               "[package]\n\
                      name = \"temp\"\n\
                      version = \"1.0.0\"\n\
                      [[bin]]\n\
                      name = \"test\"\n\
                      [dependencies]\n")
            .unwrap();

        Ok(())
    }

    fn unique_deps(&self) -> HashMap<String, RawDep> {
        self.deps.iter().map(|(_, ref dep)| (dep.name.clone(), (**dep).clone())).collect()
    }

    pub fn write_semver_manifest<W>(&self, w: &mut W) -> CliResult<()>
        where W: Write
    {
        debugln!("executing; write_semver_manifest;");
        try!(self.write_manifest_pretext(w));

        for dep in self.unique_deps().values() {
            if !dep.source.starts_with("(registry+") {
                continue;
            }
            debugln!("iter; name={}; ver={}", dep.name, dep.ver);
            if let Err(e) = write!(w, "{} = \"{}\"\n", dep.name, dep.ver) {
                return Err(CliError::Generic(format!("Failed to write Cargo.toml with error '{}'",
                                                     e.description())));
            }
        }

        Ok(())
    }
    pub fn write_latest_manifest<W>(&self, w: &mut W) -> CliResult<()>
        where W: Write
    {
        debugln!("write_latest_manifest;");
        try!(self.write_manifest_pretext(w));

        for dep in self.unique_deps().values() {
            if !dep.source.starts_with("(registry+") {
                continue;
            }
            debugln!("write_latest_manifest:iter:ver=*,name={}", dep.name);
            if let Err(e) = write!(w, "{} = \"*\"\n", dep.name) {
                return Err(CliError::Generic(format!("Failed to write manifest with error: '{}'",
                                                     e.description())));
            }
        }

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


<commit_before>//! Windowing system interoperability
//!
//! Screen presentation (fullscreen or window) of images requires two objects:
//!
//! * [`Surface`] is the host abstraction of the native screen
//! * [`Swapchain`] is the device abstraction for a surface, containing multiple presentable images
//!
//! ## Window
//!
//! // DOC TODO
//!
//! ## Surface
//!
//! // DOC TODO
//!
//! ## Swapchain
//!
//! The most interesting part of a swapchain are the contained presentable images/backbuffers.
//! Presentable images are specialized images, which can be presented on the screen. They are
//! 2D color images with optionally associated depth-stencil images.
//!
//! The common steps for presentation of a frame are acquisition and presentation:
//!
//! ```no_run
//! # extern crate gfx_backend_empty as empty;
//! # extern crate gfx_hal;
//! # fn main() {
//! use gfx_hal::{Device, FrameSync};
//! # use gfx_hal::{CommandQueue, Graphics, Swapchain};
//!
//! # let mut swapchain: empty::Swapchain = return;
//! # let device: empty::Device = return;
//! # let mut present_queue: CommandQueue<empty::Backend, Graphics> = return;
//! let acquisition_semaphore = device.create_semaphore();
//! let render_semaphore = device.create_semaphore();
//!
//! let frame = swapchain.acquire_frame(FrameSync::Semaphore(&acquisition_semaphore));
//! // render the scene..
//! // `render_semaphore` will be signalled once rendering has been finished
//! swapchain.present(&mut present_queue, &[render_semaphore]);
//! # }
//! ```
//!
//! Queues need to synchronize with the presentation engine, usually done via signalling a semaphore
//! once a frame is available for rendering and waiting on a separate semaphore until scene rendering
//! has finished.
//!
//! ### Recreation
//!
//! DOC TODO

use Backend;
use image;
use format::Format;
use queue::CommandQueue;

use std::any::Any;
use std::borrow::{Borrow, BorrowMut};
use std::ops::Range;

/// An extent describes the size of a rectangle, such as
/// a window or texture. It is not used for referring to a
/// sub-rectangle; for that see `command::Rect`.
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Extent2D {
    /// Width
    pub width: image::Size,
    /// Height
    pub height: image::Size,
}

impl From<image::Extent> for Extent2D {
    fn from(ex: image::Extent) -> Self {
        Extent2D {
            width: ex.width,
            height: ex.height,
        }
    }
}

/// Describes information about what a `Surface`'s properties are.
/// Fetch this with `surface.capabilities_and_formats(device)`.
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SurfaceCapabilities {
    /// Number of presentable images supported by the adapter for a swapchain
    /// created from this surface.
    ///
    /// - `image_count.start` must be at least 1.
    /// - `image_count.end` must be larger of equal to `image_count.start`.
    pub image_count: Range<u32>,

    /// Current extent of the surface.
    ///
    /// `None` if the surface has no explicit size, depending on the swapchain extent.
    pub current_extent: Option<Extent2D>,

    /// Range of supported extents.
    ///
    /// `current_extent` must be inside this range.
    pub extents: Range<Extent2D>,

    /// Maximum number of layers supported for presentable images.
    ///
    /// Must be at least 1.
    pub max_image_layers: u32,
}

/// A `Surface` abstracts the surface of a native window, which will be presented
/// on the display.
pub trait Surface<B: Backend>: Any + Send + Sync {
    /// Retrieve the surface image kind.
    fn kind(&self) -> image::Kind;

    /// Check if the queue family supports presentation to this surface.
    ///
    /// # Examples
    ///
    /// ```no_run
    ///
    /// ```
    fn supports_queue_family(&self, family: &B::QueueFamily) -> bool;

    /// Query surface capabilities and formats for this physical device.
    ///
    /// Use this function for configuring swapchain creation.
    ///
    /// Returns a tuple of surface capabilities and formats.
    /// If formats is `None` than the surface has no preferred format and the
    /// application may use any desired format.
    fn capabilities_and_formats(&self, physical_device: &B::PhysicalDevice) -> (SurfaceCapabilities, Option<Vec<Format>>);
}

/// Handle to a backbuffer of the swapchain.
///
/// The swapchain is a series of one or more images, usually
/// with one being drawn on while the other is displayed by
/// the GPU (aka double-buffering). A `Frame` refers to a
/// particular image in the swapchain.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Frame(pub(crate) usize);

impl Frame {
    /// Retrieve frame id.
    ///
    /// The can be used to access the currently used backbuffer image
    /// in `Backbuffer::Images`.
    ///
    /// # Examples
    ///
    /// ```no_run
    ///
    /// ```
    pub fn id(&self) -> usize {
        self.0
    }
}

/// Synchronization primitives which will be signalled once a frame got retrieved.
///
/// The semaphore or fence _must_ be unsignalled.
pub enum FrameSync<'a, B: Backend> {
    /// Semaphore used for synchronization.
    ///
    /// Will be signaled once the frame backbuffer is available.
    Semaphore(&'a B::Semaphore),

    /// Fence used for synchronization.
    ///
    /// Will be signaled once the frame backbuffer is available.
    Fence(&'a B::Fence),
}

/// Contains all the data necessary to create a new `Swapchain`:
/// color, depth, and number of images.
///
/// # Examples
///
/// This type implements the builder pattern, method calls can be
/// easily chained.
///
/// ```no_run
/// # extern crate gfx_hal;
/// # fn main() {
/// # use gfx_hal::{SwapchainConfig};
/// # use gfx_hal::format::Format;
/// let config = SwapchainConfig::new()
///     .with_color(Format::Bgra8Unorm)
///     .with_depth_stencil(Format::D16Unorm)
///     .with_image_count(2);
/// # }
/// ```
#[derive(Debug, Clone)]
pub struct SwapchainConfig {
    /// Color format of the backbuffer images.
    pub color_format: Format,
    /// Depth stencil format of the backbuffer images (optional).
    pub depth_stencil_format: Option<Format>,
    /// Number of images in the swapchain.
    pub image_count: u32,
    /// Image usage of the backbuffer images.
    pub image_usage: image::Usage,
}

impl SwapchainConfig {
    /// Create a new default configuration (color images only).
    ///
    /// # Examples
    ///
    /// ```no_run
    ///
    /// ```
    pub fn new() -> Self {
        SwapchainConfig {
            color_format: Format::Bgra8Unorm, // TODO: try to find best default format
            depth_stencil_format: None,
            image_count: 2,
            image_usage: image::Usage::empty(),
        }
    }

    /// Specify the color format for the backbuffer images.
    ///
    /// # Examples
    ///
    /// ```no_run
    ///
    /// ```
    pub fn with_color(mut self, cf: Format) -> Self {
        self.color_format = cf;
        self
    }

    /// Specify the depth stencil format for the backbuffer images.
    ///
    /// The Swapchain will create additional depth-stencil images for each backbuffer.
    ///
    /// # Examples
    ///
    /// ```no_run
    ///
    /// ```
    pub fn with_depth_stencil(mut self, dsf: Format) -> Self {
        self.depth_stencil_format = Some(dsf);
        self
    }

    /// Specify the requested number of backbuffer images.
    ///
    /// The implementation may choose to create more if necessary.
    ///
    /// # Examples
    ///
    /// ```no_run
    ///
    /// ```
    pub fn with_image_count(mut self, count: u32) -> Self {
        self.image_count = count;
        self
    }

    // TODO: depth-only, stencil-only, swapchain size, present modes, etc.
}

/// Swapchain backbuffer type
#[derive(Debug)]
pub enum Backbuffer<B: Backend> {
    /// Color image chain
    Images(Vec<B::Image>),
    /// A single opaque framebuffer
    Framebuffer(B::Framebuffer),
}

/// The `Swapchain` is the backend representation of the surface.
/// It consists of multiple buffers, which will be presented on the surface.
pub trait Swapchain<B: Backend>: Any + Send + Sync {
    /// Acquire a new frame for rendering. This needs to be called before presenting.
    ///
    /// # Synchronization
    ///
    /// The acquired image will not be immediately available when the function returns.
    /// Once available the underlying primitive of `sync` will be signaled.
    /// This can either be a [`Semaphore`](../trait.Resources.html#associatedtype.Semaphore)
    /// or a [`Fence`](../trait.Resources.html#associatedtype.Fence).
    ///
    /// # Examples
    ///
    /// ```no_run
    ///
    /// ```
    fn acquire_frame(&mut self, sync: FrameSync<B>) -> Frame;

    /// Present one acquired frame in FIFO order.
    ///
    /// # Safety
    ///
    /// The passed queue _must_ support presentation on the surface, which is
    /// used for creating this swapchain.
    ///
    /// # Examples
    ///
    /// ```no_run
    ///
    /// ```
    fn present<'a, C, IW>(
        &'a mut self,
        present_queue: &mut CommandQueue<B, C>,
        wait_semaphores: IW,
    )
    where
        &'a mut Self: BorrowMut<B::Swapchain>,
        Self: Sized + 'a,
        IW: IntoIterator,
        IW::Item: Borrow<B::Semaphore>,
    {
        present_queue.present(Some(self), wait_semaphores)
    }
}
<commit_msg>Add missing builder method<commit_after>//! Windowing system interoperability
//!
//! Screen presentation (fullscreen or window) of images requires two objects:
//!
//! * [`Surface`] is the host abstraction of the native screen
//! * [`Swapchain`] is the device abstraction for a surface, containing multiple presentable images
//!
//! ## Window
//!
//! // DOC TODO
//!
//! ## Surface
//!
//! // DOC TODO
//!
//! ## Swapchain
//!
//! The most interesting part of a swapchain are the contained presentable images/backbuffers.
//! Presentable images are specialized images, which can be presented on the screen. They are
//! 2D color images with optionally associated depth-stencil images.
//!
//! The common steps for presentation of a frame are acquisition and presentation:
//!
//! ```no_run
//! # extern crate gfx_backend_empty as empty;
//! # extern crate gfx_hal;
//! # fn main() {
//! use gfx_hal::{Device, FrameSync};
//! # use gfx_hal::{CommandQueue, Graphics, Swapchain};
//!
//! # let mut swapchain: empty::Swapchain = return;
//! # let device: empty::Device = return;
//! # let mut present_queue: CommandQueue<empty::Backend, Graphics> = return;
//! let acquisition_semaphore = device.create_semaphore();
//! let render_semaphore = device.create_semaphore();
//!
//! let frame = swapchain.acquire_frame(FrameSync::Semaphore(&acquisition_semaphore));
//! // render the scene..
//! // `render_semaphore` will be signalled once rendering has been finished
//! swapchain.present(&mut present_queue, &[render_semaphore]);
//! # }
//! ```
//!
//! Queues need to synchronize with the presentation engine, usually done via signalling a semaphore
//! once a frame is available for rendering and waiting on a separate semaphore until scene rendering
//! has finished.
//!
//! ### Recreation
//!
//! DOC TODO

use Backend;
use image;
use format::Format;
use queue::CommandQueue;

use std::any::Any;
use std::borrow::{Borrow, BorrowMut};
use std::ops::Range;

/// An extent describes the size of a rectangle, such as
/// a window or texture. It is not used for referring to a
/// sub-rectangle; for that see `command::Rect`.
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Extent2D {
    /// Width
    pub width: image::Size,
    /// Height
    pub height: image::Size,
}

impl From<image::Extent> for Extent2D {
    fn from(ex: image::Extent) -> Self {
        Extent2D {
            width: ex.width,
            height: ex.height,
        }
    }
}

/// Describes information about what a `Surface`'s properties are.
/// Fetch this with `surface.capabilities_and_formats(device)`.
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SurfaceCapabilities {
    /// Number of presentable images supported by the adapter for a swapchain
    /// created from this surface.
    ///
    /// - `image_count.start` must be at least 1.
    /// - `image_count.end` must be larger of equal to `image_count.start`.
    pub image_count: Range<u32>,

    /// Current extent of the surface.
    ///
    /// `None` if the surface has no explicit size, depending on the swapchain extent.
    pub current_extent: Option<Extent2D>,

    /// Range of supported extents.
    ///
    /// `current_extent` must be inside this range.
    pub extents: Range<Extent2D>,

    /// Maximum number of layers supported for presentable images.
    ///
    /// Must be at least 1.
    pub max_image_layers: u32,
}

/// A `Surface` abstracts the surface of a native window, which will be presented
/// on the display.
pub trait Surface<B: Backend>: Any + Send + Sync {
    /// Retrieve the surface image kind.
    fn kind(&self) -> image::Kind;

    /// Check if the queue family supports presentation to this surface.
    ///
    /// # Examples
    ///
    /// ```no_run
    ///
    /// ```
    fn supports_queue_family(&self, family: &B::QueueFamily) -> bool;

    /// Query surface capabilities and formats for this physical device.
    ///
    /// Use this function for configuring swapchain creation.
    ///
    /// Returns a tuple of surface capabilities and formats.
    /// If formats is `None` than the surface has no preferred format and the
    /// application may use any desired format.
    fn capabilities_and_formats(&self, physical_device: &B::PhysicalDevice) -> (SurfaceCapabilities, Option<Vec<Format>>);
}

/// Handle to a backbuffer of the swapchain.
///
/// The swapchain is a series of one or more images, usually
/// with one being drawn on while the other is displayed by
/// the GPU (aka double-buffering). A `Frame` refers to a
/// particular image in the swapchain.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Frame(pub(crate) usize);

impl Frame {
    /// Retrieve frame id.
    ///
    /// The can be used to access the currently used backbuffer image
    /// in `Backbuffer::Images`.
    ///
    /// # Examples
    ///
    /// ```no_run
    ///
    /// ```
    pub fn id(&self) -> usize {
        self.0
    }
}

/// Synchronization primitives which will be signalled once a frame got retrieved.
///
/// The semaphore or fence _must_ be unsignalled.
pub enum FrameSync<'a, B: Backend> {
    /// Semaphore used for synchronization.
    ///
    /// Will be signaled once the frame backbuffer is available.
    Semaphore(&'a B::Semaphore),

    /// Fence used for synchronization.
    ///
    /// Will be signaled once the frame backbuffer is available.
    Fence(&'a B::Fence),
}

/// Contains all the data necessary to create a new `Swapchain`:
/// color, depth, and number of images.
///
/// # Examples
///
/// This type implements the builder pattern, method calls can be
/// easily chained.
///
/// ```no_run
/// # extern crate gfx_hal;
/// # fn main() {
/// # use gfx_hal::{SwapchainConfig};
/// # use gfx_hal::format::Format;
/// let config = SwapchainConfig::new()
///     .with_color(Format::Bgra8Unorm)
///     .with_depth_stencil(Format::D16Unorm)
///     .with_image_count(2);
/// # }
/// ```
#[derive(Debug, Clone)]
pub struct SwapchainConfig {
    /// Color format of the backbuffer images.
    pub color_format: Format,
    /// Depth stencil format of the backbuffer images (optional).
    pub depth_stencil_format: Option<Format>,
    /// Number of images in the swapchain.
    pub image_count: u32,
    /// Image usage of the backbuffer images.
    pub image_usage: image::Usage,
}

impl SwapchainConfig {
    /// Create a new default configuration (color images only).
    ///
    /// # Examples
    ///
    /// ```no_run
    ///
    /// ```
    pub fn new() -> Self {
        SwapchainConfig {
            color_format: Format::Bgra8Unorm, // TODO: try to find best default format
            depth_stencil_format: None,
            image_count: 2,
            image_usage: image::Usage::empty(),
        }
    }

    /// Specify the color format for the backbuffer images.
    ///
    /// # Examples
    ///
    /// ```no_run
    ///
    /// ```
    pub fn with_color(mut self, cf: Format) -> Self {
        self.color_format = cf;
        self
    }

    /// Specify the depth stencil format for the backbuffer images.
    ///
    /// The Swapchain will create additional depth-stencil images for each backbuffer.
    ///
    /// # Examples
    ///
    /// ```no_run
    ///
    /// ```
    pub fn with_depth_stencil(mut self, dsf: Format) -> Self {
        self.depth_stencil_format = Some(dsf);
        self
    }

    /// Specify the requested number of backbuffer images.
    ///
    /// The implementation may choose to create more if necessary.
    ///
    /// # Examples
    ///
    /// ```no_run
    ///
    /// ```
    pub fn with_image_count(mut self, count: u32) -> Self {
        self.image_count = count;
        self
    }

    /// Specify the usage of backbuffer images.
    ///
    /// # Examples
    ///
    /// ```no_run
    ///
    /// ```
    pub fn with_image_usage(mut self, usage: image::Usage) -> Self {
        self.image_usage = usage;
        self
    }

    // TODO: depth-only, stencil-only, swapchain size, present modes, etc.
}

/// Swapchain backbuffer type
#[derive(Debug)]
pub enum Backbuffer<B: Backend> {
    /// Color image chain
    Images(Vec<B::Image>),
    /// A single opaque framebuffer
    Framebuffer(B::Framebuffer),
}

/// The `Swapchain` is the backend representation of the surface.
/// It consists of multiple buffers, which will be presented on the surface.
pub trait Swapchain<B: Backend>: Any + Send + Sync {
    /// Acquire a new frame for rendering. This needs to be called before presenting.
    ///
    /// # Synchronization
    ///
    /// The acquired image will not be immediately available when the function returns.
    /// Once available the underlying primitive of `sync` will be signaled.
    /// This can either be a [`Semaphore`](../trait.Resources.html#associatedtype.Semaphore)
    /// or a [`Fence`](../trait.Resources.html#associatedtype.Fence).
    ///
    /// # Examples
    ///
    /// ```no_run
    ///
    /// ```
    fn acquire_frame(&mut self, sync: FrameSync<B>) -> Frame;

    /// Present one acquired frame in FIFO order.
    ///
    /// # Safety
    ///
    /// The passed queue _must_ support presentation on the surface, which is
    /// used for creating this swapchain.
    ///
    /// # Examples
    ///
    /// ```no_run
    ///
    /// ```
    fn present<'a, C, IW>(
        &'a mut self,
        present_queue: &mut CommandQueue<B, C>,
        wait_semaphores: IW,
    )
    where
        &'a mut Self: BorrowMut<B::Swapchain>,
        Self: Sized + 'a,
        IW: IntoIterator,
        IW::Item: Borrow<B::Semaphore>,
    {
        present_queue.present(Some(self), wait_semaphores)
    }
}
<|endoftext|>