<commit_before>#[doc="
A process-wide libuv event loop for library use.
"];

export get, get_monitor_task_gl;

import ll = uv_ll;
import iotask = uv_iotask;
import get_gl = get;
import iotask::{iotask, spawn_iotask};
import priv::{chan_from_global_ptr, weaken_task};
import comm::{port, chan, methods, select2, listen};
import either::{left, right};

native mod rustrt {
    fn rust_uv_get_kernel_global_chan_ptr() -> *libc::uintptr_t;
}

#[doc ="
Race-free helper to get access to a global task where a libuv
loop is running.

Use `uv::hl::interact` to do operations against the global
loop that this function returns.

# Return

* A `hl::high_level_loop` that encapsulates communication with the global
loop.
"]
fn get() -> iotask {
    ret get_monitor_task_gl();
}

#[doc(hidden)]
fn get_monitor_task_gl() -> iotask unsafe {

    let monitor_loop_chan_ptr = rustrt::rust_uv_get_kernel_global_chan_ptr();

    #debug("ENTERING global_loop::get() loop chan: %?",
           monitor_loop_chan_ptr);

    let builder_fn = {||
        let builder = task::builder();
        task::set_opts(builder, {
            supervise: false,
            sched: some({
                mode: task::single_threaded,
                native_stack_size: none
            })
            with task::get_opts(builder)
        });
        builder
    };

    #debug("before priv::chan_from_global_ptr");
    type monchan = chan<iotask>;

    let monitor_ch = chan_from_global_ptr::<monchan>(monitor_loop_chan_ptr,
                                                     builder_fn) {|msg_po|
        #debug("global monitor task starting");

        // As a weak task the runtime will notify us when to exit
        weaken_task() {|weak_exit_po|
            #debug("global monitor task is now weak");
            let hl_loop = spawn_loop();
            loop {
                #debug("in outer_loop...");
                alt select2(weak_exit_po, msg_po) {
                  left(weak_exit) {
                    // all normal tasks have ended, tell the
                    // libuv loop to tear_down, then exit
                    #debug("weak_exit_po recv'd msg: %?", weak_exit);
                    iotask::exit(hl_loop);
                    break;
                  }
                  right(fetch_ch) {
                    #debug("hl_loop req recv'd: %?", fetch_ch);
                    fetch_ch.send(hl_loop);
                  }
                }
            }
            #debug("global monitor task is leaving weakend state");
        };
        #debug("global monitor task exiting");
    };

    // once we have a chan to the monitor loop, we ask it for
    // the libuv loop's async handle
    listen { |fetch_ch|
        monitor_ch.send(fetch_ch);
        fetch_ch.recv()
    }
}

fn spawn_loop() -> iotask unsafe {
    let builder = task::builder();
    task::add_wrapper(builder) {|task_body|
        fn~(move task_body) {
            // The I/O loop task also needs to be weak so it doesn't keep
            // the runtime alive
            weaken_task {|weak_exit_po|
                #debug("global libuv task is now weak %?", weak_exit_po);
                task_body();

                // We don't wait for the exit message on weak_exit_po
                // because the monitor task will tell the uv loop when to
                // exit

                #debug("global libuv task is leaving weakened state");
            }
        }
    }
    spawn_iotask(builder)
}

#[cfg(test)]
mod test {
    crust fn simple_timer_close_cb(timer_ptr: *ll::uv_timer_t) unsafe {
        let exit_ch_ptr = ll::get_data_for_uv_handle(
            timer_ptr as *libc::c_void) as *comm::chan<bool>;
        let exit_ch = *exit_ch_ptr;
        comm::send(exit_ch, true);
        log(debug, #fmt("EXIT_CH_PTR simple_timer_close_cb exit_ch_ptr: %?",
                       exit_ch_ptr));
    }
    crust fn simple_timer_cb(timer_ptr: *ll::uv_timer_t,
                             _status: libc::c_int) unsafe {
        log(debug, "in simple timer cb");
        ll::timer_stop(timer_ptr);
        let hl_loop = get_gl();
        iotask::interact(hl_loop) {|_loop_ptr|
            log(debug, "closing timer");
            ll::close(timer_ptr, simple_timer_close_cb);
            log(debug, "about to deref exit_ch_ptr");
            log(debug, "after msg sent on deref'd exit_ch");
        };
        log(debug, "exiting simple timer cb");
    }

    fn impl_uv_hl_simple_timer(iotask: iotask) unsafe {
        let exit_po = comm::port::<bool>();
        let exit_ch = comm::chan(exit_po);
        let exit_ch_ptr = ptr::addr_of(exit_ch);
        log(debug, #fmt("EXIT_CH_PTR newly created exit_ch_ptr: %?",
                       exit_ch_ptr));
        let timer_handle = ll::timer_t();
        let timer_ptr = ptr::addr_of(timer_handle);
        iotask::interact(iotask) {|loop_ptr|
            log(debug, "user code inside interact loop!!!");
            let init_status = ll::timer_init(loop_ptr, timer_ptr);
            if(init_status == 0i32) {
                ll::set_data_for_uv_handle(
                    timer_ptr as *libc::c_void,
                    exit_ch_ptr as *libc::c_void);
                let start_status = ll::timer_start(timer_ptr, simple_timer_cb,
                                                   1u, 0u);
                if(start_status == 0i32) {
                }
                else {
                    fail "failure on ll::timer_start()";
                }
            }
            else {
                fail "failure on ll::timer_init()";
            }
        };
        comm::recv(exit_po);
        log(debug, "global_loop timer test: msg recv on exit_po, done..");
    }

    #[test]
    fn test_gl_uv_global_loop_high_level_global_timer() unsafe {
        let hl_loop = get_gl();
        let exit_po = comm::port::<()>();
        let exit_ch = comm::chan(exit_po);
        task::spawn_sched(task::manual_threads(1u), {||
            impl_uv_hl_simple_timer(hl_loop);
            comm::send(exit_ch, ());
        });
        impl_uv_hl_simple_timer(hl_loop);
        comm::recv(exit_po);
    }

    // keeping this test ignored until some kind of stress-test-harness
    // is set up for the build bots
    #[test]
    #[ignore]
    fn test_stress_gl_uv_global_loop_high_level_global_timer() unsafe {
        let hl_loop = get_gl();
        let exit_po = comm::port::<()>();
        let exit_ch = comm::chan(exit_po);
        let cycles = 5000u;
        iter::repeat(cycles) {||
            task::spawn_sched(task::manual_threads(1u), {||
                impl_uv_hl_simple_timer(hl_loop);
                comm::send(exit_ch, ());
            });
        };
        iter::repeat(cycles) {||
            comm::recv(exit_po);
        };
        log(debug, "test_stress_gl_uv_global_loop_high_level_global_timer"+
            " exiting sucessfully!");
    }
}<commit_msg>std: Don't export get_monitor_task_gl<commit_after>#[doc="
A process-wide libuv event loop for library use.
"];

export get;

import ll = uv_ll;
import iotask = uv_iotask;
import get_gl = get;
import iotask::{iotask, spawn_iotask};
import priv::{chan_from_global_ptr, weaken_task};
import comm::{port, chan, methods, select2, listen};
import either::{left, right};

native mod rustrt {
    fn rust_uv_get_kernel_global_chan_ptr() -> *libc::uintptr_t;
}

#[doc ="
Race-free helper to get access to a global task where a libuv
loop is running.

Use `uv::hl::interact` to do operations against the global
loop that this function returns.

# Return

* A `hl::high_level_loop` that encapsulates communication with the global
loop.
"]
fn get() -> iotask {
    ret get_monitor_task_gl();
}

