<commit_before>// Copyright (C) 2019, Cloudflare, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#[macro_use]
extern crate log;

use std::net::ToSocketAddrs;

use ring::rand::*;

const MAX_DATAGRAM_SIZE: usize = 1350;

const USAGE: &str = "Usage:
  http3-client [options] URL
  http3-client -h | --help

Options:
  --method METHOD          Use the given HTTP request method [default: GET].
  --body FILE              Send the given file as request body.
  --max-data BYTES         Connection-wide flow control limit [default: 10000000].
  --max-stream-data BYTES  Per-stream flow control limit [default: 1000000].
  --wire-version VERSION   The version number to send to the server [default: babababa].
  --no-verify              Don't verify server's certificate.
  --no-grease              Don't send GREASE.
  -H --header HEADER ...   Add a request header.
  -n --requests REQUESTS   Send the given number of identical requests [default: 1].
  -h --help                Show this screen.
";

fn main() {
    let mut buf = [0; 65535];
    let mut out = [0; MAX_DATAGRAM_SIZE];

    env_logger::builder()
        .default_format_timestamp_nanos(true)
        .init();

    let args = docopt::Docopt::new(USAGE)
        .and_then(|dopt| dopt.parse())
        .unwrap_or_else(|e| e.exit());

    let max_data = args.get_str("--max-data");
    let max_data = u64::from_str_radix(max_data, 10).unwrap();

    let max_stream_data = args.get_str("--max-stream-data");
    let max_stream_data = u64::from_str_radix(max_stream_data, 10).unwrap();

    let version = args.get_str("--wire-version");
    let version = u32::from_str_radix(version, 16).unwrap();

    let url = url::Url::parse(args.get_str("URL")).unwrap();

    // Request headers (can be multiple).
    let req_headers = args.get_vec("--header");

    let reqs_count = args.get_str("--requests");
    let reqs_count = u64::from_str_radix(reqs_count, 10).unwrap();

    let mut reqs_complete = 0;

    // Setup the event loop.
    let poll = mio::Poll::new().unwrap();
    let mut events = mio::Events::with_capacity(1024);

    // Resolve server address.
    let peer_addr = url.to_socket_addrs().unwrap().next().unwrap();
    info!("connecting to {:}", peer_addr);

    // Bind to INADDR_ANY or IN6ADDR_ANY depending on the IP family of the
    // server address. This is needed on macOS and BSD variants that don't
    // support binding to IN6ADDR_ANY for both v4 and v6.
    let bind_addr = match peer_addr {
        std::net::SocketAddr::V4(_) => "0.0.0.0:0",
        std::net::SocketAddr::V6(_) => "[::]:0",
    };

    // Create the UDP socket backing the QUIC connection, and register it with
    // the event loop.
    let socket = std::net::UdpSocket::bind(bind_addr).unwrap();
    socket.connect(peer_addr).unwrap();

    let socket = mio::net::UdpSocket::from_socket(socket).unwrap();
    poll.register(
        &socket,
        mio::Token(0),
        mio::Ready::readable(),
        mio::PollOpt::edge(),
    )
    .unwrap();

    // Create the configuration for the QUIC connection.
    let mut config = quiche::Config::new(version).unwrap();

    config.verify_peer(true);

    config
        .set_application_protos(quiche::h3::APPLICATION_PROTOCOL)
        .unwrap();

    config.set_idle_timeout(5000);
    config.set_max_packet_size(MAX_DATAGRAM_SIZE as u64);
    config.set_initial_max_data(max_data);
    config.set_initial_max_stream_data_bidi_local(max_stream_data);
    config.set_initial_max_stream_data_bidi_remote(max_stream_data);
    config.set_initial_max_stream_data_uni(max_stream_data);
    config.set_initial_max_streams_bidi(100);
    config.set_initial_max_streams_uni(100);
    config.set_disable_migration(true);

    let mut http3_conn = None;

    if args.get_bool("--no-verify") {
        config.verify_peer(false);
    }

    if args.get_bool("--no-grease") {
        config.grease(false);
    }

    if std::env::var_os("SSLKEYLOGFILE").is_some() {
        config.log_keys();
    }

    // Generate a random source connection ID for the connection.
    let mut scid = [0; quiche::MAX_CONN_ID_LEN];
    SystemRandom::new().fill(&mut scid[..]).unwrap();

    // Create a QUIC connection and initiate handshake.
    let mut conn = quiche::connect(url.domain(), &scid, &mut config).unwrap();

    let write = conn.send(&mut out).expect("initial send failed");

    while let Err(e) = socket.send(&out[..write]) {
        if e.kind() == std::io::ErrorKind::WouldBlock {
            debug!("send() would block");
            continue;
        }

        panic!("send() failed: {:?}", e);
    }

    debug!("written {}", write);

    let req_start = std::time::Instant::now();

    loop {
        poll.poll(&mut events, conn.timeout()).unwrap();

        // Read incoming UDP packets from the socket and feed them to quiche,
        // until there are no more packets to read.
        'read: loop {
            // If the event loop reported no events, it means that the timeout
            // has expired, so handle it without attempting to read packets. We
            // will then proceed with the send loop.
            if events.is_empty() {
                debug!("timed out");

                conn.on_timeout();

                break 'read;
            }

            let len = match socket.recv(&mut buf) {
                Ok(v) => v,

                Err(e) => {
                    // There are no more UDP packets to read, so end the read
                    // loop.
                    if e.kind() == std::io::ErrorKind::WouldBlock {
                        debug!("recv() would block");
                        break 'read;
                    }

                    panic!("recv() failed: {:?}", e);
                },
            };

            debug!("got {} bytes", len);

            // Process potentially coalesced packets.
            let read = match conn.recv(&mut buf[..len]) {
                Ok(v) => v,

                Err(quiche::Error::Done) => {
                    debug!("done reading");
                    break;
                },

                Err(e) => {
                    error!("recv failed: {:?}", e);
                    break 'read;
                },
            };

            debug!("processed {} bytes", read);
        }

        if conn.is_closed() {
            info!("connection closed, {:?}", conn.stats());
            break;
        }

        // Create a new HTTP/3 connection and end an HTTP request as soon as
        // the QUIC connection is established.
        if conn.is_established() && http3_conn.is_none() {
            let h3_config = quiche::h3::Config::new(0, 1024, 0, 0).unwrap();

            let mut h3_conn =
                quiche::h3::Connection::with_transport(&mut conn, &h3_config)
                    .unwrap();

            let mut path = String::from(url.path());

            if let Some(query) = url.query() {
                path.push('?');
                path.push_str(query);
            }

            let mut req = vec![
                quiche::h3::Header::new(":method", args.get_str("--method")),
                quiche::h3::Header::new(":scheme", url.scheme()),
                quiche::h3::Header::new(":authority", url.host_str().unwrap()),
                quiche::h3::Header::new(":path", &path),
                quiche::h3::Header::new("user-agent", "quiche"),
            ];

            // Add custom headers to the request.
            for header in &req_headers {
                let header_split: Vec<&str> = header.splitn(2, ": ").collect();
                if header_split.len() != 2 {
                    panic!("malformed header provided - \"{}\"", header);
                }

                req.push(quiche::h3::Header::new(
                    header_split[0],
                    header_split[1],
                ));
            }

            let body = if args.get_bool("--body") {
                std::fs::read(args.get_str("--body")).ok()
            } else {
                None
            };

            if body.is_some() {
                req.push(quiche::h3::Header::new(
                    "content-length",
                    &body.as_ref().unwrap().len().to_string(),
                ));
            }

            for _ in 0..reqs_count {
                info!("sending HTTP request {:?}", req);

                let s =
                    match h3_conn.send_request(&mut conn, &req, body.is_none()) {
                        Ok(v) => v,

                        Err(e) => {
                            error!("failed to send request {:?}", e);
                            break;
                        },
                    };

                if let Some(body) = &body {
                    if let Err(e) = h3_conn.send_body(&mut conn, s, body, true) {
                        error!("failed to send request body {:?}", e);
                        break;
                    }
                }
            }

            http3_conn = Some(h3_conn);
        }

        if let Some(http3_conn) = &mut http3_conn {
            // Process HTTP/3 events.
            loop {
                match http3_conn.poll(&mut conn) {
                    Ok((stream_id, quiche::h3::Event::Headers(headers))) => {
                        info!(
                            "got response headers {:?} on stream id {}",
                            headers, stream_id
                        );
                    },

                    Ok((stream_id, quiche::h3::Event::Data)) => {
                        if let Ok(read) =
                            http3_conn.recv_body(&mut conn, stream_id, &mut buf)
                        {
                            debug!(
                                "got {} bytes of response data on stream {}",
                                read, stream_id
                            );

                            print!("{}", unsafe {
                                std::str::from_utf8_unchecked(&buf[..read])
                            });
                        }
                    },

                    Ok((_stream_id, quiche::h3::Event::Finished)) => {
                        reqs_complete += 1;

                        debug!(
                            "{}/{} responses received",
                            reqs_complete, reqs_count
                        );

                        if reqs_complete == reqs_count {
                            info!(
                                "{}/{} response(s) received in {:?}, closing...",
                                reqs_complete,
                                reqs_count,
                                req_start.elapsed()
                            );

                            match conn.close(true, 0x00, b"kthxbye") {
                                // Already closed.
                                Ok(_) | Err(quiche::Error::Done) => (),

                                Err(e) => panic!("error closing conn: {:?}", e),
                            }

                            break;
                        }
                    },

                    Err(quiche::h3::Error::Done) => {
                        break;
                    },

                    Err(e) => {
                        error!("HTTP/3 processing failed: {:?}", e);

                        break;
                    },
                }
            }
        }

        // Generate outgoing QUIC packets and send them on the UDP socket, until
        // quiche reports that there are no more packets to be sent.
        loop {
            let write = match conn.send(&mut out) {
                Ok(v) => v,

                Err(quiche::Error::Done) => {
                    debug!("done writing");
                    break;
                },

                Err(e) => {
                    error!("send failed: {:?}", e);

                    conn.close(false, 0x1, b"fail").ok();
                    break;
                },
            };

            if let Err(e) = socket.send(&out[..write]) {
                if e.kind() == std::io::ErrorKind::WouldBlock {
                    debug!("send() would block");
                    break;
                }

                panic!("send() failed: {:?}", e);
            }

            debug!("written {}", write);
        }

        if conn.is_closed() {
            info!("connection closed, {:?}", conn.stats());
            break;
        }
    }
}
<commit_msg>examples/http3-client: print error on timeout<commit_after>// Copyright (C) 2019, Cloudflare, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#[macro_use]
extern crate log;

