<commit_before>use LalafellBot;
use listeners::ReceivesEvents;
use commands::*;
use discord::model::{Event, Message, ReactionEmoji};

use std::sync::Arc;
use std::collections::HashMap;

pub struct CommandListener<'a> {
  bot: Arc<LalafellBot>,
  commands: HashMap<Vec<String>, Box<Command<'a> + Send + Sync>>
}

impl<'a> CommandListener<'a> {
  pub fn new(bot: Arc<LalafellBot>) -> CommandListener<'a> {
    CommandListener {
      bot: bot,
      commands: Default::default()
    }
  }

  pub fn add_command<T: AsRef<str>>(&mut self, names: &[T], command: Box<Command<'a> + Send + Sync>) {
    self.commands.insert(names.iter().map(|t| t.as_ref().to_string()).collect(), command);
  }

  fn check_command(&self, message: &Message) {
    let parts: Vec<&str> = message.content.split_whitespace().collect();
    if parts.is_empty() {
      return;
    }
    let first = parts[0];
    if !first.starts_with('!') {
      return;
    }
    let command_name = &first[1..].to_lowercase();
    let params = &parts[1..];
    let (_, command) = match self.commands.iter().find(|&(names, _)| names.contains(&command_name.to_lowercase())) {
      Some(c) => c,
      None => return
    };
    let run_result = command.run(message, params);
    let emoji = if run_result.is_ok() { "\u{2705}" } else { "\u{274c}" };
    self.bot.discord.add_reaction(message.channel_id, message.id, ReactionEmoji::Unicode(emoji.to_string())).ok();
    match run_result {
      Ok(info) => {
        if let Some(embed) = info.message {
          self.bot.discord.send_embed(message.channel_id, "", embed).ok();
        }
      },
      Err(CommandFailure::Internal(info)) => {
        self.bot.discord.send_embed(message.channel_id, "",
                                    |e| e.description("An internal error happened while processing this command.")).ok();
        for err in info.error.iter() {
          error!("error: {:#?}", err);
        }
      },
      Err(CommandFailure::External(info)) => {
        if let Some(embed) = info.message {
          self.bot.discord.send_embed(message.channel_id, "", embed).ok();
        }
      }
    }
  }
}

impl<'a> ReceivesEvents for CommandListener<'a> {
  fn receive(&self, event: &Event) {
    let message = match *event {
      Event::MessageCreate(ref m) => m,
      _ => return
    };
    self.check_command(message);
  }
}
<commit_msg>feat: color embeds instead of using reactions<commit_after>use LalafellBot;
use listeners::ReceivesEvents;
use commands::*;
use discord::model::{Event, Message, ReactionEmoji};

use std::sync::Arc;
use std::collections::HashMap;

pub struct CommandListener<'a> {
  bot: Arc<LalafellBot>,
  commands: HashMap<Vec<String>, Box<Command<'a> + Send + Sync>>
}

impl<'a> CommandListener<'a> {
  pub fn new(bot: Arc<LalafellBot>) -> CommandListener<'a> {
    CommandListener {
      bot: bot,
      commands: Default::default()
    }
  }

  pub fn add_command<T: AsRef<str>>(&mut self, names: &[T], command: Box<Command<'a> + Send + Sync>) {
    self.commands.insert(names.iter().map(|t| t.as_ref().to_string()).collect(), command);
  }

  fn check_command(&self, message: &Message) {
    let parts: Vec<&str> = message.content.split_whitespace().collect();
    if parts.is_empty() {
      return;
    }
    let first = parts[0];
    if !first.starts_with('!') {
      return;
    }
    let command_name = &first[1..].to_lowercase();
    let params = &parts[1..];
    let (_, command) = match self.commands.iter().find(|&(names, _)| names.contains(&command_name.to_lowercase())) {
      Some(c) => c,
      None => return
    };
    let run_result = command.run(message, params);
    let command_success = run_result.is_ok();
    match run_result {
      Ok(info) => {
        match info.message {
          Some(embed) => {
            let color = if command_success { 1663832 } else { 6494491 };
            self.bot.discord.send_embed(message.channel_id, "", |e| embed(e).color(color)).ok();
          },
          None => {
            let emoji = if command_success { "\u{2705}" } else { "\u{274c}" };
            self.bot.discord.add_reaction(message.channel_id, message.id, ReactionEmoji::Unicode(emoji.to_string())).ok();
          }
        }
      },
      Err(CommandFailure::Internal(info)) => {
        self.bot.discord.send_embed(message.channel_id, "",
                                    |e| e.description("An internal error happened while processing this command.")).ok();
        for err in info.error.iter() {
          error!("error: {:#?}", err);
        }
      },
      Err(CommandFailure::External(info)) => {
        if let Some(embed) = info.message {
          self.bot.discord.send_embed(message.channel_id, "", embed).ok();
        }
      }
    }
  }
}

impl<'a> ReceivesEvents for CommandListener<'a> {
  fn receive(&self, event: &Event) {
    let message = match *event {
      Event::MessageCreate(ref m) => m,
      _ => return
    };
    self.check_command(message);
  }
}
<|endoftext|>


<commit_before>extern mod glfw;

#[start]
fn start(argc: int, argv: **u8, crate_map: *u8) -> int {
    std::rt::start_on_main_thread(argc, argv, crate_map, main)
}

pub struct Wrapper {
    glfw_window: glfw::Window
}

impl Wrapper {
    /// Creates a new window.
    fn new() -> @mut Wrapper {
        // Create the GLFW window.
        let glfw_window = glfw::Window::create(800, 600, "Servo", glfw::Windowed).unwrap();
        glfw_window.make_context_current();

        // Create our window object.
        let window = @mut Wrapper {
            glfw_window:glfw_window,
        };

        // BUG: If the captured use of window is changed to instead use the provided win argument,
        // then there is no crash during the destructor. However, the change in servo is not that
        // simple. as the Wrapper struct has significantly more data and functionality, which are
        // used in the event handlers.
        do window.glfw_window.set_key_callback |_win, key, _scancode, action, _mods| {
            println("Handler");
            if action == glfw::PRESS && key == glfw::KEY_ESCAPE {
                window.glfw_window.set_should_close(true);
            }
        };

        window
    }

    fn recv(&self) -> bool {
        self.glfw_window.poll_events();
        glfw::poll_events();
        if self.glfw_window.should_close() {
            true
        } else {
            false
        }
    }

}

fn main() {
    glfw::init();

    let window: @mut Wrapper = Wrapper::new();

    // Enter the main event loop.
    while !window.recv() {
    }
    glfw::terminate();
}
<commit_msg>Revert inadvertant change to window.rs<commit_after>// Copyright 2013 The GLFW-RS Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern mod glfw;

use std::libc;

#[start]
fn start(argc: int, argv: **u8, crate_map: *u8) -> int {
    std::rt::start_on_main_thread(argc, argv, crate_map, main)
}

fn main() {
    glfw::set_error_callback(error_callback);

    do glfw::start {
        let window = glfw::Window::create(300, 300, "Hello this is window", glfw::Windowed).unwrap();

        window.set_key_callback(key_callback);
        window.make_context_current();

        while !window.should_close() {
            glfw::poll_events();
        }
    }
}

fn key_callback(window: &glfw::Window, key: libc::c_int, _: libc::c_int, action: libc::c_int, _: libc::c_int) {
    if action == glfw::PRESS && key == glfw::KEY_ESCAPE {
        window.set_should_close(true);
    }
}

fn error_callback(_: libc::c_int, description: ~str) {
    println(fmt!("GLFW Error: %s", description));
}
<|endoftext|>


<commit_before>use regex::Regex;
use serde::{Serialize, Serializer};
use std::{mem, ops, str};
use tree_sitter::{Language, Node, Parser, Query, QueryCursor, QueryError, Tree};

/// Contains the data neeeded to compute tags for code written in a
/// particular language.
pub struct TagsConfiguration {
    pub language: Language,
    pub query: Query,
    call_capture_index: Option<u32>,
    class_capture_index: Option<u32>,
    doc_capture_index: Option<u32>,
    function_capture_index: Option<u32>,
    locals_pattern_index: usize,
    module_capture_index: Option<u32>,
    name_capture_index: Option<u32>,
    doc_strip_regexes: Vec<Option<Regex>>,
}

pub struct TagsContext {
    parser: Parser,
    cursor: QueryCursor,
}

struct TagsIter<'a, I>
where
    I: Iterator<Item = tree_sitter::QueryMatch<'a>>,
{
    matches: I,
    _tree: Tree,
    source: &'a [u8],
    config: &'a TagsConfiguration,
    tag_queue: Vec<(Node<'a>, usize, Tag<'a>)>,
}

#[derive(Debug, Serialize, Clone)]
pub struct Loc {
    pub byte_range: ops::Range<usize>,
    pub span: ops::Range<Pos>,
}

#[derive(Debug, Serialize, Clone)]
pub struct Pos {
    pub line: i64,
    pub column: i64,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum TagKind {
    Function,
    Method,
    Class,
    Module,
    Call,
}

#[derive(Debug, Serialize, Clone)]
pub struct Tag<'a> {
    pub kind: TagKind,
    pub name: &'a str,
    pub docs: Option<String>,
    pub loc: Loc,
    pub line: &'a str,
}

#[derive(Debug)]
pub enum Error {
    Query(QueryError),
    Regex(regex::Error),
}

impl TagsConfiguration {
    pub fn new(language: Language, tags_query: &str, locals_query: &str) -> Result<Self, Error> {
        let query = Query::new(language, &format!("{}{}", tags_query, locals_query))?;

        let locals_query_offset = tags_query.len();
        let mut locals_pattern_index = 0;
        for i in 0..(query.pattern_count()) {
            let pattern_offset = query.start_byte_for_pattern(i);
            if pattern_offset < locals_query_offset {
                locals_pattern_index += 1;
            }
        }

        let mut call_capture_index = None;
        let mut class_capture_index = None;
        let mut doc_capture_index = None;
        let mut function_capture_index = None;
        let mut module_capture_index = None;
        let mut name_capture_index = None;
        for (i, name) in query.capture_names().iter().enumerate() {
            let index = match name.as_str() {
                "call" => &mut call_capture_index,
                "class" => &mut class_capture_index,
                "doc" => &mut doc_capture_index,
                "function" => &mut function_capture_index,
                "module" => &mut module_capture_index,
                "name" => &mut name_capture_index,
                _ => continue,
            };
            *index = Some(i as u32);
        }

        let doc_strip_regexes = (0..query.pattern_count())
            .map(|pattern_index| {
                let properties = query.property_settings(pattern_index);
                for property in properties {
                    if property.key.as_ref() == "strip"
                        && property.capture_id.map(|id| id as u32) == doc_capture_index
                    {
                        if let Some(value) = &property.value {
                            let regex = Regex::new(value.as_ref())?;
                            return Ok(Some(regex));
                        }
                    }
                }
                return Ok(None);
            })
            .collect::<Result<Vec<_>, Error>>()?;

        Ok(TagsConfiguration {
            language,
            query,
            locals_pattern_index,
            function_capture_index,
            class_capture_index,
            module_capture_index,
            doc_capture_index,
            call_capture_index,
            name_capture_index,
            doc_strip_regexes,
        })
    }
}

