<commit_before>use std::io;
use std::net::SocketAddr;
use std::collections::VecDeque;
use time::{get_time, Timespec};

use mio;

use super::messages::RawMessage;

use super::node::RequestData;
use super::crypto::PublicKey;

mod network;
mod connection;

pub use self::network::{Network, NetworkConfiguration, PeerId, EventSet, Output};

pub type EventsConfiguration = mio::EventLoopConfig;

pub type EventLoop = mio::EventLoop<MioAdapter>;

// FIXME: move this into node module
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum NodeTimeout {
    Status,
    Round(u64, u32),
    Request(RequestData, Option<PublicKey>),
    PeerExchange,
}

#[derive(PartialEq, Eq, Clone)]
pub enum InternalTimeout {
    Reconnect(SocketAddr, u64),
}

#[derive(PartialEq, Eq, Clone)]
pub enum Timeout {
    Node(NodeTimeout),
    Internal(InternalTimeout),
}

pub struct InternalMessage;

pub enum Event {
    Incoming(RawMessage),
    Internal(InternalMessage),
    Connected(SocketAddr),
    Disconnected(SocketAddr),
    Timeout(NodeTimeout),
    Error(io::Error),
    Terminate,
}

pub struct Events {
    event_loop: EventLoop,
    queue: MioAdapter,
}

pub struct MioAdapter {
    events: VecDeque<Event>,
    network: Network,
}

impl MioAdapter {
    fn new(network: Network) -> MioAdapter {
        MioAdapter {
            // FIXME: configurable capacity?
            events: VecDeque::new(),
            network: network,
        }
    }

    fn push(&mut self, event: Event) {
        self.events.push_back(event)
    }

    fn pop(&mut self) -> Option<Event> {
        self.events.pop_front()
    }
}

impl mio::Handler for MioAdapter {
    type Timeout = Timeout;
    type Message = InternalMessage;

    fn ready(&mut self, event_loop: &mut EventLoop, token: mio::Token, events: mio::EventSet) {
        // TODO: remove unwrap here
        while let Some(output) = self.network.io(event_loop, token, events).unwrap() {
            let event = match output {
                Output::Data(buf) => Event::Incoming(RawMessage::new(buf)),
                Output::Connected(addr) => Event::Connected(addr),
                Output::Disconnected(addr) => Event::Disconnected(addr),
            };
            self.push(event);
        }
    }

    fn notify(&mut self, _: &mut EventLoop, msg: Self::Message) {
        self.push(Event::Internal(msg));
    }

    fn timeout(&mut self, event_loop: &mut EventLoop, timeout: Self::Timeout) {
        match timeout {
            Timeout::Node(timeout) => {
                self.push(Event::Timeout(timeout));
            }
            Timeout::Internal(timeout) => {
                self.network.handle_timeout(event_loop, timeout);
            }
        }

    }

    fn interrupted(&mut self, _: &mut EventLoop) {
        self.push(Event::Terminate);
    }

    fn tick(&mut self, event_loop: &mut EventLoop) {
        self.network.tick(event_loop);
    }
}

pub trait Reactor {
    fn get_time(&self) -> Timespec;
    fn poll(&mut self) -> Event;
    fn bind(&mut self) -> ::std::io::Result<()>;
    fn send_to(&mut self, address: &SocketAddr, message: RawMessage);
    fn address(&self) -> SocketAddr;
    fn add_timeout(&mut self, timeout: NodeTimeout, time: Timespec);
}

impl Events {
    pub fn with_config(config: EventsConfiguration, network: Network) -> io::Result<Events> {
        // TODO: using EventLoopConfig + capacity of queue
        Ok(Events {
            event_loop: EventLoop::configured(config)?,
            queue: MioAdapter::new(network),
        })
    }
}

impl Reactor for Events {
    fn get_time(&self) -> Timespec {
        get_time()
    }

    fn poll(&mut self) -> Event {
        loop {
            if let Some(event) = self.queue.pop() {
                return event;
            }
            if let Err(err) = self.event_loop.run_once(&mut self.queue, None) {
                self.queue.push(Event::Error(err))
            }
        }
    }

    fn bind(&mut self) -> ::std::io::Result<()> {
        self.queue.network.bind(&mut self.event_loop)
    }

    fn send_to(&mut self, address: &SocketAddr, message: RawMessage) {
        self.queue.network.send_to(&mut self.event_loop, address, message)
    }

    fn address(&self) -> SocketAddr {
        *self.queue.network.address()
    }

    fn add_timeout(&mut self, timeout: NodeTimeout, time: Timespec) {
        let ms = (time - self.get_time()).num_milliseconds();
        if ms < 0 {
            self.queue.push(Event::Timeout(timeout))
        } else {
            // FIXME: remove unwrap here
            // TODO: use mio::Timeout
            self.event_loop.timeout_ms(Timeout::Node(timeout), ms as u64).unwrap();
        }
    }
}

#[cfg(test)]
mod tests {
    use std::{time, thread};
    use std::net::SocketAddr;

    use time::Duration;

    use super::{Events, Reactor, EventsConfiguration, Event, NodeTimeout};
    use super::{Network, NetworkConfiguration};

    use ::messages::{MessageWriter, RawMessage};
    use ::crypto::gen_keypair;

    impl Events {
        fn with_addr(addr: SocketAddr) -> Events {
            let network = Network::with_config(NetworkConfiguration {
                listen_address: addr,
                max_connections: 256,
                tcp_nodelay: true,
                tcp_keep_alive: None,
                tcp_reconnect_timeout: 1000,
                tcp_reconnect_timeout_max: 600000,
            });
            Events::with_config(EventsConfiguration::new(), network).unwrap()
        }

        fn wait_for_msg(&mut self, timeout: Duration) -> Option<RawMessage> {
            let time = self.get_time() + timeout;
            self.add_timeout(NodeTimeout::Status, time);
            loop {
                match self.poll() {
                    Event::Incoming(msg) => return Some(msg),
                    Event::Timeout(_) => return None,
                    Event::Error(_) => return None,
                    _ => {}
                }
            }
        }

        fn wait_for_bind(&mut self) {
            self.bind().unwrap();
            thread::sleep(time::Duration::from_millis(1000));
        }

        fn process_events(&mut self, timeout: Duration) {
            let time = self.get_time() + timeout;
            self.add_timeout(NodeTimeout::Status, time);
            loop {
                match self.poll() {
                    Event::Timeout(_) => break,
                    Event::Error(_) => return,
                    _ => {}
                }
            }
        }
    }

    fn gen_message(id: u16, len: usize) -> RawMessage {
        let writer = MessageWriter::new(id, len);
        RawMessage::new(writer.sign(&gen_keypair().1))
    }

    #[test]
    fn big_message() {
        let addrs: [SocketAddr; 2] = ["127.0.0.1:8200".parse().unwrap(),
                                      "127.0.0.1:8201".parse().unwrap()];

        let m1 = gen_message(15, 1000000);
        let m2 = gen_message(16, 400);

        let t1;
        {
            let m1 = m1.clone();
            let m2 = m2.clone();
            t1 = thread::spawn(move || {
                let mut e = Events::with_addr(addrs[0].clone());
                e.wait_for_bind();
                e.send_to(&addrs[1], m1);
                assert_eq!(e.wait_for_msg(Duration::milliseconds(1000)), Some(m2));
                e.process_events(Duration::milliseconds(10000));
            });
        }

        let t2;
        {
            let m1 = m1.clone();
            let m2 = m2.clone();
            t2 = thread::spawn(move || {
                let mut e = Events::with_addr(addrs[1].clone());
                e.wait_for_bind();
                e.send_to(&addrs[0], m2);
                assert_eq!(e.wait_for_msg(Duration::milliseconds(30000)), Some(m1));
            });
        }

        t2.join().unwrap();
        t1.join().unwrap();
    }

    #[test]
    fn reconnect() {
        let addrs: [SocketAddr; 2] = ["127.0.0.1:9000".parse().unwrap(),
                                      "127.0.0.1:9001".parse().unwrap()];

        let m1 = gen_message(15, 250);
        let m2 = gen_message(16, 400);
        let m3 = gen_message(17, 600);

        let t1;
        {
            let m1 = m1.clone();
            let m2 = m2.clone();
            let m3 = m3.clone();
            t1 = thread::spawn(move || {
                {
                    let mut e = Events::with_addr(addrs[0].clone());
                    e.wait_for_bind();
                    println!("t1: connection opened");
                    println!("t1: send m1 to t2");
                    e.send_to(&addrs[1], m1);
                    println!("t1: wait for m2");
                    assert_eq!(e.wait_for_msg(Duration::milliseconds(5000)), Some(m2));
                    println!("t1: received m2 from t2");
                    e.process_events(Duration::milliseconds(100));
                }
                println!("t1: connection closed");
                {
                    let mut e = Events::with_addr(addrs[0].clone());
                    e.wait_for_bind();
                    println!("t1: connection reopened");
                    println!("t1: send m3 to t2");
                    e.send_to(&addrs[1], m3.clone());
                    println!("t1: wait for m3");
                    assert_eq!(e.wait_for_msg(Duration::milliseconds(5000)), Some(m3));
                    e.process_events(Duration::milliseconds(100));
                    println!("t1: received m3 from t2");
                }
                println!("t1: connection closed");
            });
        }

        let t2;
        {
            let m1 = m1.clone();
            let m2 = m2.clone();
            let m3 = m3.clone();
            t2 = thread::spawn(move || {
                {
                    let mut e = Events::with_addr(addrs[1].clone());
                    e.wait_for_bind();
                    println!("t2: connection opened");
                    println!("t2: send m2 to t1");
                    e.send_to(&addrs[0], m2);
                    println!("t2: wait for m1");
                    assert_eq!(e.wait_for_msg(Duration::milliseconds(5000)), Some(m1));
                    println!("t2: received m1 from t1");
                    println!("t2: wait for m3");
                    assert_eq!(e.wait_for_msg(Duration::milliseconds(5000)),
                               Some(m3.clone()));
                    println!("t2: received m3 from t1");
                    e.process_events(Duration::milliseconds(100));
                    drop(e);
                }
                println!("t2: connection closed");
                {
                    println!("t2: connection reopened");
                    let mut e = Events::with_addr(addrs[1].clone());
                    e.wait_for_bind();
                    println!("t2: send m3 to t1");
                    e.send_to(&addrs[0], m3.clone());
                    e.process_events(Duration::milliseconds(100));
                }
                println!("t2: connection closed");
            });
        }

        t2.join().unwrap();
        t1.join().unwrap();
    }
}
<commit_msg>Handle all io errors without unwrap<commit_after>use std::io;
use std::net::SocketAddr;
use std::collections::VecDeque;
use time::{get_time, Timespec};