use std::net::ToSocketAddrs;

use ring::rand::*;

const MAX_DATAGRAM_SIZE: usize = 1350;

const USAGE: &str = "Usage:
  http3-client [options] URL
  http3-client -h | --help

Options:
  --method METHOD          Use the given HTTP request method [default: GET].
  --body FILE              Send the given file as request body.
  --max-data BYTES         Connection-wide flow control limit [default: 10000000].
  --max-stream-data BYTES  Per-stream flow control limit [default: 1000000].
  --wire-version VERSION   The version number to send to the server [default: babababa].
  --no-verify              Don't verify server's certificate.
  --no-grease              Don't send GREASE.
  -H --header HEADER ...   Add a request header.
  -n --requests REQUESTS   Send the given number of identical requests [default: 1].
  -h --help                Show this screen.
";

fn main() {
    let mut buf = [0; 65535];
    let mut out = [0; MAX_DATAGRAM_SIZE];

    env_logger::builder()
        .default_format_timestamp_nanos(true)
        .init();

    let args = docopt::Docopt::new(USAGE)
        .and_then(|dopt| dopt.parse())
        .unwrap_or_else(|e| e.exit());

    let max_data = args.get_str("--max-data");
    let max_data = u64::from_str_radix(max_data, 10).unwrap();

    let max_stream_data = args.get_str("--max-stream-data");
    let max_stream_data = u64::from_str_radix(max_stream_data, 10).unwrap();

    let version = args.get_str("--wire-version");
    let version = u32::from_str_radix(version, 16).unwrap();

    let url = url::Url::parse(args.get_str("URL")).unwrap();

    // Request headers (can be multiple).
    let req_headers = args.get_vec("--header");

    let reqs_count = args.get_str("--requests");
    let reqs_count = u64::from_str_radix(reqs_count, 10).unwrap();

    let mut reqs_complete = 0;

    // Setup the event loop.
    let poll = mio::Poll::new().unwrap();
    let mut events = mio::Events::with_capacity(1024);

    // Resolve server address.
    let peer_addr = url.to_socket_addrs().unwrap().next().unwrap();
    info!("connecting to {:}", peer_addr);

    // Bind to INADDR_ANY or IN6ADDR_ANY depending on the IP family of the
    // server address. This is needed on macOS and BSD variants that don't
    // support binding to IN6ADDR_ANY for both v4 and v6.
    let bind_addr = match peer_addr {
        std::net::SocketAddr::V4(_) => "0.0.0.0:0",
        std::net::SocketAddr::V6(_) => "[::]:0",
    };

    // Create the UDP socket backing the QUIC connection, and register it with
    // the event loop.
    let socket = std::net::UdpSocket::bind(bind_addr).unwrap();
    socket.connect(peer_addr).unwrap();

    let socket = mio::net::UdpSocket::from_socket(socket).unwrap();
    poll.register(
        &socket,
        mio::Token(0),
        mio::Ready::readable(),
        mio::PollOpt::edge(),
    )
    .unwrap();

    // Create the configuration for the QUIC connection.
    let mut config = quiche::Config::new(version).unwrap();

    config.verify_peer(true);

    config
        .set_application_protos(quiche::h3::APPLICATION_PROTOCOL)
        .unwrap();

    config.set_idle_timeout(5000);
    config.set_max_packet_size(MAX_DATAGRAM_SIZE as u64);
    config.set_initial_max_data(max_data);
    config.set_initial_max_stream_data_bidi_local(max_stream_data);
    config.set_initial_max_stream_data_bidi_remote(max_stream_data);
    config.set_initial_max_stream_data_uni(max_stream_data);
    config.set_initial_max_streams_bidi(100);
    config.set_initial_max_streams_uni(100);
    config.set_disable_migration(true);

    let mut http3_conn = None;

    if args.get_bool("--no-verify") {
        config.verify_peer(false);
    }

    if args.get_bool("--no-grease") {
        config.grease(false);
    }

    if std::env::var_os("SSLKEYLOGFILE").is_some() {
        config.log_keys();
    }

    // Generate a random source connection ID for the connection.
    let mut scid = [0; quiche::MAX_CONN_ID_LEN];
    SystemRandom::new().fill(&mut scid[..]).unwrap();

    // Create a QUIC connection and initiate handshake.
    let mut conn = quiche::connect(url.domain(), &scid, &mut config).unwrap();

    let write = conn.send(&mut out).expect("initial send failed");

    while let Err(e) = socket.send(&out[..write]) {
        if e.kind() == std::io::ErrorKind::WouldBlock {
            debug!("send() would block");
            continue;
        }

        panic!("send() failed: {:?}", e);
    }

    debug!("written {}", write);

    let req_start = std::time::Instant::now();

    loop {
        poll.poll(&mut events, conn.timeout()).unwrap();

        // Read incoming UDP packets from the socket and feed them to quiche,
        // until there are no more packets to read.
        'read: loop {
            // If the event loop reported no events, it means that the timeout
            // has expired, so handle it without attempting to read packets. We
            // will then proceed with the send loop.
            if events.is_empty() {
                debug!("timed out");

                conn.on_timeout();

                break 'read;
            }

            let len = match socket.recv(&mut buf) {
                Ok(v) => v,

                Err(e) => {
                    // There are no more UDP packets to read, so end the read
                    // loop.
                    if e.kind() == std::io::ErrorKind::WouldBlock {
                        debug!("recv() would block");
                        break 'read;
                    }

                    panic!("recv() failed: {:?}", e);
                },
            };

            debug!("got {} bytes", len);

            // Process potentially coalesced packets.
            let read = match conn.recv(&mut buf[..len]) {
                Ok(v) => v,

                Err(quiche::Error::Done) => {
                    debug!("done reading");
                    break;
                },

                Err(e) => {
                    error!("recv failed: {:?}", e);
                    break 'read;
                },
            };

            debug!("processed {} bytes", read);
        }

        if conn.is_closed() {
            info!("connection closed, {:?}", conn.stats());

            if reqs_complete != reqs_count {
                error!("connection timed out after {:?} and only completed {}/{} requests",
                       req_start.elapsed(), reqs_complete, reqs_count);
            }

            break;
        }

        // Create a new HTTP/3 connection and end an HTTP request as soon as
        // the QUIC connection is established.
        if conn.is_established() && http3_conn.is_none() {
            let h3_config = quiche::h3::Config::new(0, 1024, 0, 0).unwrap();

            let mut h3_conn =
                quiche::h3::Connection::with_transport(&mut conn, &h3_config)
                    .unwrap();

            let mut path = String::from(url.path());

            if let Some(query) = url.query() {
                path.push('?');
                path.push_str(query);
            }

            let mut req = vec![
                quiche::h3::Header::new(":method", args.get_str("--method")),
                quiche::h3::Header::new(":scheme", url.scheme()),
                quiche::h3::Header::new(":authority", url.host_str().unwrap()),
                quiche::h3::Header::new(":path", &path),
                quiche::h3::Header::new("user-agent", "quiche"),
            ];

            // Add custom headers to the request.
            for header in &req_headers {
                let header_split: Vec<&str> = header.splitn(2, ": ").collect();
                if header_split.len() != 2 {
                    panic!("malformed header provided - \"{}\"", header);
                }

                req.push(quiche::h3::Header::new(
                    header_split[0],
                    header_split[1],
                ));
            }

            let body = if args.get_bool("--body") {
                std::fs::read(args.get_str("--body")).ok()
            } else {
                None
            };

            if body.is_some() {
                req.push(quiche::h3::Header::new(
                    "content-length",
                    &body.as_ref().unwrap().len().to_string(),
                ));
            }

            for _ in 0..reqs_count {
                info!("sending HTTP request {:?}", req);

                let s =
                    match h3_conn.send_request(&mut conn, &req, body.is_none()) {
                        Ok(v) => v,

                        Err(e) => {
                            error!("failed to send request {:?}", e);
                            break;
                        },
                    };

                if let Some(body) = &body {
                    if let Err(e) = h3_conn.send_body(&mut conn, s, body, true) {
                        error!("failed to send request body {:?}", e);
                        break;
                    }
                }
            }

            http3_conn = Some(h3_conn);
        }

        if let Some(http3_conn) = &mut http3_conn {
            // Process HTTP/3 events.
            loop {
                match http3_conn.poll(&mut conn) {
                    Ok((stream_id, quiche::h3::Event::Headers(headers))) => {
                        info!(
                            "got response headers {:?} on stream id {}",
                            headers, stream_id
                        );
                    },

                    Ok((stream_id, quiche::h3::Event::Data)) => {
                        if let Ok(read) =
                            http3_conn.recv_body(&mut conn, stream_id, &mut buf)
                        {
                            debug!(
                                "got {} bytes of response data on stream {}",
                                read, stream_id
                            );

                            print!("{}", unsafe {
                                std::str::from_utf8_unchecked(&buf[..read])
                            });
                        }
                    },

                    Ok((_stream_id, quiche::h3::Event::Finished)) => {
                        reqs_complete += 1;

                        debug!(
                            "{}/{} responses received",
                            reqs_complete, reqs_count
                        );

                        if reqs_complete == reqs_count {
                            info!(
                                "{}/{} response(s) received in {:?}, closing...",
                                reqs_complete,
                                reqs_count,
                                req_start.elapsed()
                            );

                            match conn.close(true, 0x00, b"kthxbye") {
                                // Already closed.
                                Ok(_) | Err(quiche::Error::Done) => (),

                                Err(e) => panic!("error closing conn: {:?}", e),
                            }

                            break;
                        }
                    },

                    Err(quiche::h3::Error::Done) => {
                        break;
                    },

                    Err(e) => {
                        error!("HTTP/3 processing failed: {:?}", e);

                        break;
                    },
                }
            }
        }

        // Generate outgoing QUIC packets and send them on the UDP socket, until
        // quiche reports that there are no more packets to be sent.
        loop {
            let write = match conn.send(&mut out) {
                Ok(v) => v,

                Err(quiche::Error::Done) => {
                    debug!("done writing");
                    break;
                },

                Err(e) => {
                    error!("send failed: {:?}", e);

                    conn.close(false, 0x1, b"fail").ok();
                    break;
                },
            };

            if let Err(e) = socket.send(&out[..write]) {
                if e.kind() == std::io::ErrorKind::WouldBlock {
                    debug!("send() would block");
                    break;
                }

                panic!("send() failed: {:?}", e);
            }

            debug!("written {}", write);
        }

        if conn.is_closed() {
            info!("connection closed, {:?}", conn.stats());

            if reqs_complete != reqs_count {
                error!("connection timed out after {:?} and only completed {}/{} requests",
                       req_start.elapsed(), reqs_complete, reqs_count);
            }

            break;
        }
    }
}
<|endoftext|>