impl TagsContext {
    pub fn new() -> Self {
        TagsContext {
            parser: Parser::new(),
            cursor: QueryCursor::new(),
        }
    }

    // TODO: This should return an iterator rather than build up a vector
    pub fn generate_tags<'a>(
        &'a mut self,
        config: &'a TagsConfiguration,
        source: &'a [u8],
    ) -> impl Iterator<Item = Tag<'a>> + 'a {
        self.parser
            .set_language(config.language)
            .expect("Incompatible language");
        let tree = self
            .parser
            .parse(source, None)
            .expect("Parsing failed unexpectedly");

        // The `matches` iterator borrows the `Tree`, which prevents it from being moved.
        // But the tree is really just a pointer, so it's actually ok to move it.
        let tree_ref = unsafe { mem::transmute::<_, &'static Tree>(&tree) };
        let matches = self
            .cursor
            .matches(&config.query, tree_ref.root_node(), move |node| {
                &source[node.byte_range()]
            });
        TagsIter {
            matches,
            source,
            config,
            tag_queue: Vec::new(),
            _tree: tree,
        }
    }
}

impl<'a, I> Iterator for TagsIter<'a, I>
where
    I: Iterator<Item = tree_sitter::QueryMatch<'a>>,
{
    type Item = Tag<'a>;

    fn next(&mut self) -> Option<Tag<'a>> {
        loop {
            // If there is a queued tag for an earlier node in the syntax tree, then pop
            // it off of the queue and return it.
            if let Some(last_entry) = self.tag_queue.last() {
                if self.tag_queue.len() > 1
                    && self.tag_queue[0].0.end_byte() < last_entry.0.start_byte()
                {
                    return Some(self.tag_queue.remove(0).2);
                }
            }

            // If there is another match, then compute its tag and add it to the
            // tag queue.
            if let Some(mat) = self.matches.next() {
                let mut call_node = None;
                let mut doc_node = None;
                let mut class_node = None;
                let mut function_node = None;
                let mut module_node = None;
                let mut name_node = None;

                for capture in mat.captures {
                    let index = Some(capture.index);
                    let node = Some(capture.node);
                    if index == self.config.call_capture_index {
                        call_node = node;
                    } else if index == self.config.class_capture_index {
                        class_node = node;
                    } else if index == self.config.doc_capture_index {
                        doc_node = node;
                    } else if index == self.config.function_capture_index {
                        function_node = node;
                    } else if index == self.config.module_capture_index {
                        module_node = node;
                    } else if index == self.config.name_capture_index {
                        name_node = node;
                    }
                }

                let source = &self.source;
                let config = &self.config;
                let tag_from_node = |node: Node, kind: TagKind| -> Option<Tag> {
                    let name = str::from_utf8(&source[name_node?.byte_range()]).ok()?;
                    let mut line_range = node.byte_range();
                    if line_range.len() > 180 {
                        line_range.end = line_range.start + 180;
                    }
                    let line = str::from_utf8(&source[line_range]).ok()?.lines().next()?;
                    let docs = doc_node
                        .and_then(|n| str::from_utf8(&source[n.byte_range()]).ok())
                        .map(|s| {
                            if let Some(regex) = &config.doc_strip_regexes[mat.pattern_index] {
                                regex.replace_all(s, "").to_string()
                            } else {
                                s.to_string()
                            }
                        });
                    Some(Tag {
                        name,
                        line,
                        loc: loc_for_node(node),
                        kind: kind,
                        docs,
                    })
                };

                for (tag_node, tag_kind) in [
                    (call_node, TagKind::Call),
                    (class_node, TagKind::Class),
                    (function_node, TagKind::Function),
                    (module_node, TagKind::Module),
                ]
                .iter()
                .cloned()
                {
                    if let Some(found) = tag_node {
                        // Only create one tag per node. The tag queue is sorted by node position
                        // to allow for fast lookup.
                        match self.tag_queue.binary_search_by_key(
                            &(found.end_byte(), found.start_byte(), found.id()),
                            |(node, _, _)| (node.end_byte(), node.start_byte(), node.id()),
                        ) {
                            Ok(i) => {
                                let (_, old_idx, tag) = &mut self.tag_queue[i];
                                if *old_idx > mat.pattern_index {
                                    if let Some(new_tag) = tag_from_node(found, tag_kind) {
                                        *tag = new_tag;
                                        *old_idx = mat.pattern_index;
                                    }
                                }
                            }
                            Err(i) => {
                                if let Some(tag) = tag_from_node(found, tag_kind) {
                                    self.tag_queue.insert(i, (found, mat.pattern_index, tag))
                                }
                            }
                        }
                        break;
                    }
                }
            }
            // If there are no more matches, then drain the queue.
            else if !self.tag_queue.is_empty() {
                return Some(self.tag_queue.remove(0).2);
            } else {
                return None;
            }
        }
    }
}

impl Serialize for TagKind {
    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            TagKind::Call => "Call",
            TagKind::Module => "Module",
            TagKind::Class => "Class",
            TagKind::Method => "Method",
            TagKind::Function => "Function",
        }
        .serialize(s)
    }
}

fn loc_for_node(node: Node) -> Loc {
    Loc {
        byte_range: node.byte_range(),
        span: node.start_position().into()..node.start_position().into(),
    }
}

impl From<tree_sitter::Point> for Pos {
    fn from(point: tree_sitter::Point) -> Self {
        return Pos {
            line: point.row as i64,
            column: point.column as i64,
        };
    }
}

impl From<regex::Error> for Error {
    fn from(error: regex::Error) -> Self {
        Error::Regex(error)
    }
}

impl From<QueryError> for Error {
    fn from(error: QueryError) -> Self {
        Error::Query(error)
    }
}
<commit_msg>some whitespace and comments<commit_after>use regex::Regex;
use serde::{Serialize, Serializer};
use std::{mem, ops, str};
use tree_sitter::{Language, Node, Parser, Query, QueryCursor, QueryError, Tree};

/// Contains the data neeeded to compute tags for code written in a
/// particular language.
pub struct TagsConfiguration {
    pub language: Language,
    pub query: Query,
    call_capture_index: Option<u32>,
    class_capture_index: Option<u32>,
    doc_capture_index: Option<u32>,
    function_capture_index: Option<u32>,
    locals_pattern_index: usize,
    module_capture_index: Option<u32>,
    name_capture_index: Option<u32>,
    doc_strip_regexes: Vec<Option<Regex>>,
}

pub struct TagsContext {
    parser: Parser,
    cursor: QueryCursor,
}

struct TagsIter<'a, I>
where
    I: Iterator<Item = tree_sitter::QueryMatch<'a>>,
{
    matches: I,
    _tree: Tree,
    source: &'a [u8],
    config: &'a TagsConfiguration,
    tag_queue: Vec<(Node<'a>, usize, Tag<'a>)>,
}

#[derive(Debug, Serialize, Clone)]
pub struct Loc {
    pub byte_range: ops::Range<usize>,
    pub span: ops::Range<Pos>,
}

#[derive(Debug, Serialize, Clone)]
pub struct Pos {
    pub line: i64,
    pub column: i64,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum TagKind {
    Function,
    Method,
    Class,
    Module,
    Call,
}

#[derive(Debug, Serialize, Clone)]
pub struct Tag<'a> {
    pub kind: TagKind,
    pub name: &'a str,
    pub docs: Option<String>,
    pub loc: Loc,
    pub line: &'a str,
}

#[derive(Debug)]
pub enum Error {
    Query(QueryError),
    Regex(regex::Error),
}

impl TagsConfiguration {
    pub fn new(language: Language, tags_query: &str, locals_query: &str) -> Result<Self, Error> {
        let query = Query::new(language, &format!("{}{}", tags_query, locals_query))?;

        let locals_query_offset = tags_query.len();
        let mut locals_pattern_index = 0;
        for i in 0..(query.pattern_count()) {
            let pattern_offset = query.start_byte_for_pattern(i);
            if pattern_offset < locals_query_offset {
                locals_pattern_index += 1;
            }
        }

        let mut call_capture_index = None;
        let mut class_capture_index = None;
        let mut doc_capture_index = None;
        let mut function_capture_index = None;
        let mut module_capture_index = None;
        let mut name_capture_index = None;
        for (i, name) in query.capture_names().iter().enumerate() {
            let index = match name.as_str() {
                "call" => &mut call_capture_index,
                "class" => &mut class_capture_index,
                "doc" => &mut doc_capture_index,
                "function" => &mut function_capture_index,
                "module" => &mut module_capture_index,
                "name" => &mut name_capture_index,
                _ => continue,
            };
            *index = Some(i as u32);
        }

        let doc_strip_regexes = (0..query.pattern_count())
            .map(|pattern_index| {
                let properties = query.property_settings(pattern_index);
                for property in properties {
                    if property.key.as_ref() == "strip"
                        && property.capture_id.map(|id| id as u32) == doc_capture_index
                    {
                        if let Some(value) = &property.value {
                            let regex = Regex::new(value.as_ref())?;
                            return Ok(Some(regex));
                        }
                    }
                }
                return Ok(None);
            })
            .collect::<Result<Vec<_>, Error>>()?;

        Ok(TagsConfiguration {
            language,
            query,
            locals_pattern_index,
            function_capture_index,
            class_capture_index,
            module_capture_index,
            doc_capture_index,
            call_capture_index,
            name_capture_index,
            doc_strip_regexes,
        })
    }
}

impl TagsContext {
    pub fn new() -> Self {
        TagsContext {
            parser: Parser::new(),
            cursor: QueryCursor::new(),
        }
    }

