<commit_before>use std::collections::BTreeMap;

use anyhow::Result;
use log::debug;

use crate::{
    analysis::dis,
    aspace::AddressSpace,
    module::{Module, Permissions},
    VA,
};
use lancelot_flirt::*;

/// make a best guess as to the reference target, found at `ref_offset` from
/// `va`.
fn get_ref(module: &Module, decoder: &zydis::Decoder, va: VA, ref_offset: u64) -> Option<VA> {
    for i in (1..=4u64).rev() {
        let candidate_insn_va = va + ref_offset - i;
        let mut insn_buf = [0u8; 16];

        if module.address_space.read_into(candidate_insn_va, &mut insn_buf).is_ok() {
            if let Ok(Some(insn)) = decoder.decode(&insn_buf) {
                let explicit_operands = insn
                    .operands
                    .iter()
                    .filter(|op| matches!(op.visibility, zydis::OperandVisibility::EXPLICIT));
                for (i, op) in explicit_operands.take(2).enumerate() {
                    match op.ty {
                        zydis::OperandType::MEMORY => {
                            if op.mem.base == zydis::Register::NONE
                                && op.mem.index == zydis::Register::NONE
                                && op.mem.scale == 0
                                && op.mem.disp.has_displacement
                            {
                                if insn.raw.disp_offset == i as u8 {
                                    if let Ok(target) = insn.calc_absolute_address(candidate_insn_va, op) {
                                        if module.probe_va(target, Permissions::RX) {
                                            return Some(target);
                                        }
                                    }
                                }
                            } else if op.mem.base == zydis::Register::RIP
                                && op.mem.index == zydis::Register::NONE
                                && op.mem.scale == 0
                                && op.mem.disp.has_displacement
                            {
                                if insn.raw.disp_offset == i as u8 {
                                    if let Ok(target) = insn.calc_absolute_address(candidate_insn_va, op) {
                                        if module.probe_va(target, Permissions::RX) {
                                            return Some(target);
                                        }
                                    }
                                }
                            }
                            continue;
                        }
                        zydis::OperandType::IMMEDIATE => {
                            if insn.raw.imm[i].offset == i as u8 {
                                if let Ok(target) = insn.calc_absolute_address(candidate_insn_va, op) {
                                    if module.probe_va(target, Permissions::RX) {
                                        return Some(target);
                                    }
                                }
                            }
                            continue;
                        }
                        zydis::OperandType::POINTER => continue,
                        zydis::OperandType::REGISTER => continue,
                        zydis::OperandType::UNUSED => continue,
                    }
                }
            }
        }
    }

    None
}

pub fn match_flirt(module: &Module, sigs: &FlirtSignatureSet, va: VA) -> Result<Vec<FlirtSignature>> {
    fn match_flirt_inner(
        module: &Module,
        sigs: &FlirtSignatureSet,
        decoder: &zydis::Decoder,
        va: VA,
        cache: &mut BTreeMap<VA, Vec<FlirtSignature>>,
    ) -> Result<Vec<FlirtSignature>> {
        let sec = module
            .sections
            .iter()
            .find(|sec| sec.virtual_range.start <= va && va < sec.virtual_range.end)
            .unwrap();

        let size = sec.virtual_range.end - va;
        let buf = module.address_space.read_bytes(va, size as usize)?;

        Ok(sigs
            .r#match(&buf)
            .iter()
            .filter(|sig| {
                let mut does_match_references = true;

                'names: for name in sig.names.iter() {
                    if let Symbol::Reference(Name {
                        offset,
                        name: wanted_name,
                    }) = name
                    {
                        // i dont know what this means.
                        assert!(*offset >= 0, "negative offset");

                        if let Some(target) = get_ref(module, &decoder, va, *offset as u64) {
                            // TODO: special case "."

                            if !cache.contains_key(&target) {
                                let target_sigs = match_flirt_inner(module, sigs, decoder, target, cache)
                                    .unwrap_or_else(|_| Default::default());
                                cache.insert(target, target_sigs);
                            }

                            let target_sigs = cache.get(&target).unwrap();

                            let mut does_name_match = false;
                            'sigs: for target_sig in target_sigs.iter() {
                                for name in target_sig.names.iter() {
                                    match name {
                                        Symbol::Reference(_) => continue,
                                        Symbol::Local(Name {
                                            name: target_name,
                                            offset,
                                        }) => {
                                            if *offset == 0 && target_name == wanted_name {
                                                does_name_match = true;
                                                break 'sigs;
                                            }
                                        }
                                        Symbol::Public(Name {
                                            name: target_name,
                                            offset,
                                        }) => {
                                            if *offset == 0 && target_name == wanted_name {
                                                does_name_match = true;
                                                break 'sigs;
                                            }
                                        }
                                    }
                                }
                            }

                            if !does_name_match {
                                does_match_references = false;
                                break 'names;
                            }
                        } else {
                            does_match_references = false;
                            break;
                        }
                    }
                }

                does_match_references
            })
            .cloned()
            .cloned()
            .collect::<Vec<_>>())
    }

    let decoder = dis::get_disassembler(module)?;
    let mut cache = Default::default();
    match_flirt_inner(module, sigs, &decoder, va, &mut cache)
}
<commit_msg>flirt: fix reference matching bug<commit_after>use std::collections::BTreeMap;

use anyhow::Result;
use log::debug;

use crate::{
    analysis::dis,
    aspace::AddressSpace,
    module::{Module, Permissions},
    VA,
};
use lancelot_flirt::*;

/// make a best guess as to the reference target, found at `ref_offset` from
/// `va`.
fn get_ref(module: &Module, decoder: &zydis::Decoder, va: VA, ref_offset: u64) -> Option<VA> {
    for i in (1..=4u64).rev() {
        let candidate_insn_va = va + ref_offset - i;
        let mut insn_buf = [0u8; 16];

        if module.address_space.read_into(candidate_insn_va, &mut insn_buf).is_ok() {
            if let Ok(Some(insn)) = decoder.decode(&insn_buf) {
                let explicit_operands = insn
                    .operands
                    .iter()
                    .filter(|op| matches!(op.visibility, zydis::OperandVisibility::EXPLICIT));
                for (j, op) in explicit_operands.take(2).enumerate() {
                    match op.ty {
                        zydis::OperandType::MEMORY => {
                            if op.mem.base == zydis::Register::NONE
                                && op.mem.index == zydis::Register::NONE
                                && op.mem.scale == 0
                                && op.mem.disp.has_displacement
                            {
                                if insn.raw.disp_offset == i as u8 {
                                    if let Ok(target) = insn.calc_absolute_address(candidate_insn_va, op) {
                                        if module.probe_va(target, Permissions::RX) {
                                            return Some(target);
                                        }
                                    }
                                }
                            } else if op.mem.base == zydis::Register::RIP
                                && op.mem.index == zydis::Register::NONE
                                && op.mem.scale == 0
                                && op.mem.disp.has_displacement
                            {
                                if insn.raw.disp_offset == i as u8 {
                                    if let Ok(target) = insn.calc_absolute_address(candidate_insn_va, op) {
                                        if module.probe_va(target, Permissions::RX) {
                                            return Some(target);
                                        }
                                    }
                                }
                            }
                            continue;
                        }
                        zydis::OperandType::IMMEDIATE => {
                            if insn.raw.imm[j].offset == i as u8 {
                                if let Ok(target) = insn.calc_absolute_address(candidate_insn_va, op) {
                                    if module.probe_va(target, Permissions::RX) {
                                        return Some(target);
                                    }
                                }
                            }
                            continue;
                        }
                        zydis::OperandType::POINTER => continue,
                        zydis::OperandType::REGISTER => continue,
                        zydis::OperandType::UNUSED => continue,
                    }
                }
            }
        }
    }

    None
}

pub fn match_flirt(module: &Module, sigs: &FlirtSignatureSet, va: VA) -> Result<Vec<FlirtSignature>> {
    fn match_flirt_inner(
        module: &Module,
        sigs: &FlirtSignatureSet,
        decoder: &zydis::Decoder,
        va: VA,
        cache: &mut BTreeMap<VA, Vec<FlirtSignature>>,
    ) -> Result<Vec<FlirtSignature>> {
        let sec = module
            .sections
            .iter()
            .find(|sec| sec.virtual_range.start <= va && va < sec.virtual_range.end)
            .unwrap();

        let size = sec.virtual_range.end - va;
        let buf = module.address_space.read_bytes(va, size as usize)?;

        Ok(sigs
            .r#match(&buf)
            .iter()
            .filter(|sig| {
                let mut does_match_references = true;

                'names: for name in sig.names.iter() {
                    if let Symbol::Reference(Name {
                        offset,
                        name: wanted_name,
                    }) = name
                    {
                        // i dont know what this means.
                        assert!(*offset >= 0, "negative offset");

                        if let Some(target) = get_ref(module, &decoder, va, *offset as u64) {
                            // TODO: special case "."

                            if !cache.contains_key(&target) {
                                let target_sigs = match_flirt_inner(module, sigs, decoder, target, cache)
                                    .unwrap_or_else(|_| Default::default());
                                cache.insert(target, target_sigs);
                            }

                            let target_sigs = cache.get(&target).unwrap();

                            let mut does_name_match = false;
                            'sigs: for target_sig in target_sigs.iter() {
                                for name in target_sig.names.iter() {
                                    match name {
                                        Symbol::Reference(_) => continue,
                                        Symbol::Local(Name {
                                            name: target_name,
                                            offset,
                                        }) => {
                                            if *offset == 0 && target_name == wanted_name {
                                                does_name_match = true;
                                                break 'sigs;
                                            }
                                        }
                                        Symbol::Public(Name {
                                            name: target_name,
                                            offset,
                                        }) => {
                                            if *offset == 0 && target_name == wanted_name {
                                                does_name_match = true;
                                                break 'sigs;
                                            }
                                        }
                                    }
                                }
                            }

                            if !does_name_match {
                                does_match_references = false;
                                break 'names;
                            }
                        } else {
                            does_match_references = false;
                            break;
                        }
                    }
                }

                does_match_references
            })
            .cloned()
            .cloned()
            .collect::<Vec<_>>())
    }

    let decoder = dis::get_disassembler(module)?;
    let mut cache = Default::default();
    match_flirt_inner(module, sigs, &decoder, va, &mut cache)
}
<|endoftext|>


<commit_before>

struct Todo {
        id: int,
        todo: ~str,
        priority: char,
        finished: bool,
        raw_todo: ~str,
        contexts: & 'static [~str],
        projects: & 'static [~str]
}