<commit_before>extern crate nannou;

use nannou::prelude::*;
use nannou::ui::prelude::*;
use nannou::rand::random;

fn main() {
    nannou::run(model, event, view);
}

struct Model {
    ui: nannou::Ui,
    ids: Ids,
    bg_color: nannou::ui::Color,
}

struct Ids {
    button: widget::Id,
    text: widget::Id,
    background: widget::Id,
}

fn model(app: &App) -> Model {
    // Set the loop mode to wait for events, an energy-efficient option for pure-GUI apps.
    app.set_loop_mode(LoopMode::wait(3));

    // Create the UI.
    let mut ui = app.new_ui().build().unwrap();

    // Generate some ids for our widgets.
    let ids = Ids {
        button: ui.generate_widget_id(),
        text: ui.generate_widget_id(),
        background: ui.generate_widget_id(),
    };

    // Init background color
    let bg_color = color::rgba(1.0,0.0,1.0,1.0);

    Model { ui, ids, bg_color }
}

fn event(_app: &App, mut model: Model, event: Event) -> Model {
    match event {
        // Handle window events like mouse, keyboard, resize, etc here.
        Event::WindowEvent { simple: Some(event), .. } => {
            println!("{:?}", event);
        },
        // `Update` the model here.
        Event::Update(update) => {

            // Calling `set_widgets` allows us to instantiate some widgets.
            let ui = &mut model.ui.set_widgets();

            // Place a canvas as the background. A canvas auto-sizes to the window if no dimensions
            // were specified.
            widget::Canvas::new().color(model.bg_color).set(model.ids.background, ui);

            // Draw the button and increment `count` if pressed.
            for _click in widget::Button::new()
                .up_from(model.ids.text,100.0)
                .w_h(180.0, 80.0)
                .label("random bg color")
                .set(model.ids.button, ui)
            {
                model.bg_color = color::rgba(random(),random(),random(),1.0);
            }

            // Draw the update event using a `Text` widget.
            let text = format!("{:#?}", update);
            widget::Text::new(&text)
                .color(color::WHITE)
                .middle_of(model.ids.background)
                .set(model.ids.text, ui);
        },
        _ => (),
    }
    model
}

// Draw the state of your `Model` into the given `Frame` here.
fn view(app: &App, model: &Model, frame: Frame) -> Frame {
    // Draw the state of the `Ui` to the frame.
    model.ui.draw_to_frame(app, &frame).unwrap();
    // Return the drawn frame.
    frame
}
<commit_msg>Updated the simple_ui example<commit_after>extern crate nannou;

use nannou::prelude::*;
use nannou::ui::prelude::*;

fn main() {
    nannou::run(model, event, view);
}

struct Model {
    ui: Ui,
    ids: Ids,
    resolution: usize,
    scale: f32,
    rotation: f32,
    color: Rgb,
    position: Point2<f32>,
}

struct Ids {
    resolution: widget::Id,
    scale: widget::Id,
    rotation: widget::Id,
    random_color: widget::Id,
    position: widget::Id,
}

fn model(app: &App) -> Model {
    // Set the loop mode to wait for events, an energy-efficient option for pure-GUI apps.
    app.set_loop_mode(LoopMode::wait(3));

    // Create the UI.
    let mut ui = app.new_ui().build().unwrap();

    // Generate some ids for our widgets.
    let ids = Ids {
        resolution: ui.generate_widget_id(),
        scale: ui.generate_widget_id(),
        rotation: ui.generate_widget_id(),
        random_color: ui.generate_widget_id(),
        position: ui.generate_widget_id(),
    };

    // Init our variables
    let resolution = 6;
    let scale = 200.0;
    let rotation = 0.0;
    let position = pt2(0.0, 0.0);
    let color = Rgb::new(1.0, 0.0, 1.0);

    Model {
        ui,
        ids,
        resolution,
        scale,
        rotation,
        position,
        color,
    }
}

fn event(_app: &App, mut model: Model, event: Event) -> Model {
    if let Event::Update(_update) = event {
        // Calling `set_widgets` allows us to instantiate some widgets.
        let ui = &mut model.ui.set_widgets();

        fn slider(val: f32, min: f32, max: f32) -> widget::Slider<'static, f32> {
            widget::Slider::new(val, min, max)
                .w_h(200.0, 30.0)
                .label_font_size(15)
                .rgb(0.3, 0.3, 0.3)
                .label_rgb(1.0, 1.0, 1.0)
                .border(0.0)
        }

        for value in slider(model.resolution as f32, 3.0, 15.0)
            .top_left_with_margin(20.0)
            .label("Resolution")
            .set(model.ids.resolution, ui)
        {
            model.resolution = value as usize;
        }

        for value in slider(model.scale, 10.0, 500.0)
            .down(10.0)
            .label("Scale")
            .set(model.ids.scale, ui)
        {
            model.scale = value;
        }

        for value in slider(model.rotation, -PI, PI)
            .down(10.0)
            .label("Rotation")
            .set(model.ids.rotation, ui)
        {
            model.rotation = value;
        }

        for _click in widget::Button::new()
            .down(10.0)
            .w_h(200.0, 60.0)
            .label("Random Color")
            .label_font_size(15)
            .rgb(0.3, 0.3, 0.3)
            .label_rgb(1.0, 1.0, 1.0)
            .border(0.0)
            .set(model.ids.random_color, ui)
        {
            model.color = Rgb::new(random(), random(), random());
        }

        for (x, y) in widget::XYPad::new(
            model.position.x,
            -200.0,
            200.0,
            model.position.y,
            -200.0,
            200.0,
        ).down(10.0)
            .w_h(200.0, 200.0)
            .label("Position")
            .label_font_size(15)
            .rgb(0.3, 0.3, 0.3)
            .label_rgb(1.0, 1.0, 1.0)
            .border(0.0)
            .set(model.ids.position, ui)
        {
            model.position = Point2::new(x, y);
        }
    }
    model
}

// Draw the state of your `Model` into the given `Frame` here.
fn view(app: &App, model: &Model, frame: Frame) -> Frame {
    // Begin drawing
    let draw = app.draw();

    draw.background().rgb(0.02, 0.02, 0.02);

    draw.ellipse()
        .xy(model.position)
        .radius(model.scale)
        .resolution(model.resolution)
        .rotate(model.rotation)
        .color(model.color);

    // Write the result of our drawing to the window's OpenGL frame.
    draw.to_frame(app, &frame).unwrap();

    // Draw the state of the `Ui` to the frame.
    model.ui.draw_to_frame(app, &frame).unwrap();

    // Return the drawn frame.
    frame
}
<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use super::{Coprocessor, RegionObserver, ObserverContext, Result as CopResult};
use util::codec::table;
use util::escape;

use kvproto::raft_cmdpb::{SplitRequest, AdminRequest, Request, AdminResponse, Response,
                          AdminCmdType};
use protobuf::RepeatedField;
use std::result::Result as StdResult;

/// `SplitObserver` adjusts the split key so that it won't separate
/// the data of a row into two region. It adjusts the key according
/// to the key format of `TiDB`.
pub struct SplitObserver;

const VERSION_LENGTH: usize = 8;

type Result<T> = StdResult<T, String>;

impl SplitObserver {
    fn on_split(&mut self, ctx: &mut ObserverContext, split: &mut SplitRequest) -> Result<()> {
        if !split.has_split_key() {
            return Err("split key is expected!".to_owned());
        }
        let mut key = split.get_split_key().to_vec();

        if key.len() < VERSION_LENGTH {
            // bypass non-mvcc key.
            return Ok(());
        }

        // format of a key is TABLE_PREFIX + table_id + TABLE_ROW_MARK + handle + column_id
        // + version or TABLE_PREFIX + table_id + TABLE_INDEX_MARK + index_id + values + version
        // or meta_key + version

        let table_prefix_len = table::TABLE_PREFIX.len() + table::ID_LEN;
        if key.starts_with(table::TABLE_PREFIX) && key.len() > table::PREFIX_LEN + table::ID_LEN &&
           key[table_prefix_len..].starts_with(table::RECORD_PREFIX_SEP) {
            // row key, truncate to handle
            key.truncate(table::PREFIX_LEN + table::ID_LEN);
        } else {
            // index key or meta key, just remove the tailing version.
            let key_len = key.len();
            key.truncate(key_len - VERSION_LENGTH);
        }

        let region_start_key = ctx.snap.get_region().get_start_key();
        info!("checking region_start_key {}, split key {}",
              escape(region_start_key),
              escape(&key));
        if &*key <= region_start_key {
            return Err("no need to split".to_owned());
        }

        split.set_split_key(key);
        Ok(())
    }
}

impl Coprocessor for SplitObserver {
    fn start(&mut self) {}
    fn stop(&mut self) {}
}

impl RegionObserver for SplitObserver {
    fn pre_admin(&mut self, ctx: &mut ObserverContext, req: &mut AdminRequest) -> CopResult<()> {
        if req.get_cmd_type() != AdminCmdType::Split {
            return Ok(());
        }
        if !req.has_split() {
            box_try!(Err("cmd_type is Split but it doesn't have split request, message maybe \
                          corrupted!"
                             .to_owned()));
        }
        if let Err(e) = self.on_split(ctx, req.mut_split()) {
            error!("failed to handle split req: {:?}", e);
            return Err(box_err!(e));
        }
        Ok(())
    }

    fn post_admin(&mut self, _: &mut ObserverContext, _: &AdminRequest, _: &mut AdminResponse) {}

    /// Hook to call before execute read/write request.
    fn pre_query(&mut self,
                 _: &mut ObserverContext,
                 _: &mut RepeatedField<Request>)
                 -> CopResult<()> {
        Ok(())
    }

