<commit_before>#![feature(macro_rules)]

struct Tree<T> {
    root: Option<~Node<T>>
}
pub struct Node<T> {
    left_child: Option<~Node<T>>,
    right_child: Option<~Node<T>>,
    key: T
}

macro_rules! tree_iterator(
    ($name:ident -> $body:block) => (
        pub struct $name<'t, T> {
            stack: Vec<&'t ~Node<T>>
        }

        impl<'t, T:Ord+Eq> Iterator<&'t ~Node<T>> for $name<'t, T> {
            fn next(&mut self) -> Option<&'t ~Node<T>> $body
        }
        )
    )

tree_iterator!(PreOrderTreeIterator -> {
    match self.stack.pop() {
        Some(ref n) => {
            match n.left_child {
                Some(ref n) => {
                    self.stack.push(n);
                },
                _ => ()
            };
            match n.right_child {
                Some(ref n) => {
                    self.stack.push(n);
                },
                _ => ()
            };
            Some(*n)
        },
        None => None
    }
})

tree_iterator!(InOrderTreeIterator -> {
    None // TODO implement this one yet
})

impl<T:Ord+Eq> Node<T> {
    pub fn new (nodeKey: T) -> Node<T> {
        Node {
            left_child: None,
            right_child: None,
            key: nodeKey
        }
    }

    pub fn add_child_node(&mut self, new_node: ~Node<T>) {
        if new_node.key > self.key {
            self.add_right_child(new_node);
        }
        else {
            self.add_left_child(new_node);
        }
    }

    fn add_right_child(&mut self, new_node: ~Node<T>) {
        match self.right_child {
            None => {
                self.right_child = Some(new_node);
            },
            Some(ref mut right_child) => {
                right_child.add_child_node(new_node);
            }
        }
    }

    fn add_left_child(&mut self, new_node: ~Node<T>) {
        match self.left_child {
            None => {
                self.left_child = Some(new_node);
            },
            Some(ref mut left_child) => {
                left_child.add_child_node(new_node);
            }
        }
    }

    pub fn has_children(node: &Node<T>) -> bool {
        match node.left_child {
            Some(_) => true,
            _ => {
                match node.right_child {
                    Some(_) => true,
                    _ => false
                }
            }
        }
    }

    /*pub fn visit_in_order(&self, visitor: &fn(&T)) {
        match self.left_child {
            Some (ref n) => {
                n.visit_in_order(visitor);
            },
            _ => {}
        }

        visitor(&self.key);

        match self.right_child {
            Some (ref n) => {
                n.visit_in_order(visitor);
            },
            _ => {}
        }
    }*/

    /*pub fn search(&self, needle: T) -> Option<T> {
        if self.key == needle {
            return Some(self.key);
        }
        else if self.key < needle {
            match self.left_child {
                Some(ref n) => {
                    return n.search(needle);
                },
                _ => {
                    return None;
                }
            }
        }
        return None;
    }*/
}

impl<T:Ord+Eq> Tree<T> {
    pub fn new () -> Tree<T> {
        Tree {
            root: None
        }
    }

    pub fn insert_value (&mut self, value: T) {
        let new_node = ~Node::new(value);
        self.insert_node(new_node);
    }

    pub fn insert_node (&mut self, new_node: ~Node<T>) {
        match self.root {
            None => {
                self.root = Some(new_node);
            },
            Some(ref mut n) => {
                n.add_child_node(new_node);
            }
        }
    }

    pub fn visit_pre_order<'n>(&'n self) -> PreOrderTreeIterator<'n, T> {
        match self.root {
            Some(ref n) => {
                PreOrderTreeIterator {
                    stack: vec!(&*n)
                }
            },
            _ => {
                PreOrderTreeIterator {
                    stack: vec!()
                }
            }
        }
    }
}

fn main () {
    let mut my_tree: Tree<int> = Tree::new();

    for key in vec!(3, 2, 4, 0, 8, 11, 18, 22, 16, 12, 7, 10).iter() {
        my_tree.insert_value(*key);
    }

    for node in my_tree.visit_pre_order() {
        println!("{}", node.key);
    }
}
<commit_msg>Update trees to build and run<commit_after>#![feature(macro_rules)]

struct Tree<T> {
    root: Option<Box<Node<T>>>
}
pub struct Node<T> {
    left_child: Option<Box<Node<T>>>,
    right_child: Option<Box<Node<T>>>,
    key: T
}

macro_rules! tree_iterator(
    ($name:ident -> $body:block) => (
        pub struct $name<'t, T> {
            stack: Vec<&'t Box<Node<T>>>
        }

        impl<'t, T:Ord+Eq> Iterator<&'t Box<Node<T>>> for $name<'t, T> {
            fn next(&mut self) -> Option<&'t Box<Node<T>>> $body
        }
        )
    )

tree_iterator!(PreOrderTreeIterator -> {
    match self.stack.pop() {
        Some(ref n) => {
            match n.left_child {
                Some(ref n) => {
                    self.stack.push(n);
                },
                _ => ()
            };
            match n.right_child {
                Some(ref n) => {
                    self.stack.push(n);
                },
                _ => ()
            };
            Some(*n)
        },
        None => None
    }
})

tree_iterator!(InOrderTreeIterator -> {
    None // TODO implement this one yet
})

impl<T:Ord+Eq> Node<T> {
    pub fn new (nodeKey: T) -> Node<T> {
        Node {
            left_child: None,
            right_child: None,
            key: nodeKey
        }
    }

    pub fn add_child_node(&mut self, new_node: Box<Node<T>>) {
        if new_node.key > self.key {
            self.add_right_child(new_node);
        }
        else {
            self.add_left_child(new_node);
        }
    }

    fn add_right_child(&mut self, new_node: Box<Node<T>>) {
        match self.right_child {
            None => {
                self.right_child = Some(new_node);
            },
            Some(ref mut right_child) => {
                right_child.add_child_node(new_node);
            }
        }
    }

    fn add_left_child(&mut self, new_node: Box<Node<T>>) {
        match self.left_child {
            None => {
                self.left_child = Some(new_node);
            },
            Some(ref mut left_child) => {
                left_child.add_child_node(new_node);
            }
        }
    }

    pub fn has_children(node: &Node<T>) -> bool {
        match node.left_child {
            Some(_) => true,
            _ => {
                match node.right_child {
                    Some(_) => true,
                    _ => false
                }
            }
        }
    }

    /*pub fn visit_in_order(&self, visitor: &fn(&T)) {
        match self.left_child {
            Some (ref n) => {
                n.visit_in_order(visitor);
            },
            _ => {}
        }

        visitor(&self.key);

        match self.right_child {
            Some (ref n) => {
                n.visit_in_order(visitor);
            },
            _ => {}
        }
    }*/

    /*pub fn search(&self, needle: T) -> Option<T> {
        if self.key == needle {
            return Some(self.key);
        }
        else if self.key < needle {
            match self.left_child {
                Some(ref n) => {
                    return n.search(needle);
                },
                _ => {
                    return None;
                }
            }
        }
        return None;
    }*/
}

impl<T:Ord+Eq> Tree<T> {
    pub fn new () -> Tree<T> {
        Tree {
            root: None
        }
    }

    pub fn insert_value (&mut self, value: T) {
        let new_node = box Node::new(value);
        self.insert_node(new_node);
    }

    pub fn insert_node (&mut self, new_node: Box<Node<T>>) {
        match self.root {
            None => {
                self.root = Some(new_node);
            },
            Some(ref mut n) => {
                n.add_child_node(new_node);
            }
        }
    }

    pub fn visit_pre_order<'n>(&'n self) -> PreOrderTreeIterator<'n, T> {
        match self.root {
            Some(ref n) => {
                PreOrderTreeIterator {
                    stack: vec!(&*n)
                }
            },
            _ => {
                PreOrderTreeIterator {
                    stack: vec!()
                }
            }
        }
    }
}

fn main () {
    let mut my_tree: Tree<int> = Tree::new();

    for key in vec!(3, 2, 4, 0, 8, 11, 18, 22, 16, 12, 7, 10).iter() {
        my_tree.insert_value(*key);
    }

    for node in my_tree.visit_pre_order() {
        println!("{}", node.key);
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate rand;

use test::Bencher;

use rand::prelude::*;
use rand::seq::*;

#[bench]
fn misc_shuffle_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &mut [usize] = &mut [1; 100];
    b.iter(|| {
        rng.shuffle(x);
        x[0]
    })
}

#[bench]
fn misc_sample_iter_10_of_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    b.iter(|| {
        sample_iter(&mut rng, x, 10).unwrap_or_else(|e| e)
    })
}

#[bench]
fn misc_sample_slice_10_of_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    b.iter(|| {
        sample_slice(&mut rng, x, 10)
    })
}

#[bench]
fn misc_sample_slice_ref_10_of_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    b.iter(|| {
        sample_slice_ref(&mut rng, x, 10)
    })
}

macro_rules! sample_indices {
    ($name:ident, $amount:expr, $length:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
            b.iter(|| {
                sample_indices(&mut rng, $length, $amount)
            })
        }
    }
}

sample_indices!(misc_sample_indices_10_of_1k, 10, 1000);
sample_indices!(misc_sample_indices_50_of_1k, 50, 1000);
sample_indices!(misc_sample_indices_100_of_1k, 100, 1000);
<commit_msg>Revise seq benches<commit_after>#![feature(test)]

extern crate test;
extern crate rand;

use test::Bencher;

use rand::prelude::*;
use rand::seq::*;

#[bench]
fn seq_shuffle_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &mut [usize] = &mut [1; 100];
    b.iter(|| {
        x.shuffle(&mut rng);
        x[0]
    })
}

#[bench]
fn seq_slice_choose_1_of_1000(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 1000];
    b.iter(|| {
        x.choose(&mut rng)
    })
}

#[bench]
fn seq_slice_choose_multiple_1_of_1000(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 1000];
    b.iter(|| {
        x.choose_multiple(&mut rng, 1).cloned().next()
    })
}

#[bench]
fn seq_slice_choose_multiple_10_of_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    let mut buf = [0; 10];
    b.iter(|| {
        for (v, slot) in x.choose_multiple(&mut rng, buf.len()).zip(buf.iter_mut()) {
            *slot = *v;
        }
        buf
    })
}

#[bench]
fn seq_iter_choose_from_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    b.iter(|| {
        x.iter().cloned().choose(&mut rng)
    })
}

#[bench]
fn seq_iter_choose_multiple_10_of_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    b.iter(|| {
        x.iter().cloned().choose_multiple(&mut rng, 10)
    })
}

#[bench]
fn seq_iter_choose_multiple_fill_10_of_100(b: &mut Bencher) {
    let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
    let x : &[usize] = &[1; 100];
    let mut buf = [0; 10];
    b.iter(|| {
        x.iter().cloned().choose_multiple_fill(&mut rng, &mut buf)
    })
}

macro_rules! sample_indices {
    ($name:ident, $amount:expr, $length:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
            b.iter(|| {
                sample_indices(&mut rng, $length, $amount)
            })
        }
    }
}

sample_indices!(seq_sample_indices_10_of_1k, 10, 1000);
sample_indices!(seq_sample_indices_50_of_1k, 50, 1000);
sample_indices!(seq_sample_indices_100_of_1k, 100, 1000);
<|endoftext|>


<commit_before>#![crate_name = "tango"]
#![no_std]
#![no_main]
#![feature(lang_items)]

extern crate drivers;
extern crate hotel;
extern crate hil;
extern crate main;

#[macro_use]
pub mod io;

use main::{Chip, MPU, Platform};