use mio;

use super::messages::RawMessage;

use super::node::RequestData;
use super::crypto::PublicKey;

mod network;
mod connection;

pub use self::network::{Network, NetworkConfiguration, PeerId, EventSet, Output};

pub type EventsConfiguration = mio::EventLoopConfig;

pub type EventLoop = mio::EventLoop<MioAdapter>;

// FIXME: move this into node module
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum NodeTimeout {
    Status,
    Round(u64, u32),
    Request(RequestData, Option<PublicKey>),
    PeerExchange,
}

#[derive(PartialEq, Eq, Clone)]
pub enum InternalTimeout {
    Reconnect(SocketAddr, u64),
}

#[derive(PartialEq, Eq, Clone)]
pub enum Timeout {
    Node(NodeTimeout),
    Internal(InternalTimeout),
}

pub struct InternalMessage;

pub enum Event {
    Incoming(RawMessage),
    Internal(InternalMessage),
    Connected(SocketAddr),
    Disconnected(SocketAddr),
    Timeout(NodeTimeout),
    Error(io::Error),
    Terminate,
}

pub struct Events {
    event_loop: EventLoop,
    queue: MioAdapter,
}

pub struct MioAdapter {
    events: VecDeque<Event>,
    network: Network,
}

impl MioAdapter {
    fn new(network: Network) -> MioAdapter {
        MioAdapter {
            // FIXME: configurable capacity?
            events: VecDeque::new(),
            network: network,
        }
    }

    fn push(&mut self, event: Event) {
        self.events.push_back(event)
    }

    fn pop(&mut self) -> Option<Event> {
        self.events.pop_front()
    }
}

impl mio::Handler for MioAdapter {
    type Timeout = Timeout;
    type Message = InternalMessage;

    fn ready(&mut self, event_loop: &mut EventLoop, token: mio::Token, events: mio::EventSet) {
        loop {
            match self.network.io(event_loop, token, events) {
                Ok(Some(output)) => {
                    let event = match output {
                        Output::Data(buf) => Event::Incoming(RawMessage::new(buf)),
                        Output::Connected(addr) => Event::Connected(addr),
                        Output::Disconnected(addr) => Event::Disconnected(addr),
                    };
                    self.push(event);
                }
                Ok(None) => break,
                Err(e) => {
                    error!("{}: An error occured {:?}", self.network.address(), e);
                    break;
                }
            }
        }
    }

    fn notify(&mut self, _: &mut EventLoop, msg: Self::Message) {
        self.push(Event::Internal(msg));
    }

    fn timeout(&mut self, event_loop: &mut EventLoop, timeout: Self::Timeout) {
        match timeout {
            Timeout::Node(timeout) => {
                self.push(Event::Timeout(timeout));
            }
            Timeout::Internal(timeout) => {
                self.network.handle_timeout(event_loop, timeout);
            }
        }

    }

    fn interrupted(&mut self, _: &mut EventLoop) {
        self.push(Event::Terminate);
    }

    fn tick(&mut self, event_loop: &mut EventLoop) {
        self.network.tick(event_loop);
    }
}

pub trait Reactor {
    fn get_time(&self) -> Timespec;
    fn poll(&mut self) -> Event;
    fn bind(&mut self) -> ::std::io::Result<()>;
    fn send_to(&mut self, address: &SocketAddr, message: RawMessage);
    fn address(&self) -> SocketAddr;
    fn add_timeout(&mut self, timeout: NodeTimeout, time: Timespec);
}

impl Events {
    pub fn with_config(config: EventsConfiguration, network: Network) -> io::Result<Events> {
        // TODO: using EventLoopConfig + capacity of queue
        Ok(Events {
            event_loop: EventLoop::configured(config)?,
            queue: MioAdapter::new(network),
        })
    }
}

impl Reactor for Events {
    fn get_time(&self) -> Timespec {
        get_time()
    }

    fn poll(&mut self) -> Event {
        loop {
            if let Some(event) = self.queue.pop() {
                return event;
            }
            if let Err(err) = self.event_loop.run_once(&mut self.queue, None) {
                self.queue.push(Event::Error(err))
            }
        }
    }

    fn bind(&mut self) -> ::std::io::Result<()> {
        self.queue.network.bind(&mut self.event_loop)
    }

    fn send_to(&mut self, address: &SocketAddr, message: RawMessage) {
        self.queue.network.send_to(&mut self.event_loop, address, message)
    }

    fn address(&self) -> SocketAddr {
        *self.queue.network.address()
    }

    fn add_timeout(&mut self, timeout: NodeTimeout, time: Timespec) {
        let ms = (time - self.get_time()).num_milliseconds();
        if ms < 0 {
            self.queue.push(Event::Timeout(timeout))
        } else {
            // FIXME: remove unwrap here
            // TODO: use mio::Timeout
            self.event_loop.timeout_ms(Timeout::Node(timeout), ms as u64).unwrap();
        }
    }
}

#[cfg(test)]
mod tests {
    use std::{time, thread};
    use std::net::SocketAddr;

    use time::Duration;

    use super::{Events, Reactor, EventsConfiguration, Event, NodeTimeout};
    use super::{Network, NetworkConfiguration};

    use ::messages::{MessageWriter, RawMessage};
    use ::crypto::gen_keypair;

    impl Events {
        fn with_addr(addr: SocketAddr) -> Events {
            let network = Network::with_config(NetworkConfiguration {
                listen_address: addr,
                max_connections: 256,
                tcp_nodelay: true,
                tcp_keep_alive: None,
                tcp_reconnect_timeout: 1000,
                tcp_reconnect_timeout_max: 600000,
            });
            Events::with_config(EventsConfiguration::new(), network).unwrap()
        }

        fn wait_for_msg(&mut self, timeout: Duration) -> Option<RawMessage> {
            let time = self.get_time() + timeout;
            self.add_timeout(NodeTimeout::Status, time);
            loop {
                match self.poll() {
                    Event::Incoming(msg) => return Some(msg),
                    Event::Timeout(_) => return None,
                    Event::Error(_) => return None,
                    _ => {}
                }
            }
        }

        fn wait_for_bind(&mut self, addr: &SocketAddr) {
            self.bind().unwrap();
            thread::sleep(time::Duration::from_millis(1000));
        }

        fn process_events(&mut self, timeout: Duration) {
            let time = self.get_time() + timeout;
            self.add_timeout(NodeTimeout::Status, time);
            loop {
                match self.poll() {
                    Event::Timeout(_) => break,
                    Event::Error(_) => return,
                    _ => {}
                }
            }
        }
    }

    fn gen_message(id: u16, len: usize) -> RawMessage {
        let writer = MessageWriter::new(id, len);
        RawMessage::new(writer.sign(&gen_keypair().1))
    }

    #[test]
    fn big_message() {
        let addrs: [SocketAddr; 2] = ["127.0.0.1:8200".parse().unwrap(),
                                      "127.0.0.1:8201".parse().unwrap()];

        let m1 = gen_message(15, 1000000);
        let m2 = gen_message(16, 400);

        let t1;
        {
            let m1 = m1.clone();
            let m2 = m2.clone();
            t1 = thread::spawn(move || {
                let mut e = Events::with_addr(addrs[0].clone());
                e.wait_for_bind(&addrs[1]);

                e.send_to(&addrs[1], m1);
                assert_eq!(e.wait_for_msg(Duration::milliseconds(1000)), Some(m2));
                e.process_events(Duration::milliseconds(10000));
            });
        }

        let t2;
        {
            let m1 = m1.clone();
            let m2 = m2.clone();
            t2 = thread::spawn(move || {
                let mut e = Events::with_addr(addrs[1].clone());
                e.wait_for_bind(&addrs[0]);

                e.send_to(&addrs[0], m2);
                assert_eq!(e.wait_for_msg(Duration::milliseconds(30000)), Some(m1));
            });
        }

        t2.join().unwrap();
        t1.join().unwrap();
    }

    #[test]
    fn reconnect() {
        let addrs: [SocketAddr; 2] = ["127.0.0.1:9000".parse().unwrap(),
                                      "127.0.0.1:9001".parse().unwrap()];

        let m1 = gen_message(15, 250);
        let m2 = gen_message(16, 400);
        let m3 = gen_message(17, 600);

        let t1;
        {
            let m1 = m1.clone();
            let m2 = m2.clone();
            let m3 = m3.clone();
            t1 = thread::spawn(move || {
                {
                    let mut e = Events::with_addr(addrs[0].clone());
                    e.wait_for_bind(&addrs[1]);

                    println!("t1: connection opened");
                    println!("t1: send m1 to t2");
                    e.send_to(&addrs[1], m1);
                    println!("t1: wait for m2");
                    assert_eq!(e.wait_for_msg(Duration::milliseconds(5000)), Some(m2));
                    println!("t1: received m2 from t2");
                    e.process_events(Duration::milliseconds(100));
                }
                println!("t1: connection closed");
                {
                    let mut e = Events::with_addr(addrs[0].clone());
                    e.wait_for_bind(&addrs[1]);

                    println!("t1: connection reopened");
                    println!("t1: send m3 to t2");
                    e.send_to(&addrs[1], m3.clone());
                    println!("t1: wait for m3");
                    assert_eq!(e.wait_for_msg(Duration::milliseconds(5000)), Some(m3));
                    e.process_events(Duration::milliseconds(100));
                    println!("t1: received m3 from t2");
                }
                println!("t1: connection closed");
            });
        }

        let t2;
        {
            let m1 = m1.clone();
            let m2 = m2.clone();
            let m3 = m3.clone();
            t2 = thread::spawn(move || {
                {
                    let mut e = Events::with_addr(addrs[1].clone());
                    e.wait_for_bind(&addrs[0]);

                    println!("t2: connection opened");
                    println!("t2: send m2 to t1");
                    e.send_to(&addrs[0], m2);
                    println!("t2: wait for m1");
                    assert_eq!(e.wait_for_msg(Duration::milliseconds(5000)), Some(m1));
                    println!("t2: received m1 from t1");
                    println!("t2: wait for m3");
                    assert_eq!(e.wait_for_msg(Duration::milliseconds(5000)),
                               Some(m3.clone()));
                    println!("t2: received m3 from t1");
                    e.process_events(Duration::milliseconds(100));
                    drop(e);
                }
                println!("t2: connection closed");
                {
                    println!("t2: connection reopened");
                    let mut e = Events::with_addr(addrs[1].clone());
                    e.wait_for_bind(&addrs[0]);

                    println!("t2: send m3 to t1");
                    e.send_to(&addrs[0], m3.clone());
                    e.process_events(Duration::milliseconds(100));
                }
                println!("t2: connection closed");
            });
        }

        t2.join().unwrap();
        t1.join().unwrap();
    }
}
<|endoftext|>