fn create_task(todo: ~str, id: int) -> Todo {
        let mut task = Todo{id: id, raw_todo: todo.clone(), todo: ~"", finished: false,
                                priority: '^', contexts: &[], projects: &[]};

        if (todo[0] == "x".as_bytes()[0]) {
                task.finished = true;
        }

        task.todo = todo.clone();

        return task;
}

impl Todo {
        fn to_str(&self) -> ~str {
                return format!("{:d} ({:c}) '{:s}'", self.id, self.priority, self.todo)
        }
}

fn main () {

        let t = create_task(~"some important task", 1);
        let x = create_task(~"x some important task", 1);
}
<commit_msg>better to_str<commit_after>

struct Todo {
        id: int,
        todo: ~str,
        priority: char,
        finished: bool,
        raw_todo: ~str,
        contexts: & 'static [~str],
        projects: & 'static [~str]
}

fn create_task(todo: ~str, id: int) -> Todo {
        let mut task = Todo{id: id, raw_todo: todo.clone(), todo: ~"", finished: false,
                                priority: '^', contexts: &[], projects: &[]};

        if (todo[0] == "x".as_bytes()[0]) {
                task.finished = true;
        }

        task.todo = todo.clone();

        return task;
}

impl Todo {
        fn to_str(&self) -> ~str {
                return format!("{:d} {:b} ({:c}) '{:s}' \"{:s}\"",
                                self.id, self.finished, self.priority,
                                self.todo, self.raw_todo)
        }
}

fn main () {

        let t = create_task(~"some important task", 1);
        println(t.to_str());
        let x = create_task(~"x some important task", 1);
        println(x.to_str());
}
<|endoftext|>


<commit_before>use Printer;
use With;
use XY;
use direction;
use event::{Event, EventResult, Key};
use std::any::Any;
use std::cmp::min;
use std::ops::Deref;
use vec::Vec2;
use view::{Selector, SizeCache};
use view::View;

/// Arranges its children linearly according to its orientation.
pub struct LinearLayout {
    children: Vec<Child>,
    orientation: direction::Orientation,
    focus: usize,

    cache: Option<XY<SizeCache>>,
}

struct Child {
    view: Box<View>,
    size: Vec2,
    weight: usize,
}

impl Child {
    // Compute and caches the required size.
    fn required_size(&mut self, req: Vec2) -> Vec2 {
        self.size = self.view.required_size(req);
        self.size
    }

    fn as_view(&self) -> &View {
        &*self.view
    }
}

struct ChildIterator<I> {
    inner: I,
    offset: usize,
    orientation: direction::Orientation,
}

impl<'a, T: Deref<Target = Child>, I: Iterator<Item = T>> Iterator
    for ChildIterator<I> {
    type Item = (usize, T);

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next().map(|child| {
            let previous = self.offset;
            self.offset += *child.size.get(self.orientation);
            (previous, child)
        })
    }
}

fn cap<'a, I: Iterator<Item = &'a mut usize>>(iter: I, max: usize) {
    let mut available = max;
    for item in iter {
        if *item > available {
            *item = available;
        }

        available -= *item;
    }
}

impl LinearLayout {
    /// Creates a new layout with the given orientation.
    pub fn new(orientation: direction::Orientation) -> Self {
        LinearLayout {
            children: Vec::new(),
            orientation: orientation,
            focus: 0,
            cache: None,
        }
    }

    /// Modifies the weight of the last child added.
    ///
    /// It is an error to call this before adding a child (and it will panic).
    pub fn weight(mut self, weight: usize) -> Self {
        self.children.last_mut().unwrap().weight = weight;

        self
    }

    /// Adds a child to the layout.
    ///
    /// Chainable variant.
    pub fn child<V: View + 'static>(self, view: V) -> Self {
        self.with(|s| s.add_child(view))
    }

    /// Adds a child to the layout.
    pub fn add_child<V: View + 'static>(&mut self, view: V) {
        self.children.push(Child {
            view: Box::new(view),
            size: Vec2::zero(),
            weight: 0,
        });
        self.invalidate();
    }

    // Invalidate the view, to request a layout next time
    fn invalidate(&mut self) {
        self.cache = None;
    }

    /// Creates a new vertical layout.
    pub fn vertical() -> Self {
        LinearLayout::new(direction::Orientation::Vertical)
    }

    /// Creates a new horizontal layout.
    pub fn horizontal() -> Self {
        LinearLayout::new(direction::Orientation::Horizontal)
    }

    // If the cache can be used, return the cached size.
    // Otherwise, return None.
    fn get_cache(&self, req: Vec2) -> Option<Vec2> {
        match self.cache {
            None => None,
            Some(ref cache) => {
                // Is our cache even valid?
                // Also, is any child invalidating the layout?
                if cache.zip_map(req, SizeCache::accept).both()
                    && self.children_are_sleeping()
                {
                    Some(cache.map(|s| s.value))
                } else {
                    None
                }
            }
        }
    }

    fn children_are_sleeping(&self) -> bool {
        !self.children
            .iter()
            .map(Child::as_view)
            .any(View::needs_relayout)
    }

    /// Returns a cyclic mutable iterator starting with the child in focus
    fn iter_mut<'a>(
        &'a mut self, from_focus: bool, source: direction::Relative
    ) -> Box<Iterator<Item = (usize, &mut Child)> + 'a> {
        match source {
            direction::Relative::Front => {
                let start = if from_focus { self.focus } else { 0 };

                Box::new(self.children.iter_mut().enumerate().skip(start))
            }
            direction::Relative::Back => {
                let end = if from_focus {
                    self.focus + 1
                } else {
                    self.children.len()
                };
                Box::new(self.children[..end].iter_mut().enumerate().rev())
            }
        }
    }

    fn move_focus(&mut self, source: direction::Direction) -> EventResult {
        let i = if let Some(i) =
            source.relative(self.orientation).and_then(|rel| {
                // The iterator starts at the focused element.
                // We don't want that one.
                self.iter_mut(true, rel)
                    .skip(1)
                    .filter_map(|p| try_focus(p, source))
                    .next()
            }) {
            i
        } else {
            return EventResult::Ignored;
        };
        self.focus = i;
        EventResult::Consumed(None)
    }

    fn check_focus_grab(&mut self, event: &Event) {
        if let Event::Mouse {
            offset,
            position,
            event,
        } = *event
        {
            if !event.grabs_focus() {
                return;
            }

            let position = match position.checked_sub(offset) {
                None => return,
                Some(pos) => pos,
            };

            // Find the selected child
            let position = *position.get(self.orientation);
            let iterator = ChildIterator {
                inner: self.children.iter_mut(),
                offset: 0,
                orientation: self.orientation,
            };
            for (i, (offset, child)) in iterator.enumerate() {
                let child_size = child.size.get(self.orientation);
                // eprintln!(
                //     "Offset {:?}, size {:?}, position: {:?}",
                //     offset,
                //     child_size,
                //     position
                // );
                if (offset + child_size > position)
                    && child.view.take_focus(direction::Direction::none())
                {
                    // eprintln!("It's a match!");
                    self.focus = i;
                    return;
                }
            }
        }
    }
}

fn try_focus(
    (i, child): (usize, &mut Child), source: direction::Direction
) -> Option<usize> {
    if child.view.take_focus(source) {
        Some(i)
    } else {
        None
    }
}

impl View for LinearLayout {
    fn draw(&self, printer: &Printer) {
        // Use pre-computed sizes
        let mut offset = Vec2::zero();
        for (i, child) in self.children.iter().enumerate() {
            let printer =
                &printer.sub_printer(offset, child.size, i == self.focus);
            child.view.draw(printer);

            // On the axis given by the orientation,
            // add the child size to the offset.
            *self.orientation.get_ref(&mut offset) +=
                self.orientation.get(&child.size);
        }
    }

    fn needs_relayout(&self) -> bool {
        if self.cache.is_none() {
            return true;
        }

        !self.children_are_sleeping()
    }

    fn layout(&mut self, size: Vec2) {
        // If we can get away without breaking a sweat, you can bet we will.
        if self.get_cache(size).is_none() {
            self.required_size(size);
        }

        let o = self.orientation;

        for child in &mut self.children {
            // Every item has the same size orthogonal to the layout
            child.size.set_axis_from(o.swap(), &size);
            child.view.layout(size.with_axis_from(o, &child.size));
        }
    }

    fn required_size(&mut self, req: Vec2) -> Vec2 {
        // Did anything change since last time?
        if let Some(size) = self.get_cache(req) {
            return size;
        }

        // First, make a naive scenario: everything will work fine.
        let sizes: Vec<Vec2> = self.children
            .iter_mut()
            .map(|c| c.required_size(req))
            .collect();
        debug!("Ideal sizes: {:?}", sizes);
        let ideal = self.orientation.stack(sizes.iter());
        debug!("Ideal result: {:?}", ideal);

        // Does it fit?
        if ideal.fits_in(req) {
            // Champagne!
            self.cache = Some(SizeCache::build(ideal, req));
            return ideal;
        }

        // Ok, so maybe it didn't. Budget cuts, everyone.
        // Let's pretend we have almost no space in this direction.
        let budget_req = req.with_axis(self.orientation, 1);
        debug!("Budget req: {:?}", budget_req);

        // See how they like it that way
        let min_sizes: Vec<Vec2> = self.children
            .iter_mut()
            .map(|c| c.required_size(budget_req))
            .collect();
        let desperate = self.orientation.stack(min_sizes.iter());
        debug!("Min sizes: {:?}", min_sizes);
        debug!("Desperate: {:?}", desperate);

        // This is the lowest we'll ever go. It better fit at least.
        let orientation = self.orientation;
        if !desperate.fits_in(req) {
            // Just give up...
            // TODO: hard-cut
            cap(
                self.children
                    .iter_mut()
                    .map(|c| c.size.get_mut(orientation)),
                *req.get(self.orientation),
            );

            // TODO: print some error message or something
            debug!("Seriously? {:?} > {:?}???", desperate, req);
            // self.cache = Some(SizeCache::build(desperate, req));
            self.cache = None;
            return desperate;
        }

        // This here is how much we're generously offered
        // (We just checked that req >= desperate, so the subtraction is safe
        let mut available = self.orientation.get(&(req - desperate));
        debug!("Available: {:?}", available);

        // Here, we have to make a compromise between the ideal
        // and the desperate solutions.
        let mut overweight: Vec<(usize, usize)> = sizes
            .iter()
            .map(|v| self.orientation.get(v))
            .zip(min_sizes.iter().map(|v| self.orientation.get(v)))
            .map(|(a, b)| a.saturating_sub(b))
            .enumerate()
            .collect();
        debug!("Overweight: {:?}", overweight);

        // So... distribute `available` to reduce the overweight...
        // TODO: use child weight in the distribution...

        // We'll give everyone his share of what we have left,
        // starting with those who ask the least.
        overweight.sort_by_key(|&(_, weight)| weight);
        let mut allocations = vec![0; overweight.len()];

        for (i, &(j, weight)) in overweight.iter().enumerate() {
            // This is the number of people we still have to feed.
            let remaining = overweight.len() - i;
            // How much we can spare on each one
            let budget = available / remaining;
            // Maybe he doesn't even need that much?
            let spent = min(budget, weight);
            allocations[j] = spent;
            available -= spent;
        }
        debug!("Allocations: {:?}", allocations);

        // Final lengths are the minimum ones + generous allocations
        let final_lengths: Vec<Vec2> = min_sizes
            .iter()
            .map(|v| self.orientation.get(v))
            .zip(allocations.iter())
            .map(|(a, b)| a + b)
            .map(|l| req.with_axis(self.orientation, l))
            .collect();
        debug!("Final sizes: {:?}", final_lengths);

        // Let's ask everyone one last time. Everyone should be happy.
        // (But they may ask more on the other axis.)
        let final_sizes: Vec<Vec2> = self.children
            .iter_mut()
            .enumerate()
            .map(|(i, c)| c.required_size(final_lengths[i]))
            .collect();
        debug!("Final sizes2: {:?}", final_sizes);

        // Let's stack everything to see what it looks like.
        let compromise = self.orientation.stack(final_sizes.iter());

        // Phew, that was a lot of work! I'm not doing it again.
        self.cache = Some(SizeCache::build(compromise, req));

        compromise
    }