unsafe fn load_processes() -> &'static mut [Option<main::process::Process<'static>>] {
    extern {
        /// Beginning of the ROM region containing app images.
        static _sapps : u8;
    }

    const NUM_PROCS: usize = 2;

    #[link_section = ".app_memory"]
    static mut MEMORIES: [[u8; 8192]; NUM_PROCS] = [[0; 8192]; NUM_PROCS];

    static mut processes: [Option<main::process::Process<'static>>; NUM_PROCS] = [None, None];

    let mut addr = &_sapps as *const u8;
    for i in 0..NUM_PROCS {
        // The first member of the LoadInfo header contains the total size of each process image. A
        // sentinel value of 0 (invalid because it's smaller than the header itself) is used to
        // mark the end of the list of processes.
        let total_size = *(addr as *const usize);
        if total_size == 0 {
            break;
        }

        let process = &mut processes[i];
        let memory = &mut MEMORIES[i];
        *process = Some(main::process::Process::create(addr, total_size, memory));
        // TODO: panic if loading failed?

        addr = addr.offset(total_size as isize);
    }

    if *(addr as *const usize) != 0 {
        panic!("Exceeded maximum NUM_PROCS.");
    }

    &mut processes
}

pub struct Tango {
    gpio: &'static drivers::gpio::GPIO<'static, hotel::gpio::GPIOPin>
}

macro_rules! static_init {
   ($V:ident : $T:ty = $e:expr) => {
        let $V : &mut $T = {
            use core::mem::transmute;
            // Waiting out for size_of to be available at compile-time to avoid
            // hardcoding an abitrary large size...
            static mut BUF : [u8; 1024] = [0; 1024];
            let mut tmp : &mut $T = transmute(&mut BUF);
            *tmp = $e;
            tmp
        };
   }
}

#[no_mangle]
pub unsafe fn reset_handler() {
    hotel::init();

    let timer = {
        use hotel::pmu::*;
        use hotel::timeus::Timeus;
        Clock::new(PeripheralClock::Bank1(PeripheralClock1::TimeUs0Timer)).enable();
        let timer = Timeus::new(0);
        timer
    };

    timer.start();
    let start = timer.now();

    hotel::usb::USB0.init(&mut hotel::usb::OUT_DESCRIPTORS,
                          &mut hotel::usb::OUT_BUFFERS,
                          &mut hotel::usb::IN_DESCRIPTORS,
                          &mut hotel::usb::IN_BUFFERS,
                          hotel::usb::PHY::A,
                          None, Some(0x0011), Some(0x7788));

    {
        use hotel::pmu::*;
        Clock::new(PeripheralClock::Bank0(PeripheralClock0::Gpio0)).enable();
        let pinmux = &mut *hotel::pinmux::PINMUX;
        pinmux.diob0.select.set(hotel::pinmux::Function::Gpio0Gpio0);
    }

    static_init!(gpio_pins : [&'static hotel::gpio::GPIOPin; 1] =
        [ &hotel::gpio::PORT0.pins[0] ]
    );

    static_init!(gpio : drivers::gpio::GPIO<'static, hotel::gpio::GPIOPin> =
                 drivers::gpio::GPIO::new(gpio_pins));

    static_init!(platform : Tango = Tango {
        gpio: gpio
    });

    let end = timer.now();

    println!("Hello from Rust! Initialization took {} tics.", end.wrapping_sub(start));

    let mut chip = hotel::chip::Hotel::new();
    chip.mpu().enable_mpu();

    main::main(platform, &mut chip, &mut []); //load_processes());
}

impl Platform for Tango {
    fn with_driver<F, R>(&mut self, driver_num: usize, f: F) -> R where
            F: FnOnce(Option<&main::Driver>) -> R {
        match driver_num {
            1 => f(Some(self.gpio)),
            _ => f(None)
        }
    }
}

<commit_msg>Load processes again in tango board<commit_after>#![crate_name = "tango"]
#![no_std]
#![no_main]
#![feature(lang_items)]

extern crate drivers;
extern crate hotel;
extern crate hil;
extern crate main;

#[macro_use]
pub mod io;

use main::{Chip, MPU, Platform};

unsafe fn load_processes() -> &'static mut [Option<main::process::Process<'static>>] {
    extern {
        /// Beginning of the ROM region containing app images.
        static _sapps : u8;
    }

    const NUM_PROCS: usize = 2;

    #[link_section = ".app_memory"]
    static mut MEMORIES: [[u8; 8192]; NUM_PROCS] = [[0; 8192]; NUM_PROCS];

    static mut processes: [Option<main::process::Process<'static>>; NUM_PROCS] = [None, None];

    let mut addr = &_sapps as *const u8;
    for i in 0..NUM_PROCS {
        // The first member of the LoadInfo header contains the total size of each process image. A
        // sentinel value of 0 (invalid because it's smaller than the header itself) is used to
        // mark the end of the list of processes.
        let total_size = *(addr as *const usize);
        if total_size == 0 {
            break;
        }

        let process = &mut processes[i];
        let memory = &mut MEMORIES[i];
        *process = Some(main::process::Process::create(addr, total_size, memory));
        // TODO: panic if loading failed?

        addr = addr.offset(total_size as isize);
    }

    if *(addr as *const usize) != 0 {
        panic!("Exceeded maximum NUM_PROCS.");
    }

    &mut processes
}

pub struct Tango {
    gpio: &'static drivers::gpio::GPIO<'static, hotel::gpio::GPIOPin>
}

macro_rules! static_init {
   ($V:ident : $T:ty = $e:expr) => {
        let $V : &mut $T = {
            use core::mem::transmute;
            // Waiting out for size_of to be available at compile-time to avoid
            // hardcoding an abitrary large size...
            static mut BUF : [u8; 1024] = [0; 1024];
            let mut tmp : &mut $T = transmute(&mut BUF);
            *tmp = $e;
            tmp
        };
   }
}

#[no_mangle]
pub unsafe fn reset_handler() {
    hotel::init();

    let timer = {
        use hotel::pmu::*;
        use hotel::timeus::Timeus;
        Clock::new(PeripheralClock::Bank1(PeripheralClock1::TimeUs0Timer)).enable();
        let timer = Timeus::new(0);
        timer
    };

    timer.start();
    let start = timer.now();

    hotel::usb::USB0.init(&mut hotel::usb::OUT_DESCRIPTORS,
                          &mut hotel::usb::OUT_BUFFERS,
                          &mut hotel::usb::IN_DESCRIPTORS,
                          &mut hotel::usb::IN_BUFFERS,
                          hotel::usb::PHY::A,
                          None, Some(0x0011), Some(0x7788));

    {
        use hotel::pmu::*;
        Clock::new(PeripheralClock::Bank0(PeripheralClock0::Gpio0)).enable();
        let pinmux = &mut *hotel::pinmux::PINMUX;
        pinmux.diob0.select.set(hotel::pinmux::Function::Gpio0Gpio0);
    }

    static_init!(gpio_pins : [&'static hotel::gpio::GPIOPin; 1] =
        [ &hotel::gpio::PORT0.pins[0] ]
    );

    static_init!(gpio : drivers::gpio::GPIO<'static, hotel::gpio::GPIOPin> =
                 drivers::gpio::GPIO::new(gpio_pins));

    static_init!(platform : Tango = Tango {
        gpio: gpio
    });

    let end = timer.now();

    println!("Hello from Rust! Initialization took {} tics.", end.wrapping_sub(start));

    let mut chip = hotel::chip::Hotel::new();
    chip.mpu().enable_mpu();

    main::main(platform, &mut chip, load_processes());
}

impl Platform for Tango {
    fn with_driver<F, R>(&mut self, driver_num: usize, f: F) -> R where
            F: FnOnce(Option<&main::Driver>) -> R {
        match driver_num {
            1 => f(Some(self.gpio)),
            _ => f(None)
        }
    }
}

<|endoftext|>


<commit_before>use std::borrow::Cow;

use crate::requests::*;
use crate::types::*;

/// Use this method to send an audio
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[must_use = "requests do nothing unless sent"]
pub struct SendAudio<'c, 'p, 't> {
    chat_id: ChatRef,
    audio: InputFile,
    caption: Option<Cow<'c, str>>,
    parse_mode: Option<ParseMode>,
    duration: Option<Integer>,
    performer: Option<Cow<'p, str>>,
    title: Option<Cow<'t, str>>,
    thumb: Option<InputFile>,
    reply_to_message_id: Option<MessageId>,
    disable_notification: bool,
    reply_markup: Option<ReplyMarkup>,
}

impl<'c, 'p, 't> ToMultipart for SendAudio<'c, 'p, 't> {
    fn to_multipart(&self) -> Result<Multipart, Error> {
        multipart_map! {
            self,
            (chat_id (text));
            (audio (raw));
            (caption (text), optional);
            (parse_mode (text), optional);
            (duration (text), optional);
            (performer (text), optional);
            (title (text), optional);
            (thumb (raw), optional);
            (reply_to_message_id (text), optional);
            (disable_notification (text), when_true);
            (reply_markup (json), optional);
        }
    }
}

impl<'c, 'p, 't> Request for SendAudio<'c, 'p, 't> {
    type Type = MultipartRequestType<Self>;
    type Response = JsonIdResponse<Message>;

    fn serialize(&self) -> Result<HttpRequest, Error> {
        Self::Type::serialize(RequestUrl::method("sendAudio"), self)
    }
}

impl<'c, 'p, 't> SendAudio<'c, 'p, 't> {
    pub fn new<C, V>(chat: C, audio: V) -> Self
    where
        C: ToChatRef,
        V: Into<InputFile>,
    {
        Self {
            chat_id: chat.to_chat_ref(),
            audio: audio.into(),
            caption: None,
            parse_mode: None,
            duration: None,
            performer: None,
            title: None,
            thumb: None,
            reply_to_message_id: None,
            reply_markup: None,
            disable_notification: false,
        }
    }

    pub fn thumb<V>(&mut self, thumb: V) -> &mut Self
    where
        V: Into<InputFileUpload>,
    {
        self.thumb = Some(thumb.into().into());
        self
    }

    pub fn caption<T>(&mut self, caption: T) -> &mut Self
    where
        T: Into<Cow<'c, str>>,
    {
        self.caption = Some(caption.into());
        self
    }

    pub fn parse_mode(&mut self, parse_mode: ParseMode) -> &mut Self {
        self.parse_mode = Some(parse_mode);
        self
    }

    pub fn duration(&mut self, duration: Integer) -> &mut Self {
        self.duration = Some(duration);
        self
    }

    pub fn performer<T>(&mut self, performer: T) -> &mut Self
    where
        T: Into<Cow<'p, str>>,
    {
        self.performer = Some(performer.into());
        self
    }

    pub fn title<T>(&mut self, title: T) -> &mut Self
    where
        T: Into<Cow<'t, str>>,
    {
        self.title = Some(title.into());
        self
    }

    pub fn reply_to<R>(&mut self, to: R) -> &mut Self
    where
        R: ToMessageId,
    {
        self.reply_to_message_id = Some(to.to_message_id());
        self
    }

    pub fn reply_markup<R>(&mut self, reply_markup: R) -> &mut Self
    where
        R: Into<ReplyMarkup>,
    {
        self.reply_markup = Some(reply_markup.into());
        self
    }
}

/// Can reply with an audio
pub trait CanReplySendAudio {
    fn audio_reply<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>;
}

impl<M> CanReplySendAudio for M
where
    M: ToMessageId + ToSourceChat,
{
    fn audio_reply<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>,
    {
        let mut req = SendAudio::new(self.to_source_chat(), audio);
        req.reply_to(self);
        req
    }
}

/// Send an audio
pub trait CanSendAudio {
    fn audio<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>;
}

impl<M> CanSendAudio for M
where
    M: ToChatRef,
{
    fn audio<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>,
    {
        SendAudio::new(self.to_chat_ref(), audio)
    }
}
<commit_msg>feat: add SendAudio::disable_notification method<commit_after>use std::borrow::Cow;

use crate::requests::*;
use crate::types::*;

/// Use this method to send an audio
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[must_use = "requests do nothing unless sent"]
pub struct SendAudio<'c, 'p, 't> {
    chat_id: ChatRef,
    audio: InputFile,
    caption: Option<Cow<'c, str>>,
    parse_mode: Option<ParseMode>,
    duration: Option<Integer>,
    performer: Option<Cow<'p, str>>,
    title: Option<Cow<'t, str>>,
    thumb: Option<InputFile>,
    reply_to_message_id: Option<MessageId>,
    disable_notification: bool,
    reply_markup: Option<ReplyMarkup>,
}

impl<'c, 'p, 't> ToMultipart for SendAudio<'c, 'p, 't> {
    fn to_multipart(&self) -> Result<Multipart, Error> {
        multipart_map! {
            self,
            (chat_id (text));
            (audio (raw));
            (caption (text), optional);
            (parse_mode (text), optional);
            (duration (text), optional);
            (performer (text), optional);
            (title (text), optional);
            (thumb (raw), optional);
            (reply_to_message_id (text), optional);
            (disable_notification (text), when_true);
            (reply_markup (json), optional);
        }
    }
}

impl<'c, 'p, 't> Request for SendAudio<'c, 'p, 't> {
    type Type = MultipartRequestType<Self>;
    type Response = JsonIdResponse<Message>;

    fn serialize(&self) -> Result<HttpRequest, Error> {
        Self::Type::serialize(RequestUrl::method("sendAudio"), self)
    }
}

impl<'c, 'p, 't> SendAudio<'c, 'p, 't> {
    pub fn new<C, V>(chat: C, audio: V) -> Self
    where
        C: ToChatRef,
        V: Into<InputFile>,
    {
        Self {
            chat_id: chat.to_chat_ref(),
            audio: audio.into(),
            caption: None,
            parse_mode: None,
            duration: None,
            performer: None,
            title: None,
            thumb: None,
            reply_to_message_id: None,
            reply_markup: None,
            disable_notification: false,
        }
    }

    pub fn thumb<V>(&mut self, thumb: V) -> &mut Self
    where
        V: Into<InputFileUpload>,
    {
        self.thumb = Some(thumb.into().into());
        self
    }

    pub fn caption<T>(&mut self, caption: T) -> &mut Self
    where
        T: Into<Cow<'c, str>>,
    {
        self.caption = Some(caption.into());
        self
    }

    pub fn parse_mode(&mut self, parse_mode: ParseMode) -> &mut Self {
        self.parse_mode = Some(parse_mode);
        self
    }

    pub fn duration(&mut self, duration: Integer) -> &mut Self {
        self.duration = Some(duration);
        self
    }

    pub fn performer<T>(&mut self, performer: T) -> &mut Self
    where
        T: Into<Cow<'p, str>>,
    {
        self.performer = Some(performer.into());
        self
    }

    pub fn title<T>(&mut self, title: T) -> &mut Self
    where
        T: Into<Cow<'t, str>>,
    {
        self.title = Some(title.into());
        self
    }

    pub fn reply_to<R>(&mut self, to: R) -> &mut Self
    where
        R: ToMessageId,
    {
        self.reply_to_message_id = Some(to.to_message_id());
        self
    }

    pub fn reply_markup<R>(&mut self, reply_markup: R) -> &mut Self
    where
        R: Into<ReplyMarkup>,
    {
        self.reply_markup = Some(reply_markup.into());
        self
    }

    pub fn disable_notification(&mut self) -> &mut Self {
        self.disable_notification = true;
        self
    }
}

/// Can reply with an audio
pub trait CanReplySendAudio {
    fn audio_reply<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>;
}

impl<M> CanReplySendAudio for M
where
    M: ToMessageId + ToSourceChat,
{
    fn audio_reply<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>,
    {
        let mut req = SendAudio::new(self.to_source_chat(), audio);
        req.reply_to(self);
        req
    }
}

/// Send an audio
pub trait CanSendAudio {
    fn audio<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>;
}

impl<M> CanSendAudio for M
where
    M: ToChatRef,
{
    fn audio<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>,
    {
        SendAudio::new(self.to_chat_ref(), audio)
    }
}
<|endoftext|>


<commit_before>extern crate ncurses;
use self::ncurses::*;

use core::editor::Editor;

pub fn main_loop(editor: &mut Editor) {
    /* If your locale env is unicode, you should use `setlocale`. */
    // let locale_conf = LcCategory::all;
    // setlocale(locale_conf, "zh_CN.UTF-8"); // if your locale is like mine(zh_CN.UTF-8).

    /* Start ncurses. */
    initscr();

    /* Print to the back buffer. */
    printw("Hello, world!");

    /* Print some unicode(Chinese) string. */
    // printw("Great Firewall dislike VPN protocol.\nGFW 不喜欢 VPN 协议。");

    /* Update the screen. */
    refresh();

    /* Wait for a key press. */
    getch();

    /* Terminate ncurses. */
    endwin();
}
<commit_msg>print screen dimensions<commit_after>extern crate ncurses;
use self::ncurses::*;

use core::editor::Editor;

pub fn main_loop(editor: &mut Editor) {
    /* If your locale env is unicode, you should use `setlocale`. */
    // let locale_conf = LcCategory::all;
    // setlocale(locale_conf, "zh_CN.UTF-8"); // if your locale is like mine(zh_CN.UTF-8).

    /* Start ncurses. */
    initscr();

    loop {
        /* Get the screen bounds. */
        let mut width = 0;
        let mut height = 0;
        getmaxyx(stdscr(), &mut height, &mut width);
        let msg = format!("width = {}, height = {}\n", width, height);

        clear();
        printw("Hello, world!\n");
        printw(&msg);

        /* Update the screen. */
        refresh();

        /* Wait for a key press. */
        let key = getch();
        if key == 'q' as i32 {
            break;
        }
    }
    /* Terminate ncurses. */
    endwin();
}
<|endoftext|>


<commit_before>use std::io;

macro_rules! print_err {
    ($($arg:tt)*) => (
        {
            use std::io::Write;
            writeln!(&mut ::std::io::stderr(), $($arg)*).ok();
        }
    )
}

macro_rules! parse_input {
    ($x:expr, $t:ident) => ($x.trim().parse::<$t>().unwrap())
}

/**
 * Auto-generated code below aims at helping you parse
 * the standard input according to the problem statement.
 * ---
 * Hint: You can use the debug stream to print initialTX and initialTY, if Thor seems not follow your orders.
 **/
fn main() {
    let mut input_line = String::new();
    io::stdin().read_line(&mut input_line).unwrap();
    let inputs = input_line.split(" ").collect::<Vec<_>>();
    let light_x = parse_input!(inputs[0], i32); // the X position of the light of power
    let light_y = parse_input!(inputs[1], i32); // the Y position of the light of power
    let initial_tx = parse_input!(inputs[2], i32); // Thor's starting X position
    let initial_ty = parse_input!(inputs[3], i32); // Thor's starting Y position

    let mut dx = initial_tx - light_x
    let mut dy = initial_ty - light_y

    let mut horizontal_move:String;
    let mut vertical_move:String;
    let mut complete_move:String;

    // game loop
    loop {
        let mut input_line = String::new();
        io::stdin().read_line(&mut input_line).unwrap();
        let remaining_turns = parse_input!(input_line, i32); // The remaining amount of turns Thor can move. Do not remove this line.

        horizontal_move = if dx > 0 {
                            dx = dx + 1;
                            "W"
                        }
                        else if dx < 0 {
                            dx = dx - 1;
                            "E"
                        }
                        else {
                            ""
                        }

        vertical_move = if dy > 0 {
            dy = dy - 1;
            "N"

        }
        else if dy < 0 {
            dy = dy + 1;
            "S"
        }
        else {
            ""
        }
        // Write an action using println!("message...");
        // To debug: print_err!("Debug message...");

        // A single line providing the move to be made: N NE E SE S SW W or NW
        println!(format!("{}{}",vertical_move,horizontal_move));
    }
}<commit_msg>Solution pour le puzzle easy "power of Thor - part 1"<commit_after>use std::io;
use std::fmt;

macro_rules! print_err {
    ($($arg:tt)*) => (
        {
            use std::io::Write;
            writeln!(&mut ::std::io::stderr(), $($arg)*).ok();
        }
    )
}

macro_rules! parse_input {
    ($x:expr, $t:ident) => ($x.trim().parse::<$t>().unwrap())
}

/**
 * Auto-generated code below aims at helping you parse
 * the standard input according to the problem statement.
 * ---
 * Hint: You can use the debug stream to print initialTX and initialTY, if Thor seems not follow your orders.
 **/
fn main() {
    let mut input_line = String::new();
    io::stdin().read_line(&mut input_line).unwrap();
    let inputs = input_line.split(" ").collect::<Vec<_>>();
    let light_x = parse_input!(inputs[0], i32); // the X position of the light of power
    let light_y = parse_input!(inputs[1], i32); // the Y position of the light of power
    let initial_tx = parse_input!(inputs[2], i32); // Thor's starting X position
    let initial_ty = parse_input!(inputs[3], i32); // Thor's starting Y position

    let mut dx = initial_tx - light_x;
    let mut dy = initial_ty - light_y;

    let mut horizontal_move:&'static str;
    let mut vertical_move:&'static str;
    //let mut complete_move:String;

    // game loop
    loop {
        let mut input_line = String::new();
        io::stdin().read_line(&mut input_line).unwrap();
        let remaining_turns = parse_input!(input_line, i32); // The remaining amount of turns Thor can move. Do not remove this line.

        horizontal_move = if dx > 0 { dx = dx + 1; "W" } else if dx < 0 { dx = dx - 1; "E" } else {""};
        vertical_move = if dy > 0 { dy = dy - 1; "N" } else if dy < 0 { dy = dy + 1; "S" } else {""};
        // Write an action using println!("message...");
        // To debug: print_err!("Debug message...");
        //let formatted_answer = format!("{}{}",vertical_move,horizontal_move);
        // A single line providing the move to be made: N NE E SE S SW W or NW
        println!("{}",format!("{}{}",vertical_move,horizontal_move));
    }
}<|endoftext|>


<commit_before>mod helpers;

use helpers::{roundtrip, wayc, ways, TestClient, TestServer};

use ways::protocol::wl_compositor::WlCompositor as ServerCompositor;
use ways::protocol::wl_output::WlOutput as ServerOutput;
use ways::protocol::wl_shell::WlShell as ServerShell;

use std::sync::{Arc, Mutex};

#[test]
fn simple_global() {
    let mut server = TestServer::new();
    let loop_token = server.event_loop.token();
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});

    let mut client = TestClient::new(&server.socket_name);
    let manager = wayc::GlobalManager::new(&client.display);

    roundtrip(&mut client, &mut server).unwrap();
    let globals = manager.list();
    assert!(globals.len() == 1);
    assert_eq!(globals[0], (1, "wl_compositor".into(), 1));
}