<commit_before><commit_msg>Improved formatting.<commit_after><|endoftext|>


<commit_before>//! Details of the `#[ruma_api(...)]` attributes.

use syn::{
    parenthesized,
    parse::{Parse, ParseStream},
    Ident, Token,
};

/// Like syn::Meta, but only parses ruma_api attributes
pub enum Meta {
    /// A single word, like `query` in `#[ruma_api(query)]`
    Word(Ident),
    /// A name-value pair, like `header = CONTENT_TYPE` in `#[ruma_api(header = CONTENT_TYPE)]`
    NameValue(MetaNameValue),
}

impl Meta {
    pub fn from_attribute(attr: syn::Attribute) -> Result<Self, syn::Attribute> {
        match &attr.path {
            syn::Path {
                leading_colon: None,
                segments,
            } => {
                if segments.len() == 1 && segments[0].ident == "ruma_api" {
                    Ok(syn::parse2(attr.tts)
                        .expect("ruma_api! could not parse request field attributes"))
                } else {
                    Err(attr)
                }
            }
            _ => Err(attr),
        }
    }
}

/// Like syn::MetaNameValue, but expects an identifier as the value. Also, we don't care about the
/// the span of the equals sign, so we don't have the `eq_token` field from syn::MetaNameValue.
pub struct MetaNameValue {
    /// The part left of the equals sign
    pub name: Ident,
    /// The part right of the equals sign
    pub value: Ident,
}

impl Parse for Meta {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let content;
        let _ = parenthesized!(content in input);
        let ident = content.parse()?;

        if content.peek(Token![=]) {
            let _ = content.parse::<Token![=]>();
            Ok(Meta::NameValue(MetaNameValue {
                name: ident,
                value: content.parse()?,
            }))
        } else {
            Ok(Meta::Word(ident))
        }
    }
}
<commit_msg>Add documentation to Meta::from_attribute<commit_after>//! Details of the `#[ruma_api(...)]` attributes.

use syn::{
    parenthesized,
    parse::{Parse, ParseStream},
    Ident, Token,
};

/// Like syn::Meta, but only parses ruma_api attributes
pub enum Meta {
    /// A single word, like `query` in `#[ruma_api(query)]`
    Word(Ident),
    /// A name-value pair, like `header = CONTENT_TYPE` in `#[ruma_api(header = CONTENT_TYPE)]`
    NameValue(MetaNameValue),
}

impl Meta {
    /// Check if the given attribute is a ruma_api attribute. If it is, parse it, if not, return
    /// it unchanged. Panics if the argument is an invalid ruma_api attribute.
    pub fn from_attribute(attr: syn::Attribute) -> Result<Self, syn::Attribute> {
        match &attr.path {
            syn::Path {
                leading_colon: None,
                segments,
            } => {
                if segments.len() == 1 && segments[0].ident == "ruma_api" {
                    Ok(syn::parse2(attr.tts)
                        .expect("ruma_api! could not parse request field attributes"))
                } else {
                    Err(attr)
                }
            }
            _ => Err(attr),
        }
    }
}

/// Like syn::MetaNameValue, but expects an identifier as the value. Also, we don't care about the
/// the span of the equals sign, so we don't have the `eq_token` field from syn::MetaNameValue.
pub struct MetaNameValue {
    /// The part left of the equals sign
    pub name: Ident,
    /// The part right of the equals sign
    pub value: Ident,
}

impl Parse for Meta {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let content;
        let _ = parenthesized!(content in input);
        let ident = content.parse()?;