#[doc(hidden)]
fn get_monitor_task_gl() -> iotask unsafe {

    let monitor_loop_chan_ptr = rustrt::rust_uv_get_kernel_global_chan_ptr();

    #debug("ENTERING global_loop::get() loop chan: %?",
           monitor_loop_chan_ptr);

    let builder_fn = {||
        let builder = task::builder();
        task::set_opts(builder, {
            supervise: false,
            sched: some({
                mode: task::single_threaded,
                native_stack_size: none
            })
            with task::get_opts(builder)
        });
        builder
    };

    #debug("before priv::chan_from_global_ptr");
    type monchan = chan<iotask>;

    let monitor_ch = chan_from_global_ptr::<monchan>(monitor_loop_chan_ptr,
                                                     builder_fn) {|msg_po|
        #debug("global monitor task starting");

        // As a weak task the runtime will notify us when to exit
        weaken_task() {|weak_exit_po|
            #debug("global monitor task is now weak");
            let hl_loop = spawn_loop();
            loop {
                #debug("in outer_loop...");
                alt select2(weak_exit_po, msg_po) {
                  left(weak_exit) {
                    // all normal tasks have ended, tell the
                    // libuv loop to tear_down, then exit
                    #debug("weak_exit_po recv'd msg: %?", weak_exit);
                    iotask::exit(hl_loop);
                    break;
                  }
                  right(fetch_ch) {
                    #debug("hl_loop req recv'd: %?", fetch_ch);
                    fetch_ch.send(hl_loop);
                  }
                }
            }
            #debug("global monitor task is leaving weakend state");
        };
        #debug("global monitor task exiting");
    };

    // once we have a chan to the monitor loop, we ask it for
    // the libuv loop's async handle
    listen { |fetch_ch|
        monitor_ch.send(fetch_ch);
        fetch_ch.recv()
    }
}

fn spawn_loop() -> iotask unsafe {
    let builder = task::builder();
    task::add_wrapper(builder) {|task_body|
        fn~(move task_body) {
            // The I/O loop task also needs to be weak so it doesn't keep
            // the runtime alive
            weaken_task {|weak_exit_po|
                #debug("global libuv task is now weak %?", weak_exit_po);
                task_body();

                // We don't wait for the exit message on weak_exit_po
                // because the monitor task will tell the uv loop when to
                // exit

                #debug("global libuv task is leaving weakened state");
            }
        }
    }
    spawn_iotask(builder)
}

#[cfg(test)]
mod test {
    crust fn simple_timer_close_cb(timer_ptr: *ll::uv_timer_t) unsafe {
        let exit_ch_ptr = ll::get_data_for_uv_handle(
            timer_ptr as *libc::c_void) as *comm::chan<bool>;
        let exit_ch = *exit_ch_ptr;
        comm::send(exit_ch, true);
        log(debug, #fmt("EXIT_CH_PTR simple_timer_close_cb exit_ch_ptr: %?",
                       exit_ch_ptr));
    }
    crust fn simple_timer_cb(timer_ptr: *ll::uv_timer_t,
                             _status: libc::c_int) unsafe {
        log(debug, "in simple timer cb");
        ll::timer_stop(timer_ptr);
        let hl_loop = get_gl();
        iotask::interact(hl_loop) {|_loop_ptr|
            log(debug, "closing timer");
            ll::close(timer_ptr, simple_timer_close_cb);
            log(debug, "about to deref exit_ch_ptr");
            log(debug, "after msg sent on deref'd exit_ch");
        };
        log(debug, "exiting simple timer cb");
    }

    fn impl_uv_hl_simple_timer(iotask: iotask) unsafe {
        let exit_po = comm::port::<bool>();
        let exit_ch = comm::chan(exit_po);
        let exit_ch_ptr = ptr::addr_of(exit_ch);
        log(debug, #fmt("EXIT_CH_PTR newly created exit_ch_ptr: %?",
                       exit_ch_ptr));
        let timer_handle = ll::timer_t();
        let timer_ptr = ptr::addr_of(timer_handle);
        iotask::interact(iotask) {|loop_ptr|
            log(debug, "user code inside interact loop!!!");
            let init_status = ll::timer_init(loop_ptr, timer_ptr);
            if(init_status == 0i32) {
                ll::set_data_for_uv_handle(
                    timer_ptr as *libc::c_void,
                    exit_ch_ptr as *libc::c_void);
                let start_status = ll::timer_start(timer_ptr, simple_timer_cb,
                                                   1u, 0u);
                if(start_status == 0i32) {
                }
                else {
                    fail "failure on ll::timer_start()";
                }
            }
            else {
                fail "failure on ll::timer_init()";
            }
        };
        comm::recv(exit_po);
        log(debug, "global_loop timer test: msg recv on exit_po, done..");
    }

    #[test]
    fn test_gl_uv_global_loop_high_level_global_timer() unsafe {
        let hl_loop = get_gl();
        let exit_po = comm::port::<()>();
        let exit_ch = comm::chan(exit_po);
        task::spawn_sched(task::manual_threads(1u), {||
            impl_uv_hl_simple_timer(hl_loop);
            comm::send(exit_ch, ());
        });
        impl_uv_hl_simple_timer(hl_loop);
        comm::recv(exit_po);
    }

    // keeping this test ignored until some kind of stress-test-harness
    // is set up for the build bots
    #[test]
    #[ignore]
    fn test_stress_gl_uv_global_loop_high_level_global_timer() unsafe {
        let hl_loop = get_gl();
        let exit_po = comm::port::<()>();
        let exit_ch = comm::chan(exit_po);
        let cycles = 5000u;
        iter::repeat(cycles) {||
            task::spawn_sched(task::manual_threads(1u), {||
                impl_uv_hl_simple_timer(hl_loop);
                comm::send(exit_ch, ());
            });
        };
        iter::repeat(cycles) {||
            comm::recv(exit_po);
        };
        log(debug, "test_stress_gl_uv_global_loop_high_level_global_timer"+
            " exiting sucessfully!");
    }
}<|endoftext|>


<commit_before>// Copyright 2013-2016 The rust-url developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Parser and serializer for the [`application/x-www-form-urlencoded` syntax](
//! http://url.spec.whatwg.org/#application/x-www-form-urlencoded),
//! as used by HTML forms.
//!
//! Converts between a string (such as an URL’s query string)
//! and a sequence of (name, value) pairs.

extern crate percent_encoding;
#[macro_use]
extern crate matches;

use percent_encoding::{percent_decode, percent_encode_byte};
use query_encoding::decode_utf8_lossy;
use std::borrow::{Borrow, Cow};
use std::str;

mod query_encoding;

pub use query_encoding::EncodingOverride;

/// Convert a byte string in the `application/x-www-form-urlencoded` syntax
/// into a iterator of (name, value) pairs.
///
/// Use `parse(input.as_bytes())` to parse a `&str` string.
///
/// The names and values are percent-decoded. For instance, `%23first=%25try%25` will be
/// converted to `[("#first", "%try%")]`.
#[inline]
pub fn parse(input: &[u8]) -> Parse {
    Parse { input }
}
/// The return type of `parse()`.
#[derive(Copy, Clone)]
pub struct Parse<'a> {
    input: &'a [u8],
}

impl<'a> Iterator for Parse<'a> {
    type Item = (Cow<'a, str>, Cow<'a, str>);

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if self.input.is_empty() {
                return None;
            }
            let mut split2 = self.input.splitn(2, |&b| b == b'&');
            let sequence = split2.next().unwrap();
            self.input = split2.next().unwrap_or(&[][..]);
            if sequence.is_empty() {
                continue;
            }
            let mut split2 = sequence.splitn(2, |&b| b == b'=');
            let name = split2.next().unwrap();
            let value = split2.next().unwrap_or(&[][..]);
            return Some((decode(name), decode(value)));
        }
    }
}

fn decode(input: &[u8]) -> Cow<str> {
    let replaced = replace_plus(input);
    decode_utf8_lossy(match percent_decode(&replaced).into() {
        Cow::Owned(vec) => Cow::Owned(vec),
        Cow::Borrowed(_) => replaced,
    })
}

/// Replace b'+' with b' '
fn replace_plus(input: &[u8]) -> Cow<[u8]> {
    match input.iter().position(|&b| b == b'+') {
        None => Cow::Borrowed(input),
        Some(first_position) => {
            let mut replaced = input.to_owned();
            replaced[first_position] = b' ';
            for byte in &mut replaced[first_position + 1..] {
                if *byte == b'+' {
                    *byte = b' ';
                }
            }
            Cow::Owned(replaced)
        }
    }
}

impl<'a> Parse<'a> {
    /// Return a new iterator that yields pairs of `String` instead of pairs of `Cow<str>`.
    pub fn into_owned(self) -> ParseIntoOwned<'a> {
        ParseIntoOwned { inner: self }
    }
}