    /// Hook to call after read/write request being executed.
    fn post_query(&mut self,
                  _: &mut ObserverContext,
                  _: &[Request],
                  _: &mut RepeatedField<Response>)
                  -> () {
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::sync::Arc;
    use tempdir::TempDir;
    use raftstore::store::engine::*;
    use raftstore::store::PeerStorage;
    use raftstore::coprocessor::ObserverContext;
    use raftstore::coprocessor::RegionObserver;
    use kvproto::metapb::Region;
    use kvproto::raft_cmdpb::{SplitRequest, AdminRequest, AdminCmdType};
    use util::codec::{datum, table, Datum};
    use util::codec::number::NumberEncoder;
    use byteorder::{BigEndian, WriteBytesExt};

    fn new_peer_storage(path: &TempDir) -> PeerStorage {
        let engine = new_engine(path.path().to_str().unwrap()).unwrap();
        PeerStorage::new(Arc::new(engine), &Region::new()).unwrap()
    }

    fn new_split_request(key: &[u8]) -> AdminRequest {
        let mut req = AdminRequest::new();
        req.set_cmd_type(AdminCmdType::Split);
        let mut split_req = SplitRequest::new();
        split_req.set_split_key(key.to_vec());
        req.set_split(split_req);
        req
    }

    fn new_row_key(table_id: i64, row_id: i64, column_id: u64, version_id: u64) -> Vec<u8> {
        let mut buf = Vec::with_capacity(table::ID_LEN);
        buf.encode_i64(row_id).unwrap();
        let mut key = table::encode_row_key(table_id, &buf);
        if column_id > 0 {
            key.write_u64::<BigEndian>(column_id).unwrap();
        }
        key.write_u64::<BigEndian>(version_id).unwrap();
        key
    }

    fn new_index_key(table_id: i64, idx_id: i64, datums: &[Datum], version_id: u64) -> Vec<u8> {
        let mut key = table::encode_index_seek_key(table_id,
                                                   idx_id,
                                                   &datum::encode_key(datums).unwrap());
        key.write_u64::<BigEndian>(version_id).unwrap();
        key
    }

    #[test]
    fn test_split() {
        let path = TempDir::new("test-raftstore").unwrap();
        let storage = new_peer_storage(&path);
        let mut ctx = ObserverContext::new(&storage);
        let mut req = AdminRequest::new();

        let mut observer = SplitObserver;

        let resp = observer.pre_admin(&mut ctx, &mut req);
        // since no split is defined, actual coprocessor won't be invoke.
        assert!(resp.is_ok());
        assert!(!req.has_split(), "only split req should be handle.");

        req = new_split_request(b"test");
        assert!(observer.pre_admin(&mut ctx, &mut req).is_ok());
        assert_eq!(req.get_split().get_split_key(), b"test");

        let mut key = b"db:1\x00\x00\x00\x00\x00\x00\x00\x00".to_vec();
        req = new_split_request(&key);
        assert!(observer.pre_admin(&mut ctx, &mut req).is_ok());
        assert_eq!(req.get_split().get_split_key(), b"db:1");

        key = new_row_key(1, 2, 0, 0);
        req = new_split_request(&key);
        let mut expect_key = key[..key.len() - 8].to_vec();
        assert!(observer.pre_admin(&mut ctx, &mut req).is_ok());
        assert_eq!(req.get_split().get_split_key(), &*expect_key);

        key = new_row_key(1, 2, 1, 0);
        req = new_split_request(&key);
        assert!(observer.pre_admin(&mut ctx, &mut req).is_ok());
        assert_eq!(req.get_split().get_split_key(), &*expect_key);

        key = new_row_key(1, 2, 1, 1);
        req = new_split_request(&key);
        assert!(observer.pre_admin(&mut ctx, &mut req).is_ok());
        assert_eq!(req.get_split().get_split_key(), &*expect_key);

        key = new_index_key(1, 2, &[Datum::I64(1), Datum::Bytes(b"brgege".to_vec())], 0);
        req = new_split_request(&key);
        expect_key = key[..key.len() - 8].to_vec();
        assert!(observer.pre_admin(&mut ctx, &mut req).is_ok());
        assert_eq!(req.get_split().get_split_key(), &*expect_key);

        key = new_index_key(1, 2, &[Datum::I64(1), Datum::Bytes(b"brgege".to_vec())], 5);
        req = new_split_request(&key);
        observer.pre_admin(&mut ctx, &mut req).unwrap();
        assert_eq!(req.get_split().get_split_key(), &*expect_key);

        let key = b"t\x80\x00\x00\x00\x00\x00\x00\xea_r\x80\x00\x00\x00\x00\x05\
    \x82\x7f\x80\x00\x00\x00\x00\x00\x00\xd3";
        let expect_key = b"t\x80\x00\x00\x00\x00\x00\x00\xea_r\x80\x00\x00\x00\x00\x05\x82\x7f";
        req = new_split_request(key);
        observer.pre_admin(&mut ctx, &mut req).unwrap();
        assert_eq!(req.get_split().get_split_key(), expect_key);
    }
}
<commit_msg>coprocessor: decode/encode in on_split (#568)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use super::{Coprocessor, RegionObserver, ObserverContext, Result as CopResult};
use util::codec::table;
use util::codec::bytes::{encode_bytes, BytesDecoder};
use util::escape;

use kvproto::raft_cmdpb::{SplitRequest, AdminRequest, Request, AdminResponse, Response,
                          AdminCmdType};
use protobuf::RepeatedField;
use std::result::Result as StdResult;

/// `SplitObserver` adjusts the split key so that it won't separate
/// the data of a row into two region. It adjusts the key according
/// to the key format of `TiDB`.
pub struct SplitObserver;

const VERSION_LENGTH: usize = 8;

type Result<T> = StdResult<T, String>;

impl SplitObserver {
    fn on_split(&mut self, ctx: &mut ObserverContext, split: &mut SplitRequest) -> Result<()> {
        if !split.has_split_key() {
            return Err("split key is expected!".to_owned());
        }
        let mut key = match split.get_split_key().decode_bytes() {
            Ok(x) => x,
            Err(_) => return Ok(()),
        };

        // format of a key is TABLE_PREFIX + table_id + TABLE_ROW_MARK + handle + column_id
        // + version or TABLE_PREFIX + table_id + TABLE_INDEX_MARK + index_id + values + version
        // or meta_key + version

        let table_prefix_len = table::TABLE_PREFIX.len() + table::ID_LEN;
        if key.starts_with(table::TABLE_PREFIX) && key.len() > table::PREFIX_LEN + table::ID_LEN &&
           key[table_prefix_len..].starts_with(table::RECORD_PREFIX_SEP) {
            // row key, truncate to handle
            key.truncate(table::PREFIX_LEN + table::ID_LEN);
        }

        let region_start_key = ctx.snap.get_region().get_start_key();
        info!("checking region_start_key {}, split key {}",
              escape(region_start_key),
              escape(&key));
        if &*key <= region_start_key {
            return Err("no need to split".to_owned());
        }

        split.set_split_key(encode_bytes(&key));
        Ok(())
    }
}

impl Coprocessor for SplitObserver {
    fn start(&mut self) {}
    fn stop(&mut self) {}
}

impl RegionObserver for SplitObserver {
    fn pre_admin(&mut self, ctx: &mut ObserverContext, req: &mut AdminRequest) -> CopResult<()> {
        if req.get_cmd_type() != AdminCmdType::Split {
            return Ok(());
        }
        if !req.has_split() {
            box_try!(Err("cmd_type is Split but it doesn't have split request, message maybe \
                          corrupted!"
                             .to_owned()));
        }
        if let Err(e) = self.on_split(ctx, req.mut_split()) {
            error!("failed to handle split req: {:?}", e);
            return Err(box_err!(e));
        }
        Ok(())
    }

    fn post_admin(&mut self, _: &mut ObserverContext, _: &AdminRequest, _: &mut AdminResponse) {}

    /// Hook to call before execute read/write request.
    fn pre_query(&mut self,
                 _: &mut ObserverContext,
                 _: &mut RepeatedField<Request>)
                 -> CopResult<()> {
        Ok(())
    }

    /// Hook to call after read/write request being executed.
    fn post_query(&mut self,
                  _: &mut ObserverContext,
                  _: &[Request],
                  _: &mut RepeatedField<Response>)
                  -> () {
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::sync::Arc;
    use tempdir::TempDir;
    use raftstore::store::engine::*;
    use raftstore::store::PeerStorage;
    use raftstore::coprocessor::ObserverContext;
    use raftstore::coprocessor::RegionObserver;
    use kvproto::metapb::Region;
    use kvproto::raft_cmdpb::{SplitRequest, AdminRequest, AdminCmdType};
    use util::codec::{datum, table, Datum};
    use util::codec::number::NumberEncoder;
    use util::codec::bytes::encode_bytes;
    use byteorder::{BigEndian, WriteBytesExt};

    fn new_peer_storage(path: &TempDir) -> PeerStorage {
        let engine = new_engine(path.path().to_str().unwrap()).unwrap();
        PeerStorage::new(Arc::new(engine), &Region::new()).unwrap()
    }

    fn new_split_request(key: &[u8]) -> AdminRequest {
        let mut req = AdminRequest::new();
        req.set_cmd_type(AdminCmdType::Split);
        let mut split_req = SplitRequest::new();
        split_req.set_split_key(key.to_vec());
        req.set_split(split_req);
        req
    }

    fn new_row_key(table_id: i64, row_id: i64, column_id: u64, version_id: u64) -> Vec<u8> {
        let mut buf = Vec::with_capacity(table::ID_LEN);
        buf.encode_i64(row_id).unwrap();
        let mut key = table::encode_row_key(table_id, &buf);
        if column_id > 0 {
            key.write_u64::<BigEndian>(column_id).unwrap();
        }
        key = encode_bytes(&key);
        key.write_u64::<BigEndian>(version_id).unwrap();
        key
    }

    fn new_index_key(table_id: i64, idx_id: i64, datums: &[Datum], version_id: u64) -> Vec<u8> {
        let mut key = table::encode_index_seek_key(table_id,
                                                   idx_id,
                                                   &datum::encode_key(datums).unwrap());
        key = encode_bytes(&key);
        key.write_u64::<BigEndian>(version_id).unwrap();
        key
    }

    #[test]
    fn test_split() {
        let path = TempDir::new("test-raftstore").unwrap();
        let storage = new_peer_storage(&path);
        let mut ctx = ObserverContext::new(&storage);
        let mut req = AdminRequest::new();

        let mut observer = SplitObserver;

        let resp = observer.pre_admin(&mut ctx, &mut req);
        // since no split is defined, actual coprocessor won't be invoke.
        assert!(resp.is_ok());
        assert!(!req.has_split(), "only split req should be handle.");

        req = new_split_request(b"test");
        assert!(observer.pre_admin(&mut ctx, &mut req).is_ok());
        assert_eq!(req.get_split().get_split_key(), b"test");

        let mut key = encode_bytes(b"db:1");
        key.write_u64::<BigEndian>(0).unwrap();
        let mut expect_key = encode_bytes(b"db:1");
        req = new_split_request(&key);
        assert!(observer.pre_admin(&mut ctx, &mut req).is_ok());
        assert_eq!(req.get_split().get_split_key(), &*expect_key);

        key = new_row_key(1, 2, 0, 0);
        req = new_split_request(&key);
        expect_key = key[..key.len() - 8].to_vec();
        assert!(observer.pre_admin(&mut ctx, &mut req).is_ok());
        assert_eq!(req.get_split().get_split_key(), &*expect_key);

        key = new_row_key(1, 2, 1, 0);
        req = new_split_request(&key);
        assert!(observer.pre_admin(&mut ctx, &mut req).is_ok());
        assert_eq!(req.get_split().get_split_key(), &*expect_key);

        key = new_row_key(1, 2, 1, 1);
        req = new_split_request(&key);
        assert!(observer.pre_admin(&mut ctx, &mut req).is_ok());
        assert_eq!(req.get_split().get_split_key(), &*expect_key);

        key = new_index_key(1, 2, &[Datum::I64(1), Datum::Bytes(b"brgege".to_vec())], 0);
        req = new_split_request(&key);
        expect_key = key[..key.len() - 8].to_vec();
        assert!(observer.pre_admin(&mut ctx, &mut req).is_ok());
        assert_eq!(req.get_split().get_split_key(), &*expect_key);

        key = new_index_key(1, 2, &[Datum::I64(1), Datum::Bytes(b"brgege".to_vec())], 5);
        req = new_split_request(&key);
        observer.pre_admin(&mut ctx, &mut req).unwrap();
        assert_eq!(req.get_split().get_split_key(), &*expect_key);

        expect_key =
            encode_bytes(b"t\x80\x00\x00\x00\x00\x00\x00\xea_r\x80\x00\x00\x00\x00\x05\x82\x7f");
        key = expect_key.clone();
        key.extend_from_slice(b"\x80\x00\x00\x00\x00\x00\x00\xd3");
        req = new_split_request(&key);
        observer.pre_admin(&mut ctx, &mut req).unwrap();
        assert_eq!(req.get_split().get_split_key(), &*expect_key);
    }
}
<|endoftext|>


<commit_before>use std::iter::FromIterator;
use std::slice;
use std::vec;

#[cfg_attr(feature = "extra-traits", derive(Eq, PartialEq, Hash, Debug))]
#[cfg_attr(feature = "clone-impls", derive(Clone))]
pub struct Delimited<T, D> {
    inner: Vec<(T, Option<D>)>
}

impl<T, D> Delimited<T, D> {
    pub fn new() -> Delimited<T, D> {
        Delimited {
            inner: Vec::new(),
        }
    }

    pub fn is_empty(&self) -> bool {
        self.inner.len() == 0
    }

    pub fn len(&self) -> usize {
        self.inner.len()
    }

    pub fn get(&self, idx: usize) -> Element<&T, &D> {
        let (ref t, ref d) = self.inner[idx];
        match *d {
            Some(ref d) => Element::Delimited(t, d),
            None => Element::End(t),
        }
    }

    pub fn get_mut(&mut self, idx: usize) -> Element<&mut T, &mut D> {
        let (ref mut t, ref mut d) = self.inner[idx];
        match *d {
            Some(ref mut d) => Element::Delimited(t, d),
            None => Element::End(t),
        }
    }

    pub fn first(&self) -> Option<Element<&T, &D>> {
        self.inner.first().map(|&(ref t, ref d)| {
            match *d {
                Some(ref d) => Element::Delimited(t, d),
                None => Element::End(t),
            }
        })
    }

    pub fn first_mut(&mut self) -> Option<Element<&mut T, &mut D>> {
        self.inner.first_mut().map(|&mut (ref mut t, ref mut d)| {
            match *d {
                Some(ref mut d) => Element::Delimited(t, d),
                None => Element::End(t),
            }
        })
    }

    pub fn last(&self) -> Option<Element<&T, &D>> {
        self.inner.last().map(|&(ref t, ref d)| {
            match *d {
                Some(ref d) => Element::Delimited(t, d),
                None => Element::End(t),
            }
        })
    }

    pub fn last_mut(&mut self) -> Option<Element<&mut T, &mut D>> {
        self.inner.last_mut().map(|&mut (ref mut t, ref mut d)| {
            match *d {
                Some(ref mut d) => Element::Delimited(t, d),
                None => Element::End(t),
            }
        })
    }

    pub fn iter(&self) -> Iter<T, D> {
        Iter { inner: self.inner.iter() }
    }

    pub fn iter_mut(&mut self) -> IterMut<T, D> {
        IterMut { inner: self.inner.iter_mut() }
    }

    pub fn items(&self) -> Items<T, D> {
        Items { inner: self.inner.iter() }
    }

    pub fn push(&mut self, token: Element<T, D>) {
        assert!(self.is_empty() || self.trailing_delim());
        match token {
            Element::Delimited(t, d) => self.inner.push((t, Some(d))),
            Element::End(t) => self.inner.push((t, None)),
        }
    }

    pub fn push_first(&mut self, token: T) {
        assert!(self.is_empty());
        self.inner.push((token, None));
    }

    pub fn push_next(&mut self, token: T, delimiter: D) {
        self.push_trailing(delimiter);
        self.inner.push((token, None));
    }

    pub fn push_trailing(&mut self, delimiter: D) {
        let len = self.len();
        assert!(self.inner[len - 1].1.is_none());
        self.inner[len - 1].1 = Some(delimiter);
    }

    pub fn push_default(&mut self, token: T) where D: Default {
        if self.is_empty() || self.trailing_delim() {
            self.inner.push((token, None));
        } else {
            self.push_next(token, D::default());
        }
    }

    pub fn pop(&mut self) -> Option<Element<T, D>> {
        self.inner.pop().map(|e| {
            match e {
                (t, Some(d)) => Element::Delimited(t, d),
                (t, None) => Element::End(t),
            }
        })
    }

    pub fn into_vec(self) -> Vec<T> {
        self.inner.into_iter().map(|t| t.0).collect()
    }

    pub fn trailing_delim(&self) -> bool {
        self.inner[self.inner.len() - 1].1.is_some()
    }

    /// Returns true if either this `Delimited` is empty, or it has a trailing
    /// delimiter. This is useful within `ToTokens` implementations for `syn`.
    #[doc(hidden)]
    pub fn empty_or_trailing(&self) -> bool {
        self.is_empty() || self.trailing_delim()
    }
}

impl<T, D> From<Vec<(T, Option<D>)>> for Delimited<T, D> {
    fn from(v: Vec<(T, Option<D>)>) -> Self {
        Delimited {
            inner: v,
        }
    }
}

impl<T, D> From<Vec<T>> for Delimited<T, D>
    where D: Default,
{
    fn from(v: Vec<T>) -> Self {
        let len = v.len();
        Delimited {
            inner: v.into_iter().enumerate().map(|(i, item)| {
                (item, if i + 1 == len {None} else {Some(D::default())})
            }).collect(),
        }
    }
}

impl<T, D> FromIterator<Element<T, D>> for Delimited<T, D> {
    fn from_iter<I: IntoIterator<Item = Element<T, D>>>(i: I) -> Self {
        let mut ret = Delimited::new();
        for element in i {
            match element {
                Element::Delimited(a, b) => ret.inner.push((a, Some(b))),
                Element::End(a) => ret.inner.push((a, None)),
            }
        }
        ret
    }
}

impl<T, D> FromIterator<T> for Delimited<T, D>
    where D: Default,
{
    fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
        let mut ret = Delimited::new();
        for element in i {
            ret.push_default(element);
        }
        ret
    }
}

impl<'a, T, D> IntoIterator for &'a Delimited<T, D> {
    type Item = Element<&'a T, &'a D>;
    type IntoIter = Iter<'a, T, D>;

    fn into_iter(self) -> Iter<'a, T, D> {
        <Delimited<T, D>>::iter(self)
    }
}

impl<T, D> IntoIterator for Delimited<T, D> {
    type Item = Element<T, D>;
    type IntoIter = IntoIter<T, D>;