    fn take_focus(&mut self, source: direction::Direction) -> bool {
        // In what order will we iterate on the children?
        let rel = source.relative(self.orientation);
        // We activate from_focus only if coming from the "sides".
        let i = if let Some(i) = self.iter_mut(
            rel.is_none(),
            rel.unwrap_or(direction::Relative::Front),
        ).filter_map(|p| try_focus(p, source))
            .next()
        {
            // ... we can't update `self.focus` here,
            // because rustc thinks we still borrow `self`.
            // :(
            i
        } else {
            return false;
        };

        self.focus = i;
        true
    }

    fn on_event(&mut self, event: Event) -> EventResult {
        self.check_focus_grab(&event);

        let result = {
            let mut iterator = ChildIterator {
                inner: self.children.iter_mut(),
                offset: 0,
                orientation: self.orientation,
            };
            let (offset, child) = iterator.nth(self.focus).unwrap();
            let offset = self.orientation.make_vec(offset, 0);
            child.view.on_event(event.relativized(offset))
        };
        match result {
            EventResult::Ignored => match event {
                Event::Shift(Key::Tab) if self.focus > 0 => {
                    self.move_focus(direction::Direction::back())
                }
                Event::Key(Key::Tab)
                    if self.focus + 1 < self.children.len() =>
                {
                    self.move_focus(direction::Direction::front())
                }
                Event::Key(Key::Left)
                    if self.orientation == direction::Orientation::Horizontal
                        && self.focus > 0 =>
                {
                    self.move_focus(direction::Direction::right())
                }
                Event::Key(Key::Up)
                    if self.orientation == direction::Orientation::Vertical
                        && self.focus > 0 =>
                {
                    self.move_focus(direction::Direction::down())
                }
                Event::Key(Key::Right)
                    if self.orientation == direction::Orientation::Horizontal
                        && self.focus + 1 < self.children.len() =>
                {
                    self.move_focus(direction::Direction::left())
                }
                Event::Key(Key::Down)
                    if self.orientation == direction::Orientation::Vertical
                        && self.focus + 1 < self.children.len() =>
                {
                    self.move_focus(direction::Direction::up())
                }
                _ => EventResult::Ignored,
            },
            res => res,
        }
    }

    fn call_on_any<'a>(
        &mut self, selector: &Selector,
        mut callback: Box<FnMut(&mut Any) + 'a>,
    ) {
        for child in &mut self.children {
            child
                .view
                .call_on_any(selector, Box::new(|any| callback(any)));
        }
    }

    fn focus_view(&mut self, selector: &Selector) -> Result<(), ()> {
        for (i, child) in self.children.iter_mut().enumerate() {
            if child.view.focus_view(selector).is_ok() {
                self.focus = i;
                return Ok(());
            }
        }

        Err(())
    }
}
<commit_msg>Never layout a child larger than the parent<commit_after>use Printer;
use With;
use XY;
use direction;
use event::{Event, EventResult, Key};
use std::any::Any;
use std::cmp::min;
use std::ops::Deref;
use vec::Vec2;
use view::{Selector, SizeCache};
use view::View;

/// Arranges its children linearly according to its orientation.
pub struct LinearLayout {
    children: Vec<Child>,
    orientation: direction::Orientation,
    focus: usize,

    cache: Option<XY<SizeCache>>,
}

struct Child {
    view: Box<View>,
    // The last result from the child's required_size
    // Doesn't have to be what the child actually gets.
    size: Vec2,
    weight: usize,
}

impl Child {
    // Compute and caches the required size.
    fn required_size(&mut self, req: Vec2) -> Vec2 {
        self.size = self.view.required_size(req);
        self.size
    }

    fn as_view(&self) -> &View {
        &*self.view
    }
}

struct ChildIterator<I> {
    inner: I,
    offset: usize,
    orientation: direction::Orientation,
}

impl<'a, T: Deref<Target = Child>, I: Iterator<Item = T>> Iterator
    for ChildIterator<I> {
    type Item = (usize, T);

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next().map(|child| {
            let previous = self.offset;
            self.offset += *child.size.get(self.orientation);
            (previous, child)
        })
    }
}

fn cap<'a, I: Iterator<Item = &'a mut usize>>(iter: I, max: usize) {
    let mut available = max;
    for item in iter {
        if *item > available {
            *item = available;
        }

        available -= *item;
    }
}

impl LinearLayout {
    /// Creates a new layout with the given orientation.
    pub fn new(orientation: direction::Orientation) -> Self {
        LinearLayout {
            children: Vec::new(),
            orientation: orientation,
            focus: 0,
            cache: None,
        }
    }

    /// Modifies the weight of the last child added.
    ///
    /// It is an error to call this before adding a child (and it will panic).
    pub fn weight(mut self, weight: usize) -> Self {
        self.children.last_mut().unwrap().weight = weight;

        self
    }

    /// Adds a child to the layout.
    ///
    /// Chainable variant.
    pub fn child<V: View + 'static>(self, view: V) -> Self {
        self.with(|s| s.add_child(view))
    }

    /// Adds a child to the layout.
    pub fn add_child<V: View + 'static>(&mut self, view: V) {
        self.children.push(Child {
            view: Box::new(view),
            size: Vec2::zero(),
            weight: 0,
        });
        self.invalidate();
    }

    // Invalidate the view, to request a layout next time
    fn invalidate(&mut self) {
        self.cache = None;
    }

    /// Creates a new vertical layout.
    pub fn vertical() -> Self {
        LinearLayout::new(direction::Orientation::Vertical)
    }

    /// Creates a new horizontal layout.
    pub fn horizontal() -> Self {
        LinearLayout::new(direction::Orientation::Horizontal)
    }

    // If the cache can be used, return the cached size.
    // Otherwise, return None.
    fn get_cache(&self, req: Vec2) -> Option<Vec2> {
        match self.cache {
            None => None,
            Some(ref cache) => {
                // Is our cache even valid?
                // Also, is any child invalidating the layout?
                if cache.zip_map(req, SizeCache::accept).both()
                    && self.children_are_sleeping()
                {
                    Some(cache.map(|s| s.value))
                } else {
                    None
                }
            }
        }
    }

    fn children_are_sleeping(&self) -> bool {
        !self.children
            .iter()
            .map(Child::as_view)
            .any(View::needs_relayout)
    }

    /// Returns a cyclic mutable iterator starting with the child in focus
    fn iter_mut<'a>(
        &'a mut self, from_focus: bool, source: direction::Relative
    ) -> Box<Iterator<Item = (usize, &mut Child)> + 'a> {
        match source {
            direction::Relative::Front => {
                let start = if from_focus { self.focus } else { 0 };

                Box::new(self.children.iter_mut().enumerate().skip(start))
            }
            direction::Relative::Back => {
                let end = if from_focus {
                    self.focus + 1
                } else {
                    self.children.len()
                };
                Box::new(self.children[..end].iter_mut().enumerate().rev())
            }
        }
    }

    fn move_focus(&mut self, source: direction::Direction) -> EventResult {
        let i = if let Some(i) =
            source.relative(self.orientation).and_then(|rel| {
                // The iterator starts at the focused element.
                // We don't want that one.
                self.iter_mut(true, rel)
                    .skip(1)
                    .filter_map(|p| try_focus(p, source))
                    .next()
            }) {
            i
        } else {
            return EventResult::Ignored;
        };
        self.focus = i;
        EventResult::Consumed(None)
    }

    fn check_focus_grab(&mut self, event: &Event) {
        if let Event::Mouse {
            offset,
            position,
            event,
        } = *event
        {
            if !event.grabs_focus() {
                return;
            }

            let position = match position.checked_sub(offset) {
                None => return,
                Some(pos) => pos,
            };

            // Find the selected child
            let position = *position.get(self.orientation);
            let iterator = ChildIterator {
                inner: self.children.iter_mut(),
                offset: 0,
                orientation: self.orientation,
            };
            for (i, (offset, child)) in iterator.enumerate() {
                let child_size = child.size.get(self.orientation);
                // eprintln!(
                //     "Offset {:?}, size {:?}, position: {:?}",
                //     offset,
                //     child_size,
                //     position
                // );
                if (offset + child_size > position)
                    && child.view.take_focus(direction::Direction::none())
                {
                    // eprintln!("It's a match!");
                    self.focus = i;
                    return;
                }
            }
        }
    }
}

fn try_focus(
    (i, child): (usize, &mut Child), source: direction::Direction
) -> Option<usize> {
    if child.view.take_focus(source) {
        Some(i)
    } else {
        None
    }
}

impl View for LinearLayout {
    fn draw(&self, printer: &Printer) {
        // Use pre-computed sizes
        let mut offset = Vec2::zero();
        for (i, child) in self.children.iter().enumerate() {
            // eprintln!("Printer size: {:?}", printer.size);
            // eprintln!("Child size: {:?}", child.size);
            // eprintln!("Offset: {:?}", offset);
            let printer =
                &printer.sub_printer(offset, child.size, i == self.focus);
            child.view.draw(printer);

            // On the axis given by the orientation,
            // add the child size to the offset.
            *self.orientation.get_ref(&mut offset) +=
                self.orientation.get(&child.size);
        }
    }