    // TODO: This should return an iterator rather than build up a vector
    pub fn generate_tags<'a>(
        &'a mut self,
        config: &'a TagsConfiguration,
        source: &'a [u8],
    ) -> impl Iterator<Item = Tag<'a>> + 'a {
        self.parser
            .set_language(config.language)
            .expect("Incompatible language");
        let tree = self
            .parser
            .parse(source, None)
            .expect("Parsing failed unexpectedly");

        // The `matches` iterator borrows the `Tree`, which prevents it from being moved.
        // But the tree is really just a pointer, so it's actually ok to move it.
        let tree_ref = unsafe { mem::transmute::<_, &'static Tree>(&tree) };
        let matches = self
            .cursor
            .matches(&config.query, tree_ref.root_node(), move |node| {
                &source[node.byte_range()]
            });
        TagsIter {
            matches,
            source,
            config,
            tag_queue: Vec::new(),
            _tree: tree,
        }
    }
}

impl<'a, I> Iterator for TagsIter<'a, I>
where
    I: Iterator<Item = tree_sitter::QueryMatch<'a>>,
{
    type Item = Tag<'a>;

    fn next(&mut self) -> Option<Tag<'a>> {
        loop {
            // If there is a queued tag for an earlier node in the syntax tree, then pop
            // it off of the queue and return it.
            if let Some(last_entry) = self.tag_queue.last() {
                if self.tag_queue.len() > 1
                    && self.tag_queue[0].0.end_byte() < last_entry.0.start_byte()
                {
                    return Some(self.tag_queue.remove(0).2);
                }
            }

            // If there is another match, then compute its tag and add it to the
            // tag queue.
            if let Some(mat) = self.matches.next() {
                let mut call_node = None;
                let mut doc_node = None;
                let mut class_node = None;
                let mut function_node = None;
                let mut module_node = None;
                let mut name_node = None;

                for capture in mat.captures {
                    let index = Some(capture.index);
                    let node = Some(capture.node);
                    if index == self.config.call_capture_index {
                        call_node = node;
                    } else if index == self.config.class_capture_index {
                        class_node = node;
                    } else if index == self.config.doc_capture_index {
                        doc_node = node;
                    } else if index == self.config.function_capture_index {
                        function_node = node;
                    } else if index == self.config.module_capture_index {
                        module_node = node;
                    } else if index == self.config.name_capture_index {
                        name_node = node;
                    }
                }

                let source = &self.source;
                let config = &self.config;
                let tag_from_node = |node: Node, kind: TagKind| -> Option<Tag> {
                    let name = str::from_utf8(&source[name_node?.byte_range()]).ok()?;

                    // Slice out the first line of the text corresponding to the node in question.
                    let mut line_range = node.byte_range();
                    line_range.end = line_range.end.min(line_range.start + 180);
                    let line = str::from_utf8(&source[line_range]).ok()?.lines().next()?;

                    let docs = doc_node
                        .and_then(|n| str::from_utf8(&source[n.byte_range()]).ok())
                        .map(|s| {
                            if let Some(regex) = &config.doc_strip_regexes[mat.pattern_index] {
                                regex.replace_all(s, "").to_string()
                            } else {
                                s.to_string()
                            }
                        });
                    Some(Tag {
                        name,
                        line,
                        loc: loc_for_node(node),
                        kind: kind,
                        docs,
                    })
                };

                for (tag_node, tag_kind) in [
                    (call_node, TagKind::Call),
                    (class_node, TagKind::Class),
                    (function_node, TagKind::Function),
                    (module_node, TagKind::Module),
                ]
                .iter()
                .cloned()
                {
                    if let Some(found) = tag_node {
                        // Only create one tag per node. The tag queue is sorted by node position
                        // to allow for fast lookup.
                        match self.tag_queue.binary_search_by_key(
                            &(found.end_byte(), found.start_byte(), found.id()),
                            |(node, _, _)| (node.end_byte(), node.start_byte(), node.id()),
                        ) {
                            Ok(i) => {
                                let (_, old_idx, tag) = &mut self.tag_queue[i];
                                if *old_idx > mat.pattern_index {
                                    if let Some(new_tag) = tag_from_node(found, tag_kind) {
                                        *tag = new_tag;
                                        *old_idx = mat.pattern_index;
                                    }
                                }
                            }
                            Err(i) => {
                                if let Some(tag) = tag_from_node(found, tag_kind) {
                                    self.tag_queue.insert(i, (found, mat.pattern_index, tag))
                                }
                            }
                        }
                        break;
                    }
                }
            }
            // If there are no more matches, then drain the queue.
            else if !self.tag_queue.is_empty() {
                return Some(self.tag_queue.remove(0).2);
            } else {
                return None;
            }
        }
    }
}

impl Serialize for TagKind {
    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            TagKind::Call => "Call",
            TagKind::Module => "Module",
            TagKind::Class => "Class",
            TagKind::Method => "Method",
            TagKind::Function => "Function",
        }
        .serialize(s)
    }
}

fn loc_for_node(node: Node) -> Loc {
    Loc {
        byte_range: node.byte_range(),
        span: node.start_position().into()..node.start_position().into(),
    }
}

impl From<tree_sitter::Point> for Pos {
    fn from(point: tree_sitter::Point) -> Self {
        return Pos {
            line: point.row as i64,
            column: point.column as i64,
        };
    }
}

impl From<regex::Error> for Error {
    fn from(error: regex::Error) -> Self {
        Error::Regex(error)
    }
}

impl From<QueryError> for Error {
    fn from(error: QueryError) -> Self {
        Error::Query(error)
    }
}
<|endoftext|>


<commit_before>use std::fmt::Debug;
use std::intrinsics::type_name;
use super::Matcher;

pub struct Nothing;
pub struct Something;

impl<T: Debug> Matcher<Option<T>> for Nothing {
    fn matches(&self, lhs: &Option<T>) -> bool {
        lhs.is_none()
    }

    fn fail_msg(&self, lhs: &Option<T>) -> String {
        format!("expected {:?} to be None", lhs)
    }

    fn negated_fail_msg(&self, lhs: &Option<T>) -> String {
        format!("expected {:?} to be Some<{}>", lhs, unsafe { type_name::<T>() })
    }
}

impl<T: Debug> Matcher<Option<T>> for Something {
    fn matches(&self, lhs: &Option<T>) -> bool {
        lhs.is_some()
    }

    fn fail_msg(&self, lhs: &Option<T>) -> String {
        format!("expected {:?} to be Some<{}>", lhs, unsafe { type_name::<T>() })
    }

    fn negated_fail_msg(&self, lhs: &Option<T>) -> String {
        format!("expected {:?} to be None", lhs)
    }
}

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

    #[test]
    fn test_none() {
        let n: Option<String> = None;
        expect(n).is(none());
    }

    #[test]
    #[should_panic(expected="expected Some(\"Hello\") to be None")]
    fn test_not_none_to_fail() {
        let n = Some("Hello");
        expect(n).is(none());
    }

    #[test]
    fn test_some() {
        let n = Some(32);
        expect(n).is(some());
    }

    #[test]
    #[should_panic(expected="expected None to be Some<i32>")]
    fn test_not_some_to_fail() {
        let n: Option<i32> = None;
        expect(n).is(some());
    }
}
<commit_msg>Refactor tests for negation methods<commit_after>use std::fmt::Debug;
use std::intrinsics::type_name;
use super::Matcher;

pub struct Nothing;
pub struct Something;

impl<T: Debug> Matcher<Option<T>> for Nothing {
    fn matches(&self, lhs: &Option<T>) -> bool {
        lhs.is_none()
    }

    fn fail_msg(&self, lhs: &Option<T>) -> String {
        format!("expected {:?} to be None", lhs)
    }

    fn negated_fail_msg(&self, lhs: &Option<T>) -> String {
        format!("expected {:?} to be Some<{}>", lhs, unsafe { type_name::<T>() })
    }
}

impl<T: Debug> Matcher<Option<T>> for Something {
    fn matches(&self, lhs: &Option<T>) -> bool {
        lhs.is_some()
    }

    fn fail_msg(&self, lhs: &Option<T>) -> String {
        format!("expected {:?} to be Some<{}>", lhs, unsafe { type_name::<T>() })
    }

    fn negated_fail_msg(&self, lhs: &Option<T>) -> String {
        format!("expected {:?} to be None", lhs)
    }
}

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

    #[test]
    fn test_none_matches() {
        let n: Option<String> = None;
        expect(n).is(none());
    }

    #[test]
    #[should_panic(expected="expected Some(\"Hello\") to be None")]
    fn test_none_fails_with_message() {
        let n = Some("Hello");
        expect(n).is(none());
    }

    #[test]
    #[should_panic(expected="expected None to be Some<i32>")]
    fn test_negated_none_fails_with_message() {
        let n: Option<i32> = None;
        expect(n).is_not(none());
    }

    #[test]
    fn test_some_matches() {
        let n = Some(32);
        expect(n).is(some());
    }

    #[test]
    #[should_panic(expected="expected None to be Some<i32>")]
    fn test_some_fails_with_message() {
        let n: Option<i32> = None;
        expect(n).is(some());
    }

    #[test]
    #[should_panic(expected="expected Some(32) to be None")]
    fn test_negated_some_fails_with_message() {
        let n = Some(32);
        expect(n).is_not(some());
    }
}
<|endoftext|>


<commit_before>//!
//! Generic addressing
//!

use std::{fmt, mem};
use num::PrimInt;
use addr::Address;

/// A trait for anything that has an address bus and can get/set data. The address (any type that
/// implements the `Address` trait) is 16 bit always. The data that can be get/set is 8 bit.
pub trait Addressable {
    /// Memory read: returns the data at the given address
    fn get<A: Address> (&self, addr: A) -> u8;

    /// Get a number in host platform byte order format from the given address. Note: Don't use
    /// this directly, better use `get_be` or `get_le` instead.
    fn get_number<A: Address, T: PrimInt> (&self, addr: A) -> T {
        let mut val: T = T::zero();
        let ptr = &mut val as *mut T as *mut u8;
        for (i, addr) in addr.successive().take(mem::size_of::<T>()).enumerate() {
            unsafe { *ptr.offset(i as isize) = self.get(addr); }
        }
        val
    }

    /// Get a number in big endian format from the given address
    fn get_be<A: Address, T: PrimInt> (&self, addr: A) -> T {
        T::from_be(self.get_number(addr))
    }

    /// Get a number in little endian format from the given address
    fn get_le<A: Address, T: PrimInt> (&self, addr: A) -> T {
        T::from_le(self.get_number(addr))
    }

    /// Memory write: set the data at the given address
    fn set<A: Address> (&mut self, addr: A, data: u8);

    /// Store a number in host platform byte order format to the given address. Note: Don't use
    /// this directly, better use `set_be` or `set_le` instead.
    fn set_number<A: Address, T: PrimInt> (&mut self, addr: A, val: T) {
        let ptr = &val as *const T as *const u8;
        for (i, addr) in addr.successive().take(mem::size_of::<T>()).enumerate() {
            unsafe { self.set(addr, *ptr.offset(i as isize)); }
        }
    }