    fn into_iter(self) -> IntoIter<T, D> {
        IntoIter { inner: self.inner.into_iter() }
    }
}

impl<T, D> Default for Delimited<T, D> {
    fn default() -> Self {
        Delimited::new()
    }
}

pub struct Iter<'a, T: 'a, D: 'a> {
    inner: slice::Iter<'a, (T, Option<D>)>,
}

impl<'a, T, D> Iterator for Iter<'a, T, D> {
    type Item = Element<&'a T, &'a D>;

    fn next(&mut self) -> Option<Element<&'a T, &'a D>> {
        self.inner.next().map(|pair| {
            match pair.1 {
                Some(ref delimited) => Element::Delimited(&pair.0, delimited),
                None => Element::End(&pair.0),
            }
        })
    }
}

pub struct IterMut<'a, T: 'a, D: 'a> {
    inner: slice::IterMut<'a, (T, Option<D>)>,
}

impl<'a, T, D> Iterator for IterMut<'a, T, D> {
    type Item = Element<&'a mut T, &'a mut D>;

    fn next(&mut self) -> Option<Element<&'a mut T, &'a mut D>> {
        self.inner.next().map(|pair| {
            match pair.1 {
                Some(ref mut delimited) => Element::Delimited(&mut pair.0, delimited),
                None => Element::End(&mut pair.0),
            }
        })
    }
}

pub struct Items<'a, T: 'a, D: 'a> {
    inner: slice::Iter<'a, (T, Option<D>)>,
}

impl<'a, T, D> Iterator for Items<'a, T, D> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        self.inner.next().map(|pair| &pair.0)
    }
}

pub struct IntoIter<T, D> {
    inner: vec::IntoIter<(T, Option<D>)>,
}

impl<T, D> Iterator for IntoIter<T, D> {
    type Item = Element<T, D>;

    fn next(&mut self) -> Option<Element<T, D>> {
        self.inner.next().map(|pair| {
            match pair.1 {
                Some(v) => Element::Delimited(pair.0, v),
                None => Element::End(pair.0)
            }
        })
    }
}

pub enum Element<T, D> {
    Delimited(T, D),
    End(T),
}

impl<T, D> Element<T, D> {
    pub fn into_item(self) -> T {
        match self {
            Element::Delimited(t, _) |
            Element::End(t) => t,
        }
    }

    pub fn item(&self) -> &T {
        match *self {
            Element::Delimited(ref t, _) |
            Element::End(ref t) => t,
        }
    }

    pub fn item_mut(&mut self) -> &mut T {
        match *self {
            Element::Delimited(ref mut t, _) |
            Element::End(ref mut t) => t,
        }
    }