    fn needs_relayout(&self) -> bool {
        if self.cache.is_none() {
            return true;
        }

        !self.children_are_sleeping()
    }

    fn layout(&mut self, size: Vec2) {
        // If we can get away without breaking a sweat, you can bet we will.
        // eprintln!("Laying out with {:?}", size);
        if self.get_cache(size).is_none() {
            self.required_size(size);
        }

        let o = self.orientation;

        for child in &mut self.children {
            // Every item has the same size orthogonal to the layout
            child.size.set_axis_from(o.swap(), &size);
            child.view.layout(Vec2::min(size, child.size));
        }
    }

    fn required_size(&mut self, req: Vec2) -> Vec2 {
        // Did anything change since last time?
        if let Some(size) = self.get_cache(req) {
            return size;
        }

        // First, make a naive scenario: everything will work fine.
        let ideal_sizes: Vec<Vec2> = self.children
            .iter_mut()
            .map(|c| c.required_size(req))
            .collect();
        debug!("Ideal sizes: {:?}", ideal_sizes);
        let ideal = self.orientation.stack(ideal_sizes.iter());
        debug!("Ideal result: {:?}", ideal);

        // Does it fit?
        if ideal.fits_in(req) {
            // Champagne!
            self.cache = Some(SizeCache::build(ideal, req));
            return ideal;
        }

        // Ok, so maybe it didn't. Budget cuts, everyone.
        // Let's pretend we have almost no space in this direction.
        // budget_req is the dummy requirements, in an extreme budget situation.
        let budget_req = req.with_axis(self.orientation, 1);
        debug!("Budget req: {:?}", budget_req);

        // See how they like it that way.
        // This is, hopefully, the absolute minimum these views will accept.
        let min_sizes: Vec<Vec2> = self.children
            .iter_mut()
            .map(|c| c.required_size(budget_req))
            .collect();
        let desperate = self.orientation.stack(min_sizes.iter());
        debug!("Min sizes: {:?}", min_sizes);
        debug!("Desperate: {:?}", desperate);

        // This is the lowest we'll ever go. It better fit at least.
        let orientation = self.orientation;
        if !desperate.fits_in(req) {
            // Just give up...
            // TODO: hard-cut
            cap(
                self.children
                    .iter_mut()
                    .map(|c| c.size.get_mut(orientation)),
                *req.get(self.orientation),
            );

            // TODO: print some error message or something
            debug!("Seriously? {:?} > {:?}???", desperate, req);
            // self.cache = Some(SizeCache::build(desperate, req));
            self.cache = None;
            return desperate;
        }

        // So now that we know we _can_ make it all fit, we can redistribute
        // the extra space we have.

        // This here is how much we're generously offered
        // (We just checked that req >= desperate, so the subtraction is safe
        let mut available = self.orientation.get(&(req - desperate));
        debug!("Available: {:?}", available);

        // Here, we have to make a compromise between the ideal
        // and the desperate solutions.
        // This is the vector of (ideal - minimum) sizes for each view.
        // (which is how much they would like to grow)
        let mut overweight: Vec<(usize, usize)> = ideal_sizes
            .iter()
            .map(|v| self.orientation.get(v))
            .zip(min_sizes.iter().map(|v| self.orientation.get(v)))
            .map(|(a, b)| a.saturating_sub(b))
            .enumerate()
            .collect();
        debug!("Overweight: {:?}", overweight);

        // So... distribute `available` to reduce the overweight...
        // TODO: use child weight in the distribution...

        // We'll give everyone his share of what we have left,
        // starting with those who ask the least.
        overweight.sort_by_key(|&(_, weight)| weight);
        let mut allocations = vec![0; overweight.len()];

        for (i, &(j, weight)) in overweight.iter().enumerate() {
            // This is the number of people we still have to feed.
            let remaining = overweight.len() - i;
            // How much we can spare on each one
            let budget = available / remaining;
            // Maybe he doesn't even need that much?
            let spent = min(budget, weight);
            allocations[j] = spent;
            available -= spent;
        }
        debug!("Allocations: {:?}", allocations);

        // Final lengths are the minimum ones + generous allocations
        let final_lengths: Vec<Vec2> = min_sizes
            .iter()
            .map(|v| self.orientation.get(v))
            .zip(allocations.iter())
            .map(|(a, b)| a + b)
            .map(|l| req.with_axis(self.orientation, l))
            .collect();
        debug!("Final sizes: {:?}", final_lengths);

        // Let's ask everyone one last time. Everyone should be happy.
        // (But they may ask more on the other axis.)
        let final_sizes: Vec<Vec2> = self.children
            .iter_mut()
            .enumerate()
            .map(|(i, c)| c.required_size(final_lengths[i]))
            .collect();
        debug!("Final sizes2: {:?}", final_sizes);

        // Let's stack everything to see what it looks like.
        let compromise = self.orientation.stack(final_sizes.iter());

        // Phew, that was a lot of work! I'm not doing it again.
        self.cache = Some(SizeCache::build(compromise, req));

        compromise
    }

    fn take_focus(&mut self, source: direction::Direction) -> bool {
        // In what order will we iterate on the children?
        let rel = source.relative(self.orientation);
        // We activate from_focus only if coming from the "sides".
        let i = if let Some(i) = self.iter_mut(
            rel.is_none(),
            rel.unwrap_or(direction::Relative::Front),
        ).filter_map(|p| try_focus(p, source))
            .next()
        {
            // ... we can't update `self.focus` here,
            // because rustc thinks we still borrow `self`.
            // :(
            i
        } else {
            return false;
        };

        self.focus = i;
        true
    }

    fn on_event(&mut self, event: Event) -> EventResult {
        self.check_focus_grab(&event);

        let result = {
            let mut iterator = ChildIterator {
                inner: self.children.iter_mut(),
                offset: 0,
                orientation: self.orientation,
            };
            let (offset, child) = iterator.nth(self.focus).unwrap();
            let offset = self.orientation.make_vec(offset, 0);
            child.view.on_event(event.relativized(offset))
        };
        match result {
            EventResult::Ignored => match event {
                Event::Shift(Key::Tab) if self.focus > 0 => {
                    self.move_focus(direction::Direction::back())
                }
                Event::Key(Key::Tab)
                    if self.focus + 1 < self.children.len() =>
                {
                    self.move_focus(direction::Direction::front())
                }
                Event::Key(Key::Left)
                    if self.orientation == direction::Orientation::Horizontal
                        && self.focus > 0 =>
                {
                    self.move_focus(direction::Direction::right())
                }
                Event::Key(Key::Up)
                    if self.orientation == direction::Orientation::Vertical
                        && self.focus > 0 =>
                {
                    self.move_focus(direction::Direction::down())
                }
                Event::Key(Key::Right)
                    if self.orientation == direction::Orientation::Horizontal
                        && self.focus + 1 < self.children.len() =>
                {
                    self.move_focus(direction::Direction::left())
                }
                Event::Key(Key::Down)
                    if self.orientation == direction::Orientation::Vertical
                        && self.focus + 1 < self.children.len() =>
                {
                    self.move_focus(direction::Direction::up())
                }
                _ => EventResult::Ignored,
            },
            res => res,
        }
    }

    fn call_on_any<'a>(
        &mut self, selector: &Selector,
        mut callback: Box<FnMut(&mut Any) + 'a>,
    ) {
        for child in &mut self.children {
            child
                .view
                .call_on_any(selector, Box::new(|any| callback(any)));
        }
    }

    fn focus_view(&mut self, selector: &Selector) -> Result<(), ()> {
        for (i, child) in self.children.iter_mut().enumerate() {
            if child.view.focus_view(selector).is_ok() {
                self.focus = i;
                return Ok(());
            }
        }

        Err(())
    }
}
<|endoftext|>


<commit_before>use graphics::{DrawState, Transformed, rectangle};
use graphics::polygon::Polygon;
use graphics::line::Line;
use opengl_graphics::GlGraphics;
use piston::input::Key;
use rand::Rng;
use std::f64::consts::PI;

fn to_cartesian(theta: f64, r: f64) -> (f64, f64) {
    return (
        theta.sin()*r,
        -theta.cos()*r,
    )
}

pub struct Spaceship {
    x: f64,
    y: f64,
    v: f64,
    v_theta: f64,
    theta: f64,
    accel: f64,
    reverse: f64,
    left: f64,
    right: f64,
    firing: bool,
    cooldown: f64,
}

const SPACESHIP_POINTS: [[f64; 2]; 3] = [
    [5.0, 7.0],
    [-5.0, 7.0],
    [0.0, -13.0],
];

impl Spaceship {
    pub fn new() -> Spaceship {
        return Spaceship{
            x: 100.0,
            y: 100.0,
            v: 0.0,
            v_theta: 0.0,
            theta: 0.0,
            accel: 0.0,
            reverse: 0.0,
            left: 0.0,
            right: 0.0,
            firing: false,
            cooldown: 0.0,
        };
    }

    pub fn handle_press(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 1.0,
            Key::Down => self.reverse = 1.0,
            Key::Left => self.left = 0.05,
            Key::Right => self.right = 0.05,
            Key::Space => self.firing = true,
            _ => (),
        }
    }

    pub fn handle_release(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 0.0,
            Key::Down => self.reverse = 0.0,
            Key::Left => self.left = 0.0,
            Key::Right => self.right = 0.0,
            Key::Space => self.firing = false,
            _ => (),
        }
    }

    pub fn draw(&mut self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        Polygon::new(color).draw(
            &SPACESHIP_POINTS,
            ds,
            t
                .trans(self.x, self.y)
                .rot_rad(self.theta),
            gl,
        );
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let (dx, dy) = to_cartesian(self.v_theta, self.v*dt);
        self.x = (self.x + dx + x_max) % x_max;
        self.y = (self.y + dy + y_max) % y_max;
    }

    pub fn accelerate(&mut self, dt: f64) {
        let net_accel = (self.accel - self.reverse)*dt*100.0;
        let (dx, dy) = to_cartesian(self.v_theta, self.v);
        let (ddx, ddy) = to_cartesian(self.theta, net_accel);
        let new_dx = dx + ddx;
        let new_dy = dy + ddy;
        self.v = (new_dx*new_dx+new_dy*new_dy).sqrt().min(200.0).max(-200.0);
        self.v_theta = new_dx.atan2(-new_dy);
    }

    pub fn turn(&mut self, dt: f64) {
        self.theta += (self.right - self.left)*dt*100.0;
    }

    pub fn cooldown(&mut self, dt: f64) {
        self.cooldown = (self.cooldown - dt).max(0.0);
    }

    pub fn ready_to_fire(&self) -> bool {
        return self.cooldown == 0.0;
    }

    pub fn is_firing(&self) -> bool {
        return self.firing;
    }

    pub fn fire(&mut self, bullets: &mut Vec<Bullet>) {
        self.cooldown = 0.5;
        bullets.push(Bullet::new(self.x, self.y, self.theta));
    }
}