/// Like `Parse`, but yields pairs of `String` instead of pairs of `Cow<str>`.
pub struct ParseIntoOwned<'a> {
    inner: Parse<'a>,
}

impl<'a> Iterator for ParseIntoOwned<'a> {
    type Item = (String, String);

    fn next(&mut self) -> Option<Self::Item> {
        self.inner
            .next()
            .map(|(k, v)| (k.into_owned(), v.into_owned()))
    }
}

/// The [`application/x-www-form-urlencoded` byte serializer](
/// https://url.spec.whatwg.org/#concept-urlencoded-byte-serializer).
///
/// Return an iterator of `&str` slices.
pub fn byte_serialize(input: &[u8]) -> ByteSerialize {
    ByteSerialize { bytes: input }
}

/// Return value of `byte_serialize()`.
#[derive(Debug)]
pub struct ByteSerialize<'a> {
    bytes: &'a [u8],
}

fn byte_serialized_unchanged(byte: u8) -> bool {
    matches!(byte, b'*' | b'-' | b'.' | b'0' ..= b'9' | b'A' ..= b'Z' | b'_' | b'a' ..= b'z')
}

impl<'a> Iterator for ByteSerialize<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        if let Some((&first, tail)) = self.bytes.split_first() {
            if !byte_serialized_unchanged(first) {
                self.bytes = tail;
                return Some(if first == b' ' {
                    "+"
                } else {
                    percent_encode_byte(first)
                });
            }
            let position = tail.iter().position(|&b| !byte_serialized_unchanged(b));
            let (unchanged_slice, remaining) = match position {
                // 1 for first_byte + i unchanged in tail
                Some(i) => self.bytes.split_at(1 + i),
                None => (self.bytes, &[][..]),
            };
            self.bytes = remaining;
            Some(unsafe { str::from_utf8_unchecked(unchanged_slice) })
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.bytes.is_empty() {
            (0, Some(0))
        } else {
            (1, Some(self.bytes.len()))
        }
    }
}

/// The [`application/x-www-form-urlencoded` serializer](
/// https://url.spec.whatwg.org/#concept-urlencoded-serializer).
pub struct Serializer<'a, T: Target> {
    target: Option<T>,
    start_position: usize,
    encoding: EncodingOverride<'a>,
}

pub trait Target {
    fn as_mut_string(&mut self) -> &mut String;
    fn finish(self) -> Self::Finished;
    type Finished;
}

impl Target for String {
    fn as_mut_string(&mut self) -> &mut String {
        self
    }
    fn finish(self) -> Self {
        self
    }
    type Finished = Self;
}

impl<'a> Target for &'a mut String {
    fn as_mut_string(&mut self) -> &mut String {
        &mut **self
    }
    fn finish(self) -> Self {
        self
    }
    type Finished = Self;
}

impl<'a, T: Target> Serializer<'a, T> {
    /// Create a new `application/x-www-form-urlencoded` serializer for the given target.
    ///
    /// If the target is non-empty,
    /// its content is assumed to already be in `application/x-www-form-urlencoded` syntax.
    pub fn new(target: T) -> Self {
        Self::for_suffix(target, 0)
    }

    /// Create a new `application/x-www-form-urlencoded` serializer
    /// for a suffix of the given target.
    ///
    /// If that suffix is non-empty,
    /// its content is assumed to already be in `application/x-www-form-urlencoded` syntax.
    pub fn for_suffix(mut target: T, start_position: usize) -> Self {
        &target.as_mut_string()[start_position..]; // Panic if out of bounds
        Serializer {
            target: Some(target),
            start_position,
            encoding: None,
        }
    }

    /// Remove any existing name/value pair.
    ///
    /// Panics if called after `.finish()`.
    pub fn clear(&mut self) -> &mut Self {
        string(&mut self.target).truncate(self.start_position);
        self
    }

    /// Set the character encoding to be used for names and values before percent-encoding.
    pub fn encoding_override(&mut self, new: EncodingOverride<'a>) -> &mut Self {
        self.encoding = new;
        self
    }

    /// Serialize and append a name/value pair.
    ///
    /// Panics if called after `.finish()`.
    pub fn append_pair(&mut self, name: &str, value: &str) -> &mut Self {
        append_pair(
            string(&mut self.target),
            self.start_position,
            self.encoding,
            name,
            value,
        );
        self
    }

    /// Serialize and append a number of name/value pairs.
    ///
    /// This simply calls `append_pair` repeatedly.
    /// This can be more convenient, so the user doesn’t need to introduce a block
    /// to limit the scope of `Serializer`’s borrow of its string.
    ///
    /// Panics if called after `.finish()`.
    pub fn extend_pairs<I, K, V>(&mut self, iter: I) -> &mut Self
    where
        I: IntoIterator,
        I::Item: Borrow<(K, V)>,
        K: AsRef<str>,
        V: AsRef<str>,
    {
        {
            let string = string(&mut self.target);
            for pair in iter {
                let &(ref k, ref v) = pair.borrow();
                append_pair(
                    string,
                    self.start_position,
                    self.encoding,
                    k.as_ref(),
                    v.as_ref(),
                );
            }
        }
        self
    }

    /// If this serializer was constructed with a string, take and return that string.
    ///
    /// ```rust
    /// use form_urlencoded;
    /// let encoded: String = form_urlencoded::Serializer::new(String::new())
    ///     .append_pair("foo", "bar & baz")
    ///     .append_pair("saison", "Été+hiver")
    ///     .finish();
    /// assert_eq!(encoded, "foo=bar+%26+baz&saison=%C3%89t%C3%A9%2Bhiver");
    /// ```
    ///
    /// Panics if called more than once.
    pub fn finish(&mut self) -> T::Finished {
        self.target
            .take()
            .expect("url::form_urlencoded::Serializer double finish")
            .finish()
    }
}

fn append_separator_if_needed(string: &mut String, start_position: usize) {
    if string.len() > start_position {
        string.push('&')
    }
}

fn string<T: Target>(target: &mut Option<T>) -> &mut String {
    target
        .as_mut()
        .expect("url::form_urlencoded::Serializer finished")
        .as_mut_string()
}

fn append_pair(
    string: &mut String,
    start_position: usize,
    encoding: EncodingOverride,
    name: &str,
    value: &str,
) {
    append_separator_if_needed(string, start_position);
    append_encoded(name, string, encoding);
    string.push('=');
    append_encoded(value, string, encoding);
}

fn append_encoded(s: &str, string: &mut String, encoding: EncodingOverride) {
    string.extend(byte_serialize(&query_encoding::encode(encoding, s.into())))
}
<commit_msg>form_urlencoded: clean up clippy warnings<commit_after>// Copyright 2013-2016 The rust-url developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Parser and serializer for the [`application/x-www-form-urlencoded` syntax](
//! http://url.spec.whatwg.org/#application/x-www-form-urlencoded),
//! as used by HTML forms.
//!
//! Converts between a string (such as an URL’s query string)
//! and a sequence of (name, value) pairs.

extern crate percent_encoding;
#[macro_use]
extern crate matches;

use percent_encoding::{percent_decode, percent_encode_byte};
use query_encoding::decode_utf8_lossy;
use std::borrow::{Borrow, Cow};
use std::str;

mod query_encoding;

pub use query_encoding::EncodingOverride;

/// Convert a byte string in the `application/x-www-form-urlencoded` syntax
/// into a iterator of (name, value) pairs.
///
/// Use `parse(input.as_bytes())` to parse a `&str` string.
///
/// The names and values are percent-decoded. For instance, `%23first=%25try%25` will be
/// converted to `[("#first", "%try%")]`.
#[inline]
pub fn parse(input: &[u8]) -> Parse {
    Parse { input }
}
/// The return type of `parse()`.
#[derive(Copy, Clone)]
pub struct Parse<'a> {
    input: &'a [u8],
}

impl<'a> Iterator for Parse<'a> {
    type Item = (Cow<'a, str>, Cow<'a, str>);

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if self.input.is_empty() {
                return None;
            }
            let mut split2 = self.input.splitn(2, |&b| b == b'&');
            let sequence = split2.next().unwrap();
            self.input = split2.next().unwrap_or(&[][..]);
            if sequence.is_empty() {
                continue;
            }
            let mut split2 = sequence.splitn(2, |&b| b == b'=');
            let name = split2.next().unwrap();
            let value = split2.next().unwrap_or(&[][..]);
            return Some((decode(name), decode(value)));
        }
    }
}