        if content.peek(Token![=]) {
            let _ = content.parse::<Token![=]>();
            Ok(Meta::NameValue(MetaNameValue {
                name: ident,
                value: content.parse()?,
            }))
        } else {
            Ok(Meta::Word(ident))
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>utilities for handling subscopes and comments<commit_after>fn scope_start(src:&str, point:uint) -> uint {
    let s = src.slice(0,point);
    let mut pt = point;
    let mut levels = 0;
    for c in s.chars_rev() {
        if c == '{' {
            if levels == 0 {
                break;
            } else {
                levels -= 1;
            }
        }
        if c == '}' {
            levels += 1;
        }
        pt -= 1;
    }
    return pt;
}

fn gen_mask(mut len: uint) -> ~str {
    let mut s = ~"";
    while len != 0 {
        len -=1;
        s.push_str(" ");
    }
    return s;
}

fn mask_comments(src:&str) -> ~str {
    let mut result = ~"";
    let mut s:&str = src;
    let mut in_comment = false;
    let mut res = s.find_str("//");
    let mut pos = 0;
    while res.is_some() {
        let end = res.unwrap();
        if in_comment {
            // mask out the comment
            result.push_str(gen_mask(end));
            s = s.slice_from(end);
            res = s.find_str("//");
            in_comment = false;
        } else {
            result.push_str(s.slice_to(end));
            s = s.slice_from(end);
            res = s.find_str("\n");
            in_comment = true;
        }
        pos += end;
    }
    result.push_str(src.slice_from(pos));
    return result;
}

fn mask_sub_scopes(src:&str) -> ~str {
    let mut result = ~"";
    let mut levels = 0;

    for c in src.chars() {
        println!("c:{}",c);
        if c == '}' {
            levels -= 1;
        }

        if c == '\n' {
            result.push_char(c);
        } else if levels > 0 {
            result.push_str(" ");
        } else {
            result.push_char(c);
        }

        if c == '{' {
            levels += 1;
        }
    }
    return result;
}

fn visible_scope(src:&str, point:uint) ->~str {
    let s = mask_comments(src);
    let n = scope_start(s, point);
    return mask_sub_scopes(s.slice(n,point));
}

fn coords_to_point(src:&str, mut linenum:uint, col:uint) -> uint {
    let mut point=0;
    for line in src.lines() {
        linenum -= 1;
        if linenum == 0 { break }
        point+=line.len() + 1;  // +1 for the \n
    }
    return point + col;
}

fn point_to_coords(src:&str, point:uint) -> (uint, uint) {
    let mut i = 0;
    let mut linestart = 0;
    let mut nlines = 1;  // lines start at 1
    while i != point {
        if src.char_at(i) == '\n' {
            nlines += 1;
            linestart = i+1;
        }
        i+=1;
    }
    return (nlines, point - linestart);
}

#[test]
fn coords_to_point_works() {
    let src = "
fn myfn() {
    let a = 3;
    print(a);
}";
    assert!(coords_to_point(src, 3, 5) == 18);
}

#[test]
fn test_scope_start() {
    let src = "
fn myfn() {
    let a = 3;
    print(a);
}
";
    let point = coords_to_point(src, 4, 10);
    let start = scope_start(src,point);
    assert!(start == 12);
}

#[test]
fn test_scope_start_handles_sub_scopes() {
    let src = "
fn myfn() {
    let a = 3;
    {
      let b = 4;
    }
    print(a);
}
";
    let point = coords_to_point(src, 7, 10);
    let start = scope_start(src,point);
    println!("PHIL {}",start);
    assert!(start == 12);
}

#[test]
fn masks_out_comments() {
    let src = "
this is some code
this is a line // with a comment
some more
";
    let r = mask_comments(src.to_owned());
    assert!(src.len() == r.len());
    // characters at the start are the same
    assert!(src[5] == r[5]);
    // characters in the comments are masked
    let commentoffset = coords_to_point(src,3,23);
    assert!(r.char_at(commentoffset) == ' ');
    assert!(src[commentoffset] != r[commentoffset]);
    // characters afterwards are the same
    assert!(src[src.len()-3] == r[src.len()-3]);
}

#[test]
fn masks_out_sub_scopes() {
    let src = "
this is some code
{
  this is a sub-scope
  {
    so is this
  }
  and this
}
some more code
";
    let expected = "
this is some code
{

}
some more code
";
    let res = mask_sub_scopes(src);
    println!("PHIL{}",expected);
    println!("PHIL{}",res);
    println!("PHIL");
    assert!(expected == res);
}

#[test]
fn test_point_to_coords() {
    let src = "
fn myfn(b:uint) {
   let a = 3;
   if b == 12 {
       let a = 24;
       do_something_with(a);
   }
   do_something_with(a);
}
";
    round_trip_point_and_coords(src, 4, 5);
}

fn round_trip_point_and_coords(src:&str, lineno:uint, charno:uint) {
    let (a,b) = point_to_coords(src, coords_to_point(src, lineno, charno));
    println!("PHIL{}",(a,b));
    assert!((a,b) == (lineno,charno));
}

#[test]
fn generates_the_visible_scope() {
    let src = "
fn myfn(b:uint) {
   let a = 3;
   if b == 12 {
       let a = 24;
       do_something_with(a);
   }
   do_something_with(a);
}
";
    let expected = "
   let a = 3;
   if b == 12 {

   }
   do_something_with(";

    let res = visible_scope(src, coords_to_point(src,8,21));
    assert!(expected == res);
}
<|endoftext|>


<commit_before><commit_msg>Change the native_thread interface<commit_after><|endoftext|>


<commit_before><commit_msg>Minor typo.<commit_after><|endoftext|>


<commit_before><commit_msg>ncpus tested<commit_after><|endoftext|>


<commit_before><commit_msg>Add testcase for reading multiple lines<commit_after><|endoftext|>


<commit_before><commit_msg>Publish unsubscribe message even if the subscription didnt exist<commit_after><|endoftext|>


<commit_before><commit_msg>am bbcf2079: Merge "Fix struct initializer for balls." into honeycomb<commit_after><|endoftext|>


<commit_before>#![allow(non_camel_case_types)]
// FIXME ^ should be removed

use pyffi::*;
use libc::FILE;

pub type npy_intp = Py_intptr_t;
pub type npy_hash_t = Py_hash_t;

#[repr(u32)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_CLIPMODE {
    NPY_CLIP = 0,
    NPY_WRAP = 1,
    NPY_RAISE = 2,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct _object {
    pub ob_refcnt: Py_ssize_t,
    pub ob_type: *mut PyTypeObject,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyMethodDef {
    pub ml_name: *const ::std::os::raw::c_char,
    pub ml_meth: PyCFunction,
    pub ml_flags: ::std::os::raw::c_int,
    pub ml_doc: *const ::std::os::raw::c_char,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct PyArrayFlagsObject {
    pub ob_base: PyObject,
    pub arr: *mut PyObject,
    pub flags: ::std::os::raw::c_int,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct PyArray_Dims {
    pub ptr: *mut npy_intp,
    pub len: ::std::os::raw::c_int,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct PyArray_Chunk {
    pub ob_base: PyObject,
    pub base: *mut PyObject,
    pub ptr: *mut ::std::os::raw::c_void,
    pub len: npy_intp,
    pub flags: ::std::os::raw::c_int,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyArray_Descr {
    pub ob_base: PyObject,
    pub typeobj: *mut PyTypeObject,
    pub kind: ::std::os::raw::c_char,
    pub type_: ::std::os::raw::c_char,
    pub byteorder: ::std::os::raw::c_char,
    pub flags: ::std::os::raw::c_char,
    pub type_num: ::std::os::raw::c_int,
    pub elsize: ::std::os::raw::c_int,
    pub alignment: ::std::os::raw::c_int,
    pub subarray: *mut _PyArray_Descr__arr_descr,
    pub fields: *mut PyObject,
    pub names: *mut PyObject,
    pub f: *mut PyArray_ArrFuncs,
    pub metadata: *mut PyObject,
    pub c_metadata: *mut NpyAuxData,
    pub hash: npy_hash_t,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyMemberDef([u8; 0]);

#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyTypeObject {
    pub ob_base: PyVarObject,
    pub tp_name: *const ::std::os::raw::c_char,
    pub tp_basicsize: Py_ssize_t,
    pub tp_itemsize: Py_ssize_t,
    pub tp_dealloc: destructor,
    pub tp_print: printfunc,
    pub tp_getattr: getattrfunc,
    pub tp_setattr: setattrfunc,
    pub tp_as_async: *mut PyAsyncMethods,
    pub tp_repr: reprfunc,
    pub tp_as_number: *mut PyNumberMethods,
    pub tp_as_sequence: *mut PySequenceMethods,
    pub tp_as_mapping: *mut PyMappingMethods,
    pub tp_hash: hashfunc,
    pub tp_call: ternaryfunc,
    pub tp_str: reprfunc,
    pub tp_getattro: getattrofunc,
    pub tp_setattro: setattrofunc,
    pub tp_as_buffer: *mut PyBufferProcs,
    pub tp_flags: ::std::os::raw::c_ulong,
    pub tp_doc: *const ::std::os::raw::c_char,
    pub tp_traverse: traverseproc,
    pub tp_clear: inquiry,
    pub tp_richcompare: richcmpfunc,
    pub tp_weaklistoffset: Py_ssize_t,
    pub tp_iter: getiterfunc,
    pub tp_iternext: iternextfunc,
    pub tp_methods: *mut PyMethodDef,
    pub tp_members: *mut PyMemberDef,
    pub tp_getset: *mut PyGetSetDef,
    pub tp_base: *mut PyTypeObject,
    pub tp_dict: *mut PyObject,
    pub tp_descr_get: descrgetfunc,
    pub tp_descr_set: descrsetfunc,
    pub tp_dictoffset: Py_ssize_t,
    pub tp_init: initproc,
    pub tp_alloc: allocfunc,
    pub tp_new: newfunc,
    pub tp_free: freefunc,
    pub tp_is_gc: inquiry,
    pub tp_bases: *mut PyObject,
    pub tp_mro: *mut PyObject,
    pub tp_cache: *mut PyObject,
    pub tp_subclasses: *mut PyObject,
    pub tp_weaklist: *mut PyObject,
    pub tp_del: destructor,
    pub tp_version_tag: ::std::os::raw::c_uint,
    pub tp_finalize: destructor,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyArrayObject {
    pub ob_base: PyObject,
    pub data: *mut ::std::os::raw::c_char,
    pub nd: ::std::os::raw::c_int,
    pub dimensions: *mut npy_intp,
    pub strides: *mut npy_intp,
    pub base: *mut PyObject,
    pub descr: *mut PyArray_Descr,
    pub flags: ::std::os::raw::c_int,
    pub weakreflist: *mut PyObject,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct _PyArray_Descr__arr_descr {
    pub base: *mut PyArray_Descr,
    pub shape: *mut PyObject,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyArray_ArrFuncs {
    pub cast: [PyArray_VectorUnaryFunc; 21usize],
    pub getitem: PyArray_GetItemFunc,
    pub setitem: PyArray_SetItemFunc,
    pub copyswapn: PyArray_CopySwapNFunc,
    pub copyswap: PyArray_CopySwapFunc,
    pub compare: PyArray_CompareFunc,
    pub argmax: PyArray_ArgFunc,
    pub dotfunc: PyArray_DotFunc,
    pub scanfunc: PyArray_ScanFunc,
    pub fromstr: PyArray_FromStrFunc,
    pub nonzero: PyArray_NonzeroFunc,
    pub fill: PyArray_FillFunc,
    pub fillwithscalar: PyArray_FillWithScalarFunc,
    pub sort: [PyArray_SortFunc; 3usize],
    pub argsort: [PyArray_ArgSortFunc; 3usize],
    pub castdict: *mut PyObject,
    pub scalarkind: PyArray_ScalarKindFunc,
    pub cancastscalarkindto: *mut *mut ::std::os::raw::c_int,
    pub cancastto: *mut ::std::os::raw::c_int,
    pub fastclip: PyArray_FastClipFunc,
    pub fastputmask: PyArray_FastPutmaskFunc,
    pub fasttake: PyArray_FastTakeFunc,
    pub argmin: PyArray_ArgFunc,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct NpyAuxData {
    pub free: NpyAuxData_FreeFunc,
    pub clone: NpyAuxData_CloneFunc,
    pub reserved: [*mut ::std::os::raw::c_void; 2usize],
}

pub type PyArray_GetItemFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: *mut ::std::os::raw::c_void)
                                                 -> *mut _object>;
pub type PyArray_SetItemFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut PyObject,
                                                 arg2: *mut ::std::os::raw::c_void,
                                                 arg3: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_CopySwapNFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: npy_intp,
                                                 arg3: *mut ::std::os::raw::c_void,
                                                 arg4: npy_intp,
                                                 arg5: npy_intp,
                                                 arg6: ::std::os::raw::c_int,
                                                 arg7: *mut ::std::os::raw::c_void)>;
pub type PyArray_CopySwapFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: *mut ::std::os::raw::c_void,
                                                 arg3: ::std::os::raw::c_int,
                                                 arg4: *mut ::std::os::raw::c_void)>;
pub type PyArray_NonzeroFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_uchar>;
pub type PyArray_CompareFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *const ::std::os::raw::c_void,
                                                 arg2: *const ::std::os::raw::c_void,
                                                 arg3: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_ArgFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: npy_intp,
                                                 arg3: *mut npy_intp,
                                                 arg4: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_DotFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: npy_intp,
                                                 arg3: *mut ::std::os::raw::c_void,
                                                 arg4: npy_intp,
                                                 arg5: *mut ::std::os::raw::c_void,
                                                 arg6: npy_intp,
                                                 arg7: *mut ::std::os::raw::c_void)>;
pub type PyArray_VectorUnaryFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: *mut ::std::os::raw::c_void,
                                                 arg3: npy_intp,
                                                 arg4: *mut ::std::os::raw::c_void,
                                                 arg5: *mut ::std::os::raw::c_void)>;
pub type PyArray_ScanFunc =
    ::std::option::Option<unsafe extern "C" fn(fp: *mut FILE,
                                                 dptr: *mut ::std::os::raw::c_void,
                                                 ignore: *mut ::std::os::raw::c_char,
                                                 arg1: *mut PyArray_Descr)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_FromStrFunc =
    ::std::option::Option<unsafe extern "C" fn(s: *mut ::std::os::raw::c_char,
                                                 dptr: *mut ::std::os::raw::c_void,
                                                 endptr: *mut *mut ::std::os::raw::c_char,
                                                 arg1: *mut PyArray_Descr)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_FillFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: npy_intp,
                                                 arg3: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_SortFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: npy_intp,
                                                 arg3: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_ArgSortFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: *mut npy_intp,
                                                 arg3: npy_intp,
                                                 arg4: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_PartitionFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: npy_intp,
                                                 arg3: npy_intp,
                                                 arg4: *mut npy_intp,
                                                 arg5: *mut npy_intp,
                                                 arg6: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_ArgPartitionFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: *mut npy_intp,
                                                 arg3: npy_intp,
                                                 arg4: npy_intp,
                                                 arg5: *mut npy_intp,
                                                 arg6: *mut npy_intp,
                                                 arg7: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_FillWithScalarFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: npy_intp,
                                                 arg3: *mut ::std::os::raw::c_void,
                                                 arg4: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_ScalarKindFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_FastClipFunc =
    ::std::option::Option<unsafe extern "C" fn(in_: *mut ::std::os::raw::c_void,
                                                 n_in: npy_intp,
                                                 min: *mut ::std::os::raw::c_void,
                                                 max: *mut ::std::os::raw::c_void,
                                                 out: *mut ::std::os::raw::c_void)>;
pub type PyArray_FastPutmaskFunc =
    ::std::option::Option<unsafe extern "C" fn(in_: *mut ::std::os::raw::c_void,
                                                 mask: *mut ::std::os::raw::c_void,
                                                 n_in: npy_intp,
                                                 values: *mut ::std::os::raw::c_void,
                                                 nv: npy_intp)>;
pub type PyArray_FastTakeFunc =
    ::std::option::Option<unsafe extern "C" fn(dest: *mut ::std::os::raw::c_void,
                                                 src: *mut ::std::os::raw::c_void,
                                                 indarray: *mut npy_intp,
                                                 nindarray: npy_intp,
                                                 n_outer: npy_intp,
                                                 m_middle: npy_intp,
                                                 nelem: npy_intp,
                                                 clipmode: NPY_CLIPMODE)
                                                 -> ::std::os::raw::c_int>;
pub type NpyAuxData_FreeFunc = ::std::option::Option<unsafe extern "C" fn(arg1: *mut NpyAuxData)>;
pub type NpyAuxData_CloneFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut NpyAuxData) -> *mut NpyAuxData>;
<commit_msg>PyArrayInterface<commit_after>#![allow(non_camel_case_types)]
// FIXME ^ should be removed

use pyffi::*;
use libc::FILE;

pub type npy_intp = Py_intptr_t;
pub type npy_hash_t = Py_hash_t;

#[repr(u32)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub enum NPY_CLIPMODE {
    NPY_CLIP = 0,
    NPY_WRAP = 1,
    NPY_RAISE = 2,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct _object {
    pub ob_refcnt: Py_ssize_t,
    pub ob_type: *mut PyTypeObject,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyMethodDef {
    pub ml_name: *const ::std::os::raw::c_char,
    pub ml_meth: PyCFunction,
    pub ml_flags: ::std::os::raw::c_int,
    pub ml_doc: *const ::std::os::raw::c_char,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct PyArrayFlagsObject {
    pub ob_base: PyObject,
    pub arr: *mut PyObject,
    pub flags: ::std::os::raw::c_int,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct PyArray_Dims {
    pub ptr: *mut npy_intp,
    pub len: ::std::os::raw::c_int,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct PyArray_Chunk {
    pub ob_base: PyObject,
    pub base: *mut PyObject,
    pub ptr: *mut ::std::os::raw::c_void,
    pub len: npy_intp,
    pub flags: ::std::os::raw::c_int,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct PyArrayInterface {
    pub two: ::std::os::raw::c_int,
    pub nd: ::std::os::raw::c_int,
    pub typekind: ::std::os::raw::c_char,
    pub itemsize: ::std::os::raw::c_int,
    pub flags: ::std::os::raw::c_int,
    pub shape: *mut npy_intp,
    pub strides: *mut npy_intp,
    pub data: *mut ::std::os::raw::c_void,
    pub descr: *mut PyObject,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyArray_Descr {
    pub ob_base: PyObject,
    pub typeobj: *mut PyTypeObject,
    pub kind: ::std::os::raw::c_char,
    pub type_: ::std::os::raw::c_char,
    pub byteorder: ::std::os::raw::c_char,
    pub flags: ::std::os::raw::c_char,
    pub type_num: ::std::os::raw::c_int,
    pub elsize: ::std::os::raw::c_int,
    pub alignment: ::std::os::raw::c_int,
    pub subarray: *mut _PyArray_Descr__arr_descr,
    pub fields: *mut PyObject,
    pub names: *mut PyObject,
    pub f: *mut PyArray_ArrFuncs,
    pub metadata: *mut PyObject,
    pub c_metadata: *mut NpyAuxData,
    pub hash: npy_hash_t,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyMemberDef([u8; 0]);

#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyTypeObject {
    pub ob_base: PyVarObject,
    pub tp_name: *const ::std::os::raw::c_char,
    pub tp_basicsize: Py_ssize_t,
    pub tp_itemsize: Py_ssize_t,
    pub tp_dealloc: destructor,
    pub tp_print: printfunc,
    pub tp_getattr: getattrfunc,
    pub tp_setattr: setattrfunc,
    pub tp_as_async: *mut PyAsyncMethods,
    pub tp_repr: reprfunc,
    pub tp_as_number: *mut PyNumberMethods,
    pub tp_as_sequence: *mut PySequenceMethods,
    pub tp_as_mapping: *mut PyMappingMethods,
    pub tp_hash: hashfunc,
    pub tp_call: ternaryfunc,
    pub tp_str: reprfunc,
    pub tp_getattro: getattrofunc,
    pub tp_setattro: setattrofunc,
    pub tp_as_buffer: *mut PyBufferProcs,
    pub tp_flags: ::std::os::raw::c_ulong,
    pub tp_doc: *const ::std::os::raw::c_char,
    pub tp_traverse: traverseproc,
    pub tp_clear: inquiry,
    pub tp_richcompare: richcmpfunc,
    pub tp_weaklistoffset: Py_ssize_t,
    pub tp_iter: getiterfunc,
    pub tp_iternext: iternextfunc,
    pub tp_methods: *mut PyMethodDef,
    pub tp_members: *mut PyMemberDef,
    pub tp_getset: *mut PyGetSetDef,
    pub tp_base: *mut PyTypeObject,
    pub tp_dict: *mut PyObject,
    pub tp_descr_get: descrgetfunc,
    pub tp_descr_set: descrsetfunc,
    pub tp_dictoffset: Py_ssize_t,
    pub tp_init: initproc,
    pub tp_alloc: allocfunc,
    pub tp_new: newfunc,
    pub tp_free: freefunc,
    pub tp_is_gc: inquiry,
    pub tp_bases: *mut PyObject,
    pub tp_mro: *mut PyObject,
    pub tp_cache: *mut PyObject,
    pub tp_subclasses: *mut PyObject,
    pub tp_weaklist: *mut PyObject,
    pub tp_del: destructor,
    pub tp_version_tag: ::std::os::raw::c_uint,
    pub tp_finalize: destructor,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyArrayObject {
    pub ob_base: PyObject,
    pub data: *mut ::std::os::raw::c_char,
    pub nd: ::std::os::raw::c_int,
    pub dimensions: *mut npy_intp,
    pub strides: *mut npy_intp,
    pub base: *mut PyObject,
    pub descr: *mut PyArray_Descr,
    pub flags: ::std::os::raw::c_int,
    pub weakreflist: *mut PyObject,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct _PyArray_Descr__arr_descr {
    pub base: *mut PyArray_Descr,
    pub shape: *mut PyObject,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyArray_ArrFuncs {
    pub cast: [PyArray_VectorUnaryFunc; 21usize],
    pub getitem: PyArray_GetItemFunc,
    pub setitem: PyArray_SetItemFunc,
    pub copyswapn: PyArray_CopySwapNFunc,
    pub copyswap: PyArray_CopySwapFunc,
    pub compare: PyArray_CompareFunc,
    pub argmax: PyArray_ArgFunc,
    pub dotfunc: PyArray_DotFunc,
    pub scanfunc: PyArray_ScanFunc,
    pub fromstr: PyArray_FromStrFunc,
    pub nonzero: PyArray_NonzeroFunc,
    pub fill: PyArray_FillFunc,
    pub fillwithscalar: PyArray_FillWithScalarFunc,
    pub sort: [PyArray_SortFunc; 3usize],
    pub argsort: [PyArray_ArgSortFunc; 3usize],
    pub castdict: *mut PyObject,
    pub scalarkind: PyArray_ScalarKindFunc,
    pub cancastscalarkindto: *mut *mut ::std::os::raw::c_int,
    pub cancastto: *mut ::std::os::raw::c_int,
    pub fastclip: PyArray_FastClipFunc,
    pub fastputmask: PyArray_FastPutmaskFunc,
    pub fasttake: PyArray_FastTakeFunc,
    pub argmin: PyArray_ArgFunc,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct NpyAuxData {
    pub free: NpyAuxData_FreeFunc,
    pub clone: NpyAuxData_CloneFunc,
    pub reserved: [*mut ::std::os::raw::c_void; 2usize],
}

pub type PyArray_GetItemFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: *mut ::std::os::raw::c_void)
                                                 -> *mut _object>;
pub type PyArray_SetItemFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut PyObject,
                                                 arg2: *mut ::std::os::raw::c_void,
                                                 arg3: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_CopySwapNFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: npy_intp,
                                                 arg3: *mut ::std::os::raw::c_void,
                                                 arg4: npy_intp,
                                                 arg5: npy_intp,
                                                 arg6: ::std::os::raw::c_int,
                                                 arg7: *mut ::std::os::raw::c_void)>;
pub type PyArray_CopySwapFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: *mut ::std::os::raw::c_void,
                                                 arg3: ::std::os::raw::c_int,
                                                 arg4: *mut ::std::os::raw::c_void)>;
pub type PyArray_NonzeroFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_uchar>;
pub type PyArray_CompareFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *const ::std::os::raw::c_void,
                                                 arg2: *const ::std::os::raw::c_void,
                                                 arg3: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_ArgFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: npy_intp,
                                                 arg3: *mut npy_intp,
                                                 arg4: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_DotFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: npy_intp,
                                                 arg3: *mut ::std::os::raw::c_void,
                                                 arg4: npy_intp,
                                                 arg5: *mut ::std::os::raw::c_void,
                                                 arg6: npy_intp,
                                                 arg7: *mut ::std::os::raw::c_void)>;
pub type PyArray_VectorUnaryFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: *mut ::std::os::raw::c_void,
                                                 arg3: npy_intp,
                                                 arg4: *mut ::std::os::raw::c_void,
                                                 arg5: *mut ::std::os::raw::c_void)>;
pub type PyArray_ScanFunc =
    ::std::option::Option<unsafe extern "C" fn(fp: *mut FILE,
                                                 dptr: *mut ::std::os::raw::c_void,
                                                 ignore: *mut ::std::os::raw::c_char,
                                                 arg1: *mut PyArray_Descr)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_FromStrFunc =
    ::std::option::Option<unsafe extern "C" fn(s: *mut ::std::os::raw::c_char,
                                                 dptr: *mut ::std::os::raw::c_void,
                                                 endptr: *mut *mut ::std::os::raw::c_char,
                                                 arg1: *mut PyArray_Descr)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_FillFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: npy_intp,
                                                 arg3: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_SortFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: npy_intp,
                                                 arg3: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_ArgSortFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: *mut npy_intp,
                                                 arg3: npy_intp,
                                                 arg4: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_PartitionFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: npy_intp,
                                                 arg3: npy_intp,
                                                 arg4: *mut npy_intp,
                                                 arg5: *mut npy_intp,
                                                 arg6: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_ArgPartitionFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: *mut npy_intp,
                                                 arg3: npy_intp,
                                                 arg4: npy_intp,
                                                 arg5: *mut npy_intp,
                                                 arg6: *mut npy_intp,
                                                 arg7: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_FillWithScalarFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void,
                                                 arg2: npy_intp,
                                                 arg3: *mut ::std::os::raw::c_void,
                                                 arg4: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_ScalarKindFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)
                                                 -> ::std::os::raw::c_int>;
pub type PyArray_FastClipFunc =
    ::std::option::Option<unsafe extern "C" fn(in_: *mut ::std::os::raw::c_void,
                                                 n_in: npy_intp,
                                                 min: *mut ::std::os::raw::c_void,
                                                 max: *mut ::std::os::raw::c_void,
                                                 out: *mut ::std::os::raw::c_void)>;
pub type PyArray_FastPutmaskFunc =
    ::std::option::Option<unsafe extern "C" fn(in_: *mut ::std::os::raw::c_void,
                                                 mask: *mut ::std::os::raw::c_void,
                                                 n_in: npy_intp,
                                                 values: *mut ::std::os::raw::c_void,
                                                 nv: npy_intp)>;
pub type PyArray_FastTakeFunc =
    ::std::option::Option<unsafe extern "C" fn(dest: *mut ::std::os::raw::c_void,
                                                 src: *mut ::std::os::raw::c_void,
                                                 indarray: *mut npy_intp,
                                                 nindarray: npy_intp,
                                                 n_outer: npy_intp,
                                                 m_middle: npy_intp,
                                                 nelem: npy_intp,
                                                 clipmode: NPY_CLIPMODE)
                                                 -> ::std::os::raw::c_int>;
pub type NpyAuxData_FreeFunc = ::std::option::Option<unsafe extern "C" fn(arg1: *mut NpyAuxData)>;
pub type NpyAuxData_CloneFunc =
    ::std::option::Option<unsafe extern "C" fn(arg1: *mut NpyAuxData) -> *mut NpyAuxData>;
<|endoftext|>


<commit_before>#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]

#[miri_run(expected = "Int(1)")]
fn ret() -> i32 {
    1
}

#[miri_run(expected = "Int(-1)")]
fn neg() -> i32 {
    -1
}

#[miri_run(expected = "Int(3)")]
fn add() -> i32 {
    1 + 2
}

#[miri_run(expected = "Int(3)")]
fn indirect_add() -> i32 {
    let x = 1;
    let y = 2;
    x + y
}

#[miri_run(expected = "Int(25)")]
fn arith() -> i32 {
    3*3 + 4*4
}

#[miri_run(expected = "Int(0)")]
fn if_false() -> i32 {
    if false { 1 } else { 0 }
}

#[miri_run(expected = "Int(1)")]
fn if_true() -> i32 {
    if true { 1 } else { 0 }
}

#[miri_run(expected = "Int(2)")]
fn call() -> i32 {
    fn increment(x: i32) -> i32 {
        x + 1
    }

    increment(1)
}

fn main() {}
<commit_msg>Test looping and recursive factorial.<commit_after>#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]

#[miri_run(expected = "Int(1)")]
fn ret() -> i32 {
    1
}

#[miri_run(expected = "Int(-1)")]
fn neg() -> i32 {
    -1
}

#[miri_run(expected = "Int(3)")]
fn add() -> i32 {
    1 + 2
}

#[miri_run(expected = "Int(3)")]
fn indirect_add() -> i32 {
    let x = 1;
    let y = 2;
    x + y
}

#[miri_run(expected = "Int(25)")]
fn arith() -> i32 {
    3*3 + 4*4
}

#[miri_run(expected = "Int(0)")]
fn if_false() -> i32 {
    if false { 1 } else { 0 }
}

#[miri_run(expected = "Int(1)")]
fn if_true() -> i32 {
    if true { 1 } else { 0 }
}

#[miri_run(expected = "Int(2)")]
fn call() -> i32 {
    fn increment(x: i32) -> i32 {
        x + 1
    }

    increment(1)
}

#[miri_run(expected = "Int(3628800)")]
fn factorial_loop() -> i32 {
    let mut product = 1;
    let mut i = 1;

    while i <= 10 {
        product *= i;
        i += 1;
    }

    product
}

#[miri_run(expected = "Int(3628800)")]
fn factorial_recursive() -> i32 {
    fn fact(n: i32) -> i32 {
        if n == 0 {
            1
        } else {
            n * fact(n - 1)
        }
    }

    fact(10)
}

fn main() {}
<|endoftext|>


<commit_before>#![cfg(all(feature = "arbitrary", feature = "debug"))]

macro_rules! gen_tests(
    ($module: ident, $scalar: ty) => {
        mod $module {
            use na::debug::RandomSDP;
            use na::dimension::{U4, Dynamic};
            use na::{DMatrix, DVector, Matrix4x3, Vector4};
            use rand::random;
            #[allow(unused_imports)]
            use crate::core::helper::{RandScalar, RandComplex};
            use std::cmp;

            quickcheck! {
                fn cholesky(n: usize) -> bool {
                    let m = RandomSDP::new(Dynamic::new(n.max(1).min(50)), || random::<$scalar>().0).unwrap();
                    let l = m.clone().cholesky().unwrap().unpack();
                    relative_eq!(m, &l * l.adjoint(), epsilon = 1.0e-7)
                }

                fn cholesky_static(_m: RandomSDP<f64, U4>) -> bool {
                    let m = RandomSDP::new(U4, || random::<$scalar>().0).unwrap();
                    let chol = m.cholesky().unwrap();
                    let l    = chol.unpack();

                    if !relative_eq!(m, &l * l.adjoint(), epsilon = 1.0e-7) {
                        false
                    }
                    else {
                        true
                    }
                }

                fn cholesky_solve(n: usize, nb: usize) -> bool {
                    let n = n.max(1).min(50);
                    let m = RandomSDP::new(Dynamic::new(n), || random::<$scalar>().0).unwrap();
                    let nb = cmp::min(nb, 50); // To avoid slowing down the test too much.

                    let chol = m.clone().cholesky().unwrap();
                    let b1 = DVector::<$scalar>::new_random(n).map(|e| e.0);
                    let b2 = DMatrix::<$scalar>::new_random(n, nb).map(|e| e.0);

                    let sol1 = chol.solve(&b1);
                    let sol2 = chol.solve(&b2);

                    relative_eq!(&m * &sol1, b1, epsilon = 1.0e-7) &&
                    relative_eq!(&m * &sol2, b2, epsilon = 1.0e-7)
                }

                fn cholesky_solve_static(_n: usize) -> bool {
                    let m = RandomSDP::new(U4, || random::<$scalar>().0).unwrap();
                    let chol = m.clone().cholesky().unwrap();
                    let b1 = Vector4::<$scalar>::new_random().map(|e| e.0);
                    let b2 = Matrix4x3::<$scalar>::new_random().map(|e| e.0);

                    let sol1 = chol.solve(&b1);
                    let sol2 = chol.solve(&b2);

                    relative_eq!(m * sol1, b1, epsilon = 1.0e-7) &&
                    relative_eq!(m * sol2, b2, epsilon = 1.0e-7)
                }

                fn cholesky_inverse(n: usize) -> bool {
                    let m = RandomSDP::new(Dynamic::new(n.max(1).min(50)), || random::<$scalar>().0).unwrap();
                    let m1 = m.clone().cholesky().unwrap().inverse();
                    let id1 = &m  * &m1;
                    let id2 = &m1 * &m;

                    id1.is_identity(1.0e-7) && id2.is_identity(1.0e-7)
                }

                fn cholesky_inverse_static(_n: usize) -> bool {
                    let m = RandomSDP::new(U4, || random::<$scalar>().0).unwrap();
                    let m1 = m.clone().cholesky().unwrap().inverse();
                    let id1 = &m  * &m1;
                    let id2 = &m1 * &m;

                    id1.is_identity(1.0e-7) && id2.is_identity(1.0e-7)
                }
            }
        }
    }
);

gen_tests!(complex, RandComplex<f64>);
gen_tests!(f64, RandScalar<f64>);
<commit_msg>added test for update<commit_after>#![cfg(all(feature = "arbitrary", feature = "debug"))]

macro_rules! gen_tests(
    ($module: ident, $scalar: ty) => {
        mod $module {
            use na::debug::RandomSDP;
            use na::dimension::{U4, Dynamic};
            use na::{DMatrix, DVector, Matrix4x3, Vector4};
            use rand::random;
            #[allow(unused_imports)]
            use crate::core::helper::{RandScalar, RandComplex};
            use std::cmp;

            quickcheck! {
                fn cholesky(n: usize) -> bool {
                    let m = RandomSDP::new(Dynamic::new(n.max(1).min(50)), || random::<$scalar>().0).unwrap();
                    let l = m.clone().cholesky().unwrap().unpack();
                    relative_eq!(m, &l * l.adjoint(), epsilon = 1.0e-7)
                }

                fn cholesky_static(_m: RandomSDP<f64, U4>) -> bool {
                    let m = RandomSDP::new(U4, || random::<$scalar>().0).unwrap();
                    let chol = m.cholesky().unwrap();
                    let l    = chol.unpack();

                    if !relative_eq!(m, &l * l.adjoint(), epsilon = 1.0e-7) {
                        false
                    }
                    else {
                        true
                    }
                }

                fn cholesky_solve(n: usize, nb: usize) -> bool {
                    let n = n.max(1).min(50);
                    let m = RandomSDP::new(Dynamic::new(n), || random::<$scalar>().0).unwrap();
                    let nb = cmp::min(nb, 50); // To avoid slowing down the test too much.

                    let chol = m.clone().cholesky().unwrap();
                    let b1 = DVector::<$scalar>::new_random(n).map(|e| e.0);
                    let b2 = DMatrix::<$scalar>::new_random(n, nb).map(|e| e.0);

                    let sol1 = chol.solve(&b1);
                    let sol2 = chol.solve(&b2);

                    relative_eq!(&m * &sol1, b1, epsilon = 1.0e-7) &&
                    relative_eq!(&m * &sol2, b2, epsilon = 1.0e-7)
                }

                fn cholesky_solve_static(_n: usize) -> bool {
                    let m = RandomSDP::new(U4, || random::<$scalar>().0).unwrap();
                    let chol = m.clone().cholesky().unwrap();
                    let b1 = Vector4::<$scalar>::new_random().map(|e| e.0);
                    let b2 = Matrix4x3::<$scalar>::new_random().map(|e| e.0);

                    let sol1 = chol.solve(&b1);
                    let sol2 = chol.solve(&b2);

                    relative_eq!(m * sol1, b1, epsilon = 1.0e-7) &&
                    relative_eq!(m * sol2, b2, epsilon = 1.0e-7)
                }

                fn cholesky_inverse(n: usize) -> bool {
                    let m = RandomSDP::new(Dynamic::new(n.max(1).min(50)), || random::<$scalar>().0).unwrap();
                    let m1 = m.clone().cholesky().unwrap().inverse();
                    let id1 = &m  * &m1;
                    let id2 = &m1 * &m;

                    id1.is_identity(1.0e-7) && id2.is_identity(1.0e-7)
                }

                fn cholesky_inverse_static(_n: usize) -> bool {
                    let m = RandomSDP::new(U4, || random::<$scalar>().0).unwrap();
                    let m1 = m.clone().cholesky().unwrap().inverse();
                    let id1 = &m  * &m1;
                    let id2 = &m1 * &m;

                    id1.is_identity(1.0e-7) && id2.is_identity(1.0e-7)
                }

                fn cholesky_rank_one_update(_n: usize) -> bool {
                    let m = RandomSDP::new(U4, || random::<$scalar>().0).unwrap();
                    let x = Vector4::<$scalar>::new_random().map(|e| e.0);
                    let sigma : $scalar = 1.;

                    // updates m manually
                    let m_updated = m + sigma * x * x.transpose();

                    // updates cholesky deomposition and reconstruct m
                    let mut chol = m.clone().cholesky().unwrap();
                    chol.rank_one_update(x, sigma);
                    let m_chol_updated = chol.l() * chol.l().transpose();

                    relative_eq!(m_updated, m_chol_updated, epsilon = 1.0e-7)
                }
            }
        }
    }
);

gen_tests!(complex, RandComplex<f64>);
gen_tests!(f64, RandScalar<f64>);
<|endoftext|>


<commit_before><commit_msg>Fix win32 surface<commit_after><|endoftext|>


<commit_before><commit_msg>Make Fuchsia signal matching nonexhaustive<commit_after><|endoftext|>


<commit_before>use std::io;

macro_rules! readln {
    () => {
        {
            let mut line = String::new();
            match io::stdin().read_line(&mut line) {
                Ok(n) => Some(line.trim().to_string()),
                Err(e) => None
            }
        }
    };
}

fn console_title(title: &str){

}

#[no_mangle]
pub fn main() {
    console_title("Test");

    println!("Type help for a command list");
    while let Some(line) = readln!() {
        let mut args: Vec<String> = Vec::new();
        for arg in line.split(' ') {
            args.push(arg.to_string());
        }

        if let Some(command) = args.get(0) {
            println!("# {}", line);

            if command == "panic" {
                panic!("Test panic");
            } else {
                println!("Commands: panic");
            }
        }
    }
}
<commit_msg>Adding `ls` command for test.rs<commit_after>use std::{io, fs};

macro_rules! readln {
    () => {
        {
            let mut line = String::new();
            match io::stdin().read_line(&mut line) {
                Ok(n) => Some(line.trim().to_string()),
                Err(e) => None
            }
        }
    };
}

fn console_title(title: &str){

}

#[no_mangle]
pub fn main() {
    console_title("Test");

    println!("Type help for a command list");
    while let Some(line) = readln!() {
        let args: Vec<String> = line.split(' ').map(|arg| arg.to_string()).collect();

        if let Some(command) = args.get(0) {
            println!("# {}", line);

            match &command[..]
            {
                "panic" => panic!("Test panic"),
                "ls" => {
                    // TODO: when libredox is completed
                    //fs::read_dir("/").unwrap().map(|dir| println!("{}", dir));
                }
                _ => println!("Commands: panic"),
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Reimport CommandReceiver<commit_after><|endoftext|>


<commit_before><commit_msg>yes, it can catch panic<commit_after><|endoftext|>


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

//! Code for the 'normalization' query. This consists of a wrapper
//! which folds deeply, invoking the underlying
//! `normalize_projection_ty` query when it encounters projections.

use infer::{InferCtxt, InferOk};
use infer::at::At;
use mir::interpret::{GlobalId, ConstVal};
use traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
use traits::project::Normalized;
use ty::{self, Ty, TyCtxt};
use ty::fold::{TypeFoldable, TypeFolder};
use ty::subst::{Subst, Substs};

use super::NoSolution;

impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> {
    /// Normalize `value` in the context of the inference context,
    /// yielding a resulting type, or an error if `value` cannot be
    /// normalized. If you don't care about regions, you should prefer
    /// `normalize_erasing_regions`, which is more efficient.
    ///
    /// If the normalization succeeds and is unambiguous, returns back
    /// the normalized value along with various outlives relations (in
    /// the form of obligations that must be discharged).
    ///
    /// NB. This will *eventually* be the main means of
    /// normalizing, but for now should be used only when we actually
    /// know that normalization will succeed, since error reporting
    /// and other details are still "under development".
    pub fn normalize<T>(&self, value: &T) -> Result<Normalized<'tcx, T>, NoSolution>
    where
        T: TypeFoldable<'tcx>,
    {
        debug!(
            "normalize::<{}>(value={:?}, param_env={:?})",
            unsafe { ::std::intrinsics::type_name::<T>() },
            value,
            self.param_env,
        );
        let mut normalizer = QueryNormalizer {
            infcx: self.infcx,
            cause: self.cause,
            param_env: self.param_env,
            obligations: vec![],
            error: false,
            anon_depth: 0,
        };
        if !value.has_projections() {
            return Ok(Normalized {
                value: value.clone(),
                obligations: vec![],
            });
        }

        let value1 = value.fold_with(&mut normalizer);
        if normalizer.error {
            Err(NoSolution)
        } else {
            Ok(Normalized {
                value: value1,
                obligations: normalizer.obligations,
            })
        }
    }
}

/// Result from the `normalize_projection_ty` query.
#[derive(Clone, Debug)]
pub struct NormalizationResult<'tcx> {
    /// Result of normalization.
    pub normalized_ty: Ty<'tcx>,
}

struct QueryNormalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
    infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
    cause: &'cx ObligationCause<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    obligations: Vec<PredicateObligation<'tcx>>,
    error: bool,
    anon_depth: usize,
}

impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx> {
    fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'tcx> {
        self.infcx.tcx
    }

    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
        let ty = ty.super_fold_with(self);
        match ty.sty {
            ty::TyAnon(def_id, substs) if !substs.has_escaping_regions() => {
                // (*)
                // Only normalize `impl Trait` after type-checking, usually in codegen.
                match self.param_env.reveal {
                    Reveal::UserFacing => ty,

                    Reveal::All => {
                        let recursion_limit = *self.tcx().sess.recursion_limit.get();
                        if self.anon_depth >= recursion_limit {
                            let obligation = Obligation::with_depth(
                                self.cause.clone(),
                                recursion_limit,
                                self.param_env,
                                ty,
                            );
                            self.infcx.report_overflow_error(&obligation, true);
                        }

                        let generic_ty = self.tcx().type_of(def_id);
                        let concrete_ty = generic_ty.subst(self.tcx(), substs);
                        self.anon_depth += 1;
                        if concrete_ty == ty {
                            bug!("infinite recursion generic_ty: {:#?}, substs: {:#?}, \
                                  concrete_ty: {:#?}, ty: {:#?}", generic_ty, substs, concrete_ty,
                                  ty);
                        }
                        let folded_ty = self.fold_ty(concrete_ty);
                        self.anon_depth -= 1;
                        folded_ty
                    }
                }
            }

            ty::TyProjection(ref data) if !data.has_escaping_regions() => {
                // (*)
                // (*) This is kind of hacky -- we need to be able to
                // handle normalization within binders because
                // otherwise we wind up a need to normalize when doing
                // trait matching (since you can have a trait
                // obligation like `for<'a> T::B : Fn(&'a int)`), but
                // we can't normalize with bound regions in scope. So
                // far now we just ignore binders but only normalize
                // if all bound regions are gone (and then we still
                // have to renormalize whenever we instantiate a
                // binder). It would be better to normalize in a
                // binding-aware fashion.

                let gcx = self.infcx.tcx.global_tcx();

                let (c_data, orig_values) =
                    self.infcx.canonicalize_query(&self.param_env.and(*data));
                debug!("QueryNormalizer: c_data = {:#?}", c_data);
                debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
                match gcx.normalize_projection_ty(c_data) {
                    Ok(result) => {
                        // We don't expect ambiguity.
                        if result.is_ambiguous() {
                            self.error = true;
                            return ty;
                        }

                        match self.infcx.instantiate_query_result_and_region_obligations(
                            self.cause,
                            self.param_env,
                            &orig_values,
                            &result,
                        ) {
                            Ok(InferOk {
                                value: result,
                                obligations,
                            }) => {
                                debug!("QueryNormalizer: result = {:#?}", result);
                                debug!("QueryNormalizer: obligations = {:#?}", obligations);
                                self.obligations.extend(obligations);
                                return result.normalized_ty;
                            }

                            Err(_) => {
                                self.error = true;
                                return ty;
                            }
                        }
                    }

                    Err(NoSolution) => {
                        self.error = true;
                        ty
                    }
                }
            }

            _ => ty,
        }
    }

    fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
        if let ConstValue::Unevaluated(def_id, substs) = constant.val {
            let tcx = self.infcx.tcx.global_tcx();
            if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
                if substs.needs_infer() || substs.has_skol() {
                    let identity_substs = Substs::identity_for_item(tcx, def_id);
                    let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs);
                    if let Some(instance) = instance {
                        let cid = GlobalId {
                            instance,
                            promoted: None,
                        };
                        match tcx.const_eval(param_env.and(cid)) {
                            Ok(evaluated) => {
                                let evaluated = evaluated.subst(self.tcx(), substs);
                                return self.fold_const(evaluated);
                            }
                            Err(_) => {}
                        }
                    }
                } else {
                    if let Some(substs) = self.tcx().lift_to_global(&substs) {
                        let instance = ty::Instance::resolve(tcx, param_env, def_id, substs);
                        if let Some(instance) = instance {
                            let cid = GlobalId {
                                instance,
                                promoted: None,
                            };
                            match tcx.const_eval(param_env.and(cid)) {
                                Ok(evaluated) => return self.fold_const(evaluated),
                                Err(_) => {}
                            }
                        }
                    }
                }
            }
        }
        constant
    }
}

BraceStructTypeFoldableImpl! {
    impl<'tcx> TypeFoldable<'tcx> for NormalizationResult<'tcx> {
        normalized_ty
    }
}

BraceStructLiftImpl! {
    impl<'a, 'tcx> Lift<'tcx> for NormalizationResult<'a> {
        type Lifted = NormalizationResult<'tcx>;
        normalized_ty
    }
}

impl_stable_hash_for!(struct NormalizationResult<'tcx> {
    normalized_ty
});
<commit_msg>Rebase fallout<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Code for the 'normalization' query. This consists of a wrapper
//! which folds deeply, invoking the underlying
//! `normalize_projection_ty` query when it encounters projections.

use infer::{InferCtxt, InferOk};
use infer::at::At;
use mir::interpret::{GlobalId, ConstValue};
use traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
use traits::project::Normalized;
use ty::{self, Ty, TyCtxt};
use ty::fold::{TypeFoldable, TypeFolder};
use ty::subst::{Subst, Substs};

use super::NoSolution;

impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> {
    /// Normalize `value` in the context of the inference context,
    /// yielding a resulting type, or an error if `value` cannot be
    /// normalized. If you don't care about regions, you should prefer
    /// `normalize_erasing_regions`, which is more efficient.
    ///
    /// If the normalization succeeds and is unambiguous, returns back
    /// the normalized value along with various outlives relations (in
    /// the form of obligations that must be discharged).
    ///
    /// NB. This will *eventually* be the main means of
    /// normalizing, but for now should be used only when we actually
    /// know that normalization will succeed, since error reporting
    /// and other details are still "under development".
    pub fn normalize<T>(&self, value: &T) -> Result<Normalized<'tcx, T>, NoSolution>
    where
        T: TypeFoldable<'tcx>,
    {
        debug!(
            "normalize::<{}>(value={:?}, param_env={:?})",
            unsafe { ::std::intrinsics::type_name::<T>() },
            value,
            self.param_env,
        );
        let mut normalizer = QueryNormalizer {
            infcx: self.infcx,
            cause: self.cause,
            param_env: self.param_env,
            obligations: vec![],
            error: false,
            anon_depth: 0,
        };
        if !value.has_projections() {
            return Ok(Normalized {
                value: value.clone(),
                obligations: vec![],
            });
        }

        let value1 = value.fold_with(&mut normalizer);
        if normalizer.error {
            Err(NoSolution)
        } else {
            Ok(Normalized {
                value: value1,
                obligations: normalizer.obligations,
            })
        }
    }
}

/// Result from the `normalize_projection_ty` query.
#[derive(Clone, Debug)]
pub struct NormalizationResult<'tcx> {
    /// Result of normalization.
    pub normalized_ty: Ty<'tcx>,
}

struct QueryNormalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
    infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
    cause: &'cx ObligationCause<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    obligations: Vec<PredicateObligation<'tcx>>,
    error: bool,
    anon_depth: usize,
}

impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx> {
    fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'tcx> {
        self.infcx.tcx
    }

    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
        let ty = ty.super_fold_with(self);
        match ty.sty {
            ty::TyAnon(def_id, substs) if !substs.has_escaping_regions() => {
                // (*)
                // Only normalize `impl Trait` after type-checking, usually in codegen.
                match self.param_env.reveal {
                    Reveal::UserFacing => ty,

                    Reveal::All => {
                        let recursion_limit = *self.tcx().sess.recursion_limit.get();
                        if self.anon_depth >= recursion_limit {
                            let obligation = Obligation::with_depth(
                                self.cause.clone(),
                                recursion_limit,
                                self.param_env,
                                ty,
                            );
                            self.infcx.report_overflow_error(&obligation, true);
                        }

                        let generic_ty = self.tcx().type_of(def_id);
                        let concrete_ty = generic_ty.subst(self.tcx(), substs);
                        self.anon_depth += 1;
                        if concrete_ty == ty {
                            bug!("infinite recursion generic_ty: {:#?}, substs: {:#?}, \
                                  concrete_ty: {:#?}, ty: {:#?}", generic_ty, substs, concrete_ty,
                                  ty);
                        }
                        let folded_ty = self.fold_ty(concrete_ty);
                        self.anon_depth -= 1;
                        folded_ty
                    }
                }
            }

            ty::TyProjection(ref data) if !data.has_escaping_regions() => {
                // (*)
                // (*) This is kind of hacky -- we need to be able to
                // handle normalization within binders because
                // otherwise we wind up a need to normalize when doing
                // trait matching (since you can have a trait
                // obligation like `for<'a> T::B : Fn(&'a int)`), but
                // we can't normalize with bound regions in scope. So
                // far now we just ignore binders but only normalize
                // if all bound regions are gone (and then we still
                // have to renormalize whenever we instantiate a
                // binder). It would be better to normalize in a
                // binding-aware fashion.

                let gcx = self.infcx.tcx.global_tcx();

                let (c_data, orig_values) =
                    self.infcx.canonicalize_query(&self.param_env.and(*data));
                debug!("QueryNormalizer: c_data = {:#?}", c_data);
                debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
                match gcx.normalize_projection_ty(c_data) {
                    Ok(result) => {
                        // We don't expect ambiguity.
                        if result.is_ambiguous() {
                            self.error = true;
                            return ty;
                        }

                        match self.infcx.instantiate_query_result_and_region_obligations(
                            self.cause,
                            self.param_env,
                            &orig_values,
                            &result,
                        ) {
                            Ok(InferOk {
                                value: result,
                                obligations,
                            }) => {
                                debug!("QueryNormalizer: result = {:#?}", result);
                                debug!("QueryNormalizer: obligations = {:#?}", obligations);
                                self.obligations.extend(obligations);
                                return result.normalized_ty;
                            }

                            Err(_) => {
                                self.error = true;
                                return ty;
                            }
                        }
                    }

                    Err(NoSolution) => {
                        self.error = true;
                        ty
                    }
                }
            }

            _ => ty,
        }
    }

    fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
        if let ConstValue::Unevaluated(def_id, substs) = constant.val {
            let tcx = self.infcx.tcx.global_tcx();
            if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
                if substs.needs_infer() || substs.has_skol() {
                    let identity_substs = Substs::identity_for_item(tcx, def_id);
                    let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs);
                    if let Some(instance) = instance {
                        let cid = GlobalId {
                            instance,
                            promoted: None,
                        };
                        match tcx.const_eval(param_env.and(cid)) {
                            Ok(evaluated) => {
                                let evaluated = evaluated.subst(self.tcx(), substs);
                                return self.fold_const(evaluated);
                            }
                            Err(_) => {}
                        }
                    }
                } else {
                    if let Some(substs) = self.tcx().lift_to_global(&substs) {
                        let instance = ty::Instance::resolve(tcx, param_env, def_id, substs);
                        if let Some(instance) = instance {
                            let cid = GlobalId {
                                instance,
                                promoted: None,
                            };
                            match tcx.const_eval(param_env.and(cid)) {
                                Ok(evaluated) => return self.fold_const(evaluated),
                                Err(_) => {}
                            }
                        }
                    }
                }
            }
        }
        constant
    }
}