pub struct Bullet {
    x: f64,
    y: f64,
    theta: f64,
    distance: f64,
}

impl Bullet {
    fn new(x: f64, y: f64, theta: f64) -> Bullet {
        return Bullet{
            x: x,
            y: y,
            theta: theta,
            distance: 0.0,
        };
    }

    pub fn draw(&self, color: [f32; 4], t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        rectangle(color, rectangle::square(self.x, self.y, 2.0), t, gl);
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let v = 100.0;
        self.x = (self.x + self.theta.sin()*v*dt + x_max) % x_max;
        self.y = (self.y - self.theta.cos()*v*dt + y_max) % y_max;
        self.distance += v*dt;
    }

    pub fn is_alive(&self) -> bool {
        return self.distance < 100.0;
    }
}

pub struct Astroid {
    x: f64,
    y: f64,
    v: f64,
    theta: f64,
    border: Vec<[f64; 4]>,
}

impl Astroid {
    pub fn new<R: Rng>(rng: &mut R) -> Astroid {
        let radius = (rng.gen_range(1, 3)*5) as f64;
        return Astroid {
            x: rng.gen_range(0.0, 100.0),
            y: rng.gen_range(0.0, 100.0),
            v: rng.gen_range(40.0, 60.0),
            theta: rng.gen_range(0.0, 2.0*PI),
            border: Astroid::create_border(rng, radius),
        }
    }

    pub fn draw(&self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        let line_info = Line::new(color, 0.5);
        for line_points in self.border.iter() {
            line_info.draw(*line_points, ds, t.trans(self.x, self.y), gl);
        }
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        self.x = (self.x + self.theta.sin()*self.v*dt + x_max) % x_max;
        self.y = (self.y - self.theta.cos()*self.v*dt + y_max) % y_max;
    }

    pub fn create_border<R: Rng>(rng: &mut R, radius: f64) -> Vec<[f64; 4]> {
        let spread = radius/5.0;
        let point_count = rng.gen_range(8, 12);
        let mut points = Vec::with_capacity(point_count);
        let theta_0 = rng.gen_range(0.0, 2.0*PI);
        for theta in (1..point_count+1).map(|i| theta_0 + 2.0*PI*i as f64/point_count as f64) {
            let distance = radius + rng.gen_range(-spread, spread);
            points.push(to_cartesian(theta, distance));
        };
        let point = points[0];
        points.push(point);
        let mut lines = Vec::with_capacity(point_count);
        for point in points.iter().zip(points.iter().skip(1)) {
            let (&(x1, x2), &(y1, y2)) = point;
            lines.push([x1, x2, y1, y2]);
        }
        return lines;
    }
}<commit_msg>Added preliminary collision detection code<commit_after>use graphics::{DrawState, Transformed, rectangle};
use graphics::polygon::Polygon;
use graphics::line::Line;
use opengl_graphics::GlGraphics;
use piston::input::Key;
use rand::Rng;
use std::f64::consts::PI;
use std::ops::{Sub, Mul, Div};

fn to_cartesian(theta: f64, r: f64) -> (f64, f64) {
    return (
        theta.sin()*r,
        -theta.cos()*r,
    )
}

#[derive(Copy, Clone)]
struct Point {
    x: f64,
    y: f64,
}

impl Point {
    fn new(x: f64, y: f64) -> Self {
        Point {
            x: x,
            y: y,
        }
    }

    fn cross(self, other: Point) -> f64 {
        return self.x*other.y - other.x*self.y;
    }

    fn dot(self, other: Point) -> f64 {
        return self.x*other.x + self.y*other.y;
    }
}

impl Sub<Point> for Point {
    type Output = Point;

    fn sub(self, other: Point) -> Self::Output {
        return Point{
            x: self.x - other.x,
            y: self.y - other.y,
        }
    }
}

impl Div<f64> for Point {
    type Output = Point;

    fn div(self, other: f64) -> Self::Output {
        return Point{
            x: self.x / other,
            y: self.y / other,
        }
    }
}

// Intersection of p, p+r and q, q+s
// p + t r = q + u s
// t = ((q − p) × s) / (r × s)
// u = ((q − p) × r) / (r × s)

fn lines_intersect(l1: [f64; 4], l2: [f64; 4]) -> bool {
    let p = Point::new(l1[0], l1[1]);
    let q = Point::new(l2[0], l2[1]);
    let r = Point::new(l1[2] - l1[0], l1[3] - l1[1]);
    let s = Point::new(l2[2] - l2[0], l2[3] - l2[1]);

    //If r × s = 0 and (q − p) × r = 0, then the two lines are collinear.
    if (r.cross(s) == 0.0 && (p - q).cross(r) == 0.0) {
        // If the interval between t0 and t1 intersects the interval [0, 1] then the line segments are collinear and overlapping; otherwise they are collinear and disjoint.
        // Note that if s and r point in opposite directions, then s · r < 0 and so the interval to be checked is [t1, t0] rather than [t0, t1].
        //t0 = (q − p) · r / (r · r)
        //t1 = (q + s − p) · r / (r · r) = t0 + s · r / (r · r)
        let t0 = (q - p).dot(r / r.dot(r));
        let t1 = t0 + s.dot(r / r.dot(r));
        return !(t0 <= 0.0 && t1 <= 0.0 || t0 >= 1.0 && t1 >= 1.0)
    }

    // If r × s = 0 and (q − p) × r ≠ 0, then the two lines are parallel and non-intersecting.
    if (r.cross(s) == 0.0) {
        return false;
    }

    // t = (q − p) × s / (r × s)
    // u = (p − q) × r / (s × r)
    let t = (q - p).cross(s / (r.cross(s)));
    let u = (p - q).cross(r / (s.cross(r)));

    // If r × s ≠ 0 and 0 ≤ t ≤ 1 and 0 ≤ u ≤ 1, the two line segments meet at the point p + t r = q + u s.
    return 0.0 <= t && t <= 1.0 && 0.0 <= u && u <= 1.0;
}

pub struct Spaceship {
    x: f64,
    y: f64,
    v: f64,
    v_theta: f64,
    theta: f64,
    accel: f64,
    reverse: f64,
    left: f64,
    right: f64,
    firing: bool,
    cooldown: f64,
}

const SPACESHIP_POINTS: [[f64; 2]; 3] = [
    [5.0, 7.0],
    [-5.0, 7.0],
    [0.0, -13.0],
];

impl Spaceship {
    pub fn new() -> Spaceship {
        return Spaceship{
            x: 100.0,
            y: 100.0,
            v: 0.0,
            v_theta: 0.0,
            theta: 0.0,
            accel: 0.0,
            reverse: 0.0,
            left: 0.0,
            right: 0.0,
            firing: false,
            cooldown: 0.0,
        };
    }

    pub fn handle_press(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 1.0,
            Key::Down => self.reverse = 1.0,
            Key::Left => self.left = 0.05,
            Key::Right => self.right = 0.05,
            Key::Space => self.firing = true,
            _ => (),
        }
    }

    pub fn handle_release(&mut self, key: Key) {
        match key {
            Key::Up => self.accel = 0.0,
            Key::Down => self.reverse = 0.0,
            Key::Left => self.left = 0.0,
            Key::Right => self.right = 0.0,
            Key::Space => self.firing = false,
            _ => (),
        }
    }

    pub fn draw(&mut self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        Polygon::new(color).draw(
            &SPACESHIP_POINTS,
            ds,
            t
                .trans(self.x, self.y)
                .rot_rad(self.theta),
            gl,
        );
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let (dx, dy) = to_cartesian(self.v_theta, self.v*dt);
        self.x = (self.x + dx + x_max) % x_max;
        self.y = (self.y + dy + y_max) % y_max;
    }

    pub fn accelerate(&mut self, dt: f64) {
        let net_accel = (self.accel - self.reverse)*dt*100.0;
        let (dx, dy) = to_cartesian(self.v_theta, self.v);
        let (ddx, ddy) = to_cartesian(self.theta, net_accel);
        let new_dx = dx + ddx;
        let new_dy = dy + ddy;
        self.v = (new_dx*new_dx+new_dy*new_dy).sqrt().min(200.0).max(-200.0);
        self.v_theta = new_dx.atan2(-new_dy);
    }

    pub fn turn(&mut self, dt: f64) {
        self.theta += (self.right - self.left)*dt*100.0;
    }

    pub fn cooldown(&mut self, dt: f64) {
        self.cooldown = (self.cooldown - dt).max(0.0);
    }

    pub fn ready_to_fire(&self) -> bool {
        return self.cooldown == 0.0;
    }

    pub fn is_firing(&self) -> bool {
        return self.firing;
    }

    pub fn fire(&mut self, bullets: &mut Vec<Bullet>) {
        self.cooldown = 0.5;
        bullets.push(Bullet::new(self.x, self.y, self.theta));
    }
}

pub struct Bullet {
    x: f64,
    y: f64,
    theta: f64,
    distance: f64,
}

impl Bullet {
    fn new(x: f64, y: f64, theta: f64) -> Bullet {
        return Bullet{
            x: x,
            y: y,
            theta: theta,
            distance: 0.0,
        };
    }

    pub fn draw(&self, color: [f32; 4], t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        rectangle(color, rectangle::square(self.x, self.y, 2.0), t, gl);
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        let v = 100.0;
        self.x = (self.x + self.theta.sin()*v*dt + x_max) % x_max;
        self.y = (self.y - self.theta.cos()*v*dt + y_max) % y_max;
        self.distance += v*dt;
    }

    pub fn is_alive(&self) -> bool {
        return self.distance < 100.0;
    }
}

pub struct Astroid {
    x: f64,
    y: f64,
    v: f64,
    theta: f64,
    border: Vec<[f64; 4]>,
}

impl Astroid {
    pub fn new<R: Rng>(rng: &mut R) -> Astroid {
        let radius = (rng.gen_range(1, 3)*5) as f64;
        return Astroid {
            x: rng.gen_range(0.0, 100.0),
            y: rng.gen_range(0.0, 100.0),
            v: rng.gen_range(40.0, 60.0),
            theta: rng.gen_range(0.0, 2.0*PI),
            border: Astroid::create_border(rng, radius),
        }
    }