    pub fn delimiter(&self) -> Option<&D> {
        match *self {
            Element::Delimited(_, ref d) => Some(d),
            Element::End(_) => None,
        }
    }
}

#[cfg(feature = "parsing")]
mod parsing {
    use super::Delimited;
    use {PResult, Cursor, Synom, parse_error};

    impl<T, D> Delimited<T, D>
        where T: Synom,
              D: Synom,
    {
        pub fn parse_separated(input: Cursor) -> PResult<Self>
        {
            Self::parse(input, T::parse, false)
        }

        pub fn parse_separated_nonempty(input: Cursor) -> PResult<Self>
        {
            Self::parse_separated_nonempty_with(input, T::parse)
        }

        pub fn parse_terminated(input: Cursor) -> PResult<Self>
        {
            Self::parse_terminated_with(input, T::parse)
        }
    }

    impl<T, D> Delimited<T, D>
        where D: Synom,
    {
        pub fn parse_separated_nonempty_with(
                input: Cursor,
                parse: fn(Cursor) -> PResult<T>)
            -> PResult<Self>
        {
            match Self::parse(input, parse, false) {
                Ok((_, ref b)) if b.is_empty() => parse_error(),
                other => other,
            }
        }

        pub fn parse_terminated_with(
                input: Cursor,
                parse: fn(Cursor) -> PResult<T>)
            -> PResult<Self>
        {
            Self::parse(input, parse, true)
        }

        fn parse(mut input: Cursor,
                 parse: fn(Cursor) -> PResult<T>,
                 terminated: bool)
            -> PResult<Self>
        {
            let mut res = Delimited::new();

            // get the first element
            match parse(input) {
                Err(_) => Ok((input, res)),
                Ok((i, o)) => {
                    if i == input {
                        return parse_error();
                    }
                    input = i;
                    res.push_first(o);

                    // get the separator first
                    while let Ok((i2, s)) = D::parse(input) {
                        if i2 == input {
                            break;
                        }

                        // get the element next
                        if let Ok((i3, o3)) = parse(i2) {
                            if i3 == i2 {
                                break;
                            }
                            res.push_next(o3, s);
                            input = i3;
                        } else {
                            break;
                        }
                    }
                    if terminated {
                        if let Ok((after, sep)) = D::parse(input) {
                            res.push_trailing(sep);
                            input = after;
                        }
                    }
                    Ok((input, res))
                }
            }
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{Tokens, ToTokens};

    impl<T, D> ToTokens for Delimited<T, D>
        where T: ToTokens,
              D: ToTokens,
    {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append_all(self.iter())
        }
    }

    impl<T, D> ToTokens for Element<T, D>
        where T: ToTokens,
              D: ToTokens,
    {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                Element::Delimited(ref a, ref b) => {
                    a.to_tokens(tokens);
                    b.to_tokens(tokens);
                }
                Element::End(ref a) => a.to_tokens(tokens),
            }
        }
    }
}
<commit_msg>Implement `Extend for Delimited`<commit_after>use std::iter::FromIterator;
use std::slice;
use std::vec;

#[cfg_attr(feature = "extra-traits", derive(Eq, PartialEq, Hash, Debug))]
#[cfg_attr(feature = "clone-impls", derive(Clone))]
pub struct Delimited<T, D> {
    inner: Vec<(T, Option<D>)>
}

impl<T, D> Delimited<T, D> {
    pub fn new() -> Delimited<T, D> {
        Delimited {
            inner: Vec::new(),
        }
    }

    pub fn is_empty(&self) -> bool {
        self.inner.len() == 0
    }

    pub fn len(&self) -> usize {
        self.inner.len()
    }

    pub fn get(&self, idx: usize) -> Element<&T, &D> {
        let (ref t, ref d) = self.inner[idx];
        match *d {
            Some(ref d) => Element::Delimited(t, d),
            None => Element::End(t),
        }
    }

    pub fn get_mut(&mut self, idx: usize) -> Element<&mut T, &mut D> {
        let (ref mut t, ref mut d) = self.inner[idx];
        match *d {
            Some(ref mut d) => Element::Delimited(t, d),
            None => Element::End(t),
        }
    }

    pub fn first(&self) -> Option<Element<&T, &D>> {
        self.inner.first().map(|&(ref t, ref d)| {
            match *d {
                Some(ref d) => Element::Delimited(t, d),
                None => Element::End(t),
            }
        })
    }

    pub fn first_mut(&mut self) -> Option<Element<&mut T, &mut D>> {
        self.inner.first_mut().map(|&mut (ref mut t, ref mut d)| {
            match *d {
                Some(ref mut d) => Element::Delimited(t, d),
                None => Element::End(t),
            }
        })
    }

    pub fn last(&self) -> Option<Element<&T, &D>> {
        self.inner.last().map(|&(ref t, ref d)| {
            match *d {
                Some(ref d) => Element::Delimited(t, d),
                None => Element::End(t),
            }
        })
    }

    pub fn last_mut(&mut self) -> Option<Element<&mut T, &mut D>> {
        self.inner.last_mut().map(|&mut (ref mut t, ref mut d)| {
            match *d {
                Some(ref mut d) => Element::Delimited(t, d),
                None => Element::End(t),
            }
        })
    }

    pub fn iter(&self) -> Iter<T, D> {
        Iter { inner: self.inner.iter() }
    }

    pub fn iter_mut(&mut self) -> IterMut<T, D> {
        IterMut { inner: self.inner.iter_mut() }
    }

    pub fn items(&self) -> Items<T, D> {
        Items { inner: self.inner.iter() }
    }

    pub fn push(&mut self, token: Element<T, D>) {
        assert!(self.is_empty() || self.trailing_delim());
        match token {
            Element::Delimited(t, d) => self.inner.push((t, Some(d))),
            Element::End(t) => self.inner.push((t, None)),
        }
    }

    pub fn push_first(&mut self, token: T) {
        assert!(self.is_empty());
        self.inner.push((token, None));
    }

    pub fn push_next(&mut self, token: T, delimiter: D) {
        self.push_trailing(delimiter);
        self.inner.push((token, None));
    }

    pub fn push_trailing(&mut self, delimiter: D) {
        let len = self.len();
        assert!(self.inner[len - 1].1.is_none());
        self.inner[len - 1].1 = Some(delimiter);
    }

    pub fn push_default(&mut self, token: T) where D: Default {
        if self.is_empty() || self.trailing_delim() {
            self.inner.push((token, None));
        } else {
            self.push_next(token, D::default());
        }
    }

    pub fn pop(&mut self) -> Option<Element<T, D>> {
        self.inner.pop().map(|e| {
            match e {
                (t, Some(d)) => Element::Delimited(t, d),
                (t, None) => Element::End(t),
            }
        })
    }

    pub fn into_vec(self) -> Vec<T> {
        self.inner.into_iter().map(|t| t.0).collect()
    }

    pub fn trailing_delim(&self) -> bool {
        self.inner[self.inner.len() - 1].1.is_some()
    }

    /// Returns true if either this `Delimited` is empty, or it has a trailing
    /// delimiter. This is useful within `ToTokens` implementations for `syn`.
    #[doc(hidden)]
    pub fn empty_or_trailing(&self) -> bool {
        self.is_empty() || self.trailing_delim()
    }
}

impl<T, D> From<Vec<(T, Option<D>)>> for Delimited<T, D> {
    fn from(v: Vec<(T, Option<D>)>) -> Self {
        Delimited {
            inner: v,
        }
    }
}

impl<T, D> From<Vec<T>> for Delimited<T, D>
    where D: Default,
{
    fn from(v: Vec<T>) -> Self {
        let len = v.len();
        Delimited {
            inner: v.into_iter().enumerate().map(|(i, item)| {
                (item, if i + 1 == len {None} else {Some(D::default())})
            }).collect(),
        }
    }
}

impl<T, D> FromIterator<Element<T, D>> for Delimited<T, D> {
    fn from_iter<I: IntoIterator<Item = Element<T, D>>>(i: I) -> Self {
        let mut ret = Delimited::new();
        ret.extend(i);
        ret
    }
}

impl<T, D> FromIterator<T> for Delimited<T, D>
    where D: Default,
{
    fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
        let mut ret = Delimited::new();
        ret.extend(i);
        ret
    }
}

impl<T, D> Extend<Element<T, D>> for Delimited<T, D> {
    fn extend<I: IntoIterator<Item = Element<T, D>>>(&mut self, i: I) {
        for element in i {
            match element {
                Element::Delimited(a, b) => self.inner.push((a, Some(b))),
                Element::End(a) => self.inner.push((a, None)),
            }
        }
    }
}

impl<T, D> Extend<T> for Delimited<T, D>
    where D: Default,
{
    fn extend<I: IntoIterator<Item = T>>(&mut self, i: I) {
        for element in i {
            self.push_default(element);
        }
    }
}

impl<'a, T, D> IntoIterator for &'a Delimited<T, D> {
    type Item = Element<&'a T, &'a D>;
    type IntoIter = Iter<'a, T, D>;

    fn into_iter(self) -> Iter<'a, T, D> {
        <Delimited<T, D>>::iter(self)
    }
}

impl<T, D> IntoIterator for Delimited<T, D> {
    type Item = Element<T, D>;
    type IntoIter = IntoIter<T, D>;

    fn into_iter(self) -> IntoIter<T, D> {
        IntoIter { inner: self.inner.into_iter() }
    }
}

impl<T, D> Default for Delimited<T, D> {
    fn default() -> Self {
        Delimited::new()
    }
}

pub struct Iter<'a, T: 'a, D: 'a> {
    inner: slice::Iter<'a, (T, Option<D>)>,
}

impl<'a, T, D> Iterator for Iter<'a, T, D> {
    type Item = Element<&'a T, &'a D>;

    fn next(&mut self) -> Option<Element<&'a T, &'a D>> {
        self.inner.next().map(|pair| {
            match pair.1 {
                Some(ref delimited) => Element::Delimited(&pair.0, delimited),
                None => Element::End(&pair.0),
            }
        })
    }
}

pub struct IterMut<'a, T: 'a, D: 'a> {
    inner: slice::IterMut<'a, (T, Option<D>)>,
}

impl<'a, T, D> Iterator for IterMut<'a, T, D> {
    type Item = Element<&'a mut T, &'a mut D>;

    fn next(&mut self) -> Option<Element<&'a mut T, &'a mut D>> {
        self.inner.next().map(|pair| {
            match pair.1 {
                Some(ref mut delimited) => Element::Delimited(&mut pair.0, delimited),
                None => Element::End(&mut pair.0),
            }
        })
    }
}