fn decode(input: &[u8]) -> Cow<str> {
    let replaced = replace_plus(input);
    decode_utf8_lossy(match percent_decode(&replaced).into() {
        Cow::Owned(vec) => Cow::Owned(vec),
        Cow::Borrowed(_) => replaced,
    })
}

/// Replace b'+' with b' '
fn replace_plus(input: &[u8]) -> Cow<[u8]> {
    match input.iter().position(|&b| b == b'+') {
        None => Cow::Borrowed(input),
        Some(first_position) => {
            let mut replaced = input.to_owned();
            replaced[first_position] = b' ';
            for byte in &mut replaced[first_position + 1..] {
                if *byte == b'+' {
                    *byte = b' ';
                }
            }
            Cow::Owned(replaced)
        }
    }
}

impl<'a> Parse<'a> {
    /// Return a new iterator that yields pairs of `String` instead of pairs of `Cow<str>`.
    pub fn into_owned(self) -> ParseIntoOwned<'a> {
        ParseIntoOwned { inner: self }
    }
}

/// Like `Parse`, but yields pairs of `String` instead of pairs of `Cow<str>`.
pub struct ParseIntoOwned<'a> {
    inner: Parse<'a>,
}

impl<'a> Iterator for ParseIntoOwned<'a> {
    type Item = (String, String);

    fn next(&mut self) -> Option<Self::Item> {
        self.inner
            .next()
            .map(|(k, v)| (k.into_owned(), v.into_owned()))
    }
}

/// The [`application/x-www-form-urlencoded` byte serializer](
/// https://url.spec.whatwg.org/#concept-urlencoded-byte-serializer).
///
/// Return an iterator of `&str` slices.
pub fn byte_serialize(input: &[u8]) -> ByteSerialize {
    ByteSerialize { bytes: input }
}

/// Return value of `byte_serialize()`.
#[derive(Debug)]
pub struct ByteSerialize<'a> {
    bytes: &'a [u8],
}

fn byte_serialized_unchanged(byte: u8) -> bool {
    matches!(byte, b'*' | b'-' | b'.' | b'0' ..= b'9' | b'A' ..= b'Z' | b'_' | b'a' ..= b'z')
}

impl<'a> Iterator for ByteSerialize<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        if let Some((&first, tail)) = self.bytes.split_first() {
            if !byte_serialized_unchanged(first) {
                self.bytes = tail;
                return Some(if first == b' ' {
                    "+"
                } else {
                    percent_encode_byte(first)
                });
            }
            let position = tail.iter().position(|&b| !byte_serialized_unchanged(b));
            let (unchanged_slice, remaining) = match position {
                // 1 for first_byte + i unchanged in tail
                Some(i) => self.bytes.split_at(1 + i),
                None => (self.bytes, &[][..]),
            };
            self.bytes = remaining;
            Some(unsafe { str::from_utf8_unchecked(unchanged_slice) })
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.bytes.is_empty() {
            (0, Some(0))
        } else {
            (1, Some(self.bytes.len()))
        }
    }
}

/// The [`application/x-www-form-urlencoded` serializer](
/// https://url.spec.whatwg.org/#concept-urlencoded-serializer).
pub struct Serializer<'a, T: Target> {
    target: Option<T>,
    start_position: usize,
    encoding: EncodingOverride<'a>,
}

pub trait Target {
    fn as_mut_string(&mut self) -> &mut String;
    fn finish(self) -> Self::Finished;
    type Finished;
}

impl Target for String {
    fn as_mut_string(&mut self) -> &mut String {
        self
    }
    fn finish(self) -> Self {
        self
    }
    type Finished = Self;
}

impl<'a> Target for &'a mut String {
    fn as_mut_string(&mut self) -> &mut String {
        &mut **self
    }
    fn finish(self) -> Self {
        self
    }
    type Finished = Self;
}

impl<'a, T: Target> Serializer<'a, T> {
    /// Create a new `application/x-www-form-urlencoded` serializer for the given target.
    ///
    /// If the target is non-empty,
    /// its content is assumed to already be in `application/x-www-form-urlencoded` syntax.
    pub fn new(target: T) -> Self {
        Self::for_suffix(target, 0)
    }

    /// Create a new `application/x-www-form-urlencoded` serializer
    /// for a suffix of the given target.
    ///
    /// If that suffix is non-empty,
    /// its content is assumed to already be in `application/x-www-form-urlencoded` syntax.
    pub fn for_suffix(mut target: T, start_position: usize) -> Self {
        if target.as_mut_string().len() < start_position {
            panic!(
                "invalid length {} for target of length {}",
                start_position,
                target.as_mut_string().len()
            );
        }

        Serializer {
            target: Some(target),
            start_position,
            encoding: None,
        }
    }

    /// Remove any existing name/value pair.
    ///
    /// Panics if called after `.finish()`.
    pub fn clear(&mut self) -> &mut Self {
        string(&mut self.target).truncate(self.start_position);
        self
    }

    /// Set the character encoding to be used for names and values before percent-encoding.
    pub fn encoding_override(&mut self, new: EncodingOverride<'a>) -> &mut Self {
        self.encoding = new;
        self
    }

    /// Serialize and append a name/value pair.
    ///
    /// Panics if called after `.finish()`.
    pub fn append_pair(&mut self, name: &str, value: &str) -> &mut Self {
        append_pair(
            string(&mut self.target),
            self.start_position,
            self.encoding,
            name,
            value,
        );
        self
    }

    /// Serialize and append a number of name/value pairs.
    ///
    /// This simply calls `append_pair` repeatedly.
    /// This can be more convenient, so the user doesn’t need to introduce a block
    /// to limit the scope of `Serializer`’s borrow of its string.
    ///
    /// Panics if called after `.finish()`.
    pub fn extend_pairs<I, K, V>(&mut self, iter: I) -> &mut Self
    where
        I: IntoIterator,
        I::Item: Borrow<(K, V)>,
        K: AsRef<str>,
        V: AsRef<str>,
    {
        {
            let string = string(&mut self.target);
            for pair in iter {
                let &(ref k, ref v) = pair.borrow();
                append_pair(
                    string,
                    self.start_position,
                    self.encoding,
                    k.as_ref(),
                    v.as_ref(),
                );
            }
        }
        self
    }

    /// If this serializer was constructed with a string, take and return that string.
    ///
    /// ```rust
    /// use form_urlencoded;
    /// let encoded: String = form_urlencoded::Serializer::new(String::new())
    ///     .append_pair("foo", "bar & baz")
    ///     .append_pair("saison", "Été+hiver")
    ///     .finish();
    /// assert_eq!(encoded, "foo=bar+%26+baz&saison=%C3%89t%C3%A9%2Bhiver");
    /// ```
    ///
    /// Panics if called more than once.
    pub fn finish(&mut self) -> T::Finished {
        self.target
            .take()
            .expect("url::form_urlencoded::Serializer double finish")
            .finish()
    }
}

fn append_separator_if_needed(string: &mut String, start_position: usize) {
    if string.len() > start_position {
        string.push('&')
    }
}

fn string<T: Target>(target: &mut Option<T>) -> &mut String {
    target
        .as_mut()
        .expect("url::form_urlencoded::Serializer finished")
        .as_mut_string()
}

fn append_pair(
    string: &mut String,
    start_position: usize,
    encoding: EncodingOverride,
    name: &str,
    value: &str,
) {
    append_separator_if_needed(string, start_position);
    append_encoded(name, string, encoding);
    string.push('=');
    append_encoded(value, string, encoding);
}

fn append_encoded(s: &str, string: &mut String, encoding: EncodingOverride) {
    string.extend(byte_serialize(&query_encoding::encode(encoding, s)))
}
<|endoftext|>


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

//! Data structures representing (multiple) selections and cursors.

// TODO: actually use these
#![allow(unused)]

use std::cmp::{min, max};
use std::ops::Deref;
use index_set::remove_n_at;