#[test]
fn multi_versions() {
    let mut server = TestServer::new();
    let loop_token = server.event_loop.token();
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 4, |_, _| {});
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 3, |_, _| {});
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 2, |_, _| {});
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});

    let mut client = TestClient::new(&server.socket_name);
    let manager = wayc::GlobalManager::new(&client.display);

    roundtrip(&mut client, &mut server).unwrap();
    let globals = manager.list();
    assert!(globals.len() == 4);
    let mut seen = [false; 4];
    for &(_, ref interface, version) in &globals {
        assert!(interface == "wl_compositor");
        seen[version as usize - 1] = true;
    }
    assert_eq!(seen, [true, true, true, true]);
}

#[test]
fn dynamic_global() {
    let mut server = TestServer::new();
    let loop_token = server.event_loop.token();
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});

    let mut client = TestClient::new(&server.socket_name);
    let manager = wayc::GlobalManager::new(&client.display);

    roundtrip(&mut client, &mut server).unwrap();
    assert!(manager.list().len() == 1);

    server
        .display
        .create_global::<ServerShell, _>(&loop_token, 1, |_, _| {});

    roundtrip(&mut client, &mut server).unwrap();
    assert!(manager.list().len() == 2);

    let output = server
        .display
        .create_global::<ServerOutput, _>(&loop_token, 1, |_, _| {});

    roundtrip(&mut client, &mut server).unwrap();
    assert!(manager.list().len() == 3);

    output.destroy();

    roundtrip(&mut client, &mut server).unwrap();
    assert!(manager.list().len() == 2);
}