    pub fn draw(&self, color: [f32; 4], ds: &DrawState, t: [[f64; 3]; 2], gl: &mut GlGraphics) {
        let line_info = Line::new(color, 0.5);
        for line_points in self.border.iter() {
            line_info.draw(*line_points, ds, t.trans(self.x, self.y), gl);
        }
    }

    pub fn go(&mut self, dt: f64, x_max: f64, y_max: f64) {
        self.x = (self.x + self.theta.sin()*self.v*dt + x_max) % x_max;
        self.y = (self.y - self.theta.cos()*self.v*dt + y_max) % y_max;
    }

    pub fn create_border<R: Rng>(rng: &mut R, radius: f64) -> Vec<[f64; 4]> {
        let spread = radius/5.0;
        let point_count = rng.gen_range(8, 12);
        let mut points = Vec::with_capacity(point_count);
        let theta_0 = rng.gen_range(0.0, 2.0*PI);
        for theta in (1..point_count+1).map(|i| theta_0 + 2.0*PI*i as f64/point_count as f64) {
            let distance = radius + rng.gen_range(-spread, spread);
            points.push(to_cartesian(theta, distance));
        };
        let point = points[0];
        points.push(point);
        let mut lines = Vec::with_capacity(point_count);
        for point in points.iter().zip(points.iter().skip(1)) {
            let (&(x1, x2), &(y1, y2)) = point;
            lines.push([x1, x2, y1, y2]);
        }
        return lines;
    }

    pub fn is_collision(&self, bullet_path: [f64; 4]) -> bool {
        return false;
    }
}<|endoftext|>


<commit_before>pub mod lexer;
pub mod parser;
pub mod ast;
pub mod codegen;
<commit_msg>Add Documentation to frondend module<commit_after>//! Processes Twee files and generates an AST
//!
//! The Frontend is responsible for processing a Twee file by
//! generating a Token Stream from the input and parsing this stream to build
//! an Abstract Syntax Tree.
//!
//! # Example
//!
//! This small example shows how the differend submodules interact and can
//! be used to parse a Twee-File.
//!
//! ```
//! # extern crate zwreec;
//! use std::io::Cursor;
//!
//! let cfg = zwreec::config::Config::default_config();
//! let mut twee = Cursor::new("::Start\nHello World".to_string().into_bytes());
//!
//! // Generate Token Stream
//! let tokens = zwreec::frontend::lexer::lex(&cfg, &mut twee);
//!
//! // Parse Tokens
//! let p = zwreec::frontend::parser::Parser::new(&cfg);
//! let ast = zwreec::frontend::ast::AST::build(
//!     p.parse(tokens)
//! );
//! ```
pub mod lexer;
pub mod parser;
pub mod ast;
pub mod codegen;
<|endoftext|>


<commit_before>use std::iter::Peekable;
use std::str::FromStr;
use std::time::Duration;

use game::{Position, FromTo, White, Black, NumPlies, NumMoves};
use search::NumNodes;
use types::{Cmd, RegisterParam, GoParam};
use types::options;

pub fn parse(s: &str) -> Option<Cmd> {
    let mut words = s.split(' ').peekable();

    let mut cmd_val: Option<Cmd> = None;

    while cmd_val.is_none() {
        let next_word_opt = words.next();
        let next_word = match next_word_opt {
            Some(val) => val,
            None => break,
        };

        cmd_val = match next_word {
            "uci" => Some(Cmd::Uci),
            "debug" => parse_on_off(&mut words).map(|val| Cmd::Debug(val)),
            "isready" => Some(Cmd::IsReady),
            "setoption" => parse_option_val(&mut words)
                               .map(|x| Cmd::SetOption(x)),
            "register" => parse_register_vec(&mut words).map(|val| Cmd::Register(val)),
            "ucinewgame" => Some(Cmd::UciNewGame),
            "position" => parse_setup_position(&mut words)
                              .map(|(pos, moves)| Cmd::SetupPosition(pos, moves)),
            "go" => parse_go_param_vec(&mut words).map(|val| Cmd::Go(val)),
            "stop" => Some(Cmd::Stop),
            "ponderhit" => Some(Cmd::PonderHit),
            "quit" => Some(Cmd::Quit),
            _ => None,
        }
    }

    if let Some(Cmd::Debug(val)) = cmd_val {
        // TODO set debug
        debug!("debug is now {:?}", val);
    }

    debug!("parse() returning {:?}", cmd_val);

    cmd_val
}

fn parse_on_off(words: &mut Iterator<Item = &str>) -> Option<bool> {
    let mut ans = None;
    while ans.is_none() {
        let next_word_opt = words.next();
        let next_word = match next_word_opt {
            Some(val) => val,
            None => break,
        };
        ans = match next_word {
            "on" => Some(true),
            "off" => Some(false),
            _ => None,
        }
    }

    debug!("parse_on_off() returning {:?}", ans);

    ans
}

fn parse_option_val<'a, T>(_words: &mut Peekable<T>) -> Option<options::NameAndVal>
where T: Iterator<Item = &'a str> {
    debug!("dummy option parsing");
    // TODO parse options.
    Some(options::NameAndVal::Dummy(1))
}

fn parse_register_vec<'a, T>(words: &mut Peekable<T>) -> Option<Vec<RegisterParam>>
where T: Iterator<Item = &'a str> {
    let mut res = Vec::<RegisterParam>::new();
    while let Some(next_word) = words.next() {
        let register_val = match next_word {
            "later" => Some(RegisterParam::Later),
            "name" => {
                let mut name_vec = Vec::<&str>::new();
                loop {
                    let curr_name = words.peek().and_then( |s| {
                        if ["later", "name", "code"].contains(s) { None }
                        else { Some(*s) }
                    });
                    match curr_name {
                        Some(val) => {
                            name_vec.push(val);
                            words.next();
                        },
                        None => break,
                    }
                }
                Some(RegisterParam::Name(name_vec.connect(" ")))
            },
            "code" => words.next().map( |x| RegisterParam::Code(x.to_string())),
            _ => None,
        };
        if let Some(val) = register_val {
            res.push(val);
        }
    }
    let ans = if res.is_empty() { None } else { Some(res) };

    debug!("parse_register_vec() returning {:?}", ans);

    ans
}

fn parse_setup_position<'a, T>(words: &mut Peekable<T>) -> Option<(Position, Vec<FromTo>)>
where T: Iterator<Item = &'a str> {
    let temp = parse_position(words);
    temp.map(|pos| {
        // consume everything up to and including "moves"
        let mut curr_word = words.next();
        while let Some(val) = curr_word {
            if val == "moves" { break; }
            curr_word = words.next();
        }

        // Attempt to parse the moves
        let moves = match parse_move_vec(words) {
            Some(val) => val,
            None => Vec::new(),
        };

        (pos, moves)
    })
}

fn parse_position<'a, T>(words: &mut Peekable<T>) -> Option<Position>
where T: Iterator<Item = &'a str> {
    let ans = if words.peek() == Some(&"startpos") {
        debug!("parse_position() consumed \"startpos\"");
        words.next();
        Some(Position::start())
    } else if words.peek() == Some(&"fen") {
        words.next();
        let six_words: Vec<_> = words.by_ref().take(6).collect();
        debug!("parse_position(): six_words = {:?}", six_words);
        six_words.connect(" ").parse::<Position>().ok()
    } else {
        None
    };

    debug!("parse_position() returning {:?}", ans);

    ans
}

fn parse_move_vec<'a, T>(words: &mut Peekable<T>) -> Option<Vec<FromTo>>
where T: Iterator<Item = &'a str> {
    let mut res = Vec::<FromTo>::new();
    debug!("parse_move_vec() peeked at {:?}", words.peek());
    while let Some(val) = words.peek().and_then(|val| FromStr::from_str(*val).ok()) {
        debug!("parse_move_vec(): val = {:?}", val);
        res.push(val);
        words.next();
        debug!("parse_move_vec() peeked at {:?}", words.peek());
    }
    let ans = if res.is_empty() { None } else { Some(res) };

    debug!("parse_move_vec() returning {:?}", ans);

    ans
}

fn parse_go_param_vec<'a, T>(words: &mut Peekable<T>) -> Option<Vec<GoParam>>
where T: Iterator<Item = &'a str> {
    let mut res = Vec::<GoParam>::new();
    while let Some(next_word) = words.next() {
        match next_word {
            "searchmoves" => parse_move_vec(words).map(|x| GoParam::SearchMoves(x)),
            "ponder" => Some(GoParam::Ponder),
            "wtime"     => words.next().and_then(|s| s.parse::<i64>().ok())
                                       .map(|x| GoParam::Time(White,
                                                              Duration::milliseconds(x))),
            "btime"     => words.next().and_then(|s| s.parse::<i64>().ok())
                                       .map(|x| GoParam::Time(Black,
                                                              Duration::milliseconds(x))),
            "winc"      => words.next().and_then(|s| s.parse::<i64>().ok())
                                       .map(|x| GoParam::IncTime(White,
                                                                 Duration::milliseconds(x))),
            "binc"      => words.next().and_then(|s| s.parse::<i64>().ok())
                                       .map(|x| GoParam::IncTime(Black,
                                                                 Duration::milliseconds(x))),
            "movestogo" => words.next().and_then(|s| s.parse::<u32>().ok())
                                       .map(|x| GoParam::MovesToGo(NumMoves(x))),
            "depth"     => words.next().and_then(|s| s.parse::<u32>().ok())
                                       .map(|x| GoParam::Depth(NumPlies(x))),
            "nodes"     => words.next().and_then(|s| s.parse::<u64>().ok())
                                       .map(|x| GoParam::Nodes(NumNodes(x))),
            "mate"      => words.next().and_then(|s| s.parse::<u32>().ok())
                                       .map(|x| GoParam::Mate(NumMoves(x))),
            "movetime"  => words.next().and_then(|s| s.parse::<i64>().ok())
                                       .map(|x| GoParam::MoveTime(Duration::milliseconds(x))),
            "infinite" => Some(GoParam::Infinite),
            _ => None,
        }.map(|val| res.push(val));
    }
    let ans = if res.is_empty() { None } else { Some(res) };

    debug!("parse_go_param_vec() returning {:?}", ans);

    ans
}
<commit_msg>Refactor parsing<commit_after>use std::iter::Peekable;
use std::str::FromStr;
use std::time::Duration;

use game::{Position, FromTo, White, Black, NumPlies, NumMoves};
use search::NumNodes;
use types::{Cmd, RegisterParam, GoParam};
use types::options;