/// A type representing horizontal measurements. This is currently in units
/// that are not very well defined except that ASCII characters count as
/// 1 each. It will change.
pub type HorizPos = usize;

/// A set of zero or more selection regions, representing a selection state.
#[derive(Default, Debug)]
pub struct Selection {
    // an invariant: regions[i].max() <= regions[i+1].min()
    // and < if either is_caret()
    regions: Vec<SelRegion>,
}

impl Selection {
    /// Creates a new empty selection.
    pub fn new() -> Selection {
        Selection::default()
    }

    /// Clear the selection.
    pub fn clear(&mut self) {
        self.regions.clear();
    }

    // The smallest index so that offset > region.max() for all preceding
    // regions.
    fn search(&self, offset: usize) -> usize {
        if self.regions.is_empty() || offset > self.regions.last().unwrap().max() {
            return self.regions.len();
        }
        match self.regions.binary_search_by(|r| r.max().cmp(&offset)) {
            Ok(ix) => ix,
            Err(ix) => ix,
        }
    }

    /// Add a region to the selection. This method implements merging logic.
    ///
    /// Two non-caret regions merge if their interiors intersect; merely
    /// touching at the edges does not cause a merge. A caret merges with
    /// a non-caret if it is in the interior or on either edge. Two carets
    /// merge if they are the same offset.
    ///
    /// Performance note: should be O(1) if the new region strictly comes
    /// after all the others in the selection, otherwise O(n).
    pub fn add_region(&mut self, region: SelRegion) {
        let mut ix = self.search(region.min());
        if ix == self.regions.len() {
            self.regions.push(region);
            return;
        }
        let mut region = region;
        let mut end_ix = ix;
        if self.regions[ix].min() <= region.min() {
            if self.regions[ix].should_merge(&region) {
                region = self.regions[ix].merge_with(&region);
            } else {
                ix += 1;
            }
            end_ix += 1;
        }
        while end_ix < self.regions.len() && region.should_merge(&self.regions[end_ix]) {
            region = region.merge_with(&self.regions[end_ix]);
            end_ix += 1;
        }
        if ix == end_ix {
            self.regions.insert(ix, region);
        } else {
            self.regions[ix] = region;
            remove_n_at(&mut self.regions, ix + 1, end_ix - ix - 1);
        }
    }

    /// Gets a slice of regions that intersect the given range. Regions that
    /// merely touch the range at the edges are also included, so it is the
    /// caller's responsibility to further trim them, in particular to only
    /// display one caret in the upstream/downstream cases.
    ///
    /// Performance note: O(log n).
    pub fn regions_in_range(&self, start: usize, end: usize) -> &[SelRegion] {
        let first = self.search(start);
        let mut last = self.search(end);
        if last < self.regions.len() && self.regions[last].min() <= end {
            last += 1;
        }
        &self.regions[first..last]
    }
}

/// Implementing the Deref trait allows callers to easily test `is_empty`, iterate
/// through all ranges, etc.
impl Deref for Selection {
    type Target = [SelRegion];

    fn deref(&self) -> &[SelRegion] {
        &self.regions
    }
}

/// A type representing a single contiguous region of a selection.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct SelRegion {
    /// The inactive edge of a selection, as a byte offset. When
    /// equal to end, the selection rage acts as a caret.
    pub start: usize,

    /// The active edge of a selection, as a byte offset.
    pub end: usize,

    /// A saved horizontal position (used primarily for line up/down movement)
    pub horiz: Option<HorizPos>,

    /// If the buffer is "abcd" and there is a line break between "ab" and
    /// "cd" and the cursor is positioned at that break, then is_upstream
    /// true causes the cursor to display after "ab" on the preceding line,
    /// while false causes the cursor to display before "cd" on the second
    /// line.
    // Discussion: should this be an enum ("affinity")?
    pub is_upstream: bool,
}

impl SelRegion {
    /// Gets the earliest offset within the region, ie the minimum of both edges.
    pub fn min(&self) -> usize {
        min(self.start, self.end)
    }

    /// Gets the earliest latest within the region, ie the maximum of both edges.
    pub fn max(&self) -> usize {
        max(self.start, self.end)
    }

    /// Determines whether the region is a caret (ie has no interior).
    pub fn is_caret(&self) -> bool {
        self.start == self.end
    }

    // Indicate whether this region should merge with the next.
    // Assumption: regions are sorted (self.min() <= other.min())
    fn should_merge(&self, other: &SelRegion) -> bool {
        other.min() < self.max() ||
            ((self.is_caret() || other.is_caret()) && other.min() == self.max())
    }

    fn merge_with(&self, other: &SelRegion) -> SelRegion {
        let is_forward = self.end > self.start || other.end > other.start;
        let new_min = min(self.min(), other.min());
        let new_max = max(self.max(), other.max());
        let (start, end) = if is_forward {
            (new_min, new_max)
        } else {
            (new_max, new_min)
        };
        SelRegion {
            start: start,
            end: end,
            // Could try to preserve horiz/affinity from one of the
            // sources, but very likely not worth it.
            horiz: None,
            is_upstream: false,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Selection, SelRegion};
    use std::ops::Deref;

    fn r(start: usize, end: usize) -> SelRegion {
        SelRegion {
            start: start,
            end: end,
            horiz: None,
            is_upstream: false,
        }
    }

    #[test]
    fn empty() {
        let s = Selection::new();
        assert!(s.is_empty());
        assert_eq!(s.deref(), &[]);
    }

    #[test]
    fn simple_region() {
        let mut s = Selection::new();
        s.add_region(r(3, 5));
        assert!(!s.is_empty());
        assert_eq!(s.deref(), &[r(3, 5)]);
    }

    #[test]
    fn simple_regions_in_range() {
        let mut s = Selection::new();
        s.add_region(r(3, 5));
        assert_eq!(s.regions_in_range(0, 1), &[]);
        assert_eq!(s.regions_in_range(0, 2), &[]);
        assert_eq!(s.regions_in_range(0, 3), &[r(3, 5)]);
        assert_eq!(s.regions_in_range(0, 4), &[r(3, 5)]);
        assert_eq!(s.regions_in_range(5, 6), &[r(3, 5)]);
        assert_eq!(s.regions_in_range(6, 7), &[]);
    }

    #[test]
    fn caret_regions_in_range() {
        let mut s = Selection::new();
        s.add_region(r(4, 4));
        assert_eq!(s.regions_in_range(0, 1), &[]);
        assert_eq!(s.regions_in_range(0, 2), &[]);
        assert_eq!(s.regions_in_range(0, 3), &[]);
        assert_eq!(s.regions_in_range(0, 4), &[r(4, 4)]);
        assert_eq!(s.regions_in_range(4, 4), &[r(4, 4)]);
        assert_eq!(s.regions_in_range(4, 5), &[r(4, 4)]);
        assert_eq!(s.regions_in_range(5, 6), &[]);
    }

    #[test]
    fn merge_regions() {
        let mut s = Selection::new();
        s.add_region(r(3, 5));
        assert_eq!(s.deref(), &[r(3, 5)]);
        s.add_region(r(7, 9));
        assert_eq!(s.deref(), &[r(3, 5), r(7, 9)]);
        s.add_region(r(1, 3));
        assert_eq!(s.deref(), &[r(1, 3), r(3, 5), r(7, 9)]);
        s.add_region(r(4, 6));
        assert_eq!(s.deref(), &[r(1, 3), r(3, 6), r(7, 9)]);
        s.add_region(r(2, 8));
        assert_eq!(s.deref(), &[r(1, 9)]);

        s.clear();
        assert_eq!(s.deref(), &[]);
        s.add_region(r(1, 4));
        s.add_region(r(4, 5));
        s.add_region(r(5, 6));
        s.add_region(r(6, 9));
        assert_eq!(s.deref(), &[r(1, 4), r(4, 5), r(5, 6), r(6, 9)]);
        s.add_region(r(2, 8));
        assert_eq!(s.deref(), &[r(1, 9)]);
    }

    #[test]
    fn merge_carets() {
        let mut s = Selection::new();
        s.add_region(r(1, 1));
        assert_eq!(s.deref(), &[r(1, 1)]);
        s.add_region(r(3, 3));
        assert_eq!(s.deref(), &[r(1, 1), r(3, 3)]);
        s.add_region(r(2, 2));
        assert_eq!(s.deref(), &[r(1, 1), r(2, 2), r(3, 3)]);
        s.add_region(r(1, 1));
        assert_eq!(s.deref(), &[r(1, 1), r(2, 2), r(3, 3)]);
    }

    #[test]
    fn merge_region_caret() {
        let mut s = Selection::new();
        s.add_region(r(3, 5));
        assert_eq!(s.deref(), &[r(3, 5)]);
        s.add_region(r(3, 3));
        assert_eq!(s.deref(), &[r(3, 5)]);
        s.add_region(r(4, 4));
        assert_eq!(s.deref(), &[r(3, 5)]);
        s.add_region(r(5, 5));
        assert_eq!(s.deref(), &[r(3, 5)]);
        s.add_region(r(6, 6));
        assert_eq!(s.deref(), &[r(3, 5), r(6, 6)]);
    }

    #[test]
    fn merge_reverse() {
        let mut s = Selection::new();
        s.add_region(r(5, 3));
        assert_eq!(s.deref(), &[r(5, 3)]);
        s.add_region(r(9, 7));
        assert_eq!(s.deref(), &[r(5, 3), r(9, 7)]);
        s.add_region(r(3, 1));
        assert_eq!(s.deref(), &[r(3, 1), r(5, 3), r(9, 7)]);
        s.add_region(r(6, 4));
        assert_eq!(s.deref(), &[r(3, 1), r(6, 3), r(9, 7)]);
        s.add_region(r(8, 2));
        assert_eq!(s.deref(), &[r(9, 1)]);
    }
}
<commit_msg>Change affinity into an enum, refine docs<commit_after>// Copyright 2017 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Data structures representing (multiple) selections and cursors.

// TODO: actually use these
#![allow(unused)]

use std::cmp::{min, max};
use std::ops::Deref;
use index_set::remove_n_at;

/// A type representing horizontal measurements. This is currently in units
/// that are not very well defined except that ASCII characters count as
/// 1 each. It will change.
pub type HorizPos = usize;

/// A set of zero or more selection regions, representing a selection state.
#[derive(Default, Debug)]
pub struct Selection {
    // an invariant: regions[i].max() <= regions[i+1].min()
    // and < if either is_caret()
    regions: Vec<SelRegion>,
}

impl Selection {
    /// Creates a new empty selection.
    pub fn new() -> Selection {
        Selection::default()
    }