#[test]
fn global_manager_cb() {
    use wayc::GlobalEvent;

    let mut server = TestServer::new();
    let loop_token = server.event_loop.token();
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});

    let counter = Arc::new(Mutex::new(0));
    let counter2 = counter.clone();

    let mut client = TestClient::new(&server.socket_name);
    let manager = wayc::GlobalManager::new_with_cb(&client.display, move |event, _| match event {
        GlobalEvent::New { .. } => *(counter2.lock().unwrap()) += 1,
        GlobalEvent::Removed { .. } => *(counter2.lock().unwrap()) -= 1,
    });

    roundtrip(&mut client, &mut server).unwrap();

    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});
    let comp = server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});

    roundtrip(&mut client, &mut server).unwrap();

    assert!(manager.list().len() == 4);
    assert!(*counter.lock().unwrap() == 4);

    comp.destroy();

    roundtrip(&mut client, &mut server).unwrap();

    assert!(manager.list().len() == 3);
    assert!(*counter.lock().unwrap() == 3);
}

#[test]
fn auto_instanciate() {
    use wayc::protocol::wl_compositor::WlCompositor;
    use wayc::protocol::wl_output::WlOutput;
    use wayc::protocol::wl_shell::WlShell;
    use wayc::GlobalError;

    let mut server = TestServer::new();
    let loop_token = server.event_loop.token();
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 4, |_, _| {});
    server
        .display
        .create_global::<ServerShell, _>(&loop_token, 1, |_, _| {});

    let mut client = TestClient::new(&server.socket_name);
    let manager = wayc::GlobalManager::new(&client.display);

    roundtrip(&mut client, &mut server).unwrap();

    let compositor = manager
        .instantiate_auto::<WlCompositor, _>(|newp| newp.implement(|_, _| {}))
        .unwrap();
    assert!(compositor.version() == 4);
    let shell = manager
        .instantiate_auto::<WlShell, _>(|newp| newp.implement(|_, _| {}))
        .unwrap();
    assert!(shell.version() == 1);

    assert!(
        manager.instantiate_exact::<WlCompositor, _>(5, |newp| newp.implement(|_, _| {}))
            == Err(GlobalError::VersionTooLow(4))
    );
    assert!(
        manager.instantiate_exact::<WlOutput, _>(5, |newp| newp.implement(|_, _| {}))
            == Err(GlobalError::Missing)
    );
    assert!(
        manager.instantiate_auto::<WlOutput, _>(|newp| newp.implement(|_, _| {}))
            == Err(GlobalError::Missing)
    );
}

#[test]
#[should_panic]
fn wrong_version_create_global() {
    let mut server = TestServer::new();
    let loop_token = server.event_loop.token();
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 42, |_, _| {});
}

#[test]
fn wrong_global() {
    use wayc::protocol::wl_display::RequestsTrait as DisplayRequests;
    use wayc::protocol::wl_output::WlOutput;
    use wayc::protocol::wl_registry::RequestsTrait as RegistryRequests;

    let mut server = TestServer::new();
    let loop_token = server.event_loop.token();
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});

    let mut client = TestClient::new(&server.socket_name);
    let registry = client
        .display
        .get_registry(|newp| newp.implement(|_, _| {}))
        .unwrap();

    // instanciate a wrong global, this shoudl kill the client

    registry.bind::<WlOutput, _>(2, 1, |newp| newp.implement(|_, _| {}));

    assert!(roundtrip(&mut client, &mut server).is_err());
}
<commit_msg>tests: more invalid global instanciations<commit_after>mod helpers;

use helpers::{roundtrip, wayc, ways, TestClient, TestServer};

use ways::protocol::wl_compositor::WlCompositor as ServerCompositor;
use ways::protocol::wl_output::WlOutput as ServerOutput;
use ways::protocol::wl_shell::WlShell as ServerShell;

use std::sync::{Arc, Mutex};

#[test]
fn simple_global() {
    let mut server = TestServer::new();
    let loop_token = server.event_loop.token();
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});

    let mut client = TestClient::new(&server.socket_name);
    let manager = wayc::GlobalManager::new(&client.display);

    roundtrip(&mut client, &mut server).unwrap();
    let globals = manager.list();
    assert!(globals.len() == 1);
    assert_eq!(globals[0], (1, "wl_compositor".into(), 1));
}

#[test]
fn multi_versions() {
    let mut server = TestServer::new();
    let loop_token = server.event_loop.token();
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 4, |_, _| {});
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 3, |_, _| {});
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 2, |_, _| {});
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});

    let mut client = TestClient::new(&server.socket_name);
    let manager = wayc::GlobalManager::new(&client.display);

    roundtrip(&mut client, &mut server).unwrap();
    let globals = manager.list();
    assert!(globals.len() == 4);
    let mut seen = [false; 4];
    for &(_, ref interface, version) in &globals {
        assert!(interface == "wl_compositor");
        seen[version as usize - 1] = true;
    }
    assert_eq!(seen, [true, true, true, true]);
}

#[test]
fn dynamic_global() {
    let mut server = TestServer::new();
    let loop_token = server.event_loop.token();
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});

    let mut client = TestClient::new(&server.socket_name);
    let manager = wayc::GlobalManager::new(&client.display);

    roundtrip(&mut client, &mut server).unwrap();
    assert!(manager.list().len() == 1);

    server
        .display
        .create_global::<ServerShell, _>(&loop_token, 1, |_, _| {});

    roundtrip(&mut client, &mut server).unwrap();
    assert!(manager.list().len() == 2);

    let output = server
        .display
        .create_global::<ServerOutput, _>(&loop_token, 1, |_, _| {});

    roundtrip(&mut client, &mut server).unwrap();
    assert!(manager.list().len() == 3);

    output.destroy();

    roundtrip(&mut client, &mut server).unwrap();
    assert!(manager.list().len() == 2);
}

#[test]
fn global_manager_cb() {
    use wayc::GlobalEvent;

    let mut server = TestServer::new();
    let loop_token = server.event_loop.token();
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});

    let counter = Arc::new(Mutex::new(0));
    let counter2 = counter.clone();

    let mut client = TestClient::new(&server.socket_name);
    let manager = wayc::GlobalManager::new_with_cb(&client.display, move |event, _| match event {
        GlobalEvent::New { .. } => *(counter2.lock().unwrap()) += 1,
        GlobalEvent::Removed { .. } => *(counter2.lock().unwrap()) -= 1,
    });

    roundtrip(&mut client, &mut server).unwrap();

    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});
    let comp = server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});

    roundtrip(&mut client, &mut server).unwrap();

    assert!(manager.list().len() == 4);
    assert!(*counter.lock().unwrap() == 4);

    comp.destroy();

    roundtrip(&mut client, &mut server).unwrap();

    assert!(manager.list().len() == 3);
    assert!(*counter.lock().unwrap() == 3);
}

#[test]
fn auto_instanciate() {
    use wayc::protocol::wl_compositor::WlCompositor;
    use wayc::protocol::wl_output::WlOutput;
    use wayc::protocol::wl_shell::WlShell;
    use wayc::GlobalError;

    let mut server = TestServer::new();
    let loop_token = server.event_loop.token();
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 4, |_, _| {});
    server
        .display
        .create_global::<ServerShell, _>(&loop_token, 1, |_, _| {});

    let mut client = TestClient::new(&server.socket_name);
    let manager = wayc::GlobalManager::new(&client.display);

    roundtrip(&mut client, &mut server).unwrap();

    let compositor = manager
        .instantiate_auto::<WlCompositor, _>(|newp| newp.implement(|_, _| {}))
        .unwrap();
    assert!(compositor.version() == 4);
    let shell = manager
        .instantiate_auto::<WlShell, _>(|newp| newp.implement(|_, _| {}))
        .unwrap();
    assert!(shell.version() == 1);

    assert!(
        manager.instantiate_exact::<WlCompositor, _>(5, |newp| newp.implement(|_, _| {}))
            == Err(GlobalError::VersionTooLow(4))
    );
    assert!(
        manager.instantiate_exact::<WlOutput, _>(5, |newp| newp.implement(|_, _| {}))
            == Err(GlobalError::Missing)
    );
    assert!(
        manager.instantiate_auto::<WlOutput, _>(|newp| newp.implement(|_, _| {}))
            == Err(GlobalError::Missing)
    );
}

#[test]
#[should_panic]
fn wrong_version_create_global() {
    let mut server = TestServer::new();
    let loop_token = server.event_loop.token();
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 42, |_, _| {});
}

#[test]
#[cfg_attr(feature = "native_lib", ignore)]
fn wrong_global() {
    use wayc::protocol::wl_display::RequestsTrait as DisplayRequests;
    use wayc::protocol::wl_output::WlOutput;
    use wayc::protocol::wl_registry::RequestsTrait as RegistryRequests;

    let mut server = TestServer::new();
    let loop_token = server.event_loop.token();
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});

    let mut client = TestClient::new(&server.socket_name);
    let registry = client
        .display
        .get_registry(|newp| newp.implement(|_, _| {}))
        .unwrap();

    // instanciate a wrong global, this should kill the client
    // But currently does not fail on native_lib

    registry
        .bind::<WlOutput, _>(1, 1, |newp| newp.implement(|_, _| {}))
        .unwrap();

    assert!(roundtrip(&mut client, &mut server).is_err());
}

#[test]
fn wrong_global_version() {
    use wayc::protocol::wl_compositor::WlCompositor;
    use wayc::protocol::wl_display::RequestsTrait as DisplayRequests;
    use wayc::protocol::wl_registry::RequestsTrait as RegistryRequests;

    let mut server = TestServer::new();
    let loop_token = server.event_loop.token();
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});

    let mut client = TestClient::new(&server.socket_name);
    let registry = client
        .display
        .get_registry(|newp| newp.implement(|_, _| {}))
        .unwrap();

    // instanciate a global with wrong version, this shoudl kill the client

    registry
        .bind::<WlCompositor, _>(2, 1, |newp| newp.implement(|_, _| {}))
        .unwrap();

    assert!(roundtrip(&mut client, &mut server).is_err());
}

#[test]
fn invalid_global_version() {
    use wayc::protocol::wl_compositor::WlCompositor;
    use wayc::protocol::wl_display::RequestsTrait as DisplayRequests;
    use wayc::protocol::wl_registry::RequestsTrait as RegistryRequests;

    let mut server = TestServer::new();
    let loop_token = server.event_loop.token();
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});

    let mut client = TestClient::new(&server.socket_name);
    let registry = client
        .display
        .get_registry(|newp| newp.implement(|_, _| {}))
        .unwrap();

    // instanciate a global with version 0, which is invalid this shoudl kill the client

    registry
        .bind::<WlCompositor, _>(0, 1, |newp| newp.implement(|_, _| {}))
        .unwrap();

    assert!(roundtrip(&mut client, &mut server).is_err());
}

#[test]
fn wrong_global_id() {
    use wayc::protocol::wl_compositor::WlCompositor;
    use wayc::protocol::wl_display::RequestsTrait as DisplayRequests;
    use wayc::protocol::wl_registry::RequestsTrait as RegistryRequests;

    let mut server = TestServer::new();
    let loop_token = server.event_loop.token();
    server
        .display
        .create_global::<ServerCompositor, _>(&loop_token, 1, |_, _| {});

    let mut client = TestClient::new(&server.socket_name);
    let registry = client
        .display
        .get_registry(|newp| newp.implement(|_, _| {}))
        .unwrap();

    // instanciate a global with wrong id, this should kill the client

    registry
        .bind::<WlCompositor, _>(1, 3, |newp| newp.implement(|_, _| {}))
        .unwrap();

    assert!(roundtrip(&mut client, &mut server).is_err());
}
<|endoftext|>


<commit_before>use utils;
use errors::*;
use msi;
use temp;
use env_var;
use dist;

use std::path::{Path, PathBuf};
use std::process::Command;
use std::ffi::OsStr;
use std::fs;
use std::io;
use std::env;

const REL_MANIFEST_DIR: &'static str = "rustlib";

pub struct InstallPrefix {
	path: PathBuf,
	install_type: InstallType,
}