pub struct Items<'a, T: 'a, D: 'a> {
    inner: slice::Iter<'a, (T, Option<D>)>,
}

impl<'a, T, D> Iterator for Items<'a, T, D> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        self.inner.next().map(|pair| &pair.0)
    }
}

pub struct IntoIter<T, D> {
    inner: vec::IntoIter<(T, Option<D>)>,
}

impl<T, D> Iterator for IntoIter<T, D> {
    type Item = Element<T, D>;

    fn next(&mut self) -> Option<Element<T, D>> {
        self.inner.next().map(|pair| {
            match pair.1 {
                Some(v) => Element::Delimited(pair.0, v),
                None => Element::End(pair.0)
            }
        })
    }
}

pub enum Element<T, D> {
    Delimited(T, D),
    End(T),
}

impl<T, D> Element<T, D> {
    pub fn into_item(self) -> T {
        match self {
            Element::Delimited(t, _) |
            Element::End(t) => t,
        }
    }

    pub fn item(&self) -> &T {
        match *self {
            Element::Delimited(ref t, _) |
            Element::End(ref t) => t,
        }
    }

    pub fn item_mut(&mut self) -> &mut T {
        match *self {
            Element::Delimited(ref mut t, _) |
            Element::End(ref mut t) => t,
        }
    }

    pub fn delimiter(&self) -> Option<&D> {
        match *self {
            Element::Delimited(_, ref d) => Some(d),
            Element::End(_) => None,
        }
    }
}

#[cfg(feature = "parsing")]
mod parsing {
    use super::Delimited;
    use {PResult, Cursor, Synom, parse_error};

    impl<T, D> Delimited<T, D>
        where T: Synom,
              D: Synom,
    {
        pub fn parse_separated(input: Cursor) -> PResult<Self>
        {
            Self::parse(input, T::parse, false)
        }

        pub fn parse_separated_nonempty(input: Cursor) -> PResult<Self>
        {
            Self::parse_separated_nonempty_with(input, T::parse)
        }

        pub fn parse_terminated(input: Cursor) -> PResult<Self>
        {
            Self::parse_terminated_with(input, T::parse)
        }
    }

    impl<T, D> Delimited<T, D>
        where D: Synom,
    {
        pub fn parse_separated_nonempty_with(
                input: Cursor,
                parse: fn(Cursor) -> PResult<T>)
            -> PResult<Self>
        {
            match Self::parse(input, parse, false) {
                Ok((_, ref b)) if b.is_empty() => parse_error(),
                other => other,
            }
        }

        pub fn parse_terminated_with(
                input: Cursor,
                parse: fn(Cursor) -> PResult<T>)
            -> PResult<Self>
        {
            Self::parse(input, parse, true)
        }

        fn parse(mut input: Cursor,
                 parse: fn(Cursor) -> PResult<T>,
                 terminated: bool)
            -> PResult<Self>
        {
            let mut res = Delimited::new();

            // get the first element
            match parse(input) {
                Err(_) => Ok((input, res)),
                Ok((i, o)) => {
                    if i == input {
                        return parse_error();
                    }
                    input = i;
                    res.push_first(o);

                    // get the separator first
                    while let Ok((i2, s)) = D::parse(input) {
                        if i2 == input {
                            break;
                        }

                        // get the element next
                        if let Ok((i3, o3)) = parse(i2) {
                            if i3 == i2 {
                                break;
                            }
                            res.push_next(o3, s);
                            input = i3;
                        } else {
                            break;
                        }
                    }
                    if terminated {
                        if let Ok((after, sep)) = D::parse(input) {
                            res.push_trailing(sep);
                            input = after;
                        }
                    }
                    Ok((input, res))
                }
            }
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{Tokens, ToTokens};

    impl<T, D> ToTokens for Delimited<T, D>
        where T: ToTokens,
              D: ToTokens,
    {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append_all(self.iter())
        }
    }

    impl<T, D> ToTokens for Element<T, D>
        where T: ToTokens,
              D: ToTokens,
    {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                Element::Delimited(ref a, ref b) => {
                    a.to_tokens(tokens);
                    b.to_tokens(tokens);
                }
                Element::End(ref a) => a.to_tokens(tokens),
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::rc::Rc;

use syntex_syntax::ast::{self, Attribute};
use syntex_syntax::ext::base::{
    self,
    Determinacy,
    MultiDecorator,
    MultiModifier,
    MultiItemModifier,
    SyntaxExtension,
};
use syntex_syntax::ext::expand::{Invocation, InvocationKind, Expansion};
use syntex_syntax::ext::hygiene::Mark;
use syntex_syntax::parse::token::intern;
use syntex_syntax::parse::ParseSess;

pub struct Resolver<'a> {
    session: &'a ParseSess,
    extensions: HashMap<ast::Name, Rc<SyntaxExtension>>,
    derive_modes: HashMap<ast::Name, Rc<MultiItemModifier>>,
}

impl<'a> Resolver<'a> {
    pub fn new(session: &'a ParseSess) -> Self {
        Resolver {
            session: session,
            extensions: HashMap::new(),
            derive_modes: HashMap::new(),
        }
    }
}

impl<'a> base::Resolver for Resolver<'a> {
    fn next_node_id(&mut self) -> ast::NodeId {
        ast::DUMMY_NODE_ID
    }
    fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() }

    fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {}
    fn add_macro(&mut self, _scope: Mark, def: ast::MacroDef) {
        self.session.span_diagnostic.span_bug(
            def.span,
            "add_macro is not supported yet");
    }
    fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
        self.extensions.insert(ident.name, ext);
    }
    fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}

    fn find_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute> {
        for i in 0..attrs.len() {
            let name = intern(&attrs[i].name());

            if let Some(ext) = self.extensions.get(&name) {
                match **ext {
                    MultiModifier(..) | MultiDecorator(..) => return Some(attrs.remove(i)),
                    _ => {}
                }
            }
        }
        None
    }
    fn find_extension(&mut self, _scope: Mark, name: ast::Name) -> Option<Rc<SyntaxExtension>> {
        self.extensions.get(&name).map(|ext| ext.clone())
    }
    fn find_mac(&mut self, scope: Mark, mac: &ast::Mac) -> Option<Rc<SyntaxExtension>> {
        let path = &mac.node.path;
        if path.segments.len() > 1 || path.global ||
           !path.segments[0].parameters.is_empty() {
            // NOTE: Pass macros with module separators through to the generated source.
            self.session.span_diagnostic.span_err(path.span,
                                                  "expected macro name without module separators");
            return None;
        }
        let name = path.segments[0].identifier.name;
        self.find_extension(scope, name)
    }
    fn resolve_invoc(&mut self, scope: Mark, invoc: &Invocation, force: bool)
                     -> Result<Rc<SyntaxExtension>, Determinacy> {
        let (name, span) = match invoc.kind {
            InvocationKind::Bang { ref mac, .. } => {
                let path = &mac.node.path;
                if path.segments.len() > 1 || path.global ||
                   !path.segments[0].parameters.is_empty() {
                    // NOTE: Pass macros with module separators through to the generated source.
                    self.session.span_diagnostic.span_err(path.span,
                                                          "expected macro name without module separators");
                    return Err(Determinacy::Undetermined);
                }
                (path.segments[0].identifier.name, path.span)
            }
            InvocationKind::Attr { ref attr, .. } => (intern(&*attr.name()), attr.span),
        };

        self.find_extension(scope, name).ok_or_else(|| {
            if force {
                let mut err =
                    self.session.span_diagnostic.struct_span_err(span, &format!("macro undefined: '{}!'", name));
                err.emit();
                Determinacy::Determined
            } else {
                Determinacy::Undetermined
            }
        })
    }
    fn resolve_derive_mode(&mut self, ident: ast::Ident) -> Option<Rc<MultiItemModifier>> {
        self.derive_modes.get(&ident.name).cloned()
    }
}
<commit_msg>Resolve syntex resolver<commit_after>use std::collections::HashMap;
use std::rc::Rc;

use syntex_syntax::ast::{self, Attribute};
use syntex_syntax::ext::base::{
    self,
    Determinacy,
    MultiDecorator,
    MultiModifier,
    SyntaxExtension,
};
use syntex_syntax::ext::expand::Expansion;
use syntex_syntax::ext::hygiene::Mark;
use syntex_syntax::parse::token::intern;
use syntex_syntax::parse::ParseSess;

pub struct Resolver<'a> {
    session: &'a ParseSess,
    extensions: HashMap<ast::Name, Rc<SyntaxExtension>>,
}

impl<'a> Resolver<'a> {
    pub fn new(session: &'a ParseSess) -> Self {
        Resolver {
            session: session,
            extensions: HashMap::new(),
        }
    }
}

impl<'a> base::Resolver for Resolver<'a> {
    fn next_node_id(&mut self) -> ast::NodeId {
        ast::DUMMY_NODE_ID
    }
    fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() }

    fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {}
    fn add_macro(&mut self, _scope: Mark, def: ast::MacroDef) {
        self.session.span_diagnostic.span_bug(
            def.span,
            "add_macro is not supported yet");
    }
    fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
        self.extensions.insert(ident.name, ext);
    }
    fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}

    fn find_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute> {
        for i in 0..attrs.len() {
            let name = intern(&attrs[i].name());

            if let Some(ext) = self.extensions.get(&name) {
                match **ext {
                    MultiModifier(..) | MultiDecorator(..) => return Some(attrs.remove(i)),
                    _ => {}
                }
            }
        }
        None
    }
    fn find_extension(&mut self, _scope: Mark, name: ast::Name) -> Option<Rc<SyntaxExtension>> {
        self.extensions.get(&name).map(|ext| ext.clone())
    }
    fn find_mac(&mut self, scope: Mark, mac: &ast::Mac) -> Option<Rc<SyntaxExtension>> {
        let path = &mac.node.path;
        if path.segments.len() > 1 || path.global ||
           !path.segments[0].parameters.is_empty() {
            // NOTE: Pass macros with module separators through to the generated source.
            self.session.span_diagnostic.span_err(path.span,
                                                  "expected macro name without module separators");
            return None;
        }
        let name = path.segments[0].identifier.name;
        self.find_extension(scope, name)
    }
    fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
                     -> Result<Rc<SyntaxExtension>, Determinacy> {
        if path.segments.len() > 1 || path.global ||
            !path.segments[0].parameters.is_empty() {
            // NOTE: Pass macros with module separators through to the generated source.
            self.session.span_diagnostic.span_err(path.span,
                                                    "expected macro name without module separators");
            return Err(Determinacy::Undetermined);
        }
        let name = path.segments[0].identifier.name;
        let span = path.span;

        self.find_extension(scope, name).ok_or_else(|| {
            if force {
                let mut err =
                    self.session.span_diagnostic.struct_span_err(span, &format!("macro undefined: '{}!'", name));
                err.emit();
                Determinacy::Determined
            } else {
                Determinacy::Undetermined
            }
        })
    }
}
<|endoftext|>