    /// Clear the selection.
    pub fn clear(&mut self) {
        self.regions.clear();
    }

    // The smallest index so that offset > region.max() for all preceding
    // regions.
    fn search(&self, offset: usize) -> usize {
        if self.regions.is_empty() || offset > self.regions.last().unwrap().max() {
            return self.regions.len();
        }
        match self.regions.binary_search_by(|r| r.max().cmp(&offset)) {
            Ok(ix) => ix,
            Err(ix) => ix,
        }
    }

    /// Add a region to the selection. This method implements merging logic.
    ///
    /// Two non-caret regions merge if their interiors intersect; merely
    /// touching at the edges does not cause a merge. A caret merges with
    /// a non-caret if it is in the interior or on either edge. Two carets
    /// merge if they are the same offset.
    ///
    /// Performance note: should be O(1) if the new region strictly comes
    /// after all the others in the selection, otherwise O(n).
    pub fn add_region(&mut self, region: SelRegion) {
        let mut ix = self.search(region.min());
        if ix == self.regions.len() {
            self.regions.push(region);
            return;
        }
        let mut region = region;
        let mut end_ix = ix;
        if self.regions[ix].min() <= region.min() {
            if self.regions[ix].should_merge(&region) {
                region = self.regions[ix].merge_with(&region);
            } else {
                ix += 1;
            }
            end_ix += 1;
        }
        while end_ix < self.regions.len() && region.should_merge(&self.regions[end_ix]) {
            region = region.merge_with(&self.regions[end_ix]);
            end_ix += 1;
        }
        if ix == end_ix {
            self.regions.insert(ix, region);
        } else {
            self.regions[ix] = region;
            remove_n_at(&mut self.regions, ix + 1, end_ix - ix - 1);
        }
    }

    /// Gets a slice of regions that intersect the given range. Regions that
    /// merely touch the range at the edges are also included, so it is the
    /// caller's responsibility to further trim them, in particular to only
    /// display one caret in the upstream/downstream cases.
    ///
    /// Performance note: O(log n).
    pub fn regions_in_range(&self, start: usize, end: usize) -> &[SelRegion] {
        let first = self.search(start);
        let mut last = self.search(end);
        if last < self.regions.len() && self.regions[last].min() <= end {
            last += 1;
        }
        &self.regions[first..last]
    }
}

/// Implementing the Deref trait allows callers to easily test `is_empty`, iterate
/// through all ranges, etc.
impl Deref for Selection {
    type Target = [SelRegion];

    fn deref(&self) -> &[SelRegion] {
        &self.regions
    }
}

/// The "affinity" of a cursor which is sitting exactly on a line break.
///
/// We say "cursor" here rather than "caret" because (depending on presentation)
/// the front-end may draw a cursor even when the region is not a caret.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Affinity {
    /// The cursor should be displayed downstream of the line break. For
    /// example, if the buffer is "abcd", and the cursor is on a line break
    /// after "ab", it should be displayed on the second line before "cd".
    Downstream,
    /// The cursor should be displayed upstream of the line break. For
    /// example, if the buffer is "abcd", and the cursor is on a line break
    /// after "ab", it should be displayed on the previous line after "ab".
    Upstream,
}

impl Default for Affinity {
    fn default() -> Affinity {
        Affinity::Downstream
    }
}

/// A type representing a single contiguous region of a selection. We use the
/// term "caret" (sometimes also "cursor", more loosely) to refer to a selection
/// region with an empty interior. A "non-caret region" is one with a non-empty
/// interior (i.e. `start != end`).
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct SelRegion {
    /// The inactive edge of a selection, as a byte offset. When
    /// equal to end, the selection rage acts as a caret.
    pub start: usize,

    /// The active edge of a selection, as a byte offset.
    pub end: usize,

    /// A saved horizontal position (used primarily for line up/down movement)
    pub horiz: Option<HorizPos>,

    /// The affinity of the cursor.
    pub affinity: Affinity,
}

impl SelRegion {
    /// Gets the earliest offset within the region, ie the minimum of both edges.
    pub fn min(&self) -> usize {
        min(self.start, self.end)
    }

    /// Gets the earliest latest within the region, ie the maximum of both edges.
    pub fn max(&self) -> usize {
        max(self.start, self.end)
    }

    /// Determines whether the region is a caret (ie has an empty interior).
    pub fn is_caret(&self) -> bool {
        self.start == self.end
    }

    // Indicate whether this region should merge with the next.
    // Assumption: regions are sorted (self.min() <= other.min())
    fn should_merge(&self, other: &SelRegion) -> bool {
        other.min() < self.max() ||
            ((self.is_caret() || other.is_caret()) && other.min() == self.max())
    }