BraceStructTypeFoldableImpl! {
    impl<'tcx> TypeFoldable<'tcx> for NormalizationResult<'tcx> {
        normalized_ty
    }
}

BraceStructLiftImpl! {
    impl<'a, 'tcx> Lift<'tcx> for NormalizationResult<'a> {
        type Lifted = NormalizationResult<'tcx>;
        normalized_ty
    }
}

impl_stable_hash_for!(struct NormalizationResult<'tcx> {
    normalized_ty
});
<|endoftext|>


<commit_before><commit_msg>tidy up<commit_after><|endoftext|>


<commit_before><commit_msg>Implement Reverse for hlist<commit_after><|endoftext|>


<commit_before><commit_msg>Adicionado busca senquencial recursiva em Rust<commit_after>/*
    Crontibuidores
        - Dromedario de Chapéu

    A Busca Sequencial Recusivar consiste do mesmo conceito da Busca Sequencial.
    A diferente é que invês de interar na lista utilizando um for por exemplo,
    é utlizado recursãom que é resumidamente uma função que se chama N vezes com
    mudanças no seus parametros te atingir ou o resultado desejado, ou um estado
    onde não ha mais o que fazer.

    Essa implementação é ainda mais lenta e custosa que a forma utilizando for,
    pois recursão utliza muito mais memoria e processamente para ser utlizada, para
    poucos itens na pratica ele vai ser tão rapido quanto qualquer outro algorimo.
    Porem caso seja uma lista de milhares de itens este algoritmo sera um problema.
*/