pub fn parse(s: &str) -> Option<Cmd> {
    let mut words = s.split(' ');

    let mut cmd_val: Option<Cmd> = None;

    while cmd_val.is_none() {
        let next_word_opt = words.next();
        let next_word = match next_word_opt {
            Some(val) => val,
            None => break,
        };

        cmd_val = match next_word {
            "uci" => Some(Cmd::Uci),
            "debug" => parse_on_off(&mut words).map(|val| Cmd::Debug(val)),
            "isready" => Some(Cmd::IsReady),
            "setoption" => parse_option_val(&mut words)
                               .map(|x| Cmd::SetOption(x)),
            "register" => parse_register_vec(&mut words).map(|val| Cmd::Register(val)),
            "ucinewgame" => Some(Cmd::UciNewGame),
            "position" => parse_setup_position(&mut words)
                              .map(|(pos, moves)| Cmd::SetupPosition(pos, moves)),
            "go" => parse_go_param_vec(&mut words).map(|val| Cmd::Go(val)),
            "stop" => Some(Cmd::Stop),
            "ponderhit" => Some(Cmd::PonderHit),
            "quit" => Some(Cmd::Quit),
            _ => None,
        }
    }

    if let Some(Cmd::Debug(val)) = cmd_val {
        // TODO set debug
        debug!("debug is now {:?}", val);
    }

    debug!("parse() returning {:?}", cmd_val);

    cmd_val
}

fn parse_on_off<'a, I>(mut words: I) -> Option<bool>
where I: Iterator<Item = &'a str>{
    let mut ans = None;
    while ans.is_none() {
        let next_word_opt = words.next();
        let next_word = match next_word_opt {
            Some(val) => val,
            None => break,
        };
        ans = match next_word {
            "on" => Some(true),
            "off" => Some(false),
            _ => None,
        }
    }

    debug!("parse_on_off() returning {:?}", ans);

    ans
}

fn parse_option_val<'a, I>(_words: I) -> Option<options::NameAndVal>
where I: Iterator<Item = &'a str> {
    debug!("dummy option parsing");
    // TODO parse options.
    Some(options::NameAndVal::Dummy(1))
}

fn parse_register_vec<'a, I>(words: I) -> Option<Vec<RegisterParam>>
where I: Iterator<Item = &'a str> {
    let mut words = words.peekable();
    let mut res = Vec::<RegisterParam>::new();
    while let Some(next_word) = words.next() {
        let register_val = match next_word {
            "later" => Some(RegisterParam::Later),
            "name" => {
                let mut name_vec = Vec::<&str>::new();
                loop {
                    let curr_name = words.peek().and_then( |s| {
                        if ["later", "name", "code"].contains(s) { None }
                        else { Some(*s) }
                    });
                    match curr_name {
                        Some(val) => {
                            name_vec.push(val);
                            words.next();
                        },
                        None => break,
                    }
                }
                Some(RegisterParam::Name(name_vec.connect(" ")))
            },
            "code" => words.next().map( |x| RegisterParam::Code(x.to_string())),
            _ => None,
        };
        if let Some(val) = register_val {
            res.push(val);
        }
    }
    let ans = if res.is_empty() { None } else { Some(res) };

    debug!("parse_register_vec() returning {:?}", ans);

    ans
}

fn parse_setup_position<'a, I>(mut words: I) -> Option<(Position, Vec<FromTo>)>
where I: Iterator<Item = &'a str> {
    let temp = parse_position(words.by_ref());
    temp.map(|pos| {
        // consume everything up to and including "moves"
        let mut words = words.skip_while(|&s| s != "moves");
        words.next();

        // Attempt to parse the moves
        let moves = match parse_from_to_vec(&mut words.peekable()) {
            Some(val) => val,
            None => Vec::new(),
        };

        (pos, moves)
    })
}

fn parse_position<'a, I>(words: I) -> Option<Position>
where I: Iterator<Item = &'a str> {
    let mut words = words.peekable();
    let ans = if words.peek() == Some(&"startpos") {
        debug!("parse_position() consumed \"startpos\"");
        words.next();
        Some(Position::start())
    } else if words.peek() == Some(&"fen") {
        words.next();
        let six_words: Vec<_> = words.by_ref().take(6).collect();
        debug!("parse_position(): six_words = {:?}", six_words);
        six_words.connect(" ").parse::<Position>().ok()
    } else {
        None
    };

    debug!("parse_position() returning {:?}", ans);

    ans
}

fn parse_from_to_vec<'a, I>(words: &mut Peekable<I>) -> Option<Vec<FromTo>>
where I: Iterator<Item = &'a str> {
    let mut res = Vec::<FromTo>::new();
    debug!("parse_from_to_vec() peeked at {:?}", words.peek());
    while let Some(val) = words.peek().and_then(|val| FromStr::from_str(*val).ok()) {
        debug!("parse_from_to_vec(): val = {:?}", val);
        res.push(val);
        words.next();
        debug!("parse_from_to_vec() peeked at {:?}", words.peek());
    }
    let ans = if res.is_empty() { None } else { Some(res) };

    debug!("parse_from_to_vec() returning {:?}", ans);

    ans
}

fn parse_go_param_vec<'a, I>(words: I) -> Option<Vec<GoParam>>
where I: Iterator<Item = &'a str> {
    let mut words = words.peekable();
    let mut res = Vec::<GoParam>::new();
    while let Some(next_word) = words.next() {
        match next_word {
            "searchmoves" => parse_from_to_vec(&mut words).map(|x| GoParam::SearchMoves(x)),
            "ponder" => Some(GoParam::Ponder),
            "wtime"     => words.next().and_then(|s| s.parse::<i64>().ok())
                                       .map(|x| GoParam::Time(White,
                                                              Duration::milliseconds(x))),
            "btime"     => words.next().and_then(|s| s.parse::<i64>().ok())
                                       .map(|x| GoParam::Time(Black,
                                                              Duration::milliseconds(x))),
            "winc"      => words.next().and_then(|s| s.parse::<i64>().ok())
                                       .map(|x| GoParam::IncTime(White,
                                                                 Duration::milliseconds(x))),
            "binc"      => words.next().and_then(|s| s.parse::<i64>().ok())
                                       .map(|x| GoParam::IncTime(Black,
                                                                 Duration::milliseconds(x))),
            "movestogo" => words.next().and_then(|s| s.parse::<u32>().ok())
                                       .map(|x| GoParam::MovesToGo(NumMoves(x))),
            "depth"     => words.next().and_then(|s| s.parse::<u32>().ok())
                                       .map(|x| GoParam::Depth(NumPlies(x))),
            "nodes"     => words.next().and_then(|s| s.parse::<u64>().ok())
                                       .map(|x| GoParam::Nodes(NumNodes(x))),
            "mate"      => words.next().and_then(|s| s.parse::<u32>().ok())
                                       .map(|x| GoParam::Mate(NumMoves(x))),
            "movetime"  => words.next().and_then(|s| s.parse::<i64>().ok())
                                       .map(|x| GoParam::MoveTime(Duration::milliseconds(x))),
            "infinite" => Some(GoParam::Infinite),
            _ => None,
        }.map(|val| res.push(val));
    }
    let ans = if res.is_empty() { None } else { Some(res) };

    debug!("parse_go_param_vec() returning {:?}", ans);

    ans
}
<|endoftext|>


<commit_before>
/// Implemented by all contexts that can add source rectangle.
pub trait AddSourceRectangle<'a, T> {
    /// Adds a source rectangle with coordinates in the center.
    #[inline(always)]
    fn src_rect_centered(&'a self, center_x: u32, center_y: u32, radius_width: u32, radius_height: u32) -> T {
        self.src_rect(
            center_x - radius_width,
            center_y - radius_height,
            2 * radius_width,
            2 * radius_height
       )
    }

    /// Adds a square with coordinates of upper left corner.
    #[inline(always)]
    fn src_square(&'a self, x: u32, y: u32, w: u32) -> T {
        self.src_rect(x, y, w, w)
    }

    /// Adds a square with coordinates in the center.
    #[inline(always)]
    fn src_square_centered(&'a self, center_x: u32, center_y: u32, radius: u32) -> T {
        self.src_rect(center_x - radius,
                  center_y - radius,
                  2 * radius,
                  2 * radius)
    }
}

<commit_msg>Deleted `AddSourceRectangle`<commit_after><|endoftext|>


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

// compile-flags:-Zdump-mir=NEVER_MATCHED

// Regression test for #41697. Using dump-mir was triggering
// artificial cycles: during type-checking, we had to get the MIR for
// the constant expressions in `[u8; 2]`, which in turn would trigger
// an attempt to get the item-path, which in turn would request the
// types of the impl, which would trigger a cycle. We supressed this
// cycle now by forcing mir-dump to avoid asking for types of an impl.

#![feature(rustc_attrs)]

use std::sync::Arc;

trait Foo {
    fn get(&self) -> [u8; 2];
}

impl Foo for [u8; 2] {
    fn get(&self) -> [u8; 2] {
        *self
    }
}

struct Bar<T: ?Sized>(T);

fn unsize_fat_ptr<'a>(x: &'a Bar<Foo + Send + 'a>) -> &'a Bar<Foo + 'a> {
    x
}

fn unsize_nested_fat_ptr(x: Arc<Foo + Send>) -> Arc<Foo> {
    x
}

fn main() {
    let x: Box<Bar<Foo + Send>> = Box::new(Bar([1,2]));
    assert_eq!(unsize_fat_ptr(&*x).0.get(), [1, 2]);

    let x: Arc<Foo + Send> = Arc::new([3, 4]);
    assert_eq!(unsize_nested_fat_ptr(x).get(), [3, 4]);
}
<commit_msg>remove compile-flags<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Regression test for #41697. Using dump-mir was triggering
// artificial cycles: during type-checking, we had to get the MIR for
// the constant expressions in `[u8; 2]`, which in turn would trigger
// an attempt to get the item-path, which in turn would request the
// types of the impl, which would trigger a cycle. We supressed this
// cycle now by forcing mir-dump to avoid asking for types of an impl.

#![feature(rustc_attrs)]

use std::sync::Arc;

trait Foo {
    fn get(&self) -> [u8; 2];
}

impl Foo for [u8; 2] {
    fn get(&self) -> [u8; 2] {
        *self
    }
}

struct Bar<T: ?Sized>(T);

fn unsize_fat_ptr<'a>(x: &'a Bar<Foo + Send + 'a>) -> &'a Bar<Foo + 'a> {
    x
}

fn unsize_nested_fat_ptr(x: Arc<Foo + Send>) -> Arc<Foo> {
    x
}

fn main() {
    let x: Box<Bar<Foo + Send>> = Box::new(Bar([1,2]));
    assert_eq!(unsize_fat_ptr(&*x).0.get(), [1, 2]);

    let x: Arc<Foo + Send> = Arc::new([3, 4]);
    assert_eq!(unsize_nested_fat_ptr(x).get(), [3, 4]);
}
<|endoftext|>


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