    fn merge_with(&self, other: &SelRegion) -> SelRegion {
        let is_forward = self.end > self.start || other.end > other.start;
        let new_min = min(self.min(), other.min());
        let new_max = max(self.max(), other.max());
        let (start, end) = if is_forward {
            (new_min, new_max)
        } else {
            (new_max, new_min)
        };
        SelRegion {
            start: start,
            end: end,
            // Could try to preserve horiz/affinity from one of the
            // sources, but very likely not worth it.
            horiz: None,
            affinity: Affinity::default(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Selection, SelRegion};
    use std::ops::Deref;

    fn r(start: usize, end: usize) -> SelRegion {
        SelRegion {
            start: start,
            end: end,
            horiz: None,
            is_upstream: false,
        }
    }

    #[test]
    fn empty() {
        let s = Selection::new();
        assert!(s.is_empty());
        assert_eq!(s.deref(), &[]);
    }

    #[test]
    fn simple_region() {
        let mut s = Selection::new();
        s.add_region(r(3, 5));
        assert!(!s.is_empty());
        assert_eq!(s.deref(), &[r(3, 5)]);
    }

    #[test]
    fn simple_regions_in_range() {
        let mut s = Selection::new();
        s.add_region(r(3, 5));
        assert_eq!(s.regions_in_range(0, 1), &[]);
        assert_eq!(s.regions_in_range(0, 2), &[]);
        assert_eq!(s.regions_in_range(0, 3), &[r(3, 5)]);
        assert_eq!(s.regions_in_range(0, 4), &[r(3, 5)]);
        assert_eq!(s.regions_in_range(5, 6), &[r(3, 5)]);
        assert_eq!(s.regions_in_range(6, 7), &[]);
    }

    #[test]
    fn caret_regions_in_range() {
        let mut s = Selection::new();
        s.add_region(r(4, 4));
        assert_eq!(s.regions_in_range(0, 1), &[]);
        assert_eq!(s.regions_in_range(0, 2), &[]);
        assert_eq!(s.regions_in_range(0, 3), &[]);
        assert_eq!(s.regions_in_range(0, 4), &[r(4, 4)]);
        assert_eq!(s.regions_in_range(4, 4), &[r(4, 4)]);
        assert_eq!(s.regions_in_range(4, 5), &[r(4, 4)]);
        assert_eq!(s.regions_in_range(5, 6), &[]);
    }

    #[test]
    fn merge_regions() {
        let mut s = Selection::new();
        s.add_region(r(3, 5));
        assert_eq!(s.deref(), &[r(3, 5)]);
        s.add_region(r(7, 9));
        assert_eq!(s.deref(), &[r(3, 5), r(7, 9)]);
        s.add_region(r(1, 3));
        assert_eq!(s.deref(), &[r(1, 3), r(3, 5), r(7, 9)]);
        s.add_region(r(4, 6));
        assert_eq!(s.deref(), &[r(1, 3), r(3, 6), r(7, 9)]);
        s.add_region(r(2, 8));
        assert_eq!(s.deref(), &[r(1, 9)]);

        s.clear();
        assert_eq!(s.deref(), &[]);
        s.add_region(r(1, 4));
        s.add_region(r(4, 5));
        s.add_region(r(5, 6));
        s.add_region(r(6, 9));
        assert_eq!(s.deref(), &[r(1, 4), r(4, 5), r(5, 6), r(6, 9)]);
        s.add_region(r(2, 8));
        assert_eq!(s.deref(), &[r(1, 9)]);
    }

    #[test]
    fn merge_carets() {
        let mut s = Selection::new();
        s.add_region(r(1, 1));
        assert_eq!(s.deref(), &[r(1, 1)]);
        s.add_region(r(3, 3));
        assert_eq!(s.deref(), &[r(1, 1), r(3, 3)]);
        s.add_region(r(2, 2));
        assert_eq!(s.deref(), &[r(1, 1), r(2, 2), r(3, 3)]);
        s.add_region(r(1, 1));
        assert_eq!(s.deref(), &[r(1, 1), r(2, 2), r(3, 3)]);
    }

    #[test]
    fn merge_region_caret() {
        let mut s = Selection::new();
        s.add_region(r(3, 5));
        assert_eq!(s.deref(), &[r(3, 5)]);
        s.add_region(r(3, 3));
        assert_eq!(s.deref(), &[r(3, 5)]);
        s.add_region(r(4, 4));
        assert_eq!(s.deref(), &[r(3, 5)]);
        s.add_region(r(5, 5));
        assert_eq!(s.deref(), &[r(3, 5)]);
        s.add_region(r(6, 6));
        assert_eq!(s.deref(), &[r(3, 5), r(6, 6)]);
    }

    #[test]
    fn merge_reverse() {
        let mut s = Selection::new();
        s.add_region(r(5, 3));
        assert_eq!(s.deref(), &[r(5, 3)]);
        s.add_region(r(9, 7));
        assert_eq!(s.deref(), &[r(5, 3), r(9, 7)]);
        s.add_region(r(3, 1));
        assert_eq!(s.deref(), &[r(3, 1), r(5, 3), r(9, 7)]);
        s.add_region(r(6, 4));
        assert_eq!(s.deref(), &[r(3, 1), r(6, 3), r(9, 7)]);
        s.add_region(r(8, 2));
        assert_eq!(s.deref(), &[r(9, 1)]);
    }
}
<|endoftext|>


<commit_before><commit_msg>Remove let binding for unit value<commit_after><|endoftext|>


<commit_before><commit_msg>feat: add AST definistions<commit_after>use lexer::Token::{Name, Int as IntValue, Float as FloatValue, String as StringValue};

/// Document : Definition+
pub struct Document {
  pub definitions: Vec<Definition>
}

/// Definition :
///   - OperationDefinition
///   - FragmentDefinition
pub enum Definition {
  Operation(OperationDefinition),
  Fragment(FragmentDefinition)
}

/// OperationDefinition :
///   - SelectionSet
///   - OperationType Name? VariableDefinitions? Directives? SelectionSet
pub struct OperationDefinition {
  pub operation_type: OperationType,
  pub name: Option<Name>,
  pub variable_definitions: Option<VariableDefinitions>,
  pub directives: Option<Directives>,
  pub selection_set: SelectionSet
}

/// OperationType : one of query mutation
pub enum OperationType {
  Query,
  Mutation
}

/// SelectionSet : { Selection+ }
pub type SelectionSet = Vec<Selection>;

/// Selection :
///   - Field
///   - FragmentSpread
///   - InlineFragment
pub enum Selection {
  Field(Field),
  FragmentSpread(FragmentSpread),
  InlineFragment(InlineFragment)
}

/// Field : Alias? Name Arguments? Directives? SelectionSet?
pub struct Field {
  pub alias: Option<Alias>,
  pub name: Name,
  pub arguments: Option<Arguments>,
  pub directives: Option<Directives>,
  pub selection_set: Option<SelectionSet>
}

/// Alias : Name :
pub type Alias = Name;

/// Arguments : ( Argument+ )
pub type Arguments = Vec<Argument>;

/// Argument : Name : Value
pub struct Argument {
  pub name: Name,
  pub value: Value
}

/// FragmentSpread : ... FragmentName Directives?
pub struct FragmentSpread {
  pub fragment_name: Name,
  pub directives: Option<Directives>
}

/// InlineFragment : ... TypeCondition? Directives? SelectionSet
pub struct InlineFragment {
  pub type_condition: Option<TypeCondition>,
  pub directives: Option<Directives>,
  pub selection_set: SelectionSet
}

/// FragmentDefinition : fragment FragmentName TypeCondition Directives? SelectionSet
pub struct FragmentDefinition {
  pub fragment_name: Name,
  pub type_condition: TypeCondition,
  pub directives: Option<Directives>,
  pub selection_set: SelectionSet
}

/// FragmentName : Name but not `on`
pub type FragmentName = Name;

/// TypeCondition : on NamedType
pub type TypeCondition = NamedType;

/// Value[Const] :
///   - [~Const] Variable
///   - IntValue
///   - FloatValue
///   - StringValue
///   - BooleanValue
///   - EnumValue
///   - ListValue[?Const]
///   - ObjectValue[?Const]
pub enum Value {
  Variable(Variable),
  Int(IntValue),
  Float(FloatValue),
  String(StringValue),
  Boolean(BooleanValue),
  Enum(EnumValue),
  List(ListValue),
  Object(ObjectValue)
}

/// BooleanValue : one of `true` `false`
pub enum BooleanValue {
  True,
  False
}

/// EnumValue : Name but not `true`, `false` or `null`
pub struct EnumValue {
  pub name: Name
}

/// ListValue[Const] :
///   - [ ]
///   - [ Value[?Const]+ ]
pub type ListValue = Vec<Value>;

/// ObjectValue[Const] :
///   - { }
///   - { ObjectField[?Const]+ }
pub type ObjectValue = Vec<ObjectField>;

/// ObjectField[Const] : Name : Value[?Const]
pub struct ObjectField {
  pub name: Name,
  pub value: Value
}

/// VariableDefinitions : ( VariableDefinition+ )
pub type VariableDefinitions = Vec<VariableDefinition>;

/// VariableDefinition : Variable : Type DefaultValue?
pub struct VariableDefinition {
  pub variable: Variable,
  pub type_: Type,
  pub default_value: Option<DefaultValue>
}

/// Variable : $ Name
pub type Variable = Name;

/// DefaultValue : = Value[Const]
pub type DefaultValue = Value;

/// Type :
///   - NamedType
///   - ListType
///   - NonNullType
pub enum Type {
  Named(NamedType),
  List(ListType),
  NonNull(NonNullType)
}

/// NamedType : Name
pub type NamedType = Name;

/// ListType : [ Type ]
pub type ListType = Name;

/// NonNullType :
///   - NamedType !
///   - ListType !
pub enum NonNullType {
  Named(NamedType),
  List(ListType)
}

/// Directives : Directive+
pub type Directives = Vec<Directive>;

/// Directive : @ Name Arguments?
pub struct Directive {
  pub name: Name,
  pub arguments: Option<Arguments>
}
<|endoftext|>


<commit_before><commit_msg>Resource loader<commit_after>use std::io;
use std::fs;

pub trait ResourceLoader<I, T> {
	fn load_resource(key: I) -> Box<[T]>;
}

struct FileSystemResourceLoader {
	root: Path,
}

impl FileSystemResourceLoader {
	fn new(root: Path) -> Self {
		FileSystemResourceLoader { root: root }
	}
}

impl ResourceLoader<&str, u8> for FileSystemResourceLoader {
	fn load_resource(key: &str) -> Box<[u8]> {

	}
}
<|endoftext|>


<commit_before><commit_msg>error due to same name of function in both traits<commit_after><|endoftext|>


<commit_before><commit_msg>writer mod: Truncate the output file if it exists<commit_after><|endoftext|>


<commit_before><commit_msg>add some simple tests to stty (still failing)<commit_after>use crate::common::util::*;

#[test]
fn runs() {
    new_ucmd!().succeeds();
}

#[test]
fn print_all() {
    let res = new_ucmd!().succeeds();

    // Random selection of flags to check for
    for flag in [
        "parenb", "parmrk", "ixany", "iuclc", "onlcr", "ofdel", "icanon", "noflsh",
    ] {
        res.stdout_contains(flag);
    }
}
<|endoftext|>


<commit_before><commit_msg>test(publish): Verify updating existing entries works<commit_after><|endoftext|>


<commit_before><commit_msg>2019: Day 15, part 2.<commit_after>use std::collections::HashSet;
use std::collections::VecDeque;
use std::io;

mod digits;
mod errors;
mod intcode;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct Position {
    x: isize,
    y: isize,
}

impl Position {
    const ZERO: Self = Self { x: 0, y: 0 };
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum Direction {
    North,
    South,
    West,
    East,
}

impl Direction {
    fn all() -> Vec<Self> {
        vec![Self::North, Self::East, Self::South, Self::West]
    }

    fn except(excluded: &Self) -> Vec<Self> {
        match excluded {
            Self::North => vec![Self::East, Self::South, Self::West],
            Self::East => vec![Self::North, Self::South, Self::West],
            Self::South => vec![Self::North, Self::East, Self::West],
            Self::West => vec![Self::North, Self::East, Self::South],
        }
    }

    fn opposite(&self) -> Self {
        match self {
            Self::North => Self::South,
            Self::East => Self::West,
            Self::South => Self::North,
            Self::West => Self::East,
        }
    }

    fn to_code(&self) -> intcode::Code {
        match self {
            Self::North => 1,
            Self::South => 2,
            Self::West => 3,
            Self::East => 4,
        }
    }

    fn advance(&self, position: &Position) -> Position {
        match self {
            Self::North => Position {
                x: position.x,
                y: position.y - 1,
            },
            Self::South => Position {
                x: position.x,
                y: position.y + 1,
            },
            Self::West => Position {
                x: position.x - 1,
                y: position.y,
            },
            Self::East => Position {
                x: position.x + 1,
                y: position.y,
            },
        }
    }
}

type Path = VecDeque<Direction>;

#[derive(Debug, Clone, Copy, PartialEq)]
enum RunResult {
    ValidPath,
    HitWall,
    Found,
}

impl RunResult {
    fn successful(&self) -> bool {
        match self {
            Self::ValidPath => true,
            Self::HitWall => false,
            Self::Found => true,
        }
    }
}

#[derive(Debug, Clone)]
struct State {
    path: Path,
    result: Option<RunResult>,
}

fn main() -> io::Result<()> {
    let mut code = String::new();
    io::stdin().read_line(&mut code)?;
    let program = intcode::parse(&code)?;

    let prefix = VecDeque::new();

    let mut successes: HashSet<Path> = HashSet::new();
    successes.insert(VecDeque::new());
    let mut found: Option<Path> = None;
    while found.is_none() {
        let last_successes: Vec<Path> = successes.drain().collect();
        last_successes
            .iter()
            .flat_map(|success| step(&program, &prefix, success))
            .filter(|(_, result)| result.successful())
            .for_each(|(path, result)| {
                if result == RunResult::Found {
                    found = Some(path);
                } else {
                    successes.insert(path);
                }
            });
    }

    let path_to_oxygen_tank = found.unwrap();
    successes.clear();
    successes.insert(VecDeque::new());
    let mut max_distance = 0;
    while !successes.is_empty() {
        let last_successes: Vec<Path> = successes.drain().collect();
        last_successes
            .iter()
            .flat_map(|success| step(&program, &path_to_oxygen_tank, success))
            .filter(|(_, result)| result.successful())
            .for_each(|(path, _)| {
                if path.len() > max_distance {
                    max_distance = path.len();
                }
                successes.insert(path);
            });
    }

    println!("{:?}", max_distance);

    Ok(())
}

fn step<'a>(
    program: &'a intcode::Program,
    prefix: &'a Path,
    success: &'a Path,
) -> impl Iterator<Item = (Path, RunResult)> + 'a {
    let directions = match success.back() {
        None => Direction::all(),
        Some(last) => Direction::except(&last.opposite()),
    };
    directions
        .into_iter()
        .map(move |direction| {
            let mut path = success.clone();
            path.push_back(direction);
            path
        })
        .filter(|path| !loops(path))
        .map(move |path| {
            let full_path = prefix
                .iter()
                .cloned()
                .chain(path.iter().cloned())
                .collect::<Path>();
            let result = run(program.clone(), full_path);
            (path, result)
        })
}

fn loops(path: &Path) -> bool {
    let mut positions: HashSet<Position> = HashSet::new();
    let mut position = Position::ZERO;
    positions.insert(position);
    for direction in path {
        position = direction.advance(&position);
        if positions.contains(&position) {
            return true;
        }
        positions.insert(position);
    }
    false
}

fn run(program: intcode::Program, mut path: Path) -> RunResult {
    let first = path.pop_front().unwrap();
    let device = intcode::CooperativeDevice::new(
        State { path, result: None },
        vec![first.to_code()],
        |mut state, output| match output {
            0 => {
                state.result = Some(RunResult::HitWall);
                (state, vec![])
            }
            1 => match state.path.pop_front() {
                None => {
                    state.result = Some(RunResult::ValidPath);
                    (state, vec![])
                }
                Some(first) => (state, vec![first.to_code()]),
            },
            2 => match state.path.pop_front() {
                None => {
                    state.result = Some(RunResult::Found);
                    (state, vec![])
                }
                Some(first) => (state, vec![first.to_code()]),
            },
            _ => panic!("Invalid output: {}", output),
        },
    );
    let (_, state) = intcode::evaluate(program.clone(), device);
    state.result.unwrap()
}
<|endoftext|>


<commit_before><commit_msg>Add a simple "hello" example<commit_after>extern crate futures;
extern crate tokio_core;

use futures::stream::Stream;
use tokio_core::reactor::Core;
use tokio_core::net::TcpListener;

fn main() {
    let mut core = Core::new().unwrap();
    let address = "127.0.0.1:8080".parse().unwrap();
    let listener = TcpListener::bind(&address, &core.handle()).unwrap();

    let addr = listener.local_addr().unwrap();
    println!("Listening for connections on {}", addr);

    let clients = listener.incoming();
    let welcomes = clients.and_then(|(socket, _peer_addr)| {
        tokio_core::io::write_all(socket, b"Hello!\n")
    });
    let server = welcomes.for_each(|(_socket, _welcome)| {
        Ok(())
    });

    core.run(server).unwrap();
}
<|endoftext|>