#[derive(Eq, PartialEq, Copy, Clone)]
pub enum InstallType {
	// Must be uninstalled by deleting the entire directory
	Owned,
	// Must be uninstalled via `uninstall.sh` on linux or `msiexec /x` on windows
	Shared,
}

pub enum Uninstaller {
	Sh(PathBuf),
	Msi(String),
}

impl Uninstaller {
	pub fn run(&self) -> Result<()> {
		match *self {
			Uninstaller::Sh(ref path) => {
				let mut cmd = Command::new("sudo");
				cmd.arg("sh").arg(path);
				utils::cmd_status("uninstall.sh", cmd)
			},
			Uninstaller::Msi(ref id) => {
				let mut cmd = Command::new("msiexec");
				cmd.arg("/x").arg(id);
				utils::cmd_status("msiexec", cmd)
			},
		}
	}
}

pub enum InstallMethod<'a> {
	Copy(&'a Path),
	Link(&'a Path),
	Installer(&'a Path, &'a temp::Cfg),
	Dist(&'a str, Option<&'a Path>, dist::DownloadCfg<'a>),
}

impl<'a> InstallMethod<'a> {
	pub fn install_type_possible(&self, install_type: InstallType) -> bool {
		match *self {
			InstallMethod::Copy(_)|InstallMethod::Link(_) => install_type == InstallType::Owned,
			InstallMethod::Installer(_, _)|InstallMethod::Dist(_,_,_) => true,
		}
	}
	pub fn run(self, prefix: &InstallPrefix, notify_handler: &NotifyHandler) -> Result<()> {
		if prefix.is_installed_here() {
			// Don't uninstall first for Dist method
			match self {
				InstallMethod::Dist(_,_,_) => {},
				_ => { try!(prefix.uninstall(notify_handler)); },
			}
		}

		if !self.install_type_possible(prefix.install_type) {
			return Err(Error::InstallTypeNotPossible);
		}

		match self {
			InstallMethod::Copy(src) => {
				utils::copy_dir(src, &prefix.path, notify_handler)
			},
			InstallMethod::Link(src) => {
				utils::symlink_dir(&prefix.path, src, notify_handler)
			},
			InstallMethod::Installer(src, temp_cfg) => {
				let temp_dir = try!(temp_cfg.new_directory());
				match src.extension().and_then(OsStr::to_str) {
					Some("gz") => InstallMethod::tar_gz(src, &temp_dir, prefix),
					Some("msi") => InstallMethod::msi(src, &temp_dir, prefix),
					_ => Err(Error::InvalidFileExtension),
				}
			},
			InstallMethod::Dist(toolchain, update_hash, dl_cfg) => {
				if let Some(installer) = try!(dist::download_dist(toolchain, update_hash, dl_cfg)) {
					try!(InstallMethod::Installer(&*installer, dl_cfg.temp_cfg).run(prefix, dl_cfg.notify_handler));
				}
				Ok(())
			}
		}
	}

	fn tar_gz(src: &Path, work_dir: &Path, prefix: &InstallPrefix) -> Result<()> {
		let installer_dir = Path::new(try!(Path::new(src.file_stem().unwrap()).file_stem()
			.ok_or(Error::InvalidFileExtension)));

		let mut cmd = Command::new("tar");
		cmd
			.arg("xzf").arg(src)
			.arg("-C").arg(work_dir);

		try!(utils::cmd_status("tar", cmd));

		let mut cmd = Command::new("sh");
		cmd
			.arg(installer_dir.join("install.sh"))
			.arg("--prefix").arg(&prefix.path);

		if prefix.install_type != InstallType::Shared {
			cmd.arg("--disable-ldconfig");
		}

		let result = utils::cmd_status("sh", cmd);

		if result.is_err() && prefix.install_type == InstallType::Owned {
			let _ = fs::remove_dir_all(&prefix.path);
		}

		result
	}
	fn msi(src: &Path, work_dir: &Path, prefix: &InstallPrefix) -> Result<()> {
		let msi_owned = || -> Result<()> {
			let target_arg = utils::prefix_arg("TARGETDIR=", work_dir);

			// Extract the MSI to the subfolder
			let mut cmd = Command::new("msiexec");
			cmd
				.arg("/a").arg(src)
				.arg("/qn")
				.arg(&target_arg);

			try!(utils::cmd_status("msiexec", cmd));

			// Find the root Rust folder within the subfolder
			let root_dir = try!(try!(utils::read_dir("install", work_dir))
				.filter_map(io::Result::ok)
				.map(|e| e.path())
				.filter(|p| utils::is_directory(&p))
				.next()
				.ok_or(Error::InvalidInstaller));

			// Rename and move it to the toolchain directory
			utils::rename_dir("install", &root_dir, &prefix.path)
		};

		let msi_shared = || -> Result<()> {
			let target_arg = utils::prefix_arg("TARGETDIR=", &prefix.path);

			// Extract the MSI to the subfolder
			let mut cmd = Command::new("msiexec");
			cmd
				.arg("/i").arg(src)
				.arg("/qn")
				.arg(&target_arg);

			utils::cmd_status("msiexec", cmd)
		};

		match prefix.install_type {
			InstallType::Owned => {
				let result = msi_owned();
				if result.is_err() {
					let _ = fs::remove_dir_all(&prefix.path);
				}
				result
			},
			InstallType::Shared => {
				msi_shared()
			}
		}
	}
}

pub fn bin_path(name: &str) -> PathBuf {
	let mut path = PathBuf::from("bin");
	path.push(name.to_owned() + env::consts::EXE_SUFFIX);
	path
}

impl InstallPrefix {
	pub fn from(path: PathBuf, install_type: InstallType) -> Self {
		InstallPrefix {
			path: path,
			install_type: install_type,
		}
	}
	pub fn path(&self) -> &Path {
		&self.path
	}
	pub fn manifest_dir(&self) -> PathBuf {
		let mut path = self.path.clone();
		path.push("bin");
		path.push(REL_MANIFEST_DIR);
		path
	}
	pub fn manifest_file(&self, name: &str) -> PathBuf {
		let mut path = self.manifest_dir();
		path.push(name);
		path
	}
	pub fn binary_file(&self, name: &str) -> PathBuf {
		let mut path = self.path.clone();
		path.push(bin_path(name));
		path
	}
	pub fn doc_path(&self, relative: &str) -> Result<PathBuf> {
		let parts = vec!["share", "doc", "rust", "html"];
		let mut doc_dir = self.path.clone();
		for part in parts {
			doc_dir.push(part);
		}
		doc_dir.push(relative);

		Ok(doc_dir)
	}
	pub fn is_installed_here(&self) -> bool {
		utils::is_directory(&self.manifest_dir())
	}
	pub fn get_uninstall_sh(&self) -> Option<PathBuf> {
		let path = self.manifest_file("uninstall.sh");
		if utils::is_file(&path) {
			Some(path)
		} else {
			None
		}
	}

	#[cfg(windows)]
	pub fn get_uninstall_msi(&self, notify_handler: &NotifyHandler) -> Option<String> {
		let canon_path = utils::canonicalize_path(&self.path, notify_handler);

		if let Ok(installers) = msi::all_installers() {
			for installer in &installers {
				if let Ok(loc) = installer.install_location() {
					let path = utils::canonicalize_path(&loc, notify_handler);

					if path == canon_path {
						return Some(installer.product_id().to_owned());
					}
				}
			}
		}

		None
	}
	#[cfg(not(windows))]
	pub fn get_uninstall_msi(&self, notify_handler: &NotifyHandler) -> Option<String> {
		None
	}
	pub fn get_uninstaller(&self, notify_handler: &NotifyHandler) -> Option<Uninstaller> {
		self.get_uninstall_sh().map(Uninstaller::Sh).or_else(
			|| self.get_uninstall_msi(notify_handler).map(Uninstaller::Msi)
			)
	}
	pub fn uninstall(&self, notify_handler: &NotifyHandler) -> Result<()> {
		if self.is_installed_here() {
			match self.install_type {
				InstallType::Owned => {
					utils::remove_dir("install", &self.path, notify_handler)
				},
				InstallType::Shared => {
					if let Some(uninstaller) = self.get_uninstaller(notify_handler) {
						uninstaller.run()
					} else {
						Err(Error::NotInstalledHere)
					}
				},
			}
		} else {
			Err(Error::NotInstalledHere)
		}
	}
	pub fn install(&self, method: InstallMethod, notify_handler: &NotifyHandler) -> Result<()> {
		method.run(self, notify_handler)
	}

	pub fn with_ldpath<T, F: FnOnce() -> Result<T>>(&self, f: F) -> Result<T> {
		let new_path = self.path.join("lib");

		env_var::with_path("LD_LIBRARY_PATH", &new_path, || {
			env_var::with_path("DYLD_LIBRARY_PATH", &new_path, || {
				f()
			})
		})
	}

	pub fn with_env<T, F: FnOnce() -> Result<T>>(&self, f: F) -> Result<T> {
		let cargo_path = self.path.join("cargo");

		self.with_ldpath(|| {
			env_var::with_default("CARGO_HOME", cargo_path.as_ref(), || {
				f()
			})
		})
	}

	pub fn create_command(&self, binary: &str) -> Result<Command> {
		let binary_path = self.binary_file(binary);

		self.with_env(|| Ok(Command::new(binary_path)))
	}

	pub fn open_docs(&self, relative: &str) -> Result<()> {
		utils::open_browser(&try!(self.doc_path(relative)))
	}
}
<commit_msg>Cfg out using statement<commit_after>use utils;
use errors::*;
use temp;
use env_var;
use dist;
#[cfg(windows)]
use msi;

use std::path::{Path, PathBuf};
use std::process::Command;
use std::ffi::OsStr;
use std::fs;
use std::io;
use std::env;

const REL_MANIFEST_DIR: &'static str = "rustlib";

pub struct InstallPrefix {
	path: PathBuf,
	install_type: InstallType,
}

#[derive(Eq, PartialEq, Copy, Clone)]
pub enum InstallType {
	// Must be uninstalled by deleting the entire directory
	Owned,
	// Must be uninstalled via `uninstall.sh` on linux or `msiexec /x` on windows
	Shared,
}

pub enum Uninstaller {
	Sh(PathBuf),
	Msi(String),
}

impl Uninstaller {
	pub fn run(&self) -> Result<()> {
		match *self {
			Uninstaller::Sh(ref path) => {
				let mut cmd = Command::new("sudo");
				cmd.arg("sh").arg(path);
				utils::cmd_status("uninstall.sh", cmd)
			},
			Uninstaller::Msi(ref id) => {
				let mut cmd = Command::new("msiexec");
				cmd.arg("/x").arg(id);
				utils::cmd_status("msiexec", cmd)
			},
		}
	}
}

pub enum InstallMethod<'a> {
	Copy(&'a Path),
	Link(&'a Path),
	Installer(&'a Path, &'a temp::Cfg),
	Dist(&'a str, Option<&'a Path>, dist::DownloadCfg<'a>),
}

impl<'a> InstallMethod<'a> {
	pub fn install_type_possible(&self, install_type: InstallType) -> bool {
		match *self {
			InstallMethod::Copy(_)|InstallMethod::Link(_) => install_type == InstallType::Owned,
			InstallMethod::Installer(_, _)|InstallMethod::Dist(_,_,_) => true,
		}
	}
	pub fn run(self, prefix: &InstallPrefix, notify_handler: &NotifyHandler) -> Result<()> {
		if prefix.is_installed_here() {
			// Don't uninstall first for Dist method
			match self {
				InstallMethod::Dist(_,_,_) => {},
				_ => { try!(prefix.uninstall(notify_handler)); },
			}
		}

		if !self.install_type_possible(prefix.install_type) {
			return Err(Error::InstallTypeNotPossible);
		}

		match self {
			InstallMethod::Copy(src) => {
				utils::copy_dir(src, &prefix.path, notify_handler)
			},
			InstallMethod::Link(src) => {
				utils::symlink_dir(&prefix.path, src, notify_handler)
			},
			InstallMethod::Installer(src, temp_cfg) => {
				let temp_dir = try!(temp_cfg.new_directory());
				match src.extension().and_then(OsStr::to_str) {
					Some("gz") => InstallMethod::tar_gz(src, &temp_dir, prefix),
					Some("msi") => InstallMethod::msi(src, &temp_dir, prefix),
					_ => Err(Error::InvalidFileExtension),
				}
			},
			InstallMethod::Dist(toolchain, update_hash, dl_cfg) => {
				if let Some(installer) = try!(dist::download_dist(toolchain, update_hash, dl_cfg)) {
					try!(InstallMethod::Installer(&*installer, dl_cfg.temp_cfg).run(prefix, dl_cfg.notify_handler));
				}
				Ok(())
			}
		}
	}

	fn tar_gz(src: &Path, work_dir: &Path, prefix: &InstallPrefix) -> Result<()> {
		let installer_dir = Path::new(try!(Path::new(src.file_stem().unwrap()).file_stem()
			.ok_or(Error::InvalidFileExtension)));

		let mut cmd = Command::new("tar");
		cmd
			.arg("xzf").arg(src)
			.arg("-C").arg(work_dir);

		try!(utils::cmd_status("tar", cmd));

		let mut cmd = Command::new("sh");
		cmd
			.arg(installer_dir.join("install.sh"))
			.arg("--prefix").arg(&prefix.path);

		if prefix.install_type != InstallType::Shared {
			cmd.arg("--disable-ldconfig");
		}

		let result = utils::cmd_status("sh", cmd);

		if result.is_err() && prefix.install_type == InstallType::Owned {
			let _ = fs::remove_dir_all(&prefix.path);
		}

		result
	}
	fn msi(src: &Path, work_dir: &Path, prefix: &InstallPrefix) -> Result<()> {
		let msi_owned = || -> Result<()> {
			let target_arg = utils::prefix_arg("TARGETDIR=", work_dir);

			// Extract the MSI to the subfolder
			let mut cmd = Command::new("msiexec");
			cmd
				.arg("/a").arg(src)
				.arg("/qn")
				.arg(&target_arg);

			try!(utils::cmd_status("msiexec", cmd));

			// Find the root Rust folder within the subfolder
			let root_dir = try!(try!(utils::read_dir("install", work_dir))
				.filter_map(io::Result::ok)
				.map(|e| e.path())
				.filter(|p| utils::is_directory(&p))
				.next()
				.ok_or(Error::InvalidInstaller));

			// Rename and move it to the toolchain directory
			utils::rename_dir("install", &root_dir, &prefix.path)
		};

		let msi_shared = || -> Result<()> {
			let target_arg = utils::prefix_arg("TARGETDIR=", &prefix.path);

			// Extract the MSI to the subfolder
			let mut cmd = Command::new("msiexec");
			cmd
				.arg("/i").arg(src)
				.arg("/qn")
				.arg(&target_arg);

			utils::cmd_status("msiexec", cmd)
		};

		match prefix.install_type {
			InstallType::Owned => {
				let result = msi_owned();
				if result.is_err() {
					let _ = fs::remove_dir_all(&prefix.path);
				}
				result
			},
			InstallType::Shared => {
				msi_shared()
			}
		}
	}
}

pub fn bin_path(name: &str) -> PathBuf {
	let mut path = PathBuf::from("bin");
	path.push(name.to_owned() + env::consts::EXE_SUFFIX);
	path
}

impl InstallPrefix {
	pub fn from(path: PathBuf, install_type: InstallType) -> Self {
		InstallPrefix {
			path: path,
			install_type: install_type,
		}
	}
	pub fn path(&self) -> &Path {
		&self.path
	}
	pub fn manifest_dir(&self) -> PathBuf {
		let mut path = self.path.clone();
		path.push("bin");
		path.push(REL_MANIFEST_DIR);
		path
	}
	pub fn manifest_file(&self, name: &str) -> PathBuf {
		let mut path = self.manifest_dir();
		path.push(name);
		path
	}
	pub fn binary_file(&self, name: &str) -> PathBuf {
		let mut path = self.path.clone();
		path.push(bin_path(name));
		path
	}
	pub fn doc_path(&self, relative: &str) -> Result<PathBuf> {
		let parts = vec!["share", "doc", "rust", "html"];
		let mut doc_dir = self.path.clone();
		for part in parts {
			doc_dir.push(part);
		}
		doc_dir.push(relative);

		Ok(doc_dir)
	}
	pub fn is_installed_here(&self) -> bool {
		utils::is_directory(&self.manifest_dir())
	}
	pub fn get_uninstall_sh(&self) -> Option<PathBuf> {
		let path = self.manifest_file("uninstall.sh");
		if utils::is_file(&path) {
			Some(path)
		} else {
			None
		}
	}

	#[cfg(windows)]
	pub fn get_uninstall_msi(&self, notify_handler: &NotifyHandler) -> Option<String> {
		let canon_path = utils::canonicalize_path(&self.path, notify_handler);

		if let Ok(installers) = msi::all_installers() {
			for installer in &installers {
				if let Ok(loc) = installer.install_location() {
					let path = utils::canonicalize_path(&loc, notify_handler);

					if path == canon_path {
						return Some(installer.product_id().to_owned());
					}
				}
			}
		}

		None
	}
	#[cfg(not(windows))]
	pub fn get_uninstall_msi(&self, notify_handler: &NotifyHandler) -> Option<String> {
		None
	}
	pub fn get_uninstaller(&self, notify_handler: &NotifyHandler) -> Option<Uninstaller> {
		self.get_uninstall_sh().map(Uninstaller::Sh).or_else(
			|| self.get_uninstall_msi(notify_handler).map(Uninstaller::Msi)
			)
	}
	pub fn uninstall(&self, notify_handler: &NotifyHandler) -> Result<()> {
		if self.is_installed_here() {
			match self.install_type {
				InstallType::Owned => {
					utils::remove_dir("install", &self.path, notify_handler)
				},
				InstallType::Shared => {
					if let Some(uninstaller) = self.get_uninstaller(notify_handler) {
						uninstaller.run()
					} else {
						Err(Error::NotInstalledHere)
					}
				},
			}
		} else {
			Err(Error::NotInstalledHere)
		}
	}
	pub fn install(&self, method: InstallMethod, notify_handler: &NotifyHandler) -> Result<()> {
		method.run(self, notify_handler)
	}

	pub fn with_ldpath<T, F: FnOnce() -> Result<T>>(&self, f: F) -> Result<T> {
		let new_path = self.path.join("lib");

		env_var::with_path("LD_LIBRARY_PATH", &new_path, || {
			env_var::with_path("DYLD_LIBRARY_PATH", &new_path, || {
				f()
			})
		})
	}

	pub fn with_env<T, F: FnOnce() -> Result<T>>(&self, f: F) -> Result<T> {
		let cargo_path = self.path.join("cargo");

		self.with_ldpath(|| {
			env_var::with_default("CARGO_HOME", cargo_path.as_ref(), || {
				f()
			})
		})
	}

	pub fn create_command(&self, binary: &str) -> Result<Command> {
		let binary_path = self.binary_file(binary);

		self.with_env(|| Ok(Command::new(binary_path)))
	}

	pub fn open_docs(&self, relative: &str) -> Result<()> {
		utils::open_browser(&try!(self.doc_path(relative)))
	}
}
<|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.

//! Handles syntax highlighting and other styling.
//!
//! Plugins provide syntax highlighting information in the form of 'scopes'.
//! Scope information originating from any number of plugins can be resolved
//! into styles using a theme, augmented with additional style definitions.

use std::collections::BTreeMap;
use syntect::parsing::Scope;
use syntect::highlighting::StyleModifier;

use xi_rope::interval::Interval;
use xi_rope::spans::{Spans, SpansBuilder};

use tabs::DocumentCtx;
use styles::Style;
use plugins::PluginPid;

/// A collection of layers containing scope information.
#[derive(Default)]
//TODO: rename. Probably to `Layers`
pub struct Scopes {
    layers: BTreeMap<PluginPid, ScopeLayer>,
    merged: Spans<Style>,
}

/// A collection of scope spans from a single source.
pub struct ScopeLayer {
    stack_lookup: Vec<Vec<Scope>>,
    style_lookup: Vec<Style>,
    // TODO: this might be efficient (in memory at least) if we use
    // a prefix tree.
    /// style state of existing scope spans, so we can more efficiently
    /// compute styles of child spans.
    style_cache: BTreeMap<Vec<Scope>, StyleModifier>,
    /// Human readable scope names, for debugging
    scope_spans: Spans<u32>,
    style_spans: Spans<Style>,
}

impl Scopes {

    pub fn get_merged(&self) -> &Spans<Style> {
        &self.merged
    }

    /// Adds the provided scopes to the layer's lookup table.
    pub fn add_scopes(&mut self, layer: PluginPid, scopes: Vec<Vec<String>>,
                                doc_ctx: &DocumentCtx) {
        self.create_if_missing(layer);
        self.layers.get_mut(&layer).unwrap().add_scopes(scopes, doc_ctx);
    }

    /// Inserts empty spans at the given interval for all layers.
    ///
    /// This is useful for clearing spans, and for updating spans
    /// as edits occur.
    pub fn update_all(&mut self, iv: Interval, len: usize) {
        self.merged.edit(iv, SpansBuilder::new(len).build());
        let empty_spans = SpansBuilder::new(len).build();
        for layer in self.layers.values_mut() {
            layer.update_scopes(iv, &empty_spans);
        }
        self.resolve_styles(iv);
    }

    /// Updates the scope spans for a given layer.
    pub fn update_layer(&mut self, layer: PluginPid, iv: Interval, spans: Spans<u32>) {
        self.create_if_missing(layer);
        self.layers.get_mut(&layer).unwrap().update_scopes(iv, &spans);
        self.resolve_styles(iv);
    }

    /// Removes a given layer. This will remove all styles derived from
    /// that layer's scopes.
    pub fn remove_layer(&mut self, layer: PluginPid) -> Option<ScopeLayer> {
        let layer = self.layers.remove(&layer);
        if layer.is_some() {
            let iv_all = Interval::new_closed_closed(0, self.merged.len());
            //TODO: should Spans<T> have a clear() method?
            self.merged = SpansBuilder::new(self.merged.len()).build();
            self.resolve_styles(iv_all);
        }
        layer
    }

    pub fn theme_changed(&mut self, doc_ctx: &DocumentCtx) {
        for layer in self.layers.values_mut() {
            layer.theme_changed(doc_ctx);
        }
        self.merged = SpansBuilder::new(self.merged.len()).build();
        let iv_all = Interval::new_closed_closed(0, self.merged.len());
        self.resolve_styles(iv_all);
    }

    /// Resolves styles from all layers for the given interval, updating
    /// the master style spans.
    fn resolve_styles(&mut self, iv: Interval) {
        if self.layers.is_empty() {
            return
        }
        let mut layer_iter = self.layers.values();
        let mut resolved = layer_iter.next().unwrap().style_spans.subseq(iv);

        for other in layer_iter {
            let spans = other.style_spans.subseq(iv);
            assert_eq!(resolved.len(), spans.len());
            resolved = resolved.merge(&spans, |a, b| {
                match b {
                    Some(b) => a.merge(b),
                    None => a.to_owned(),
                }
            });
        }
        self.merged.edit(iv, resolved);
    }

    /// Prints scopes and style information for the given `Interval`.
    pub fn debug_print_spans(&self, iv: Interval) {
        for (id, layer) in self.layers.iter() {
            let spans = layer.scope_spans.subseq(iv);
            let styles = layer.style_spans.subseq(iv);
            if spans.iter().next().is_some() {
                eprintln!("scopes for layer {:?}:", id);
                for (iv, val) in spans.iter() {
                    eprintln!("{}: {:?}", iv, layer.stack_lookup[*val as usize]);
                }
                eprintln!("styles:");
                for (iv, val) in styles.iter() {
                    eprintln!("{}: {:?}", iv, val);
                }
            }
        }
    }

    fn create_if_missing(&mut self, layer_id: PluginPid) {
        if !self.layers.contains_key(&layer_id) {
            self.layers.insert(layer_id, ScopeLayer::new(self.merged.len()));
        }
    }
}

impl Default for ScopeLayer {
    fn default() -> Self {
        ScopeLayer {
            stack_lookup: Vec::new(),
            style_lookup: Vec::new(),
            style_cache: BTreeMap::new(),
            scope_spans: Spans::default(),
            style_spans: Spans::default(),
        }
    }
}

impl ScopeLayer {

    pub fn new(len: usize) -> Self {
        ScopeLayer {
            stack_lookup: Vec::new(),
            style_lookup: Vec::new(),
            style_cache: BTreeMap::new(),
            scope_spans: SpansBuilder::new(len).build(),
            style_spans: SpansBuilder::new(len).build(),
        }
    }

    fn theme_changed(&mut self, doc_ctx: &DocumentCtx) {
        // recompute styles with the new theme
        let cur_stacks = self.stack_lookup.clone();
        self.style_lookup = self.styles_for_stacks(&cur_stacks, doc_ctx);
        let iv_all = Interval::new_closed_closed(0, self.style_spans.len());
        self.style_spans = SpansBuilder::new(self.style_spans.len()).build();
        // this feels unnecessary but we can't pass in a reference to self
        // and I don't want to get fancy unless there's an actual perf problem
        let scopes = self.scope_spans.clone();
        self.update_styles(iv_all, &scopes)
    }

    fn add_scopes(&mut self, scopes: Vec<Vec<String>>,
                                doc_ctx: &DocumentCtx) {
        let mut stacks = Vec::with_capacity(scopes.len());
        for stack in scopes {
            let scopes = stack.iter().map(|s| Scope::new(&s))
                .filter(|result| match *result {
                    Err(ref err) => {
                        eprintln!("failed to resolve scope {}\nErr: {:?}",
                                   &stack.join(" "),
                                   err);
                        false
                    }
                    _ => true
                })
                .map(|s| s.unwrap())
                .collect::<Vec<_>>();
            stacks.push(scopes);
        }

        let mut new_styles = self.styles_for_stacks(stacks.as_slice(), doc_ctx);
        self.stack_lookup.append(&mut stacks);
        self.style_lookup.append(&mut new_styles);
    }

    fn styles_for_stacks(&mut self, stacks: &[Vec<Scope>],
                         doc_ctx: &DocumentCtx) -> Vec<Style> {
        let style_map = doc_ctx.get_style_map().lock().unwrap();
        let highlighter = style_map.get_highlighter();
        let mut new_styles = Vec::new();

        for stack in stacks {
            let mut last_style: Option<StyleModifier> = None;
            let mut upper_bound_of_last = stack.len() as usize;

            // walk backwards through stack to see if we have an existing
            // style for any child stacks.
            for i in 0..stack.len()-1 {
                let prev_range = 0..stack.len() - (i + 1);
                if let Some(s) = self.style_cache.get(&stack[prev_range]) {
                    last_style = Some(*s);
                    upper_bound_of_last = stack.len() - (i + 1);
                    break
                }
            }
            let mut base_style_mod = last_style.unwrap_or_default();

            // apply the stack, generating children as needed.
            for i in upper_bound_of_last..stack.len() {
                let style_mod = highlighter.get_style(&stack[0..i+1]);
                base_style_mod = base_style_mod.apply(style_mod);
            }

            let style = Style::from_syntect_style_mod(&base_style_mod);
            self.style_cache.insert(stack.clone(), base_style_mod);

            new_styles.push(style);
        }
        new_styles
    }

    fn update_scopes(&mut self, iv: Interval, spans: &Spans<u32>) {
        self.scope_spans.edit(iv, spans.to_owned());
        self.update_styles(iv, spans);
    }

    /// Updates `self.style_spans`, mapping scopes to styles and combining
    /// adjacent and equal spans.
    fn update_styles(&mut self, iv: Interval, spans: &Spans<u32>) {

        // NOTE: This is a tradeoff. Keeping both u32 and Style spans for each
        // layer makes debugging simpler and reduces the total number of spans
        // on the wire (because we combine spans that resolve to the same style)
        // but it does require additional computation + memory up front.
        let mut sb = SpansBuilder::new(spans.len());
        let mut spans_iter = spans.iter();
        let mut prev = spans_iter.next();
        {
        // distinct adjacent scopes can often resolve to the same style,
        // so we combine them when building the styles.
        let style_eq = |i1: &u32, i2: &u32| {
            self.style_lookup[*i1 as usize] == self.style_lookup[*i2 as usize]
        };

        while let Some((p_iv, p_val)) = prev {
            match spans_iter.next() {
                Some((n_iv, n_val)) if n_iv.start() == p_iv.end() && style_eq(p_val, n_val) => {
                    prev = Some((p_iv.union(n_iv), p_val));
                }
                other => {
                    sb.add_span(p_iv, self.style_lookup[*p_val as usize].to_owned());
                    prev = other;
                }
            }
        }
        }
        self.style_spans.edit(iv, sb.build());
    }
}
<commit_msg>Use hashmap instead of btreemap for style cache<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.

//! Handles syntax highlighting and other styling.
//!
//! Plugins provide syntax highlighting information in the form of 'scopes'.
//! Scope information originating from any number of plugins can be resolved
//! into styles using a theme, augmented with additional style definitions.

use std::collections::{BTreeMap, HashMap};
use syntect::parsing::Scope;
use syntect::highlighting::StyleModifier;

use xi_rope::interval::Interval;
use xi_rope::spans::{Spans, SpansBuilder};

use tabs::DocumentCtx;
use styles::Style;
use plugins::PluginPid;

/// A collection of layers containing scope information.
#[derive(Default)]
//TODO: rename. Probably to `Layers`
pub struct Scopes {
    layers: BTreeMap<PluginPid, ScopeLayer>,
    merged: Spans<Style>,
}

/// A collection of scope spans from a single source.
pub struct ScopeLayer {
    stack_lookup: Vec<Vec<Scope>>,
    style_lookup: Vec<Style>,
    // TODO: this might be efficient (in memory at least) if we use
    // a prefix tree.
    /// style state of existing scope spans, so we can more efficiently
    /// compute styles of child spans.
    style_cache: HashMap<Vec<Scope>, StyleModifier>,
    /// Human readable scope names, for debugging
    scope_spans: Spans<u32>,
    style_spans: Spans<Style>,
}

impl Scopes {

    pub fn get_merged(&self) -> &Spans<Style> {
        &self.merged
    }

    /// Adds the provided scopes to the layer's lookup table.
    pub fn add_scopes(&mut self, layer: PluginPid, scopes: Vec<Vec<String>>,
                                doc_ctx: &DocumentCtx) {
        self.create_if_missing(layer);
        self.layers.get_mut(&layer).unwrap().add_scopes(scopes, doc_ctx);
    }

    /// Inserts empty spans at the given interval for all layers.
    ///
    /// This is useful for clearing spans, and for updating spans
    /// as edits occur.
    pub fn update_all(&mut self, iv: Interval, len: usize) {
        self.merged.edit(iv, SpansBuilder::new(len).build());
        let empty_spans = SpansBuilder::new(len).build();
        for layer in self.layers.values_mut() {
            layer.update_scopes(iv, &empty_spans);
        }
        self.resolve_styles(iv);
    }

    /// Updates the scope spans for a given layer.
    pub fn update_layer(&mut self, layer: PluginPid, iv: Interval, spans: Spans<u32>) {
        self.create_if_missing(layer);
        self.layers.get_mut(&layer).unwrap().update_scopes(iv, &spans);
        self.resolve_styles(iv);
    }

    /// Removes a given layer. This will remove all styles derived from
    /// that layer's scopes.
    pub fn remove_layer(&mut self, layer: PluginPid) -> Option<ScopeLayer> {
        let layer = self.layers.remove(&layer);
        if layer.is_some() {
            let iv_all = Interval::new_closed_closed(0, self.merged.len());
            //TODO: should Spans<T> have a clear() method?
            self.merged = SpansBuilder::new(self.merged.len()).build();
            self.resolve_styles(iv_all);
        }
        layer
    }

    pub fn theme_changed(&mut self, doc_ctx: &DocumentCtx) {
        for layer in self.layers.values_mut() {
            layer.theme_changed(doc_ctx);
        }
        self.merged = SpansBuilder::new(self.merged.len()).build();
        let iv_all = Interval::new_closed_closed(0, self.merged.len());
        self.resolve_styles(iv_all);
    }

    /// Resolves styles from all layers for the given interval, updating
    /// the master style spans.
    fn resolve_styles(&mut self, iv: Interval) {
        if self.layers.is_empty() {
            return
        }
        let mut layer_iter = self.layers.values();
        let mut resolved = layer_iter.next().unwrap().style_spans.subseq(iv);

        for other in layer_iter {
            let spans = other.style_spans.subseq(iv);
            assert_eq!(resolved.len(), spans.len());
            resolved = resolved.merge(&spans, |a, b| {
                match b {
                    Some(b) => a.merge(b),
                    None => a.to_owned(),
                }
            });
        }
        self.merged.edit(iv, resolved);
    }

    /// Prints scopes and style information for the given `Interval`.
    pub fn debug_print_spans(&self, iv: Interval) {
        for (id, layer) in self.layers.iter() {
            let spans = layer.scope_spans.subseq(iv);
            let styles = layer.style_spans.subseq(iv);
            if spans.iter().next().is_some() {
                eprintln!("scopes for layer {:?}:", id);
                for (iv, val) in spans.iter() {
                    eprintln!("{}: {:?}", iv, layer.stack_lookup[*val as usize]);
                }
                eprintln!("styles:");
                for (iv, val) in styles.iter() {
                    eprintln!("{}: {:?}", iv, val);
                }
            }
        }
    }

    fn create_if_missing(&mut self, layer_id: PluginPid) {
        if !self.layers.contains_key(&layer_id) {
            self.layers.insert(layer_id, ScopeLayer::new(self.merged.len()));
        }
    }
}

impl Default for ScopeLayer {
    fn default() -> Self {
        ScopeLayer {
            stack_lookup: Vec::new(),
            style_lookup: Vec::new(),
            style_cache: HashMap::new(),
            scope_spans: Spans::default(),
            style_spans: Spans::default(),
        }
    }
}

impl ScopeLayer {

    pub fn new(len: usize) -> Self {
        ScopeLayer {
            stack_lookup: Vec::new(),
            style_lookup: Vec::new(),
            style_cache: HashMap::new(),
            scope_spans: SpansBuilder::new(len).build(),
            style_spans: SpansBuilder::new(len).build(),
        }
    }

    fn theme_changed(&mut self, doc_ctx: &DocumentCtx) {
        // recompute styles with the new theme
        let cur_stacks = self.stack_lookup.clone();
        self.style_lookup = self.styles_for_stacks(&cur_stacks, doc_ctx);
        let iv_all = Interval::new_closed_closed(0, self.style_spans.len());
        self.style_spans = SpansBuilder::new(self.style_spans.len()).build();
        // this feels unnecessary but we can't pass in a reference to self
        // and I don't want to get fancy unless there's an actual perf problem
        let scopes = self.scope_spans.clone();
        self.update_styles(iv_all, &scopes)
    }

    fn add_scopes(&mut self, scopes: Vec<Vec<String>>,
                                doc_ctx: &DocumentCtx) {
        let mut stacks = Vec::with_capacity(scopes.len());
        for stack in scopes {
            let scopes = stack.iter().map(|s| Scope::new(&s))
                .filter(|result| match *result {
                    Err(ref err) => {
                        eprintln!("failed to resolve scope {}\nErr: {:?}",
                                   &stack.join(" "),
                                   err);
                        false
                    }
                    _ => true
                })
                .map(|s| s.unwrap())
                .collect::<Vec<_>>();
            stacks.push(scopes);
        }

        let mut new_styles = self.styles_for_stacks(stacks.as_slice(), doc_ctx);
        self.stack_lookup.append(&mut stacks);
        self.style_lookup.append(&mut new_styles);
    }

    fn styles_for_stacks(&mut self, stacks: &[Vec<Scope>],
                         doc_ctx: &DocumentCtx) -> Vec<Style> {
        let style_map = doc_ctx.get_style_map().lock().unwrap();
        let highlighter = style_map.get_highlighter();
        let mut new_styles = Vec::new();

        for stack in stacks {
            let mut last_style: Option<StyleModifier> = None;
            let mut upper_bound_of_last = stack.len() as usize;

            // walk backwards through stack to see if we have an existing
            // style for any child stacks.
            for i in 0..stack.len()-1 {
                let prev_range = 0..stack.len() - (i + 1);
                if let Some(s) = self.style_cache.get(&stack[prev_range]) {
                    last_style = Some(*s);
                    upper_bound_of_last = stack.len() - (i + 1);
                    break
                }
            }
            let mut base_style_mod = last_style.unwrap_or_default();

            // apply the stack, generating children as needed.
            for i in upper_bound_of_last..stack.len() {
                let style_mod = highlighter.get_style(&stack[0..i+1]);
                base_style_mod = base_style_mod.apply(style_mod);
            }

            let style = Style::from_syntect_style_mod(&base_style_mod);
            self.style_cache.insert(stack.clone(), base_style_mod);

            new_styles.push(style);
        }
        new_styles
    }

    fn update_scopes(&mut self, iv: Interval, spans: &Spans<u32>) {
        self.scope_spans.edit(iv, spans.to_owned());
        self.update_styles(iv, spans);
    }

    /// Updates `self.style_spans`, mapping scopes to styles and combining
    /// adjacent and equal spans.
    fn update_styles(&mut self, iv: Interval, spans: &Spans<u32>) {

        // NOTE: This is a tradeoff. Keeping both u32 and Style spans for each
        // layer makes debugging simpler and reduces the total number of spans
        // on the wire (because we combine spans that resolve to the same style)
        // but it does require additional computation + memory up front.
        let mut sb = SpansBuilder::new(spans.len());
        let mut spans_iter = spans.iter();
        let mut prev = spans_iter.next();
        {
        // distinct adjacent scopes can often resolve to the same style,
        // so we combine them when building the styles.
        let style_eq = |i1: &u32, i2: &u32| {
            self.style_lookup[*i1 as usize] == self.style_lookup[*i2 as usize]
        };

        while let Some((p_iv, p_val)) = prev {
            match spans_iter.next() {
                Some((n_iv, n_val)) if n_iv.start() == p_iv.end() && style_eq(p_val, n_val) => {
                    prev = Some((p_iv.union(n_iv), p_val));
                }
                other => {
                    sb.add_span(p_iv, self.style_lookup[*p_val as usize].to_owned());
                    prev = other;
                }
            }
        }
        }
        self.style_spans.edit(iv, sb.build());
    }
}
<|endoftext|>


<commit_before>import to_str::*;
import to_str::to_str;

class cat {
  priv {
    let mut meows : uint;
    fn meow() {
      #error("Meow");
      self.meows += 1u;
      if self.meows % 5u == 0u {
          self.how_hungry += 1;
      }
    }
  }

  let mut how_hungry : int;
  let name : str;

  new(in_x : uint, in_y : int, in_name: str)
    { self.meows = in_x; self.how_hungry = in_y; self.name = in_name; }

  fn speak() { self.meow(); }

  fn eat() -> bool {
    if self.how_hungry > 0 {
        #error("OM NOM NOM");
        self.how_hungry -= 2;
        ret true;
    }
    else {
        #error("Not hungry!");
        ret false;
    }
  }
}

impl of to_str for cat {
  fn to_str() -> str { self.name }
}

fn print_out<T: to_str>(thing: T, expected: str) {
  let actual = thing.to_str();
  #debug("%s", actual);
  assert(actual == expected);
}

fn main() {
  let nyan : to_str  = cat(0u, 2, "nyan") as to_str;
  print_out(nyan, "nyan");
}
<commit_msg>xfail-fast class-separate-impl<commit_after>// xfail-fast
// (Not sure why, though -- FIXME (tjc)
import to_str::*;
import to_str::to_str;

class cat {
  priv {
    let mut meows : uint;
    fn meow() {
      #error("Meow");
      self.meows += 1u;
      if self.meows % 5u == 0u {
          self.how_hungry += 1;
      }
    }
  }

  let mut how_hungry : int;
  let name : str;

  new(in_x : uint, in_y : int, in_name: str)
    { self.meows = in_x; self.how_hungry = in_y; self.name = in_name; }

  fn speak() { self.meow(); }

  fn eat() -> bool {
    if self.how_hungry > 0 {
        #error("OM NOM NOM");
        self.how_hungry -= 2;
        ret true;
    }
    else {
        #error("Not hungry!");
        ret false;
    }
  }
}

impl of to_str for cat {
  fn to_str() -> str { self.name }
}

fn print_out<T: to_str>(thing: T, expected: str) {
  let actual = thing.to_str();
  #debug("%s", actual);
  assert(actual == expected);
}

fn main() {
  let nyan : to_str  = cat(0u, 2, "nyan") as to_str;
  print_out(nyan, "nyan");
}
<|endoftext|>


<commit_before>use kay::{ID, Recipient, Actor, Individual, Swarm, ActorSystem, Fate, CreateWith};
use descartes::{Band, Curve, Into2d, FiniteCurve};
use ::core::geometry::{CPath, AnyShape};

use super::{SelectableStrokeRef, CurrentPlan, PlanControl};

#[derive(Actor, Compact, Clone)]
pub struct LaneStrokeSelectable{
    _id: ID,
    stroke_ref: SelectableStrokeRef,
    path: CPath
}

impl LaneStrokeSelectable{
    pub fn new(stroke_ref: SelectableStrokeRef, path: CPath) -> Self {
        LaneStrokeSelectable{
            _id: ID::invalid(),
            stroke_ref: stroke_ref,
            path: path
        }
    }
}

use super::AddToUI;
use ::core::ui::Add;

impl Recipient<AddToUI> for LaneStrokeSelectable {
    fn receive(&mut self, msg: &AddToUI) -> Fate {match *msg{
        AddToUI => {
            ::core::ui::UserInterface::id() << Add::Interactable3d(
                self.id(),
                AnyShape::Band(Band::new(self.path.clone(), 5.0)),
                1
            );
            Fate::Live
        }
    }}
}

use super::ClearSelectables;
use ::core::ui::Remove;

impl Recipient<ClearSelectables> for LaneStrokeSelectable {
    fn receive(&mut self, msg: &ClearSelectables) -> Fate {match *msg{
        ClearSelectables => {
            ::core::ui::UserInterface::id() << Remove::Interactable3d(self.id());
            Fate::Die
        }
    }}
}

use ::core::ui::Event3d;

impl Recipient<Event3d> for LaneStrokeSelectable {
    fn receive(&mut self, msg: &Event3d) -> Fate {match *msg{
        Event3d::DragStarted{at} => {
            if let Some(selection_start) = self.path.project(at.into_2d()) {
                CurrentPlan::id() << PlanControl::Select(
                    self.stroke_ref,
                    (selection_start - 1.5).max(0.1),
                    (selection_start + 1.5).min(self.path.length() - 0.1)
                );
            }
            Fate::Live
        },
        Event3d::DragOngoing{from, to} => {
            if let (Some(selection_start), Some(selection_end)) =
            (self.path.project(from.into_2d()), self.path.project(to.into_2d())) {
                let start = selection_start.min(selection_end);
                let end = selection_end.max(selection_start);
                CurrentPlan::id() << PlanControl::Select(
                    self.stroke_ref,
                    start.min(end - 1.5).max(0.1),
                    end.max(start + 1.5).min(self.path.length() - 0.1)
                );
            }
            Fate::Live
        },
        Event3d::DragFinished{to, ..} => {
            CurrentPlan::id() << PlanControl::Commit(true, to.into_2d());
            Fate::Live
        },
        _ => Fate::Live
    }}
}

pub fn setup(system: &mut ActorSystem) {
    system.add_individual(Swarm::<LaneStrokeSelectable>::new());
    system.add_inbox::<CreateWith<LaneStrokeSelectable, AddToUI>, Swarm<LaneStrokeSelectable>>();
    system.add_inbox::<ClearSelectables, Swarm<LaneStrokeSelectable>>();
    system.add_inbox::<Event3d, Swarm<LaneStrokeSelectable>>();
}<commit_msg>Snap selection to start, end and inbetween points #20<commit_after>use kay::{ID, Recipient, Actor, Individual, Swarm, ActorSystem, Fate, CreateWith};
use descartes::{Band, Curve, Into2d, FiniteCurve, Path};
use ::core::geometry::{CPath, AnyShape};

use super::{SelectableStrokeRef, CurrentPlan, PlanControl};

#[derive(Actor, Compact, Clone)]
pub struct LaneStrokeSelectable{
    _id: ID,
    stroke_ref: SelectableStrokeRef,
    path: CPath
}

impl LaneStrokeSelectable{
    pub fn new(stroke_ref: SelectableStrokeRef, path: CPath) -> Self {
        LaneStrokeSelectable{
            _id: ID::invalid(),
            stroke_ref: stroke_ref,
            path: path
        }
    }
}

use super::AddToUI;
use ::core::ui::Add;

impl Recipient<AddToUI> for LaneStrokeSelectable {
    fn receive(&mut self, msg: &AddToUI) -> Fate {match *msg{
        AddToUI => {
            ::core::ui::UserInterface::id() << Add::Interactable3d(
                self.id(),
                AnyShape::Band(Band::new(self.path.clone(), 5.0)),
                1
            );
            Fate::Live
        }
    }}
}

use super::ClearSelectables;
use ::core::ui::Remove;

impl Recipient<ClearSelectables> for LaneStrokeSelectable {
    fn receive(&mut self, msg: &ClearSelectables) -> Fate {match *msg{
        ClearSelectables => {
            ::core::ui::UserInterface::id() << Remove::Interactable3d(self.id());
            Fate::Die
        }
    }}
}

use ::core::ui::Event3d;

impl Recipient<Event3d> for LaneStrokeSelectable {
    fn receive(&mut self, msg: &Event3d) -> Fate {match *msg{
        Event3d::DragStarted{at} => {
            if let Some(selection_start) = self.path.project(at.into_2d()) {
                CurrentPlan::id() << PlanControl::Select(
                    self.stroke_ref,
                    (selection_start - 1.5).max(0.1),
                    (selection_start + 1.5).min(self.path.length() - 0.1)
                );
            }
            Fate::Live
        },
        Event3d::DragOngoing{from, to} => {
            if let (Some(selection_start), Some(selection_end)) =
            (self.path.project(from.into_2d()), self.path.project(to.into_2d())) {
                let mut start = selection_start.min(selection_end);
                let mut end = selection_end.max(selection_start);
                if start < 10.0 {start = 0.0}
                if end > self.path.length() - 10.0 {end = self.path.length()}
                let mut offset = 0.0;
                for segment in self.path.segments() {
                    let next_offset = offset + segment.length();
                    if start > offset - 5.0 && start < offset + 5.0 {start = offset}
                    if end > next_offset - 5.0 && end < next_offset + 5.0 {end = next_offset}
                    offset = next_offset;
                }
                CurrentPlan::id() << PlanControl::Select(
                    self.stroke_ref,
                    start.min(end - 1.5).max(0.1),
                    end.max(start + 1.5).min(self.path.length() - 0.1)
                );
            }
            Fate::Live
        },
        Event3d::DragFinished{to, ..} => {
            CurrentPlan::id() << PlanControl::Commit(true, to.into_2d());
            Fate::Live
        },
        _ => Fate::Live
    }}
}

pub fn setup(system: &mut ActorSystem) {
    system.add_individual(Swarm::<LaneStrokeSelectable>::new());
    system.add_inbox::<CreateWith<LaneStrokeSelectable, AddToUI>, Swarm<LaneStrokeSelectable>>();
    system.add_inbox::<ClearSelectables, Swarm<LaneStrokeSelectable>>();
    system.add_inbox::<Event3d, Swarm<LaneStrokeSelectable>>();
}<|endoftext|>