    /// Store a number in big endian format to the given address
    fn set_be<A: Address, T: PrimInt> (&mut self, addr: A, val: T) {
        self.set_number(addr, T::to_be(val));
    }

    /// Store a number in little endian format to the given address
    fn set_le<A: Address, T: PrimInt> (&mut self, addr: A, val: T) {
        self.set_number(addr, T::to_le(val));
    }

    /// Copy data from another addressable source
    fn copy<A1: Address, A2: Address, M: Addressable> (&mut self, self_addr: A1, other: &M, other_addr: A2, size: usize) {
        for (dst_addr, src_addr) in self_addr.successive().zip(other_addr.successive()).take(size) {
            self.set(dst_addr, other.get(src_addr));
        }
    }

    /// Return an object for displaying a hexdump of the given address range
    fn hexdump<A: Address> (&self, addr1: A, addr2: A) -> HexDump<A, Self> {
        HexDump { mem: self, addr1: addr1, addr2: addr2 }
    }
}

/// Helper struct for displaying a hexdump of an address range
pub struct HexDump<'a, A, M: 'a + ?Sized> {
    mem: &'a M,
    addr1: A,
    addr2: A,
}

impl<'a, A: Address, M: Addressable> fmt::Display for HexDump<'a, A, M> {
    fn fmt (&self, f: &mut fmt::Formatter) -> fmt::Result {
        for addr in self.addr1.successive().upto(self.addr2) {
            try!(write!(f, "{:02X} ", self.mem.get(addr)));
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use addr::Masked;
    use mem::test::TestMemory;
    use super::*;

    #[test]
    fn get_byte () {
        let data = TestMemory;
        assert_eq!(data.get(0x0012), 0x12);
        assert_eq!(data.get(0x1234), 0x46);
    }

    #[test]
    fn get_big_endian_number () {
        let data = TestMemory;
        assert_eq!(      0x02_u8 , data.get_be(0x0002));
        assert_eq!(      0x54_u8 , data.get_be(0x0054));
        assert_eq!(    0x0203_u16, data.get_be(0x0002));
        assert_eq!(    0x5455_u16, data.get_be(0x0054));
        assert_eq!(0x02030405_u32, data.get_be(0x0002));
        assert_eq!(0x54555657_u32, data.get_be(0x0054));
    }

    #[test]
    fn get_signed_big_endian_number () {
        let data = TestMemory;
        assert_eq!(       0x54_i8 , data.get_be(0x0054));
        assert_eq!(      -0x5b_i8 , data.get_be(0x00a5));
        assert_eq!(     0x5455_i16, data.get_be(0x0054));
        assert_eq!(    -0x5a5a_i16, data.get_be(0x00a5));
        assert_eq!( 0x54555657_i32, data.get_be(0x0054));
        assert_eq!(-0x5a595858_i32, data.get_be(0x00a5));
    }

    #[test]
    fn get_masked_big_endian_number () {
        let data = TestMemory;
        assert_eq!(    0x1112_u16, data.get_be(Masked(0x12ff, 0xff00)));
        assert_eq!(0x10111213_u32, data.get_be(Masked(0x12fe, 0xff00)));
    }

    #[test]
    fn get_little_endian_number () {
        let data = TestMemory;
        assert_eq!(      0x02_u8 , data.get_le(0x0002));
        assert_eq!(      0x54_u8 , data.get_le(0x0054));
        assert_eq!(    0x0302_u16, data.get_le(0x0002));
        assert_eq!(    0x5554_u16, data.get_le(0x0054));
        assert_eq!(0x05040302_u32, data.get_le(0x0002));
        assert_eq!(0x57565554_u32, data.get_le(0x0054));
    }

    #[test]
    fn get_signed_little_endian_number () {
        let data = TestMemory;
        assert_eq!(       0x54_i8 , data.get_le(0x0054));
        assert_eq!(      -0x5b_i8 , data.get_le(0x00a5));
        assert_eq!(     0x5554_i16, data.get_le(0x0054));
        assert_eq!(    -0x595b_i16, data.get_le(0x00a5));
        assert_eq!( 0x57565554_i32, data.get_le(0x0054));
        assert_eq!(-0x5758595b_i32, data.get_le(0x00a5));
    }

    #[test]
    fn get_masked_little_endian_number () {
        let data = TestMemory;
        assert_eq!(    0x1211_u16, data.get_le(Masked(0x12ff, 0xff00)));
        assert_eq!(0x13121110_u32, data.get_le(Masked(0x12fe, 0xff00)));
    }

    #[test]
    fn set_byte () {
        let mut data = TestMemory;
        data.set(0x0012, 0x12);
        data.set(0x1234, 0x46);
    }

    #[test]
    fn set_big_endian_number () {
        let mut data = TestMemory;
        data.set_be(0x0002,       0x02_u8 );
        data.set_be(0x0054,       0x54_u8 );
        data.set_be(0x0002,     0x0203_u16);
        data.set_be(0x0054,     0x5455_u16);
        data.set_be(0x0002, 0x02030405_u32);
        data.set_be(0x0054, 0x54555657_u32);
    }

    #[test]
    fn set_signed_big_endian_number () {
        let mut data = TestMemory;
        data.set_be(0x0054,        0x54_i8 );
        data.set_be(0x00a5,       -0x5b_i8 );
        data.set_be(0x0054,      0x5455_i16);
        data.set_be(0x00a5,     -0x5a5a_i16);
        data.set_be(0x0054,  0x54555657_i32);
        data.set_be(0x00a5, -0x5a595858_i32);
    }

    #[test]
    fn set_masked_big_endian_number () {
        let mut data = TestMemory;
        data.set_be(Masked(0x12ff, 0xff00),     0x1112_u16);
        data.set_be(Masked(0x12fe, 0xff00), 0x10111213_u32);
    }

    #[test]
    fn set_little_endian_number () {
        let mut data = TestMemory;
        data.set_le(0x0002,       0x02_u8 );
        data.set_le(0x0054,       0x54_u8 );
        data.set_le(0x0002,     0x0302_u16);
        data.set_le(0x0054,     0x5554_u16);
        data.set_le(0x0002, 0x05040302_u32);
        data.set_le(0x0054, 0x57565554_u32);
    }

    #[test]
    fn set_signed_little_endian_number () {
        let mut data = TestMemory;
        data.set_le(0x0054,        0x54_i8 );
        data.set_le(0x00a5,       -0x5b_i8 );
        data.set_le(0x0054,      0x5554_i16);
        data.set_le(0x00a5,     -0x595b_i16);
        data.set_le(0x0054,  0x57565554_i32);
        data.set_le(0x00a5, -0x5758595b_i32);
    }

    #[test]
    fn set_masked_little_endian_number () {
        let mut data = TestMemory;
        data.set_le(Masked(0x12ff, 0xff00),     0x1211_u16);
        data.set_le(Masked(0x12fe, 0xff00), 0x13121110_u32);
    }

    #[test]
    fn copying_memory () {
        let data1 = TestMemory;
        let mut data2 = TestMemory;
        data2.copy(0x8000, &data1, 0x0080, 0x0080);
    }

    #[test]
    fn dumping_memory () {
        let data = TestMemory;
        assert_eq!(format!("{}", data.hexdump(0x0100, 0x0100)), "01 ");
        assert_eq!(format!("{}", data.hexdump(0x0100, 0x0101)), "01 02 ");
        assert_eq!(format!("{}", data.hexdump(0x0100, 0x0105)), "01 02 03 04 05 06 ");
    }
}
<commit_msg>Refactor addressable generic type store/retrieve to work with any copyable type<commit_after>//!
//! Generic addressing
//!

use std::{fmt, mem};
use num::PrimInt;
use addr::Address;

/// A trait for anything that has an address bus and can get/set data. The address (any type that
/// implements the `Address` trait) is 16 bit always. The data that can be get/set is 8 bit.
pub trait Addressable {
    /// Memory read: returns the data at the given address
    fn get<A: Address> (&self, addr: A) -> u8;

    /// Get a type from the given address by copying data bits. This gets a number in host platform
    /// byte order format. Since this unsafely transmutes to the target type, this method is
    /// marked unsafe. For integers, better use `get_be` or `get_le` instead.
    unsafe fn get_type<A: Address, T: Copy> (&self, addr: A) -> T {
        let mut val: T = mem::uninitialized();
        let ptr = &mut val as *mut T as *mut u8;
        for (i, addr) in addr.successive().take(mem::size_of::<T>()).enumerate() {
            *ptr.offset(i as isize) = self.get(addr);
        }
        val
    }

    /// Get a number in big endian format from the given address
    fn get_be<A: Address, T: PrimInt> (&self, addr: A) -> T {
        unsafe { T::from_be(self.get_type(addr)) }
    }

    /// Get a number in little endian format from the given address
    fn get_le<A: Address, T: PrimInt> (&self, addr: A) -> T {
        unsafe { T::from_le(self.get_type(addr)) }
    }

    /// Memory write: set the data at the given address
    fn set<A: Address> (&mut self, addr: A, data: u8);

    /// Store a type to the given address by copying data bits. This stores a type in host
    /// platform byte order format. Since this unsafely transmutes the stored type, this method
    /// is marked unsafe. For integers, better use `set_be` or `set_le` instead.
    unsafe fn set_type<A: Address, T: Copy> (&mut self, addr: A, val: T) {
        let ptr = &val as *const T as *const u8;
        for (i, addr) in addr.successive().take(mem::size_of::<T>()).enumerate() {
            self.set(addr, *ptr.offset(i as isize));
        }
    }

    /// Store a number in big endian format to the given address
    fn set_be<A: Address, T: PrimInt> (&mut self, addr: A, val: T) {
        unsafe { self.set_type(addr, T::to_be(val)); }
    }

    /// Store a number in little endian format to the given address
    fn set_le<A: Address, T: PrimInt> (&mut self, addr: A, val: T) {
        unsafe { self.set_type(addr, T::to_le(val)); }
    }

    /// Copy data from another addressable source
    fn copy<A1: Address, A2: Address, M: Addressable> (&mut self, self_addr: A1, other: &M, other_addr: A2, size: usize) {
        for (dst_addr, src_addr) in self_addr.successive().zip(other_addr.successive()).take(size) {
            self.set(dst_addr, other.get(src_addr));
        }
    }

    /// Return an object for displaying a hexdump of the given address range
    fn hexdump<A: Address> (&self, addr1: A, addr2: A) -> HexDump<A, Self> {
        HexDump { mem: self, addr1: addr1, addr2: addr2 }
    }
}

/// Helper struct for displaying a hexdump of an address range
pub struct HexDump<'a, A, M: 'a + ?Sized> {
    mem: &'a M,
    addr1: A,
    addr2: A,
}

impl<'a, A: Address, M: Addressable> fmt::Display for HexDump<'a, A, M> {
    fn fmt (&self, f: &mut fmt::Formatter) -> fmt::Result {
        for addr in self.addr1.successive().upto(self.addr2) {
            try!(write!(f, "{:02X} ", self.mem.get(addr)));
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use addr::Masked;
    use mem::test::TestMemory;
    use super::*;

    #[test]
    fn get_byte () {
        let data = TestMemory;
        assert_eq!(data.get(0x0012), 0x12);
        assert_eq!(data.get(0x1234), 0x46);
    }

    #[test]
    fn get_big_endian_number () {
        let data = TestMemory;
        assert_eq!(      0x02_u8 , data.get_be(0x0002));
        assert_eq!(      0x54_u8 , data.get_be(0x0054));
        assert_eq!(    0x0203_u16, data.get_be(0x0002));
        assert_eq!(    0x5455_u16, data.get_be(0x0054));
        assert_eq!(0x02030405_u32, data.get_be(0x0002));
        assert_eq!(0x54555657_u32, data.get_be(0x0054));
    }

    #[test]
    fn get_signed_big_endian_number () {
        let data = TestMemory;
        assert_eq!(       0x54_i8 , data.get_be(0x0054));
        assert_eq!(      -0x5b_i8 , data.get_be(0x00a5));
        assert_eq!(     0x5455_i16, data.get_be(0x0054));
        assert_eq!(    -0x5a5a_i16, data.get_be(0x00a5));
        assert_eq!( 0x54555657_i32, data.get_be(0x0054));
        assert_eq!(-0x5a595858_i32, data.get_be(0x00a5));
    }

    #[test]
    fn get_masked_big_endian_number () {
        let data = TestMemory;
        assert_eq!(    0x1112_u16, data.get_be(Masked(0x12ff, 0xff00)));
        assert_eq!(0x10111213_u32, data.get_be(Masked(0x12fe, 0xff00)));
    }

    #[test]
    fn get_little_endian_number () {
        let data = TestMemory;
        assert_eq!(      0x02_u8 , data.get_le(0x0002));
        assert_eq!(      0x54_u8 , data.get_le(0x0054));
        assert_eq!(    0x0302_u16, data.get_le(0x0002));
        assert_eq!(    0x5554_u16, data.get_le(0x0054));
        assert_eq!(0x05040302_u32, data.get_le(0x0002));
        assert_eq!(0x57565554_u32, data.get_le(0x0054));
    }

    #[test]
    fn get_signed_little_endian_number () {
        let data = TestMemory;
        assert_eq!(       0x54_i8 , data.get_le(0x0054));
        assert_eq!(      -0x5b_i8 , data.get_le(0x00a5));
        assert_eq!(     0x5554_i16, data.get_le(0x0054));
        assert_eq!(    -0x595b_i16, data.get_le(0x00a5));
        assert_eq!( 0x57565554_i32, data.get_le(0x0054));
        assert_eq!(-0x5758595b_i32, data.get_le(0x00a5));
    }

    #[test]
    fn get_masked_little_endian_number () {
        let data = TestMemory;
        assert_eq!(    0x1211_u16, data.get_le(Masked(0x12ff, 0xff00)));
        assert_eq!(0x13121110_u32, data.get_le(Masked(0x12fe, 0xff00)));
    }

    #[test]
    fn set_byte () {
        let mut data = TestMemory;
        data.set(0x0012, 0x12);
        data.set(0x1234, 0x46);
    }

    #[test]
    fn set_big_endian_number () {
        let mut data = TestMemory;
        data.set_be(0x0002,       0x02_u8 );
        data.set_be(0x0054,       0x54_u8 );
        data.set_be(0x0002,     0x0203_u16);
        data.set_be(0x0054,     0x5455_u16);
        data.set_be(0x0002, 0x02030405_u32);
        data.set_be(0x0054, 0x54555657_u32);
    }

    #[test]
    fn set_signed_big_endian_number () {
        let mut data = TestMemory;
        data.set_be(0x0054,        0x54_i8 );
        data.set_be(0x00a5,       -0x5b_i8 );
        data.set_be(0x0054,      0x5455_i16);
        data.set_be(0x00a5,     -0x5a5a_i16);
        data.set_be(0x0054,  0x54555657_i32);
        data.set_be(0x00a5, -0x5a595858_i32);
    }

    #[test]
    fn set_masked_big_endian_number () {
        let mut data = TestMemory;
        data.set_be(Masked(0x12ff, 0xff00),     0x1112_u16);
        data.set_be(Masked(0x12fe, 0xff00), 0x10111213_u32);
    }

    #[test]
    fn set_little_endian_number () {
        let mut data = TestMemory;
        data.set_le(0x0002,       0x02_u8 );
        data.set_le(0x0054,       0x54_u8 );
        data.set_le(0x0002,     0x0302_u16);
        data.set_le(0x0054,     0x5554_u16);
        data.set_le(0x0002, 0x05040302_u32);
        data.set_le(0x0054, 0x57565554_u32);
    }

    #[test]
    fn set_signed_little_endian_number () {
        let mut data = TestMemory;
        data.set_le(0x0054,        0x54_i8 );
        data.set_le(0x00a5,       -0x5b_i8 );
        data.set_le(0x0054,      0x5554_i16);
        data.set_le(0x00a5,     -0x595b_i16);
        data.set_le(0x0054,  0x57565554_i32);
        data.set_le(0x00a5, -0x5758595b_i32);
    }

    #[test]
    fn set_masked_little_endian_number () {
        let mut data = TestMemory;
        data.set_le(Masked(0x12ff, 0xff00),     0x1211_u16);
        data.set_le(Masked(0x12fe, 0xff00), 0x13121110_u32);
    }

    #[test]
    fn copying_memory () {
        let data1 = TestMemory;
        let mut data2 = TestMemory;
        data2.copy(0x8000, &data1, 0x0080, 0x0080);
    }

    #[test]
    fn dumping_memory () {
        let data = TestMemory;
        assert_eq!(format!("{}", data.hexdump(0x0100, 0x0100)), "01 ");
        assert_eq!(format!("{}", data.hexdump(0x0100, 0x0101)), "01 02 ");
        assert_eq!(format!("{}", data.hexdump(0x0100, 0x0105)), "01 02 03 04 05 06 ");
    }
}
<|endoftext|>


<commit_before>// Dogfood cannot run on Windows
#![cfg(not(windows))]
#![feature(once_cell)]

use std::lazy::SyncLazy;
use std::path::{Path, PathBuf};
use std::process::Command;

mod cargo;

static CLIPPY_PATH: SyncLazy<PathBuf> = SyncLazy::new(|| cargo::TARGET_LIB.join("cargo-clippy"));

#[test]
fn dogfood_clippy() {
    // run clippy on itself and fail the test if lint warnings are reported
    if cargo::is_rustc_test_suite() {
        return;
    }
    let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));

    let mut command = Command::new(&*CLIPPY_PATH);
    command
        .current_dir(root_dir)
        .env("CLIPPY_DOGFOOD", "1")
        .env("CARGO_INCREMENTAL", "0")
        .arg("clippy-preview")
        .arg("--all-targets")
        .arg("--all-features")
        .args(&["-p", "clippy_lints", "-p", "clippy_utils", "-p", "rustc_tools_util"])
        .arg("--")
        .args(&["-D", "clippy::all"])
        .args(&["-D", "clippy::pedantic"])
        .arg("-Cdebuginfo=0"); // disable debuginfo to generate less data in the target dir

    // internal lints only exist if we build with the internal-lints feature
    if cfg!(feature = "internal-lints") {
        command.args(&["-D", "clippy::internal"]);
    }

    let output = command.output().unwrap();

    println!("status: {}", output.status);
    println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
    println!("stderr: {}", String::from_utf8_lossy(&output.stderr));

    assert!(output.status.success());
}

#[test]
fn dogfood_subprojects() {
    fn test_no_deps_ignores_path_deps_in_workspaces() {
        fn clean(cwd: &Path, target_dir: &Path) {
            Command::new("cargo")
                .current_dir(cwd)
                .env("CARGO_TARGET_DIR", target_dir)
                .arg("clean")
                .args(&["-p", "subcrate"])
                .args(&["-p", "path_dep"])
                .output()
                .unwrap();
        }

        if cargo::is_rustc_test_suite() {
            return;
        }
        let root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        let target_dir = root.join("target").join("dogfood");
        let cwd = root.join("clippy_workspace_tests");

        // Make sure we start with a clean state
        clean(&cwd, &target_dir);

        // `path_dep` is a path dependency of `subcrate` that would trigger a denied lint.
        // Make sure that with the `--no-deps` argument Clippy does not run on `path_dep`.
        let output = Command::new(&*CLIPPY_PATH)
            .current_dir(&cwd)
            .env("CLIPPY_DOGFOOD", "1")
            .env("CARGO_INCREMENTAL", "0")
            .arg("clippy")
            .args(&["-p", "subcrate"])
            .arg("--")
            .arg("--no-deps")
            .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir
            .args(&["--cfg", r#"feature="primary_package_test""#])
            .output()
            .unwrap();
        println!("status: {}", output.status);
        println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
        println!("stderr: {}", String::from_utf8_lossy(&output.stderr));

        assert!(output.status.success());

        // Make sure we start with a clean state
        clean(&cwd, &target_dir);

        // Test that without the `--no-deps` argument, `path_dep` is linted.
        let output = Command::new(&*CLIPPY_PATH)
            .current_dir(&cwd)
            .env("CLIPPY_DOGFOOD", "1")
            .env("CARGO_INCREMENTAL", "0")
            .arg("clippy")
            .args(&["-p", "subcrate"])
            .arg("--")
            .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir
            .args(&["--cfg", r#"feature="primary_package_test""#])
            .output()
            .unwrap();
        println!("status: {}", output.status);
        println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
        println!("stderr: {}", String::from_utf8_lossy(&output.stderr));

        assert!(!output.status.success());
    }

    // run clippy on remaining subprojects and fail the test if lint warnings are reported
    if cargo::is_rustc_test_suite() {
        return;
    }
    let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));

    // NOTE: `path_dep` crate is omitted on purpose here
    for d in &[
        "clippy_workspace_tests",
        "clippy_workspace_tests/src",
        "clippy_workspace_tests/subcrate",
        "clippy_workspace_tests/subcrate/src",
        "clippy_dev",
        "rustc_tools_util",
    ] {
        let output = Command::new(&*CLIPPY_PATH)
            .current_dir(root_dir.join(d))
            .env("CLIPPY_DOGFOOD", "1")
            .env("CARGO_INCREMENTAL", "0")
            .arg("clippy")
            .arg("--")
            .args(&["-D", "clippy::all"])
            .args(&["-D", "clippy::pedantic"])
            .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir
            .output()
            .unwrap();
        println!("status: {}", output.status);
        println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
        println!("stderr: {}", String::from_utf8_lossy(&output.stderr));

        assert!(output.status.success());
    }

    // NOTE: Since tests run in parallel we can't run cargo commands on the same workspace at the
    // same time, so we test this immediately after the dogfood for workspaces.
    test_no_deps_ignores_path_deps_in_workspaces();
}
<commit_msg>Fix dogfood test<commit_after>// Dogfood cannot run on Windows
#![cfg(not(windows))]
#![feature(once_cell)]

use std::lazy::SyncLazy;
use std::path::{Path, PathBuf};
use std::process::Command;

mod cargo;

static CLIPPY_PATH: SyncLazy<PathBuf> = SyncLazy::new(|| cargo::TARGET_LIB.join("cargo-clippy"));

#[test]
fn dogfood_clippy() {
    // run clippy on itself and fail the test if lint warnings are reported
    if cargo::is_rustc_test_suite() {
        return;
    }
    let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));

    let mut command = Command::new(&*CLIPPY_PATH);
    command
        .current_dir(root_dir)
        .env("CLIPPY_DOGFOOD", "1")
        .env("CARGO_INCREMENTAL", "0")
        .arg("clippy")
        .arg("--all-targets")
        .arg("--all-features")
        .arg("--")
        .args(&["-D", "clippy::all"])
        .args(&["-D", "clippy::pedantic"])
        .arg("-Cdebuginfo=0"); // disable debuginfo to generate less data in the target dir

    // internal lints only exist if we build with the internal-lints feature
    if cfg!(feature = "internal-lints") {
        command.args(&["-D", "clippy::internal"]);
    }

    let output = command.output().unwrap();

    println!("status: {}", output.status);
    println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
    println!("stderr: {}", String::from_utf8_lossy(&output.stderr));

    assert!(output.status.success());
}

#[test]
fn dogfood_subprojects() {
    fn test_no_deps_ignores_path_deps_in_workspaces() {
        fn clean(cwd: &Path, target_dir: &Path) {
            Command::new("cargo")
                .current_dir(cwd)
                .env("CARGO_TARGET_DIR", target_dir)
                .arg("clean")
                .args(&["-p", "subcrate"])
                .args(&["-p", "path_dep"])
                .output()
                .unwrap();
        }

        if cargo::is_rustc_test_suite() {
            return;
        }
        let root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        let target_dir = root.join("target").join("dogfood");
        let cwd = root.join("clippy_workspace_tests");

        // Make sure we start with a clean state
        clean(&cwd, &target_dir);

        // `path_dep` is a path dependency of `subcrate` that would trigger a denied lint.
        // Make sure that with the `--no-deps` argument Clippy does not run on `path_dep`.
        let output = Command::new(&*CLIPPY_PATH)
            .current_dir(&cwd)
            .env("CLIPPY_DOGFOOD", "1")
            .env("CARGO_INCREMENTAL", "0")
            .arg("clippy")
            .args(&["-p", "subcrate"])
            .arg("--")
            .arg("--no-deps")
            .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir
            .args(&["--cfg", r#"feature="primary_package_test""#])
            .output()
            .unwrap();
        println!("status: {}", output.status);
        println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
        println!("stderr: {}", String::from_utf8_lossy(&output.stderr));

        assert!(output.status.success());

        // Make sure we start with a clean state
        clean(&cwd, &target_dir);

        // Test that without the `--no-deps` argument, `path_dep` is linted.
        let output = Command::new(&*CLIPPY_PATH)
            .current_dir(&cwd)
            .env("CLIPPY_DOGFOOD", "1")
            .env("CARGO_INCREMENTAL", "0")
            .arg("clippy")
            .args(&["-p", "subcrate"])
            .arg("--")
            .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir
            .args(&["--cfg", r#"feature="primary_package_test""#])
            .output()
            .unwrap();
        println!("status: {}", output.status);
        println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
        println!("stderr: {}", String::from_utf8_lossy(&output.stderr));

        assert!(!output.status.success());
    }

    // run clippy on remaining subprojects and fail the test if lint warnings are reported
    if cargo::is_rustc_test_suite() {
        return;
    }
    let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));

    // NOTE: `path_dep` crate is omitted on purpose here
    for d in &[
        "clippy_workspace_tests",
        "clippy_workspace_tests/src",
        "clippy_workspace_tests/subcrate",
        "clippy_workspace_tests/subcrate/src",
        "clippy_dev",
        "clippy_lints",
        "clippy_utils",
        "rustc_tools_util",
    ] {
        let mut command = Command::new(&*CLIPPY_PATH);
        command
            .current_dir(root_dir.join(d))
            .env("CLIPPY_DOGFOOD", "1")
            .env("CARGO_INCREMENTAL", "0")
            .arg("clippy")
            .arg("--all-targets")
            .arg("--all-features")
            .arg("--")
            .args(&["-D", "clippy::all"])
            .args(&["-D", "clippy::pedantic"])
            .arg("-Cdebuginfo=0"); // disable debuginfo to generate less data in the target dir

        // internal lints only exist if we build with the internal-lints feature
        if cfg!(feature = "internal-lints") {
            command.args(&["-D", "clippy::internal"]);
        }

        let output = command.output().unwrap();

        println!("status: {}", output.status);
        println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
        println!("stderr: {}", String::from_utf8_lossy(&output.stderr));

        assert!(output.status.success());
    }

    // NOTE: Since tests run in parallel we can't run cargo commands on the same workspace at the
    // same time, so we test this immediately after the dogfood for workspaces.
    test_no_deps_ignores_path_deps_in_workspaces();
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017-2018 Ryan Huang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

use model::{BitBoard, Color};

#[derive(Clone, Copy, PartialEq)]
struct FieldCoord {
    x: i8,
    y: i8,
    f: u8,
}

#[cfg_attr(rustfmt, rustfmt_skip)]
/// Generate the Laurentius starting position.
pub fn generate_laurentius() -> (BitBoard, BitBoard) {
    let mut white = 0;
    let mut black = 0;

    // (0, 0) is the only empty hex.
    // All other hexes have exactly two pieces on them in the starting position.
    let piece_locations = [
        (-2,  2, 0, 4),
        (-2,  1, 0, 3),
        (-2,  0, 3, 5),
        (-1,  2, 1, 4),
        (-1,  1, 0, 4),
        (-1,  0, 3, 5),
        (-1, -1, 2, 5),
        ( 0,  2, 1, 5),
        ( 0,  1, 1, 5),
        ( 0, -1, 2, 4),
        ( 0, -2, 2, 4),
        ( 1,  1, 2, 5),
        ( 1,  0, 0, 2),
        ( 1, -1, 1, 3),
        ( 1, -2, 1, 4),
        ( 2,  0, 0, 2),
        ( 2, -1, 0, 3),
        ( 2, -2, 1, 3),
    ];

    {
        let mut set_field = |coord: FieldCoord| match coord.color() {
            Color::White => white |= coord.to_bitboard(),
            Color::Black => black |= coord.to_bitboard(),
        };
        for &(x, y, f1, f2) in &piece_locations {
            set_field(FieldCoord::new(x, y, f1));
            set_field(FieldCoord::new(x, y, f2));
        }
    }
    (white, black)
}

pub fn generate_edge_neighbors(color: Color) -> [BitBoard; 57] {
    let mut neighbors = [0; 57];

    for index in 0..57 {
        let coord = FieldCoord::from_index(index, color);
        neighbors[index as usize] =
            fold_coords(&[coord.flip(), coord.shift_f(1), coord.shift_f(-1)]);
    }
    neighbors
}

pub fn generate_vertex_neighbors(color: Color) -> [BitBoard; 57] {
    let mut neighbors = [0; 57];

    for index in 0..57 {
        let coord = FieldCoord::from_index(index, color);
        neighbors[index as usize] = fold_coords(&[
            coord.flip().shift_f(1),
            coord.flip().shift_f(-1),
            coord.shift_f(1).flip(),
            coord.shift_f(-1).flip(),
            coord.shift_f(2),
            coord.shift_f(-2),
        ]);
    }
    neighbors
}

pub fn generate_hex_mask() -> [BitBoard; 19] {
    let mut masks = [0; 19];
    let mut mask = 0b111;

    for hex in 0..19 {
        masks[hex] = mask;
        mask <<= 3;
    }
    masks
}

pub fn generate_hex_field_neighbors(color: Color) -> [BitBoard; 19] {
    let mut neighbors = [0; 19];

    let field_neighbor = |hex, f| FieldCoord::from_hex_f(hex, f).flip();

    for hex in 0..19 {
        neighbors[hex as usize] = fold_coords(&match color {
            Color::White => [
                field_neighbor(hex, 0),
                field_neighbor(hex, 2),
                field_neighbor(hex, 4),
            ],
            Color::Black => [
                field_neighbor(hex, 1),
                field_neighbor(hex, 3),
                field_neighbor(hex, 5),
            ],
        });
    }
    neighbors
}

pub fn generate_removable_hex_combs() -> [BitBoard; 342] {
    let mut table = [0; 342];

    let bb_neighbor = |hex, f| FieldCoord::from_hex_f(hex, f).flip().to_bitboard();

    for hex in 0..19 {
        let neighbors = [
            bb_neighbor(hex, 0),
            bb_neighbor(hex, 1),
            bb_neighbor(hex, 2),
            bb_neighbor(hex, 3),
            bb_neighbor(hex, 4),
            bb_neighbor(hex, 5),
        ];

        // This bitwise or combines bitboards of different "colors." However, since each neighbor is
        // on a different hex (i.e. in a different block of three bits), bits can never overlap each
        // other. Also, this is compared against the extant hex bitboard, so color doesn't matter.
        let mut triple = neighbors[0] | neighbors[1] | neighbors[2];
        let mut double = neighbors[0] | neighbors[1];
        let mut single = neighbors[0];

        for f in 0..6 {
            let index = hex as usize * 18 + f;
            table[index] = triple;
            table[index + 6] = double;
            table[index + 12] = single;

            triple ^= neighbors[f] | neighbors[(f + 3) % 6];
            double ^= neighbors[f] | neighbors[(f + 2) % 6];
            single ^= neighbors[f] | neighbors[(f + 1) % 6];
        }
    }
    table
}

fn fold_coords(coords: &[FieldCoord]) -> BitBoard {
    coords.iter().fold(0, |acc, &c| acc | c.to_bitboard())
}

impl FieldCoord {
    fn new(x: i8, y: i8, f: u8) -> FieldCoord {
        FieldCoord { x, y, f }
    }
    fn is_valid_coord(&self) -> bool {
        (self.x + self.y).abs() <= 2 && self.x.abs() <= 2 && self.y.abs() <= 2 && self.f < 6
    }
    fn from_index(index: u8, color: Color) -> FieldCoord {
        assert!(index < 57);

        let f = 2 * (index % 3) + match color {
            Color::White => 1,
            Color::Black => 0,
        };

        Self::from_hex_f(index / 3, f)
    }
    fn from_hex_f(hex: u8, f: u8) -> FieldCoord {
        assert!(hex < 19);
        assert!(f < 6);

        let hex = hex as i8 + match hex {
            0...2 => 2,
            3...15 => 3,
            16...18 => 4,
            _ => unreachable!(),
        };
        Self::new(hex % 5 - 2, hex / 5 - 2, f as u8)
    }
    fn to_bitboard(&self) -> BitBoard {
        if !self.is_valid_coord() {
            return 0;
        }
        let hex = 5 * (self.y + 2) + self.x + 2;
        let hex = hex as u8 - match hex {
            2...4 => 2,
            6...18 => 3,
            20...22 => 4,
            _ => unreachable!(),
        };

        1 << (hex * 3 + self.f / 2)
    }
    fn shift_f(&self, n: i8) -> FieldCoord {
        assert!(-6 < n && n < 6);

        Self::new(self.x, self.y, (self.f + (n + 6) as u8) % 6)
    }
    /// Return the edge neighbor of this field that does not share its hex, i.e. "flip" this field
    /// over the boundary of its hex.
    fn flip(&self) -> FieldCoord {
        let (x, y) = match self.f {
            0 => (self.x, self.y + 1),
            1 => (self.x + 1, self.y),
            2 => (self.x + 1, self.y - 1),
            3 => (self.x, self.y - 1),
            4 => (self.x - 1, self.y),
            5 => (self.x - 1, self.y + 1),
            _ => unreachable!(),
        };

        Self::new(x, y, (self.f + 3) % 6)
    }
    fn color(&self) -> Color {
        if self.f % 2 == 1 {
            Color::White
        } else {
            Color::Black
        }
    }
}

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

    #[test]
    fn index_reflextivity() {
        for index in 0..57 {
            let white = FieldCoord::from_index(index as u8, Color::White);
            assert_eq!(index, white.to_bitboard().trailing_zeros());

            let black = FieldCoord::from_index(index as u8, Color::Black);
            assert_eq!(index, black.to_bitboard().trailing_zeros());
        }
    }
}
<commit_msg>Add hex starting position const, Laurentius use ColorMap<commit_after>/*
 * Copyright (C) 2017-2018 Ryan Huang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

use model::{BitBoard, Color, ColorMap};

#[derive(Clone, Copy, PartialEq)]
struct FieldCoord {
    x: i8,
    y: i8,
    f: u8,
}

pub const HEX_STARTING_POSITION: BitBoard = 0x1FF_FFFF_FFFF_FFFF;

#[cfg_attr(rustfmt, rustfmt_skip)]
/// Generate the Laurentius starting position.
pub fn generate_laurentius() -> ColorMap<BitBoard> {
    let mut white = 0;
    let mut black = 0;

    // (0, 0) is the only empty hex.
    // All other hexes have exactly two pieces on them in the starting position.
    let piece_locations = [
        (-2,  2, 0, 4),
        (-2,  1, 0, 3),
        (-2,  0, 3, 5),
        (-1,  2, 1, 4),
        (-1,  1, 0, 4),
        (-1,  0, 3, 5),
        (-1, -1, 2, 5),
        ( 0,  2, 1, 5),
        ( 0,  1, 1, 5),
        ( 0, -1, 2, 4),
        ( 0, -2, 2, 4),
        ( 1,  1, 2, 5),
        ( 1,  0, 0, 2),
        ( 1, -1, 1, 3),
        ( 1, -2, 1, 4),
        ( 2,  0, 0, 2),
        ( 2, -1, 0, 3),
        ( 2, -2, 1, 3),
    ];

    {
        let mut set_field = |coord: FieldCoord| match coord.color() {
            Color::White => white |= coord.to_bitboard(),
            Color::Black => black |= coord.to_bitboard(),
        };
        for &(x, y, f1, f2) in &piece_locations {
            set_field(FieldCoord::new(x, y, f1));
            set_field(FieldCoord::new(x, y, f2));
        }
    }
    ColorMap::new(white, black)
}

pub fn generate_edge_neighbors(color: Color) -> [BitBoard; 57] {
    let mut neighbors = [0; 57];

    for index in 0..57 {
        let coord = FieldCoord::from_index(index, color);
        neighbors[index as usize] =
            fold_coords(&[coord.flip(), coord.shift_f(1), coord.shift_f(-1)]);
    }
    neighbors
}

pub fn generate_vertex_neighbors(color: Color) -> [BitBoard; 57] {
    let mut neighbors = [0; 57];

    for index in 0..57 {
        let coord = FieldCoord::from_index(index, color);
        neighbors[index as usize] = fold_coords(&[
            coord.flip().shift_f(1),
            coord.flip().shift_f(-1),
            coord.shift_f(1).flip(),
            coord.shift_f(-1).flip(),
            coord.shift_f(2),
            coord.shift_f(-2),
        ]);
    }
    neighbors
}

pub fn generate_hex_mask() -> [BitBoard; 19] {
    let mut masks = [0; 19];
    let mut mask = 0b111;

    for hex in 0..19 {
        masks[hex] = mask;
        mask <<= 3;
    }
    masks
}

pub fn generate_hex_field_neighbors(color: Color) -> [BitBoard; 19] {
    let mut neighbors = [0; 19];

    let field_neighbor = |hex, f| FieldCoord::from_hex_f(hex, f).flip();

    for hex in 0..19 {
        neighbors[hex as usize] = fold_coords(&match color {
            Color::White => [
                field_neighbor(hex, 0),
                field_neighbor(hex, 2),
                field_neighbor(hex, 4),
            ],
            Color::Black => [
                field_neighbor(hex, 1),
                field_neighbor(hex, 3),
                field_neighbor(hex, 5),
            ],
        });
    }
    neighbors
}

pub fn generate_removable_hex_combs() -> [BitBoard; 342] {
    let mut table = [0; 342];

    let bb_neighbor = |hex, f| FieldCoord::from_hex_f(hex, f).flip().to_bitboard();

    for hex in 0..19 {
        let neighbors = [
            bb_neighbor(hex, 0),
            bb_neighbor(hex, 1),
            bb_neighbor(hex, 2),
            bb_neighbor(hex, 3),
            bb_neighbor(hex, 4),
            bb_neighbor(hex, 5),
        ];

        // This bitwise or combines bitboards of different "colors." However, since each neighbor is
        // on a different hex (i.e. in a different block of three bits), bits can never overlap each
        // other. Also, this is compared against the extant hex bitboard, so color doesn't matter.
        let mut triple = neighbors[0] | neighbors[1] | neighbors[2];
        let mut double = neighbors[0] | neighbors[1];
        let mut single = neighbors[0];

        for f in 0..6 {
            let index = hex as usize * 18 + f;
            table[index] = triple;
            table[index + 6] = double;
            table[index + 12] = single;

            triple ^= neighbors[f] | neighbors[(f + 3) % 6];
            double ^= neighbors[f] | neighbors[(f + 2) % 6];
            single ^= neighbors[f] | neighbors[(f + 1) % 6];
        }
    }
    table
}

fn fold_coords(coords: &[FieldCoord]) -> BitBoard {
    coords.iter().fold(0, |acc, &c| acc | c.to_bitboard())
}

impl FieldCoord {
    fn new(x: i8, y: i8, f: u8) -> FieldCoord {
        FieldCoord { x, y, f }
    }
    fn is_valid_coord(&self) -> bool {
        (self.x + self.y).abs() <= 2 && self.x.abs() <= 2 && self.y.abs() <= 2 && self.f < 6
    }
    fn from_index(index: u8, color: Color) -> FieldCoord {
        assert!(index < 57);

        let f = 2 * (index % 3) + match color {
            Color::White => 1,
            Color::Black => 0,
        };

        Self::from_hex_f(index / 3, f)
    }
    fn from_hex_f(hex: u8, f: u8) -> FieldCoord {
        assert!(hex < 19);
        assert!(f < 6);

        let hex = hex as i8 + match hex {
            0...2 => 2,
            3...15 => 3,
            16...18 => 4,
            _ => unreachable!(),
        };
        Self::new(hex % 5 - 2, hex / 5 - 2, f as u8)
    }
    fn to_bitboard(&self) -> BitBoard {
        if !self.is_valid_coord() {
            return 0;
        }
        let hex = 5 * (self.y + 2) + self.x + 2;
        let hex = hex as u8 - match hex {
            2...4 => 2,
            6...18 => 3,
            20...22 => 4,
            _ => unreachable!(),
        };

        1 << (hex * 3 + self.f / 2)
    }
    fn shift_f(&self, n: i8) -> FieldCoord {
        assert!(-6 < n && n < 6);

        Self::new(self.x, self.y, (self.f + (n + 6) as u8) % 6)
    }
    /// Return the edge neighbor of this field that does not share its hex, i.e. "flip" this field
    /// over the boundary of its hex.
    fn flip(&self) -> FieldCoord {
        let (x, y) = match self.f {
            0 => (self.x, self.y + 1),
            1 => (self.x + 1, self.y),
            2 => (self.x + 1, self.y - 1),
            3 => (self.x, self.y - 1),
            4 => (self.x - 1, self.y),
            5 => (self.x - 1, self.y + 1),
            _ => unreachable!(),
        };

        Self::new(x, y, (self.f + 3) % 6)
    }
    fn color(&self) -> Color {
        if self.f % 2 == 1 {
            Color::White
        } else {
            Color::Black
        }
    }
}

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

    #[test]
    fn index_reflextivity() {
        for index in 0..57 {
            let white = FieldCoord::from_index(index as u8, Color::White);
            assert_eq!(index, white.to_bitboard().trailing_zeros());

            let black = FieldCoord::from_index(index as u8, Color::Black);
            assert_eq!(index, black.to_bitboard().trailing_zeros());
        }
    }
}
<|endoftext|>


<commit_before>use super::{elf,Tag};
use core::mem;

#[derive(Debug)]
#[repr(packed)]
pub struct SectionsTag { tag: Tag
                        , pub n_sections: u32
                        , section_size: u32
                        , stringtable_idx: u32
                        , first_section: Section
                        }

impl SectionsTag {
    pub fn sections(&'static self) -> Sections {
        Sections { curr: &self.first_section
                 , remaining: self.n_sections - 1
                 , size: self.section_size
                 }
    }
}

/// Represents an ELF-64 section
#[derive(Debug)]
#[repr(C)]
pub struct Section { name: u32
                   , ty: elf::SectionType
                   , pub flags: u64
                   , pub address: u64
                   , offset: u64
                   , pub length: u64
                   , link: u32
                   , address_align: u32
                   , entry_length: u64
                   }

/// Iterator over ELF64 sections
#[derive(Clone,Debug)]
pub struct Sections { curr: &'static Section
                    , remaining: u32
                    , size: u32
                    }

impl Iterator for Sections {
    type Item = &'static Section;
    fn next(&mut self) -> Option<&'static Section> {
        if self.remaining == 0 {
            None
        } else {
            let current = self.curr;
            self.curr = unsafe {
                &*((ptr!(current) as u32 + self.size) as *const Section)
            };
            self.remaining -= 1;
            if current.ty == elf::SectionType::Null {
                self.next()
            } else {
                Some(current)
            }
        }
    }
}
<commit_msg>Fix the ELF section iterator advance Turns out the `ptr!()` macro is just Evil and Should Not Be Used<commit_after>use super::{elf,Tag};
use core::mem;

#[derive(Debug)]
#[repr(packed)]
pub struct SectionsTag { tag: Tag
                        , pub n_sections: u32
                        , section_size: u32
                        , stringtable_idx: u32
                        , first_section: Section
                        }

impl SectionsTag {
    pub fn sections(&'static self) -> Sections {
        Sections { curr: &self.first_section
                 , remaining: self.n_sections - 1
                 , size: self.section_size
                 }
    }
}

/// Represents an ELF-64 section
#[derive(Debug)]
#[repr(C)]
pub struct Section { name: u32
                   , ty: elf::SectionType
                   , pub flags: u64
                   , pub address: u64
                   , offset: u64
                   , pub length: u64
                   , link: u32
                   , address_align: u32
                   , entry_length: u64
                   }

/// Iterator over ELF64 sections
#[derive(Clone,Debug)]
pub struct Sections { curr: &'static Section
                    , remaining: u32
                    , size: u32
                    }

impl Iterator for Sections {
    type Item = &'static Section;
    fn next(&mut self) -> Option<&'static Section> {
        if self.remaining == 0 {
            None
        } else {
            let current = self.curr;
            self.curr = unsafe {
                &*(((self.curr as *const Section) as u32 + self.size)
                    as *const Section)
            };
            self.remaining -= 1;
            if current.ty == elf::SectionType::Null {
                self.next()
            } else {
                Some(current)
            }
        }
    }
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

use core::mem;
use cc3200_sys::socket::{Family, Protocol, SocketError, SocketType, RawSocket, sl_Socket,
                         sl_Close, sl_Connect, sl_Send, sl_Recv, SlSockAddrIn_t, SlSockAddr_t,
                         sl_Htonl, sl_Htons};
use simplelink::SimpleLink;
use smallhttp::traits::{Channel, ChannelError};

#[derive(Clone)]
pub struct SocketChannel {
    inner: RawSocket,
}

impl SocketChannel {
    pub fn new() -> Option<Self> {
        let socket = unsafe {
            sl_Socket(Family::AF_INET,
                      SocketType::SOCK_STREAM,
                      Protocol::IPPROTO_TCP)
        };
        if socket >= 0 {
            Some(SocketChannel { inner: socket })
        } else {
            None
        }

    }
}

impl Drop for SocketChannel {
    fn drop(&mut self) {
        unsafe {
            sl_Close(self.inner);
        }
    }
}

impl Channel for SocketChannel {
    // Opens a channel to the given host:port destination, with TLS support is needed.
    fn open(&mut self, host: &str, port: u16, tls: bool) -> Result<(), ChannelError> {
        // Convert the host name into a socket address.
        let addr = match SimpleLink::netapp_get_host_by_name(host) {
            Ok(addr) => addr,
            Err(_) => return Err(ChannelError::InvalidHostName),
        };

        // TODO: use getsockopt to set the TLS options if tls is true.
        if tls {
            return Err(ChannelError::TlsUnsupported);
        }

        let inaddr = SlSockAddrIn_t {
            sin_family: Family::AF_INET,
            sin_port: unsafe { sl_Htons(port) },
            sin_addr: unsafe { sl_Htonl(addr) },
            sin_zero: [0; 8],
        };
        let sockaddr =
            unsafe { ::core::intrinsics::transmute::<SlSockAddrIn_t, SlSockAddr_t>(inaddr) };
        let ret = unsafe {
            sl_Connect(self.inner,
                       &sockaddr as *const SlSockAddr_t,
                       mem::size_of::<SlSockAddrIn_t>() as i16)
        };

        if ret != SocketError::SOC_OK {
            debug!("Unable to connect to {:?} : {:?}", sockaddr, ret);
            Err(ChannelError::UnableToConnect)
        } else {
            Ok(())
        }
    }

    // Tries to send `len` bytes. Returns the number of bytes successfully sent,
    // or an error.
    fn send(&mut self, data: &[u8], len: usize) -> Result<usize, ChannelError> {
        assert!(len < i16::max_value() as usize);
        let ret = unsafe {
            sl_Send(self.inner, data.as_ptr(), len as i16, 0 /* flags */)
        };
        // Rustc doesn't seem to return a SizeOrError but just a i16...
        if ret >= 0 {
            Ok(ret as usize)
        } else {
            debug!("Unable to send: {:?}", ret);
            Err(ChannelError::SomethingWentWrong)
        }
    }