// xfail-test
enum pat { pat_ident(Option<uint>) }

fn f(pat: pat) -> bool { true }

fn num_bindings(pat: pat) -> uint {
    match pat {
      pat_ident(_) if f(pat) { 0 }
      pat_ident(None) { 1 }
      pat_ident(Some(sub)) { sub }
    }
}

pub fn main() {}
<commit_msg>this issue is a dup of another one that has a correct test case<commit_after><|endoftext|>


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

// ignore-linux see joyent/libuv#1189
// ignore-fast
// ignore-android needs extra network permissions
// exec-env:RUST_LOG=debug

use std::libc;
use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::io::net::tcp::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};

fn main() {
    // This test has a chance to time out, try to not let it time out
    spawn(proc() {
        use std::io::timer;
        timer::sleep(30 * 1000);
        println!("timed out!");
        unsafe { libc::exit(1) }
    });

    let addr = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 0 };
    let (tx, rx) = channel();
    spawn(proc() {
        let mut listener = TcpListener::bind(addr).unwrap();
        tx.send(listener.socket_name().unwrap());
        let mut acceptor = listener.listen();
        loop {
            let mut stream = match acceptor.accept() {
                Ok(stream) => stream,
                Err(error) => {
                    debug!("accept failed: {:?}", error);
                    continue;
                }
            };
            stream.read_byte();
            stream.write([2]);
        }
    });
    let addr = rx.recv();

    let (tx, rx) = channel();
    for _ in range(0, 1000) {
        let tx = tx.clone();
        spawn(proc() {
            match TcpStream::connect(addr) {
                Ok(stream) => {
                    let mut stream = stream;
                    stream.write([1]);
                    let mut buf = [0];
                    stream.read(buf);
                },
                Err(e) => debug!("{:?}", e)
            }
            tx.send(());
        });
    }

    // Wait for all clients to exit, but don't wait for the server to exit. The
    // server just runs infinitely.
    drop(tx);
    for _ in range(0, 1000) {
        rx.recv();
    }
    unsafe { libc::exit(0) }
}
<commit_msg>Fix a test that was missed in the liblog PR<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-linux see joyent/libuv#1189
// ignore-fast
// ignore-android needs extra network permissions
// exec-env:RUST_LOG=debug

#[feature(phase)];
#[phase(syntax, link)]
extern crate log;

use std::libc;
use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::io::net::tcp::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};

fn main() {
    // This test has a chance to time out, try to not let it time out
    spawn(proc() {
        use std::io::timer;
        timer::sleep(30 * 1000);
        println!("timed out!");
        unsafe { libc::exit(1) }
    });

    let addr = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 0 };
    let (tx, rx) = channel();
    spawn(proc() {
        let mut listener = TcpListener::bind(addr).unwrap();
        tx.send(listener.socket_name().unwrap());
        let mut acceptor = listener.listen();
        loop {
            let mut stream = match acceptor.accept() {
                Ok(stream) => stream,
                Err(error) => {
                    debug!("accept failed: {:?}", error);
                    continue;
                }
            };
            stream.read_byte();
            stream.write([2]);
        }
    });
    let addr = rx.recv();

    let (tx, rx) = channel();
    for _ in range(0, 1000) {
        let tx = tx.clone();
        spawn(proc() {
            match TcpStream::connect(addr) {
                Ok(stream) => {
                    let mut stream = stream;
                    stream.write([1]);
                    let mut buf = [0];
                    stream.read(buf);
                },
                Err(e) => debug!("{:?}", e)
            }
            tx.send(());
        });
    }

    // Wait for all clients to exit, but don't wait for the server to exit. The
    // server just runs infinitely.
    drop(tx);
    for _ in range(0, 1000) {
        rx.recv();
    }
    unsafe { libc::exit(0) }
}
<|endoftext|>


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

// @has issue_25001/struct.Foo.html
pub struct Foo<T>(T);

pub trait Bar {
    type Item;

    fn quux(self);
}

impl<T> Foo<T> {
    // @has - '//*[@id="method.pass"]//code' 'fn pass()'
    pub fn pass() {}
}
impl<T> Foo<T> {
    // @has - '//*[@id="method.pass-1"]//code' 'fn pass() -> usize'
    pub fn pass() -> usize { 42 }
}
impl<T> Foo<T> {
    // @has - '//*[@id="method.pass-2"]//code' 'fn pass() -> isize'
    pub fn pass() -> isize { 42 }
}

impl<T> Bar for Foo<T> {
    // @has - '//*[@id="associatedtype.Item"]//code' 'type Item = T'
    type Item=T;

    // @has - '//*[@id="method.quux"]//code' 'fn quux(self)'
    fn quux(self) {}
}
impl<'a, T> Bar for &'a Foo<T> {
    // @has - '//*[@id="associatedtype.Item-1"]//code' "type Item = &'a T"
    type Item=&'a T;

    // @has - '//*[@id="method.quux-1"]//code' 'fn quux(self)'
    fn quux(self) {}
}
impl<'a, T> Bar for &'a mut Foo<T> {
    // @has - '//*[@id="associatedtype.Item-2"]//code' "type Item = &'a mut T"
    type Item=&'a mut T;

    // @has - '//*[@id="method.quux-2"]//code' 'fn quux(self)'
    fn quux(self) {}
}
<commit_msg>Adjust rustdoc test for new restriction<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// @has issue_25001/struct.Foo.html
pub struct Foo<T>(T);

pub trait Bar {
    type Item;

    fn quux(self);
}

impl Foo<u8> {
    // @has - '//*[@id="method.pass"]//code' 'fn pass()'
    pub fn pass() {}
}
impl Foo<u16> {
    // @has - '//*[@id="method.pass-1"]//code' 'fn pass() -> usize'
    pub fn pass() -> usize { 42 }
}
impl Foo<u32> {
    // @has - '//*[@id="method.pass-2"]//code' 'fn pass() -> isize'
    pub fn pass() -> isize { 42 }
}

impl<T> Bar for Foo<T> {
    // @has - '//*[@id="associatedtype.Item"]//code' 'type Item = T'
    type Item=T;

    // @has - '//*[@id="method.quux"]//code' 'fn quux(self)'
    fn quux(self) {}
}
impl<'a, T> Bar for &'a Foo<T> {
    // @has - '//*[@id="associatedtype.Item-1"]//code' "type Item = &'a T"
    type Item=&'a T;

    // @has - '//*[@id="method.quux-1"]//code' 'fn quux(self)'
    fn quux(self) {}
}
impl<'a, T> Bar for &'a mut Foo<T> {
    // @has - '//*[@id="associatedtype.Item-2"]//code' "type Item = &'a mut T"
    type Item=&'a mut T;

    // @has - '//*[@id="method.quux-2"]//code' 'fn quux(self)'
    fn quux(self) {}
}
<|endoftext|>


<commit_before>//! Common traits for various ways to renderer on a given graphics backend.
//!
//! Note: Not every API may be supported by every backend

mod cursor;
pub use self::cursor::*;

mod format;
pub use self::format::*;

#[cfg(feature = "renderer_gl")]
pub mod gl;
#[cfg(feature = "renderer_glium")]
pub mod glium;
#[cfg(feature = "renderer_software")]
pub mod software;

/// Error that can happen when swapping buffers.
#[derive(Debug, thiserror::Error)]
pub enum SwapBuffersError {
    /// The buffers have already been swapped.
    ///
    /// This error can be returned when `swap_buffers` has been called multiple times
    /// without any modification in between.
    #[error("Buffers are already swapped, swap_buffers was called too many times")]
    AlreadySwapped,
    /// The corresponding context has been lost and needs to be recreated.
    ///
    /// All the objects associated to it (textures, buffers, programs, etc.)
    /// need to be recreated from scratch. Underlying resources like native surfaces
    /// might also need to be recreated.
    ///
    /// Operations will have no effect. Functions that read textures, buffers, etc.
    /// will return uninitialized data instead.
    #[error("The context has been lost, it needs to be recreated")]
    ContextLost(Box<dyn std::error::Error>),
    /// A temporary condition caused to rendering to fail.
    ///
    /// Depending on the underlying error this *might* require fixing internal state of the rendering backend,
    /// but failures mapped to `TemporaryFailure` are always recoverable without re-creating the entire stack,
    /// as is represented by `ContextLost`.
    ///
    /// Proceed after investigating the source to reschedule another full rendering step or just this page_flip at a later time.
    /// If the root cause cannot be discovered and subsequent renderings also fail, it is advised to fallback to
    /// recreation.
    #[error("A temporary condition caused the page flip to fail.")]
    TemporaryFailure(Box<dyn std::error::Error>),
}
<commit_msg>graphics: Log underlying error of SwapBuffers<commit_after>//! Common traits for various ways to renderer on a given graphics backend.
//!
//! Note: Not every API may be supported by every backend

mod cursor;
pub use self::cursor::*;

mod format;
pub use self::format::*;

#[cfg(feature = "renderer_gl")]
pub mod gl;
#[cfg(feature = "renderer_glium")]
pub mod glium;
#[cfg(feature = "renderer_software")]
pub mod software;

/// Error that can happen when swapping buffers.
#[derive(Debug, thiserror::Error)]
pub enum SwapBuffersError {
    /// The buffers have already been swapped.
    ///
    /// This error can be returned when `swap_buffers` has been called multiple times
    /// without any modification in between.
    #[error("Buffers are already swapped, swap_buffers was called too many times")]
    AlreadySwapped,
    /// The corresponding context has been lost and needs to be recreated.
    ///
    /// All the objects associated to it (textures, buffers, programs, etc.)
    /// need to be recreated from scratch. Underlying resources like native surfaces
    /// might also need to be recreated.
    ///
    /// Operations will have no effect. Functions that read textures, buffers, etc.
    /// will return uninitialized data instead.
    #[error("The context has been lost, it needs to be recreated: {0}")]
    ContextLost(Box<dyn std::error::Error>),
    /// A temporary condition caused to rendering to fail.
    ///
    /// Depending on the underlying error this *might* require fixing internal state of the rendering backend,
    /// but failures mapped to `TemporaryFailure` are always recoverable without re-creating the entire stack,
    /// as is represented by `ContextLost`.
    ///
    /// Proceed after investigating the source to reschedule another full rendering step or just this page_flip at a later time.
    /// If the root cause cannot be discovered and subsequent renderings also fail, it is advised to fallback to
    /// recreation.
    #[error("A temporary condition caused the page flip to fail: {0}")]
    TemporaryFailure(Box<dyn std::error::Error>),
}
<|endoftext|>