<commit_before>//! AwesomeWM drawable interface, for all things that are drawable

use std::fmt::{self, Display, Formatter};
use rustwlc::Geometry;
use cairo::ImageSurface;
use rlua::{self, Lua, UserData, AnyUserData, UserDataMethods, MetaMethod};
use ::render::Renderable;
use super::{object, class, Signal};

pub type DrawableRefreshCallback<T: 'static> = fn (&mut T);

pub struct Drawable<T: 'static> {
    surface: Option<ImageSurface>,
    geometry: Geometry,
    refreshed: bool,
    refresh_callback: DrawableRefreshCallback<T>,
    data: T
}

impl <T> Display for Drawable<T> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Display: {:p}", self)
    }
}

impl <T: 'static> UserData for Drawable<T> {
    fn add_methods(methods: &mut UserDataMethods<Self>) {
        object::add_meta_methods(methods);
        class::add_meta_methods(methods);
        methods.add_method_mut("refresh", Drawable::refresh);
        methods.add_method_mut("geometry", Drawable::geometry);

        // for properties, original awesome has a good solution.
        // store the properties in essentially a { "prop_name": {cb_new, cb_index, cb_newindex}}
        // then store the propreties in a global state somewhere.
        // THAT way you can dynamically addd properties (sweet!) and less obnonxious code to write
        // (double sweet!) becaues we can just iterate through that on the index and newindex methods
        // instead of writing out the checks manually.
        //
        // only downside is then we have a global variable that needs to be locked behind a mutex,
        // which is annoying but whatever.
    }
}

/// Initializes the global Drawable class. This allows Lua to allocate new
/// drawables using that base class as a template.
pub fn init() -> rlua::Result<()> {
    panic!()
    // TODO Just like drawable_class_setup in AwesomeWM
    // This will be a little different, because the methods and meta methods
    // are already bound by rlua in the `add_methods` of `UserData` impl for `Drawable`.

    // This will just set up properties, and the drawable super class global.
}

impl <T: 'static> Drawable<T> {
    /// Allocator for a new drawable to be created in the Lua registry.
    pub fn allocator(lua: &Lua,
                     refresh_callback: DrawableRefreshCallback<T>,
                     data: T) -> AnyUserData {
        // TODO Emit "new" signal
        let drawable = Drawable {
            surface: None,
            geometry: Geometry::zero(),
            refreshed: false,
            refresh_callback,
            data
        };
        // TODO Set meta table to be the class Drawable
        // This allocates an Drawable _object_
        lua.create_userdata(drawable)
    }

    pub fn unset_surface(&mut self) {
        self.surface.take();
        self.refreshed = false;
    }

    fn refresh(lua: &Lua, this: &mut Drawable<T>, _: ()) -> rlua::Result<()> {
        this.refreshed = true;
        (this.refresh_callback)(&mut this.data);
        Ok(())
    }

    fn geometry<'lua>(lua: &'lua Lua, this: &mut Drawable<T>, _: ())
                -> rlua::Result<rlua::Table<'lua>> {
        let area = lua.create_table();
        area.set("x", this.geometry.origin.x)?;
        area.set("y", this.geometry.origin.y)?;
        area.set("width", this.geometry.size.w)?;
        area.set("height", this.geometry.size.h)?;
        Ok(area)
    }
}

<commit_msg>Added basic sanity tests for drawable<commit_after>//! AwesomeWM drawable interface, for all things that are drawable

use std::fmt::{self, Display, Formatter};
use rustwlc::Geometry;
use cairo::ImageSurface;
use rlua::{self, Lua, UserData, AnyUserData, UserDataMethods, MetaMethod};
use ::render::Renderable;
use super::{object, class, Signal};

pub type DrawableRefreshCallback<T: 'static> = fn (&mut T);

pub struct Drawable<T: 'static> {
    surface: Option<ImageSurface>,
    geometry: Geometry,
    refreshed: bool,
    refresh_callback: DrawableRefreshCallback<T>,
    data: T
}

impl <T> Display for Drawable<T> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Display: {:p}", self)
    }
}

impl <T: 'static> UserData for Drawable<T> {
    fn add_methods(methods: &mut UserDataMethods<Self>) {
        object::add_meta_methods(methods);
        class::add_meta_methods(methods);
        methods.add_method_mut("refresh", Drawable::refresh);
        methods.add_method_mut("geometry", Drawable::geometry);

        // for properties, original awesome has a good solution.
        // store the properties in essentially a { "prop_name": {cb_new, cb_index, cb_newindex}}
        // then store the propreties in a global state somewhere.
        // THAT way you can dynamically addd properties (sweet!) and less obnonxious code to write
        // (double sweet!) becaues we can just iterate through that on the index and newindex methods
        // instead of writing out the checks manually.
        //
        // only downside is then we have a global variable that needs to be locked behind a mutex,
        // which is annoying but whatever.
    }
}

/// Initializes the global Drawable class. This allows Lua to allocate new
/// drawables using that base class as a template.
pub fn init() -> rlua::Result<()> {
    panic!()
    // TODO Just like drawable_class_setup in AwesomeWM
    // This will be a little different, because the methods and meta methods
    // are already bound by rlua in the `add_methods` of `UserData` impl for `Drawable`.

    // This will just set up properties, and the drawable super class global.
}

impl <T: 'static> Drawable<T> {
    /// Allocator for a new drawable to be created in the Lua registry.
    pub fn allocator(lua: &Lua,
                     refresh_callback: DrawableRefreshCallback<T>,
                     data: T) -> AnyUserData {
        // TODO Emit "new" signal
        let drawable = Drawable {
            surface: None,
            geometry: Geometry::zero(),
            refreshed: false,
            refresh_callback,
            data
        };
        // TODO Set meta table to be the class Drawable
        // This allocates an Drawable _object_
        lua.create_userdata(drawable)
    }

    pub fn unset_surface(&mut self) {
        self.surface.take();
        self.refreshed = false;
    }

    fn refresh(lua: &Lua, this: &mut Drawable<T>, _: ()) -> rlua::Result<()> {
        this.refreshed = true;
        (this.refresh_callback)(&mut this.data);
        Ok(())
    }

    fn geometry<'lua>(lua: &'lua Lua, this: &mut Drawable<T>, _: ())
                -> rlua::Result<rlua::Table<'lua>> {
        let area = lua.create_table();
        area.set("x", this.geometry.origin.x)?;
        area.set("y", this.geometry.origin.y)?;
        area.set("width", this.geometry.size.w)?;
        area.set("height", this.geometry.size.h)?;
        Ok(area)
    }
}

#[cfg(test)]
mod test {
    use rlua::{self, Lua, Value, ToLua};
    use super::*;

    fn noop(input: &mut ()) {}

    #[test]
    fn test_drawable_geometry() {
        let lua = Lua::new();
        let drawable = Drawable::allocator(&lua, noop, ());
        lua.globals().set("drawable", drawable).unwrap();
        lua.eval::<()>(r#"
                       print(drawable)
                       table = drawable:geometry()
                       assert(table.x == 0)
                       assert(table.y == 0)
                       assert(table.width == 0)
                       assert(table.height == 0)
                       "#,
                       None).unwrap();
    }

    #[test]
    fn test_drawable_refresh() {
        static mut num_refreshed: u32 = 0;
        let lua = Lua::new();
        fn update(input: &mut String) {
            println!("{:?}", input);
            unsafe {
                num_refreshed = 1;
            }
        }
        let drawable = Drawable::allocator(&lua, update, "input".into());
        lua.globals().set("drawable", drawable).unwrap();
        lua.eval::<()>(r#"
                     print(drawable)
                     drawable:refresh()
                "#,
                 None).unwrap();
        unsafe {
            assert_eq!(num_refreshed, 1);
        }
    }
}
<|endoftext|>


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

extern crate chrono;
extern crate env_logger;
extern crate richter;

use std::net::UdpSocket;

use richter::client::Client;
use richter::common::net::BlockingMode;
use richter::common::pak::Pak;

use chrono::Duration;

fn main() {
    env_logger::init();
    let mut pak = Pak::new();
    pak.add("pak0.pak").unwrap();
    let mut client = Client::connect("127.0.0.1:26000", &pak).unwrap();
    client
        .parse_server_msg(BlockingMode::Timeout(Duration::milliseconds(4000)), &pak)
        .unwrap();
    client.send().unwrap();
    client
        .parse_server_msg(BlockingMode::Timeout(Duration::milliseconds(4000)), &pak)
        .unwrap();
    client.send().unwrap();
    client
        .parse_server_msg(BlockingMode::Timeout(Duration::milliseconds(4000)), &pak)
        .unwrap();
    client.send().unwrap();
    client
        .parse_server_msg(BlockingMode::Timeout(Duration::milliseconds(4000)), &pak)
        .unwrap();
}
<commit_msg>Minor connect-test updates<commit_after>// Copyright © 2018 Cormac O'Brien
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

extern crate chrono;
extern crate env_logger;
extern crate richter;

use std::env;

use richter::client::Client;
use richter::common::net::BlockingMode;
use richter::common::pak::Pak;

use chrono::Duration;

fn main() {
    env_logger::init().unwrap_or_else(|_| println!("Failed to initialize env_logger."));

    let mut pak = Pak::new();
    pak.add("pak0.pak").unwrap();

    let args: Vec<String> = env::args().collect();
    let mut client = Client::connect(&args[1], &pak).unwrap();
    client
        .parse_server_msg(BlockingMode::Timeout(Duration::milliseconds(4000)), &pak)
        .unwrap();
    client.send().unwrap();
    client
        .parse_server_msg(BlockingMode::Timeout(Duration::milliseconds(4000)), &pak)
        .unwrap();
    client.send().unwrap();
    client
        .parse_server_msg(BlockingMode::Timeout(Duration::milliseconds(4000)), &pak)
        .unwrap();
    client.send().unwrap();
    client
        .parse_server_msg(BlockingMode::Timeout(Duration::milliseconds(4000)), &pak)
        .unwrap();
}
<|endoftext|>