// A mudança da declaração da sequencial normal para esta é a adição do parametro
// indice, que indica em qual indice da lista nos estamos.
fn busca_sequencial_recursiva(lista: &[i32], valor: i32, indice: usize) -> (bool, usize) {
    // O primeiro If indica a condição onde a recursão ocorreu vezes o suficiente
    // para que o indice chega a ofinal da lista + 1, logo todos os itens da lista
    // foram percorridos
    if indice == lista.len() {
        return (false, 0)
    } else if lista[indice] == valor {
        return (true, indice)
    }

    // Caso o item atual não seja o item desejado, nos chamamos a função com o indice
    // acrescentado, para que na proxima execução da função seja verificado o proximo
    // item da lista
    return busca_sequencial_recursiva(lista, valor, indice + 1);
}

fn main() {
    let lista = vec![1, 2, 3, 4];
    let (existe, indice) = busca_sequencial_recursiva(&lista, 0, 0);
    println!("{}, {}", existe, indice);
}

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

    #[test]
    fn busca() {
        let lista = vec![1, 2, 3, 4];
        assert_eq!(busca_sequencial_recursiva(&lista, 2, 0), (true, 1));
        assert_eq!(busca_sequencial_recursiva(&lista, 0, 0), (false, 0));
    }
}<|endoftext|>