    // Tries to receive at most `max_len` bytes. Returns the number of bytes successfully received,
    // or an error.
    fn recv(&mut self, data: &mut [u8], max_len: usize) -> Result<usize, ChannelError> {
        assert!(max_len < i16::max_value() as usize);
        let ret = unsafe {
            sl_Recv(self.inner,
                    data.as_ptr() as *mut u8,
                    max_len as i16,
                    0 /* flags */)
        };
        // Rustc doesn't seem to return a SizeOrError but just a i16...
        if ret > 0 {
            Ok(ret as usize)
        } else if ret == 0 {
            Err(ChannelError::EndOfStream)
        } else {
            Err(ChannelError::SomethingWentWrong)
        }
    }
}
<commit_msg>Report hostname resolving error to the log. (#54)<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

use core::mem;
use cc3200_sys::socket::{Family, Protocol, SocketError, SocketType, RawSocket, sl_Socket,
                         sl_Close, sl_Connect, sl_Send, sl_Recv, SlSockAddrIn_t, SlSockAddr_t,
                         sl_Htonl, sl_Htons};
use simplelink::SimpleLink;
use smallhttp::traits::{Channel, ChannelError};

#[derive(Clone)]
pub struct SocketChannel {
    inner: RawSocket,
}

impl SocketChannel {
    pub fn new() -> Option<Self> {
        let socket = unsafe {
            sl_Socket(Family::AF_INET,
                      SocketType::SOCK_STREAM,
                      Protocol::IPPROTO_TCP)
        };
        if socket >= 0 {
            Some(SocketChannel { inner: socket })
        } else {
            None
        }

    }
}

impl Drop for SocketChannel {
    fn drop(&mut self) {
        unsafe {
            sl_Close(self.inner);
        }
    }
}

impl Channel for SocketChannel {
    // Opens a channel to the given host:port destination, with TLS support is needed.
    fn open(&mut self, host: &str, port: u16, tls: bool) -> Result<(), ChannelError> {
        // Convert the host name into a socket address.
        let addr = match SimpleLink::netapp_get_host_by_name(host) {
            Ok(addr) => addr,
            Err(err) => {
                error!("Unable to resolve {} : {}", host, err);
                return Err(ChannelError::InvalidHostName);
            }
        };

        // TODO: use getsockopt to set the TLS options if tls is true.
        if tls {
            return Err(ChannelError::TlsUnsupported);
        }

        let inaddr = SlSockAddrIn_t {
            sin_family: Family::AF_INET,
            sin_port: unsafe { sl_Htons(port) },
            sin_addr: unsafe { sl_Htonl(addr) },
            sin_zero: [0; 8],
        };
        let sockaddr =
            unsafe { ::core::intrinsics::transmute::<SlSockAddrIn_t, SlSockAddr_t>(inaddr) };
        let ret = unsafe {
            sl_Connect(self.inner,
                       &sockaddr as *const SlSockAddr_t,
                       mem::size_of::<SlSockAddrIn_t>() as i16)
        };

        if ret != SocketError::SOC_OK {
            debug!("Unable to connect to {:?} : {:?}", sockaddr, ret);
            Err(ChannelError::UnableToConnect)
        } else {
            Ok(())
        }
    }

    // Tries to send `len` bytes. Returns the number of bytes successfully sent,
    // or an error.
    fn send(&mut self, data: &[u8], len: usize) -> Result<usize, ChannelError> {
        assert!(len < i16::max_value() as usize);
        let ret = unsafe {
            sl_Send(self.inner, data.as_ptr(), len as i16, 0 /* flags */)
        };
        // Rustc doesn't seem to return a SizeOrError but just a i16...
        if ret >= 0 {
            Ok(ret as usize)
        } else {
            debug!("Unable to send: {:?}", ret);
            Err(ChannelError::SomethingWentWrong)
        }
    }

    // Tries to receive at most `max_len` bytes. Returns the number of bytes successfully received,
    // or an error.
    fn recv(&mut self, data: &mut [u8], max_len: usize) -> Result<usize, ChannelError> {
        assert!(max_len < i16::max_value() as usize);
        let ret = unsafe {
            sl_Recv(self.inner,
                    data.as_ptr() as *mut u8,
                    max_len as i16,
                    0 /* flags */)
        };
        // Rustc doesn't seem to return a SizeOrError but just a i16...
        if ret > 0 {
            Ok(ret as usize)
        } else if ret == 0 {
            Err(ChannelError::EndOfStream)
        } else {
            Err(ChannelError::SomethingWentWrong)
        }
    }
}
<|endoftext|>