<commit_before>//! Pull requests interface
use std::collections::HashMap;
use std::fmt;

use serde::{Deserialize, Serialize};
use url::form_urlencoded;

use crate::comments::Comments;
use crate::issues::{IssueAssignees, IssueLabels, Sort as IssueSort, State};
use crate::labels::Label;
use crate::pull_commits::PullCommits;
use crate::review_comments::ReviewComments;
use crate::review_requests::ReviewRequests;
use crate::users::User;
use crate::{Future, Github, SortDirection, Stream};

/// Sort directions for pull requests
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Sort {
    /// Sort by time created
    Created,
    /// Sort by last updated
    Updated,
    /// Sort by popularity
    Popularity,
    /// Sort by long running issues
    LongRunning,
}

impl fmt::Display for Sort {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Sort::Created => "created",
            Sort::Updated => "updated",
            Sort::Popularity => "popularity",
            Sort::LongRunning => "long-running",
        }
        .fmt(f)
    }
}

impl Default for Sort {
    fn default() -> Sort {
        Sort::Created
    }
}

/// A structure for accessing interfacing with a specific pull request
pub struct PullRequest {
    github: Github,
    owner: String,
    repo: String,
    number: u64,
}

impl PullRequest {
    #[doc(hidden)]
    pub fn new<O, R>(github: Github, owner: O, repo: R, number: u64) -> Self
    where
        O: Into<String>,
        R: Into<String>,
    {
        PullRequest {
            github,
            owner: owner.into(),
            repo: repo.into(),
            number,
        }
    }

    fn path(&self, more: &str) -> String {
        format!(
            "/repos/{}/{}/pulls/{}{}",
            self.owner, self.repo, self.number, more
        )
    }

    /// Request a pull requests information
    pub fn get(&self) -> Future<Pull> {
        self.github.get(&self.path(""))
    }

    /// Return a reference to labels operations available for this pull request
    pub fn labels(&self) -> IssueLabels {
        IssueLabels::new(
            self.github.clone(),
            self.owner.as_str(),
            self.repo.as_str(),
            self.number,
        )
    }

    /// Return a reference to assignee operations available for this pull request
    pub fn assignees(&self) -> IssueAssignees {
        IssueAssignees::new(
            self.github.clone(),
            self.owner.as_str(),
            self.repo.as_str(),
            self.number,
        )
    }

    /// short hand for editing state = open
    pub fn open(&self) -> Future<Pull> {
        self.edit(&PullEditOptions::builder().state("open").build())
    }

    /// shorthand for editing state = closed
    pub fn close(&self) -> Future<Pull> {
        self.edit(&PullEditOptions::builder().state("closed").build())
    }

    /// Edit a pull request
    pub fn edit(&self, pr: &PullEditOptions) -> Future<Pull> {
        self.github.patch::<Pull>(&self.path(""), json!(pr))
    }

    /// Returns a vector of file diffs associated with this pull
    pub fn files(&self) -> Future<Vec<FileDiff>> {
        self.github.get(&self.path("/files"))
    }

    /// returns issue comments interface
    pub fn comments(&self) -> Comments {
        Comments::new(
            self.github.clone(),
            self.owner.clone(),
            self.repo.clone(),
            self.number,
        )
    }

    /// returns review comments interface
    pub fn review_comments(&self) -> ReviewComments {
        ReviewComments::new(
            self.github.clone(),
            self.owner.clone(),
            self.repo.clone(),
            self.number,
        )
    }

    pub fn review_requests(&self) -> ReviewRequests {
        ReviewRequests::new(
            self.github.clone(),
            self.owner.clone(),
            self.repo.clone(),
            self.number,
        )
    }

    /// returns pull commits interface
    pub fn commits(&self) -> PullCommits {
        PullCommits::new(
            self.github.clone(),
            self.owner.clone(),
            self.repo.clone(),
            self.number,
        )
    }
}

/// A structure for interfacing with a repositories list of pull requests
pub struct PullRequests {
    github: Github,
    owner: String,
    repo: String,
}

impl PullRequests {
    #[doc(hidden)]
    pub fn new<O, R>(github: Github, owner: O, repo: R) -> Self
    where
        O: Into<String>,
        R: Into<String>,
    {
        PullRequests {
            github,
            owner: owner.into(),
            repo: repo.into(),
        }
    }

    fn path(&self, more: &str) -> String {
        format!("/repos/{}/{}/pulls{}", self.owner, self.repo, more)
    }

    /// Get a reference to a structure for interfacing with a specific pull request
    pub fn get(&self, number: u64) -> PullRequest {
        PullRequest::new(
            self.github.clone(),
            self.owner.as_str(),
            self.repo.as_str(),
            number,
        )
    }

    /// Create a new pull request
    pub fn create(&self, pr: &PullOptions) -> Future<Pull> {
        self.github.post(&self.path(""), json!(pr))
    }

    /// list pull requests
    pub fn list(&self, options: &PullListOptions) -> Future<Vec<Pull>> {
        let mut uri = vec![self.path("")];
        if let Some(query) = options.serialize() {
            uri.push(query);
        }
        self.github.get::<Vec<Pull>>(&uri.join("?"))
    }

    /// provides a stream over all pages of pull requests
    pub fn iter(&self, options: &PullListOptions) -> Stream<Pull> {
        let mut uri = vec![self.path("")];
        if let Some(query) = options.serialize() {
            uri.push(query);
        }
        self.github.get_stream(&uri.join("?"))
    }
}

// representations (todo: replace with derive_builder)

/// representation of a github pull request
#[derive(Debug, Deserialize)]
pub struct Pull {
    pub id: u64,
    pub url: String,
    pub html_url: String,
    pub diff_url: String,
    pub patch_url: String,
    pub issue_url: String,
    pub commits_url: String,
    pub review_comments_url: String,
    pub review_comment_url: String,
    pub comments_url: String,
    pub statuses_url: String,
    pub number: u64,
    pub state: String,
    pub title: String,
    pub body: Option<String>,
    pub created_at: String,
    pub updated_at: String,
    pub closed_at: Option<String>,
    pub merged_at: Option<String>,
    pub head: Commit,
    pub base: Commit,
    // links
    pub user: User,
    pub assignee: Option<User>,
    pub assignees: Vec<User>,
    pub merge_commit_sha: Option<String>,
    pub merged: bool,
    pub mergeable: Option<bool>,
    pub merged_by: Option<User>,
    pub comments: Option<u64>,
    pub commits: Option<u64>,
    pub additions: Option<u64>,
    pub deletions: Option<u64>,
    pub changed_files: Option<u64>,
    pub labels: Vec<Label>,
}

#[derive(Debug, Deserialize)]
pub struct Commit {
    pub label: String,
    #[serde(rename = "ref")]
    pub commit_ref: String,
    pub sha: String,
    pub user: User, //    pub repo: Option<Repo>,
}

#[derive(Default)]
pub struct PullEditOptionsBuilder(PullEditOptions);

impl PullEditOptionsBuilder {
    /// set the title of the pull
    pub fn title<T>(&mut self, title: T) -> &mut Self
    where
        T: Into<String>,
    {
        self.0.title = Some(title.into());
        self
    }

    /// set the body of the pull
    pub fn body<B>(&mut self, body: B) -> &mut Self
    where
        B: Into<String>,
    {
        self.0.body = Some(body.into());
        self
    }

    /// set the state of the pull
    pub fn state<S>(&mut self, state: S) -> &mut Self
    where
        S: Into<String>,
    {
        self.0.state = Some(state.into());
        self
    }

    /// create a new set of pull edit options
    pub fn build(&self) -> PullEditOptions {
        PullEditOptions {
            title: self.0.title.clone(),
            body: self.0.body.clone(),
            state: self.0.state.clone(),
        }
    }
}

#[derive(Debug, Default, Serialize)]
pub struct PullEditOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    title: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    body: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    state: Option<String>,
}

impl PullEditOptions {
    // todo represent state as enum
    pub fn new<T, B, S>(title: Option<T>, body: Option<B>, state: Option<S>) -> PullEditOptions
    where
        T: Into<String>,
        B: Into<String>,
        S: Into<String>,
    {
        PullEditOptions {
            title: title.map(|t| t.into()),
            body: body.map(|b| b.into()),
            state: state.map(|s| s.into()),
        }
    }
    pub fn builder() -> PullEditOptionsBuilder {
        PullEditOptionsBuilder::default()
    }
}

#[derive(Debug, Serialize)]
pub struct PullOptions {
    pub title: String,
    pub head: String,
    pub base: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub body: Option<String>,
}

impl PullOptions {
    pub fn new<T, H, BS, B>(title: T, head: H, base: BS, body: Option<B>) -> PullOptions
    where
        T: Into<String>,
        H: Into<String>,
        BS: Into<String>,
        B: Into<String>,
    {
        PullOptions {
            title: title.into(),
            head: head.into(),
            base: base.into(),
            body: body.map(|b| b.into()),
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct FileDiff {
    /// sha from GitHub may be null when file mode changed without contents changing
    pub sha: Option<String>,
    pub filename: String,
    pub status: String,
    pub additions: u64,
    pub deletions: u64,
    pub changes: u64,
    pub blob_url: String,
    pub raw_url: String,
    pub contents_url: String,
    /// patch is typically None for binary files
    pub patch: Option<String>,
}

#[derive(Default)]
pub struct PullListOptions {
    params: HashMap<&'static str, String>,
}

impl PullListOptions {
    pub fn builder() -> PullListOptionsBuilder {
        PullListOptionsBuilder::default()
    }

    /// serialize options as a string. returns None if no options are defined
    pub fn serialize(&self) -> Option<String> {
        if self.params.is_empty() {
            None
        } else {
            let encoded: String = form_urlencoded::Serializer::new(String::new())
                .extend_pairs(&self.params)
                .finish();
            Some(encoded)
        }
    }
}

#[derive(Default)]
pub struct PullListOptionsBuilder(PullListOptions);

impl PullListOptionsBuilder {
    pub fn state(&mut self, state: State) -> &mut Self {
        self.0.params.insert("state", state.to_string());
        self
    }

    pub fn sort(&mut self, sort: IssueSort) -> &mut Self {
        self.0.params.insert("sort", sort.to_string());
        self
    }

    pub fn direction(&mut self, direction: SortDirection) -> &mut Self {
        self.0.params.insert("direction", direction.to_string());
        self
    }

    pub fn build(&self) -> PullListOptions {
        PullListOptions {
            params: self.0.params.clone(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use serde::ser::Serialize;
    fn test_encoding<E: Serialize>(tests: Vec<(E, &str)>) {
        for test in tests {
            let (k, v) = test;
            assert_eq!(serde_json::to_string(&k).unwrap(), v);
        }
    }

    #[test]
    fn pull_list_reqs() {
        fn test_serialize(tests: Vec<(PullListOptions, Option<String>)>) {
            for test in tests {
                let (k, v) = test;
                assert_eq!(k.serialize(), v);
            }
        }
        let tests = vec![
            (PullListOptions::builder().build(), None),
            (
                PullListOptions::builder().state(State::Closed).build(),
                Some("state=closed".to_owned()),
            ),
        ];
        test_serialize(tests)
    }

    #[test]
    fn pullreq_edits() {
        let tests = vec![
            (
                PullEditOptions::builder().title("test").build(),
                r#"{"title":"test"}"#,
            ),
            (
                PullEditOptions::builder()
                    .title("test")
                    .body("desc")
                    .build(),
                r#"{"title":"test","body":"desc"}"#,
            ),
            (
                PullEditOptions::builder().state("closed").build(),
                r#"{"state":"closed"}"#,
            ),
        ];
        test_encoding(tests)
    }

    #[test]
    fn default_sort() {
        let default: Sort = Default::default();
        assert_eq!(default, Sort::Created)
    }
}
<commit_msg>Add PullRequest::iter_files<commit_after>//! Pull requests interface
use std::collections::HashMap;
use std::fmt;

use serde::{Deserialize, Serialize};
use url::form_urlencoded;

use crate::comments::Comments;
use crate::issues::{IssueAssignees, IssueLabels, Sort as IssueSort, State};
use crate::labels::Label;
use crate::pull_commits::PullCommits;
use crate::review_comments::ReviewComments;
use crate::review_requests::ReviewRequests;
use crate::users::User;
use crate::{Future, Github, SortDirection, Stream};

/// Sort directions for pull requests
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Sort {
    /// Sort by time created
    Created,
    /// Sort by last updated
    Updated,
    /// Sort by popularity
    Popularity,
    /// Sort by long running issues
    LongRunning,
}

impl fmt::Display for Sort {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Sort::Created => "created",
            Sort::Updated => "updated",
            Sort::Popularity => "popularity",
            Sort::LongRunning => "long-running",
        }
        .fmt(f)
    }
}

impl Default for Sort {
    fn default() -> Sort {
        Sort::Created
    }
}

/// A structure for accessing interfacing with a specific pull request
pub struct PullRequest {
    github: Github,
    owner: String,
    repo: String,
    number: u64,
}

impl PullRequest {
    #[doc(hidden)]
    pub fn new<O, R>(github: Github, owner: O, repo: R, number: u64) -> Self
    where
        O: Into<String>,
        R: Into<String>,
    {
        PullRequest {
            github,
            owner: owner.into(),
            repo: repo.into(),
            number,
        }
    }

    fn path(&self, more: &str) -> String {
        format!(
            "/repos/{}/{}/pulls/{}{}",
            self.owner, self.repo, self.number, more
        )
    }

    /// Request a pull requests information
    pub fn get(&self) -> Future<Pull> {
        self.github.get(&self.path(""))
    }

    /// Return a reference to labels operations available for this pull request
    pub fn labels(&self) -> IssueLabels {
        IssueLabels::new(
            self.github.clone(),
            self.owner.as_str(),
            self.repo.as_str(),
            self.number,
        )
    }

    /// Return a reference to assignee operations available for this pull request
    pub fn assignees(&self) -> IssueAssignees {
        IssueAssignees::new(
            self.github.clone(),
            self.owner.as_str(),
            self.repo.as_str(),
            self.number,
        )
    }

    /// short hand for editing state = open
    pub fn open(&self) -> Future<Pull> {
        self.edit(&PullEditOptions::builder().state("open").build())
    }

    /// shorthand for editing state = closed
    pub fn close(&self) -> Future<Pull> {
        self.edit(&PullEditOptions::builder().state("closed").build())
    }

    /// Edit a pull request
    pub fn edit(&self, pr: &PullEditOptions) -> Future<Pull> {
        self.github.patch::<Pull>(&self.path(""), json!(pr))
    }

    /// Returns a vector of file diffs associated with this pull request
    #[deprecated(
        note = "This only returns the first page of results; up to 30 entries. Use `iter_files` instead"
    )]
    pub fn files(&self) -> Future<Vec<FileDiff>> {
        self.github.get(&self.path("/files"))
    }

    /// Returns a stream of file diffs associated with this pull request
    pub fn iter_files(&self) -> Stream<FileDiff> {
        self.github.get_stream(&self.path("/files"))
    }

    /// returns issue comments interface
    pub fn comments(&self) -> Comments {
        Comments::new(
            self.github.clone(),
            self.owner.clone(),
            self.repo.clone(),
            self.number,
        )
    }

    /// returns review comments interface
    pub fn review_comments(&self) -> ReviewComments {
        ReviewComments::new(
            self.github.clone(),
            self.owner.clone(),
            self.repo.clone(),
            self.number,
        )
    }

    pub fn review_requests(&self) -> ReviewRequests {
        ReviewRequests::new(
            self.github.clone(),
            self.owner.clone(),
            self.repo.clone(),
            self.number,
        )
    }

    /// returns pull commits interface
    pub fn commits(&self) -> PullCommits {
        PullCommits::new(
            self.github.clone(),
            self.owner.clone(),
            self.repo.clone(),
            self.number,
        )
    }
}

/// A structure for interfacing with a repositories list of pull requests
pub struct PullRequests {
    github: Github,
    owner: String,
    repo: String,
}

impl PullRequests {
    #[doc(hidden)]
    pub fn new<O, R>(github: Github, owner: O, repo: R) -> Self
    where
        O: Into<String>,
        R: Into<String>,
    {
        PullRequests {
            github,
            owner: owner.into(),
            repo: repo.into(),
        }
    }

    fn path(&self, more: &str) -> String {
        format!("/repos/{}/{}/pulls{}", self.owner, self.repo, more)
    }

    /// Get a reference to a structure for interfacing with a specific pull request
    pub fn get(&self, number: u64) -> PullRequest {
        PullRequest::new(
            self.github.clone(),
            self.owner.as_str(),
            self.repo.as_str(),
            number,
        )
    }

    /// Create a new pull request
    pub fn create(&self, pr: &PullOptions) -> Future<Pull> {
        self.github.post(&self.path(""), json!(pr))
    }

    /// list pull requests
    pub fn list(&self, options: &PullListOptions) -> Future<Vec<Pull>> {
        let mut uri = vec![self.path("")];
        if let Some(query) = options.serialize() {
            uri.push(query);
        }
        self.github.get::<Vec<Pull>>(&uri.join("?"))
    }

    /// provides a stream over all pages of pull requests
    pub fn iter(&self, options: &PullListOptions) -> Stream<Pull> {
        let mut uri = vec![self.path("")];
        if let Some(query) = options.serialize() {
            uri.push(query);
        }
        self.github.get_stream(&uri.join("?"))
    }
}

// representations (todo: replace with derive_builder)

/// representation of a github pull request
#[derive(Debug, Deserialize)]
pub struct Pull {
    pub id: u64,
    pub url: String,
    pub html_url: String,
    pub diff_url: String,
    pub patch_url: String,
    pub issue_url: String,
    pub commits_url: String,
    pub review_comments_url: String,
    pub review_comment_url: String,
    pub comments_url: String,
    pub statuses_url: String,
    pub number: u64,
    pub state: String,
    pub title: String,
    pub body: Option<String>,
    pub created_at: String,
    pub updated_at: String,
    pub closed_at: Option<String>,
    pub merged_at: Option<String>,
    pub head: Commit,
    pub base: Commit,
    // links
    pub user: User,
    pub assignee: Option<User>,
    pub assignees: Vec<User>,
    pub merge_commit_sha: Option<String>,
    pub merged: bool,
    pub mergeable: Option<bool>,
    pub merged_by: Option<User>,
    pub comments: Option<u64>,
    pub commits: Option<u64>,
    pub additions: Option<u64>,
    pub deletions: Option<u64>,
    pub changed_files: Option<u64>,
    pub labels: Vec<Label>,
}

#[derive(Debug, Deserialize)]
pub struct Commit {
    pub label: String,
    #[serde(rename = "ref")]
    pub commit_ref: String,
    pub sha: String,
    pub user: User, //    pub repo: Option<Repo>,
}

#[derive(Default)]
pub struct PullEditOptionsBuilder(PullEditOptions);

impl PullEditOptionsBuilder {
    /// set the title of the pull
    pub fn title<T>(&mut self, title: T) -> &mut Self
    where
        T: Into<String>,
    {
        self.0.title = Some(title.into());
        self
    }

    /// set the body of the pull
    pub fn body<B>(&mut self, body: B) -> &mut Self
    where
        B: Into<String>,
    {
        self.0.body = Some(body.into());
        self
    }

    /// set the state of the pull
    pub fn state<S>(&mut self, state: S) -> &mut Self
    where
        S: Into<String>,
    {
        self.0.state = Some(state.into());
        self
    }

    /// create a new set of pull edit options
    pub fn build(&self) -> PullEditOptions {
        PullEditOptions {
            title: self.0.title.clone(),
            body: self.0.body.clone(),
            state: self.0.state.clone(),
        }
    }
}

#[derive(Debug, Default, Serialize)]
pub struct PullEditOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    title: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    body: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    state: Option<String>,
}

impl PullEditOptions {
    // todo represent state as enum
    pub fn new<T, B, S>(title: Option<T>, body: Option<B>, state: Option<S>) -> PullEditOptions
    where
        T: Into<String>,
        B: Into<String>,
        S: Into<String>,
    {
        PullEditOptions {
            title: title.map(|t| t.into()),
            body: body.map(|b| b.into()),
            state: state.map(|s| s.into()),
        }
    }
    pub fn builder() -> PullEditOptionsBuilder {
        PullEditOptionsBuilder::default()
    }
}

#[derive(Debug, Serialize)]
pub struct PullOptions {
    pub title: String,
    pub head: String,
    pub base: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub body: Option<String>,
}

impl PullOptions {
    pub fn new<T, H, BS, B>(title: T, head: H, base: BS, body: Option<B>) -> PullOptions
    where
        T: Into<String>,
        H: Into<String>,
        BS: Into<String>,
        B: Into<String>,
    {
        PullOptions {
            title: title.into(),
            head: head.into(),
            base: base.into(),
            body: body.map(|b| b.into()),
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct FileDiff {
    /// sha from GitHub may be null when file mode changed without contents changing
    pub sha: Option<String>,
    pub filename: String,
    pub status: String,
    pub additions: u64,
    pub deletions: u64,
    pub changes: u64,
    pub blob_url: String,
    pub raw_url: String,
    pub contents_url: String,
    /// patch is typically None for binary files
    pub patch: Option<String>,
}

#[derive(Default)]
pub struct PullListOptions {
    params: HashMap<&'static str, String>,
}

impl PullListOptions {
    pub fn builder() -> PullListOptionsBuilder {
        PullListOptionsBuilder::default()
    }

    /// serialize options as a string. returns None if no options are defined
    pub fn serialize(&self) -> Option<String> {
        if self.params.is_empty() {
            None
        } else {
            let encoded: String = form_urlencoded::Serializer::new(String::new())
                .extend_pairs(&self.params)
                .finish();
            Some(encoded)
        }
    }
}

#[derive(Default)]
pub struct PullListOptionsBuilder(PullListOptions);

impl PullListOptionsBuilder {
    pub fn state(&mut self, state: State) -> &mut Self {
        self.0.params.insert("state", state.to_string());
        self
    }

    pub fn sort(&mut self, sort: IssueSort) -> &mut Self {
        self.0.params.insert("sort", sort.to_string());
        self
    }

    pub fn direction(&mut self, direction: SortDirection) -> &mut Self {
        self.0.params.insert("direction", direction.to_string());
        self
    }

    pub fn build(&self) -> PullListOptions {
        PullListOptions {
            params: self.0.params.clone(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use serde::ser::Serialize;
    fn test_encoding<E: Serialize>(tests: Vec<(E, &str)>) {
        for test in tests {
            let (k, v) = test;
            assert_eq!(serde_json::to_string(&k).unwrap(), v);
        }
    }

    #[test]
    fn pull_list_reqs() {
        fn test_serialize(tests: Vec<(PullListOptions, Option<String>)>) {
            for test in tests {
                let (k, v) = test;
                assert_eq!(k.serialize(), v);
            }
        }
        let tests = vec![
            (PullListOptions::builder().build(), None),
            (
                PullListOptions::builder().state(State::Closed).build(),
                Some("state=closed".to_owned()),
            ),
        ];
        test_serialize(tests)
    }

    #[test]
    fn pullreq_edits() {
        let tests = vec![
            (
                PullEditOptions::builder().title("test").build(),
                r#"{"title":"test"}"#,
            ),
            (
                PullEditOptions::builder()
                    .title("test")
                    .body("desc")
                    .build(),
                r#"{"title":"test","body":"desc"}"#,
            ),
            (
                PullEditOptions::builder().state("closed").build(),
                r#"{"state":"closed"}"#,
            ),
        ];
        test_encoding(tests)
    }

    #[test]
    fn default_sort() {
        let default: Sort = Default::default();
        assert_eq!(default, Sort::Created)
    }
}
<|endoftext|>


<commit_before>#![warn(clippy::single_match_else)]

enum ExprNode {
    ExprAddrOf,
    Butterflies,
    Unicorns,
}

static NODE: ExprNode = ExprNode::Unicorns;

fn unwrap_addr() -> Option<&'static ExprNode> {
    match ExprNode::Butterflies {
        ExprNode::ExprAddrOf => Some(&NODE),
        _ => {
            let x = 5;
            None
        },
    }
}

fn main() {}
<commit_msg>Added test for single_match_else in macro<commit_after>#![warn(clippy::single_match_else)]

enum ExprNode {
    ExprAddrOf,
    Butterflies,
    Unicorns,
}

static NODE: ExprNode = ExprNode::Unicorns;

fn unwrap_addr() -> Option<&'static ExprNode> {
    match ExprNode::Butterflies {
        ExprNode::ExprAddrOf => Some(&NODE),
        _ => {
            let x = 5;
            None
        },
    }
}

macro_rules! unwrap_addr {
    ($expression:expr) => {
        match $expression {
            ExprNode::ExprAddrOf => Some(&NODE),
            _ => {
                let x = 5;
                None
            },
        }
    };
}

fn main() {
    unwrap_addr!(ExprNode::Unicorns);
}
<|endoftext|>


<commit_before>// does not test any rustfixable lints

#![warn(clippy::clone_on_ref_ptr)]
#![allow(unused, noop_method_call, clippy::redundant_clone, clippy::unnecessary_wraps)]

use std::cell::RefCell;
use std::rc::{self, Rc};
use std::sync::{self, Arc};

trait SomeTrait {}
struct SomeImpl;
impl SomeTrait for SomeImpl {}

fn main() {}

fn clone_on_ref_ptr() {
    let rc = Rc::new(true);
    let arc = Arc::new(true);

    let rcweak = Rc::downgrade(&rc);
    let arc_weak = Arc::downgrade(&arc);

    rc.clone();
    Rc::clone(&rc);

    arc.clone();
    Arc::clone(&arc);

    rcweak.clone();
    rc::Weak::clone(&rcweak);

    arc_weak.clone();
    sync::Weak::clone(&arc_weak);

    let x = Arc::new(SomeImpl);
    let _: Arc<dyn SomeTrait> = x.clone();
}

fn clone_on_copy_generic<T: Copy>(t: T) {
    t.clone();

    Some(t).clone();
}

fn clone_on_double_ref() {
    let x = vec![1];
    let y = &&x;
    let z: &Vec<_> = y.clone();

    println!("{:p} {:p}", *y, z);
}

mod many_derefs {
    struct A;
    struct B;
    struct C;
    struct D;
    #[derive(Copy, Clone)]
    struct E;

    macro_rules! impl_deref {
        ($src:ident, $dst:ident) => {
            impl std::ops::Deref for $src {
                type Target = $dst;
                fn deref(&self) -> &Self::Target {
                    &$dst
                }
            }
        };
    }

    impl_deref!(A, B);
    impl_deref!(B, C);
    impl_deref!(C, D);
    impl std::ops::Deref for D {
        type Target = &'static E;
        fn deref(&self) -> &Self::Target {
            &&E
        }
    }

    fn go1() {
        let a = A;
        let _: E = a.clone();
        let _: E = *****a;
    }

    fn check(mut encoded: &[u8]) {
        let _ = &mut encoded.clone();
        let _ = &encoded.clone();
    }
}

mod issue2076 {
    use std::rc::Rc;

    macro_rules! try_opt {
        ($expr: expr) => {
            match $expr {
                Some(value) => value,
                None => return None,
            }
        };
    }

    fn func() -> Option<Rc<u8>> {
        let rc = Rc::new(42);
        Some(try_opt!(Some(rc)).clone())
    }
}
<commit_msg>Fix borrow and deref<commit_after>// does not test any rustfixable lints

#![warn(clippy::clone_on_ref_ptr)]
#![allow(unused, clippy::redundant_clone, clippy::unnecessary_wraps)]

use std::cell::RefCell;
use std::rc::{self, Rc};
use std::sync::{self, Arc};

trait SomeTrait {}
struct SomeImpl;
impl SomeTrait for SomeImpl {}

fn main() {}

fn clone_on_ref_ptr() {
    let rc = Rc::new(true);
    let arc = Arc::new(true);

    let rcweak = Rc::downgrade(&rc);
    let arc_weak = Arc::downgrade(&arc);

    rc.clone();
    Rc::clone(&rc);

    arc.clone();
    Arc::clone(&arc);

    rcweak.clone();
    rc::Weak::clone(&rcweak);

    arc_weak.clone();
    sync::Weak::clone(&arc_weak);

    let x = Arc::new(SomeImpl);
    let _: Arc<dyn SomeTrait> = x.clone();
}

fn clone_on_copy_generic<T: Copy>(t: T) {
    t.clone();

    Some(t).clone();
}

fn clone_on_double_ref() {
    let x = vec![1];
    let y = &&x;
    let z: &Vec<_> = y.clone();

    println!("{:p} {:p}", *y, z);
}

mod many_derefs {
    struct A;
    struct B;
    struct C;
    struct D;
    #[derive(Copy, Clone)]
    struct E;

    macro_rules! impl_deref {
        ($src:ident, $dst:ident) => {
            impl std::ops::Deref for $src {
                type Target = $dst;
                fn deref(&self) -> &Self::Target {
                    &$dst
                }
            }
        };
    }

    impl_deref!(A, B);
    impl_deref!(B, C);
    impl_deref!(C, D);
    impl std::ops::Deref for D {
        type Target = &'static E;
        fn deref(&self) -> &Self::Target {
            &&E
        }
    }

    fn go1() {
        let a = A;
        let _: E = a.clone();
        let _: E = *****a;
    }

    fn check(mut encoded: &[u8]) {
        let _ = &mut encoded.clone();
        let _ = &encoded.clone();
    }
}

mod issue2076 {
    use std::rc::Rc;

    macro_rules! try_opt {
        ($expr: expr) => {
            match $expr {
                Some(value) => value,
                None => return None,
            }
        };
    }

    fn func() -> Option<Rc<u8>> {
        let rc = Rc::new(42);
        Some(try_opt!(Some(rc)).clone())
    }
}
<|endoftext|>


<commit_before>use std::io::Read;
use std::io::Write;

struct Buffer {
    data: [u8; 256],
    len: usize,
    cur: usize,
    bit: u8
}

impl Buffer {
    fn create() -> Buffer {
        return Buffer {
            data: [0u8; 256],
            len: 0us,
            cur: 0us,
            bit: 7u8
        };
    }

    fn fill(&mut self, istream: &mut Read) -> bool {
        match istream.read(&mut self.data[0..]) {
            Ok(0) => false,
            Ok(n) => { self.len = n; self.cur = 0; true },
            Err(_) => false
        }
    }

    fn pull(&mut self, value: &mut u8, istream: &mut Read) -> bool {
        *value = (self.data[self.cur] & (1 << self.bit)) >> self.bit;

        if self.bit == 0 {
            self.bit = 7;
            self.cur += 1;
            if self.cur == self.len && !self.fill(istream) {
                return false;
            }
        } else {
            self.bit -= 1;
        }
        return true;
    }

    fn flush(&mut self, ostream: &mut Write) -> bool {
        // Flush the remaining incomplete byte as well
        if self.bit < 7 {
            self.len += 1;
        }

        match ostream.write(&self.data[..self.len]) {
            Ok(n) => { self.len -= n; self.len == 0 },
            _ => false
        }
    }

    fn push(&mut self, value: u8, ostream: &mut Write) -> bool {
        self.data[self.len] |= value << self.bit;

        if self.bit == 0 {
            self.bit = 7;
            self.len += 1;
            if self.len == self.data.len() && !self.flush(ostream) {
                return false;
            }
            self.data[self.len] = 0;
        } else {
            self.bit -= 1;
        }
        return true;
    }
}

struct Status {
    low: u64,
    high: u64,
    range: u64,
    pending: u8,
    freq: [u64; 258],
    input: Buffer,
    output: Buffer
}

impl Status {
    fn init() -> Status {
        let mut res = Status {
            low: 0x00000000_00000000u64,
            high: 0xFFFFFFFF_FFFFFFFFu64,
            range: 0u64,
            pending: 0u8,
            freq: [0u64; 258],
            input: Buffer::create(),
            output: Buffer::create()
        };
        for i in 1..258 {
            res.freq[i] = i as u64;
        }
        return res;
    }
}

pub fn compress(istream: &mut Read, ostream: &mut Write) {
    let mut st = Status::init();
    let mut v = 0u8;
    let mut count = 0u64;

    st.input.fill(istream);
    while st.input.pull(&mut v, istream) && st.output.push(v, ostream) {
        count += 1;
    }
    st.output.flush(ostream);

    println!("{} bits", count);
}

<commit_msg>Fixed EOF handling<commit_after>use std::io::Read;
use std::io::Write;
use std::io::Result;
use std::io::Error;
use std::io::ErrorKind;

enum ReadResult<T> {
    Ok(T),
    Eof(T),
    Err(Error)
}

struct Buffer {
    data: [u8; 256],
    len: usize,
    cur: usize,
    bit: u8
}

impl Buffer {
    fn create() -> Buffer {
        return Buffer {
            data: [0u8; 256],
            len: 0us,
            cur: 0us,
            bit: 7u8
        };
    }

    fn fill(&mut self, istream: &mut Read) -> ReadResult<()> {
        match istream.read(&mut self.data[0..]) {
            Ok(0) => ReadResult::Eof(()),
            Ok(n) => { self.len = n; self.cur = 0; ReadResult::Ok(()) },
            Err(e) => ReadResult::Err(e)
        }
    }

    fn pull(&mut self, istream: &mut Read) -> ReadResult<u8> {
        let value = (self.data[self.cur] & (1 << self.bit)) >> self.bit;

        if self.bit == 0 {
            self.bit = 7;
            self.cur += 1;
            if self.cur == self.len {
                return match self.fill(istream) {
                    ReadResult::Ok(_) => ReadResult::Ok(value),
                    ReadResult::Eof(_) => ReadResult::Eof(value),
                    ReadResult::Err(e) => ReadResult::Err(e)
                }
            }
        } else {
            self.bit -= 1;
        }
        return ReadResult::Ok(value);
    }

    fn flush(&mut self, ostream: &mut Write) -> Result<()> {
        // Flush the remaining incomplete byte as well
        if self.bit < 7 {
            self.len += 1;
        }

        while self.cur < self.len {
            match ostream.write(&self.data[self.cur..self.len]) {
                Ok(0) => { return Err(Error::new(ErrorKind::WriteZero, "Zero bytes written to output")); }
                Ok(n) => { self.cur += n; },
                Err(e) => { return Err(e); }
            }
        }

        self.len = 0;
        self.cur = 0;
        return Ok(());
    }

    fn push(&mut self, value: u8, ostream: &mut Write) -> Result<()> {
        self.data[self.len] |= value << self.bit;

        if self.bit == 0 {
            self.bit = 7;
            self.len += 1;
            if self.len == self.data.len() {
                if let Err(e) = self.flush(ostream) {
                    return Err(e);
                }
            }
            self.data[self.len] = 0;
        } else {
            self.bit -= 1;
        }
        return Ok(());
    }
}

struct Status {
    low: u64,
    high: u64,
    range: u64,
    pending: u8,
    freq: [u64; 258],
    input: Buffer,
    output: Buffer
}

impl Status {
    fn init() -> Status {
        let mut res = Status {
            low: 0x00000000_00000000u64,
            high: 0xFFFFFFFF_FFFFFFFFu64,
            range: 0u64,
            pending: 0u8,
            freq: [0u64; 258],
            input: Buffer::create(),
            output: Buffer::create()
        };
        for i in 1..258 {
            res.freq[i] = i as u64;
        }
        return res;
    }
}

pub fn compress(istream: &mut Read, ostream: &mut Write) {
    let mut st = Status::init();
    let mut v = 0u8;
    let mut count = 0u64;
/*
    if st.input.fill(istream) != IOResult::Success {
        return;
    }

    loop {
        r = st.input.pull(&mut v, istream);

        if st.output.push(v, ostream) == IOResult::Error {
            r = IOResult::Error;
            break;
        }

        if r == IOResult::EOF {
            break;
        }

            count += 1;
        }
        st.output.flush(ostream);
    }
*/
    println!("{} bits", count);
}

<|endoftext|>


<commit_before>#![allow(dead_code)]

//!
//! A 3dsMax / Blender style camera that orbits about a target position
//!

use event::GenericEvent;

use std::num::{Float, FromPrimitive};
use vecmath::{
    Vector3,
    vec3_add,
    vec3_scale
};

use quaternion;
use quaternion::{ Quaternion };

use { input, Camera };

use input::Button::{Keyboard, Mouse};
use input::keyboard::Key;
use input::mouse::MouseButton;

bitflags!(
    flags Keys: u8 {
        const ZOOM  = 0b00000001,
        const PAN   = 0b00000010,
        const ORBIT = 0b00000100,
    }
);

///
/// Specifies key bindings and speed modifiers for OrbitZoomCamera
///
pub struct OrbitZoomCameraSettings<T=f32> {

    /// Which button to press to orbit with mouse
    pub orbit_button: input::Button,

    /// Which button to press to zoom with mouse
    pub zoom_button: input::Button,

    /// Which button to press to pan with mouse
    pub pan_button: input::Button,

    /// Modifier for orbiting speed (arbitrary unit)
    pub orbit_speed: T,

    /// Modifier for panning speed (arbitrary unit)
    pub pan_speed: T,

    /// Modifier for zoom speed (arbitrary unit)
    pub zoom_speed: T,
}

impl<T: Float + FromPrimitive> OrbitZoomCameraSettings<T> {

    ///
    /// Clicking and dragging OR two-finger scrolling will orbit camera,
    /// with LShift as pan modifer and LCtrl as zoom modifier
    ///
    pub fn default() -> OrbitZoomCameraSettings<T> {
        OrbitZoomCameraSettings {
            orbit_button : Mouse(MouseButton::Left),
            zoom_button : Keyboard(Key::LCtrl),
            pan_button : Keyboard(Key::LShift),
            orbit_speed: FromPrimitive::from_f32(0.05).unwrap(),
            pan_speed: FromPrimitive::from_f32(0.1).unwrap(),
            zoom_speed: FromPrimitive::from_f32(0.1).unwrap(),
        }
    }

}

///
/// A 3dsMax / Blender-style camera that orbits around a target point
///
pub struct OrbitZoomCamera<T=f32> {

    /// origin of camera rotation
    pub target: Vector3<T>,

    /// Rotation of camera
    pub rotation: Quaternion<T>,

    /// Pitch up/down from target
    pub pitch: T,

    /// Yaw left/right from target
    pub yaw: T,

    /// camera distance from target
    pub distance: T,

    /// Settings for the camera
    pub settings: OrbitZoomCameraSettings<T>,

    /// Current keys that are pressed
    keys: Keys,
}

impl<T: Float + FromPrimitive>
OrbitZoomCamera<T> {

    ///
    /// Create a new OrbitZoomCamera targeting the given coordinates
    ///
    pub fn new(target: [T; 3], settings: OrbitZoomCameraSettings<T>) -> OrbitZoomCamera<T> {
        OrbitZoomCamera {
            target: target,
            rotation: quaternion::id(),
            distance: FromPrimitive::from_f32(10.0).unwrap(),
            pitch: Float::zero(),
            yaw: Float::zero(),
            keys: Keys::empty(),
            settings: settings
        }
    }

    ///
    /// Return a Camera for the current OrbitZoomCamera configuration
    ///
    pub fn camera(&self, _dt: f64) -> Camera<T> {
        let target_to_camera = quaternion::rotate_vector(
            self.rotation,
            [Float::zero(), Float::zero(), self.distance]
        );
        let mut camera = Camera::new(vec3_add(self.target, target_to_camera));
        camera.set_rotation(self.rotation);
        camera
    }

    ///
    /// Orbit the camera using the given horizontal and vertical params,
    /// or zoom or pan if the appropriate modifier keys are pressed
    ///
    fn control_camera(&mut self, dx: T, dy: T) {

        let _1 = Float::one();
        let _0 = Float::zero();

        if self.keys.contains(PAN) {

            // Pan target position along plane normal to camera direction
            let dx = dx * self.settings.pan_speed;
            let dy = dy * self.settings.pan_speed;

            let right = quaternion::rotate_vector(self.rotation, [_1, _0, _0]);
            let up = quaternion::rotate_vector(self.rotation, [_0, _1, _0]);
            self.target = vec3_add(
                vec3_add(self.target, vec3_scale(up, dy)),
                vec3_scale(right,dx)
            );

        } else if self.keys.contains(ZOOM) {

            // Zoom to / from target
            self.distance = self.distance + dy * self.settings.zoom_speed;

        } else {

            // Orbit around target
            let dx = dx * self.settings.orbit_speed;
            let dy = dy * self.settings.orbit_speed;

            self.yaw = self.yaw + dx;
            self.pitch = self.pitch + dy;
            self.rotation = quaternion::mul(
                quaternion::axis_angle([_0, _1, _0], self.yaw),
                quaternion::axis_angle([_1, _0, _0], self.pitch)
            );

        }
    }

    ///
    /// Respond to scroll and key press/release events
    ///
    pub fn event<E: GenericEvent>(&mut self, e: &E) {

        use event::{ MouseRelativeEvent, MouseScrollEvent, PressEvent, ReleaseEvent };

        e.mouse_scroll(|dx, dy| {
            let dx: T = FromPrimitive::from_f64(dx).unwrap();
            let dy: T = FromPrimitive::from_f64(dy).unwrap();
            self.control_camera(dx, dy);
        });

        e.mouse_relative(|dx, dy| {
            let dx: T = FromPrimitive::from_f64(dx).unwrap();
            let dy: T = FromPrimitive::from_f64(dy).unwrap();
            if self.keys.contains(ORBIT){
                self.control_camera(-dx, dy);
            }
        });

        e.press(|button| {
            match button {
                x if x == self.settings.orbit_button => self.keys.insert(ORBIT),
                x if x == self.settings.pan_button => self.keys.insert(PAN),
                x if x == self.settings.zoom_button => self.keys.insert(ZOOM),
                _ => {}
            }
        });

        e.release(|button| {
            match button {
                x if x == self.settings.orbit_button => self.keys.remove(ORBIT),
                x if x == self.settings.pan_button => self.keys.remove(PAN),
                x if x == self.settings.zoom_button => self.keys.remove(ZOOM),
                _ => {}
            }
        });
    }
}
<commit_msg>Added an extra setting to control the speed of the pitch. This gives the user more flexibility, including the ability to change the direction of the pitch angle relative to the direction of the yaw direction.<commit_after>#![allow(dead_code)]

//!
//! A 3dsMax / Blender style camera that orbits about a target position
//!

use event::GenericEvent;

use std::num::{Float, FromPrimitive};
use vecmath::{
    Vector3,
    vec3_add,
    vec3_scale
};

use quaternion;
use quaternion::{ Quaternion };

use { input, Camera };

use input::Button::{Keyboard, Mouse};
use input::keyboard::Key;
use input::mouse::MouseButton;

bitflags!(
    flags Keys: u8 {
        const ZOOM  = 0b00000001,
        const PAN   = 0b00000010,
        const ORBIT = 0b00000100,
    }
);

///
/// Specifies key bindings and speed modifiers for OrbitZoomCamera
///
pub struct OrbitZoomCameraSettings<T=f32> {

    /// Which button to press to orbit with mouse
    pub orbit_button: input::Button,

    /// Which button to press to zoom with mouse
    pub zoom_button: input::Button,

    /// Which button to press to pan with mouse
    pub pan_button: input::Button,

    /// Modifier for orbiting speed (arbitrary unit)
    pub orbit_speed: T,

    /// Modifier for pitch speed relative to orbiting speed (arbitrary unit).
    /// To reverse pitch direction, set this to -1.
    pub pitch_speed: T,

    /// Modifier for panning speed (arbitrary unit)
    pub pan_speed: T,

    /// Modifier for zoom speed (arbitrary unit)
    pub zoom_speed: T,
}

impl<T: Float + FromPrimitive> OrbitZoomCameraSettings<T> {

    ///
    /// Clicking and dragging OR two-finger scrolling will orbit camera,
    /// with LShift as pan modifer and LCtrl as zoom modifier
    ///
    pub fn default() -> OrbitZoomCameraSettings<T> {
        OrbitZoomCameraSettings {
            orbit_button : Mouse(MouseButton::Left),
            zoom_button : Keyboard(Key::LCtrl),
            pan_button : Keyboard(Key::LShift),
            orbit_speed: FromPrimitive::from_f32(0.05).unwrap(),
            pitch_speed: FromPrimitive::from_f32(1.0).unwrap(),
            pan_speed: FromPrimitive::from_f32(0.1).unwrap(),
            zoom_speed: FromPrimitive::from_f32(0.1).unwrap(),
        }
    }
}

///
/// A 3dsMax / Blender-style camera that orbits around a target point
///
pub struct OrbitZoomCamera<T=f32> {

    /// origin of camera rotation
    pub target: Vector3<T>,

    /// Rotation of camera
    pub rotation: Quaternion<T>,

    /// Pitch up/down from target
    pub pitch: T,

    /// Yaw left/right from target
    pub yaw: T,

    /// camera distance from target
    pub distance: T,

    /// Settings for the camera
    pub settings: OrbitZoomCameraSettings<T>,

    /// Current keys that are pressed
    keys: Keys,
}

impl<T: Float + FromPrimitive>
OrbitZoomCamera<T> {

    ///
    /// Create a new OrbitZoomCamera targeting the given coordinates
    ///
    pub fn new(target: [T; 3], settings: OrbitZoomCameraSettings<T>) -> OrbitZoomCamera<T> {
        OrbitZoomCamera {
            target: target,
            rotation: quaternion::id(),
            distance: FromPrimitive::from_f32(10.0).unwrap(),
            pitch: Float::zero(),
            yaw: Float::zero(),
            keys: Keys::empty(),
            settings: settings
        }
    }

    ///
    /// Return a Camera for the current OrbitZoomCamera configuration
    ///
    pub fn camera(&self, _dt: f64) -> Camera<T> {
        let target_to_camera = quaternion::rotate_vector(
            self.rotation,
            [Float::zero(), Float::zero(), self.distance]
        );
        let mut camera = Camera::new(vec3_add(self.target, target_to_camera));
        camera.set_rotation(self.rotation);
        camera
    }

    ///
    /// Orbit the camera using the given horizontal and vertical params,
    /// or zoom or pan if the appropriate modifier keys are pressed
    ///
    fn control_camera(&mut self, dx: T, dy: T) {

        let _1 = Float::one();
        let _0 = Float::zero();

        if self.keys.contains(PAN) {

            // Pan target position along plane normal to camera direction
            let dx = dx * self.settings.pan_speed;
            let dy = dy * self.settings.pan_speed;

            let right = quaternion::rotate_vector(self.rotation, [_1, _0, _0]);
            let up = quaternion::rotate_vector(self.rotation, [_0, _1, _0]);
            self.target = vec3_add(
                vec3_add(self.target, vec3_scale(up, dy)),
                vec3_scale(right,dx)
            );

        } else if self.keys.contains(ZOOM) {

            // Zoom to / from target
            self.distance = self.distance + dy * self.settings.zoom_speed;

        } else {

            // Orbit around target
            let dx = dx * self.settings.orbit_speed;
            let dy = dy * self.settings.orbit_speed;

            self.yaw = self.yaw + dx;
            self.pitch = self.pitch + dy*self.settings.pitch_speed;
            self.rotation = quaternion::mul(
                quaternion::axis_angle([_0, _1, _0], self.yaw),
                quaternion::axis_angle([_1, _0, _0], self.pitch)
            );

        }
    }

    ///
    /// Respond to scroll and key press/release events
    ///
    pub fn event<E: GenericEvent>(&mut self, e: &E) {

        use event::{ MouseRelativeEvent, MouseScrollEvent, PressEvent, ReleaseEvent };

        e.mouse_scroll(|dx, dy| {
            let dx: T = FromPrimitive::from_f64(dx).unwrap();
            let dy: T = FromPrimitive::from_f64(dy).unwrap();
            self.control_camera(dx, dy);
        });

        e.mouse_relative(|dx, dy| {
            let dx: T = FromPrimitive::from_f64(dx).unwrap();
            let dy: T = FromPrimitive::from_f64(dy).unwrap();
            if self.keys.contains(ORBIT){
                self.control_camera(-dx, dy);
            }
        });

        e.press(|button| {
            match button {
                x if x == self.settings.orbit_button => self.keys.insert(ORBIT),
                x if x == self.settings.pan_button => self.keys.insert(PAN),
                x if x == self.settings.zoom_button => self.keys.insert(ZOOM),
                _ => {}
            }
        });

        e.release(|button| {
            match button {
                x if x == self.settings.orbit_button => self.keys.remove(ORBIT),
                x if x == self.settings.pan_button => self.keys.remove(PAN),
                x if x == self.settings.zoom_button => self.keys.remove(ZOOM),
                _ => {}
            }
        });
    }
}
<|endoftext|>


<commit_before>use std::path::{Path, PathBuf};
use std::io;
use std::str;
use std::io::{Cursor, Read, Write};
use std::ops::DerefMut;
use std::collections::hash_map::{HashMap, Entry};
use std::sync::{Arc, Mutex};
use std::mem;
use std::marker::PhantomData;

use rex::filesystem::Filesystem;

const CONFIG_PATH: &'static str = "/config/rex/rex.conf";

pub struct MockFile(Arc<Mutex<Vec<u8>>>, u64);

impl MockFile {
    fn new(vec: Arc<Mutex<Vec<u8>>>) -> MockFile {
        MockFile(vec, 0)
    }
}

// A small wrapper to help with a workaround until https://github.com/rust-lang/rust/issues/30132
// is fixed.
macro_rules! do_with_cursor {
    ($obj:expr, $func:ident($($arg:expr),*)) => ({
        let mut self_ = $obj;
        let mut vec = self_.0.lock().unwrap();
        let mut p_vec = vec.deref_mut();
        let mut tmp = Vec::new();

        mem::swap(p_vec, &mut tmp);
        let mut c = Cursor::new(tmp);
        c.set_position(self_.1);
        let ret = c.$func($($arg),*);
        self_.1 = c.position();
        tmp = c.into_inner();
        mem::swap(p_vec, &mut tmp);
        ret
    })
}

impl Read for MockFile {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        do_with_cursor!(self, read(buf))
    }
}

impl Write for MockFile {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        do_with_cursor!(self, write(buf))
    }

    fn flush(&mut self) -> io::Result<()> {
        do_with_cursor!(self, flush())
    }
}

/// A backend for the mock filesystem, providing access to the actual filesystem data needed to
/// implement the filesystem. This allows it to be saved in a per-thread or global basis, for
/// example.
pub trait MockFilesystemBackend {
    /// Returns the file system implementation data, whereever it may be saved.
    fn get_backend() -> MockFilesystemImpl;
}

struct MockFilesystemImpl {
    files: Arc<Mutex<HashMap<PathBuf, Arc<Mutex<Vec<u8>>>>>>,
}

impl Default for MockFilesystemImpl {
    fn default() -> MockFilesystemImpl {
        MockFilesystemImpl {
            files: Arc::new(Mutex::new(HashMap::new()))
        }
    }
}

impl Clone for MockFilesystemImpl {
    fn clone(&self) -> MockFilesystemImpl {
        MockFilesystemImpl {
            files: self.files.clone()
        }
    }
}

/// A mock filesystem, providing basic filesystem APIs, the backend data storage is generic.
pub struct MockFilesystem<T: MockFilesystemBackend + 'static = ThreadLocalMockFilesystemBackend>(PhantomData<T>);

#[derive(Debug, Clone, Copy)]
struct ThreadLocalMockFilesystemBackend;

/// A mock filesystem that saves seperate data per thread.
pub type ThreadedMockFilesystem = MockFilesystem<ThreadLocalMockFilesystemBackend>;

thread_local!(static THREAD_LOCAL_MOCK_FILESYSTEM: MockFilesystemImpl = Default::default());

impl MockFilesystemBackend for ThreadLocalMockFilesystemBackend {
    fn get_backend() -> MockFilesystemImpl {
        let mut ret: Option<MockFilesystemImpl> = None;
        THREAD_LOCAL_MOCK_FILESYSTEM.with(
            |val| ret = Some(val.clone())
        );
        ret.unwrap()
    }
}

impl<T: MockFilesystemBackend + 'static> Filesystem for MockFilesystem<T> {
    type FSRead = MockFile;
    type FSWrite = MockFile;

    fn get_config_home() -> PathBuf {
        PathBuf::from("/config/")
    }

    fn make_absolute<P: AsRef<Path>>(p: P) -> io::Result<PathBuf> {
        Ok(p.as_ref().into())
    }

    fn open<P: AsRef<Path>>(path: P) -> io::Result<Self::FSRead> {
        let backend = T::get_backend();
        let file_map = backend.files.lock().unwrap();
        file_map.get(path.as_ref()).ok_or(io::Error::new(io::ErrorKind::NotFound, "File not found!")).map(|file|
            MockFile::new(file.clone())
        )
    }

    fn can_open<P: AsRef<Path>>(_p: P) -> io::Result<()> {
        Ok(())
    }

    fn save<P: AsRef<Path>>(path: P) -> io::Result<Self::FSWrite> {
        let backend = T::get_backend();
        let mut file_map = backend.files.lock().unwrap();
        let file = file_map.entry(path.as_ref().into()).or_insert_with(|| Arc::new(Mutex::new(Vec::new())));

        Ok(MockFile::new(file.clone()))
    }

    fn can_save<P: AsRef<Path>>(_p: P) -> io::Result<()> {
        Ok(())
    }
}

impl<T: MockFilesystemBackend + 'static> MockFilesystem<T> {
    pub fn open_config() -> io::Result<<MockFilesystem<T> as Filesystem>::FSRead> {
        Self::open(CONFIG_PATH)
    }

    pub fn save_config() -> io::Result<<MockFilesystem<T> as Filesystem>::FSWrite> {
        Self::save(CONFIG_PATH)
    }

    pub fn list_paths() -> Vec<PathBuf> {
        let backend = T::get_backend();
        let r : Vec<PathBuf> = backend.files.lock().unwrap().keys().map( |i| i.clone() ).collect();
        r
    }

    pub fn reset() {
        let backend = T::get_backend();
        backend.files.lock().unwrap().clear();
    }

    pub fn get_inner<'a, P: AsRef<Path>>(path: P) -> Vec<u8> {
        // This function is very ugly, in general we would like to "unwrap" the file from the
        // mock filesystem. Sadly, there doesn't seem to be a better way.
        let backend = T::get_backend();
        let mut file_map = backend.files.lock().unwrap();
        let f = file_map.remove(path.as_ref()).unwrap();
        let a = Arc::try_unwrap(f).unwrap();
        let m = a.lock().unwrap();
        let v = m.clone();
        v
    }

    pub fn put<'a, P: AsRef<Path>>(path: P, v: Vec<u8>) {
        let backend = T::get_backend();
        let mut file_map = backend.files.lock().unwrap();
        file_map.insert(path.as_ref().into(), Arc::new(Mutex::new(v)));
    }
}
<commit_msg>Add globally shared variant of the mock filesystem.<commit_after>use std::path::{Path, PathBuf};
use std::io;
use std::str;
use std::io::{Cursor, Read, Write};
use std::ops::DerefMut;
use std::collections::hash_map::{HashMap, Entry};
use std::sync::{Arc, Mutex};
use std::mem;
use std::marker::PhantomData;

use rex::filesystem::Filesystem;

const CONFIG_PATH: &'static str = "/config/rex/rex.conf";

pub struct MockFile(Arc<Mutex<Vec<u8>>>, u64);

impl MockFile {
    fn new(vec: Arc<Mutex<Vec<u8>>>) -> MockFile {
        MockFile(vec, 0)
    }
}

// A small wrapper to help with a workaround until https://github.com/rust-lang/rust/issues/30132
// is fixed.
macro_rules! do_with_cursor {
    ($obj:expr, $func:ident($($arg:expr),*)) => ({
        let mut self_ = $obj;
        let mut vec = self_.0.lock().unwrap();
        let mut p_vec = vec.deref_mut();
        let mut tmp = Vec::new();

        mem::swap(p_vec, &mut tmp);
        let mut c = Cursor::new(tmp);
        c.set_position(self_.1);
        let ret = c.$func($($arg),*);
        self_.1 = c.position();
        tmp = c.into_inner();
        mem::swap(p_vec, &mut tmp);
        ret
    })
}

impl Read for MockFile {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        do_with_cursor!(self, read(buf))
    }
}

impl Write for MockFile {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        do_with_cursor!(self, write(buf))
    }

    fn flush(&mut self) -> io::Result<()> {
        do_with_cursor!(self, flush())
    }
}

/// A backend for the mock filesystem, providing access to the actual filesystem data needed to
/// implement the filesystem. This allows it to be saved in a per-thread or global basis, for
/// example.
pub trait MockFilesystemBackend {
    /// Returns the file system implementation data, whereever it may be saved.
    fn get_backend() -> MockFilesystemImpl;
}

struct MockFilesystemImpl {
    files: Arc<Mutex<HashMap<PathBuf, Arc<Mutex<Vec<u8>>>>>>,
}

impl Default for MockFilesystemImpl {
    fn default() -> MockFilesystemImpl {
        MockFilesystemImpl {
            files: Arc::new(Mutex::new(HashMap::new()))
        }
    }
}

impl Clone for MockFilesystemImpl {
    fn clone(&self) -> MockFilesystemImpl {
        MockFilesystemImpl {
            files: self.files.clone()
        }
    }
}

/// A mock filesystem, providing basic filesystem APIs, the backend data storage is generic.
pub struct MockFilesystem<T: MockFilesystemBackend + 'static = ThreadLocalMockFilesystemBackend>(PhantomData<T>);

#[derive(Debug, Clone, Copy)]
struct ThreadLocalMockFilesystemBackend;

/// A mock filesystem that saves seperate data per thread.
pub type ThreadedMockFilesystem = MockFilesystem<ThreadLocalMockFilesystemBackend>;

thread_local!(static THREAD_LOCAL_MOCK_FILESYSTEM: MockFilesystemImpl = Default::default());

impl MockFilesystemBackend for ThreadLocalMockFilesystemBackend {
    fn get_backend() -> MockFilesystemImpl {
        let mut ret: Option<MockFilesystemImpl> = None;
        THREAD_LOCAL_MOCK_FILESYSTEM.with(
            |val| ret = Some(val.clone())
        );
        ret.unwrap()
    }
}

#[derive(Debug, Clone, Copy)]
struct GlobalMockFilesystemBackend;

/// A mock filesystem that saves seperate data per thread.
pub type GlobalMockFilesystem = MockFilesystem<GlobalMockFilesystemBackend>;

lazy_static!{
    static ref GLOBAL_MOCK_FILESYSTEM: MockFilesystemImpl = Default::default();
}

impl MockFilesystemBackend for GlobalMockFilesystemBackend {
    fn get_backend() -> MockFilesystemImpl {
        GLOBAL_MOCK_FILESYSTEM.clone()
    }
}

impl<T: MockFilesystemBackend + 'static> Filesystem for MockFilesystem<T> {
    type FSRead = MockFile;
    type FSWrite = MockFile;

    fn get_config_home() -> PathBuf {
        PathBuf::from("/config/")
    }

    fn make_absolute<P: AsRef<Path>>(p: P) -> io::Result<PathBuf> {
        Ok(p.as_ref().into())
    }

    fn open<P: AsRef<Path>>(path: P) -> io::Result<Self::FSRead> {
        let backend = T::get_backend();
        let file_map = backend.files.lock().unwrap();
        file_map.get(path.as_ref()).ok_or(io::Error::new(io::ErrorKind::NotFound, "File not found!")).map(|file|
            MockFile::new(file.clone())
        )
    }

    fn can_open<P: AsRef<Path>>(_p: P) -> io::Result<()> {
        Ok(())
    }

    fn save<P: AsRef<Path>>(path: P) -> io::Result<Self::FSWrite> {
        let backend = T::get_backend();
        let mut file_map = backend.files.lock().unwrap();
        let file = file_map.entry(path.as_ref().into()).or_insert_with(|| Arc::new(Mutex::new(Vec::new())));

        Ok(MockFile::new(file.clone()))
    }

    fn can_save<P: AsRef<Path>>(_p: P) -> io::Result<()> {
        Ok(())
    }
}

impl<T: MockFilesystemBackend + 'static> MockFilesystem<T> {
    pub fn open_config() -> io::Result<<MockFilesystem<T> as Filesystem>::FSRead> {
        Self::open(CONFIG_PATH)
    }

    pub fn save_config() -> io::Result<<MockFilesystem<T> as Filesystem>::FSWrite> {
        Self::save(CONFIG_PATH)
    }

    pub fn list_paths() -> Vec<PathBuf> {
        let backend = T::get_backend();
        let r : Vec<PathBuf> = backend.files.lock().unwrap().keys().map( |i| i.clone() ).collect();
        r
    }

    pub fn reset() {
        let backend = T::get_backend();
        backend.files.lock().unwrap().clear();
    }

    pub fn get_inner<'a, P: AsRef<Path>>(path: P) -> Vec<u8> {
        // This function is very ugly, in general we would like to "unwrap" the file from the
        // mock filesystem. Sadly, there doesn't seem to be a better way.
        let backend = T::get_backend();
        let mut file_map = backend.files.lock().unwrap();
        let f = file_map.remove(path.as_ref()).unwrap();
        let a = Arc::try_unwrap(f).unwrap();
        let m = a.lock().unwrap();
        let v = m.clone();
        v
    }

    pub fn put<'a, P: AsRef<Path>>(path: P, v: Vec<u8>) {
        let backend = T::get_backend();
        let mut file_map = backend.files.lock().unwrap();
        file_map.insert(path.as_ref().into(), Arc::new(Mutex::new(v)));
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::os::raw::c_void;
use neon_runtime;
use neon_runtime::raw;
use context::{CallbackInfo, FunctionContext};
use context::internal::Env;
use types::error::convert_panics;
use types::{JsObject, Handle, Managed};
use result::JsResult;
use object::class::Callback;
use super::Value;

pub trait ValueInternal: Managed + 'static {
    fn name() -> String;

    fn is_typeof<Other: Value>(env: Env, other: Other) -> bool;

    fn downcast<Other: Value>(env: Env, other: Other) -> Option<Self> {
        if Self::is_typeof(env, other) {
            Some(Self::from_raw(other.to_raw()))
        } else {
            None
        }
    }

    fn cast<'a, T: Value, F: FnOnce(raw::Local) -> T>(self, f: F) -> Handle<'a, T> {
        Handle::new_internal(f(self.to_raw()))
    }
}

#[repr(C)]
pub struct FunctionCallback<T: Value>(pub fn(FunctionContext) -> JsResult<T>);

#[cfg(feature = "legacy-runtime")]
impl<T: Value> Callback<()> for FunctionCallback<T> {
    extern "C" fn invoke(env: Env, info: CallbackInfo) {
        unsafe {
            info.with_cx::<JsObject, _, _>(env, |cx| {
                let data = info.data(env);
                let dynamic_callback: fn(FunctionContext) -> JsResult<T> =
                    mem::transmute(neon_runtime::fun::get_dynamic_callback(env.to_raw(), data));
                if let Ok(value) = convert_panics(|| { dynamic_callback(cx) }) {
                    info.set_return(value);
                }
            })
        }
    }

    fn as_ptr(self) -> *mut c_void {
        unsafe { mem::transmute(self.0) }
    }
}

#[cfg(feature = "napi-runtime")]
impl<T: Value> Callback<raw::Local> for FunctionCallback<T> {
    extern "C" fn invoke(env: Env, info: CallbackInfo) -> raw::Local {
        unsafe {
            info.with_cx::<JsObject, _, _>(env, |cx| {
                let data = info.data(env);
                let dynamic_callback: fn(FunctionContext) -> JsResult<T> =
                    mem::transmute(neon_runtime::fun::get_dynamic_callback(env.to_raw(), data));
                if let Ok(value) = convert_panics(|| { dynamic_callback(cx) }) {
                    value.to_raw()
                } else {
                    // TODO this should probably not be null
                    std::ptr::null_mut()
                }
            })
        }
    }

    fn as_ptr(self) -> *mut c_void {
        unsafe { mem::transmute(self.0) }
    }
}
<commit_msg>Remove possibly-incorrect handling of Rust panics in callback<commit_after>use std::mem;
use std::os::raw::c_void;
use neon_runtime;
use neon_runtime::raw;
use context::{CallbackInfo, FunctionContext};
use context::internal::Env;
use types::error::convert_panics;
use types::{JsObject, Handle, Managed};
use result::JsResult;
use object::class::Callback;
use super::Value;

pub trait ValueInternal: Managed + 'static {
    fn name() -> String;

    fn is_typeof<Other: Value>(env: Env, other: Other) -> bool;

    fn downcast<Other: Value>(env: Env, other: Other) -> Option<Self> {
        if Self::is_typeof(env, other) {
            Some(Self::from_raw(other.to_raw()))
        } else {
            None
        }
    }

    fn cast<'a, T: Value, F: FnOnce(raw::Local) -> T>(self, f: F) -> Handle<'a, T> {
        Handle::new_internal(f(self.to_raw()))
    }
}

#[repr(C)]
pub struct FunctionCallback<T: Value>(pub fn(FunctionContext) -> JsResult<T>);

#[cfg(feature = "legacy-runtime")]
impl<T: Value> Callback<()> for FunctionCallback<T> {
    extern "C" fn invoke(env: Env, info: CallbackInfo) {
        unsafe {
            info.with_cx::<JsObject, _, _>(env, |cx| {
                let data = info.data(env);
                let dynamic_callback: fn(FunctionContext) -> JsResult<T> =
                    mem::transmute(neon_runtime::fun::get_dynamic_callback(env.to_raw(), data));
                if let Ok(value) = convert_panics(|| { dynamic_callback(cx) }) {
                    info.set_return(value);
                }
            })
        }
    }

    fn as_ptr(self) -> *mut c_void {
        unsafe { mem::transmute(self.0) }
    }
}

#[cfg(feature = "napi-runtime")]
impl<T: Value> Callback<raw::Local> for FunctionCallback<T> {
    extern "C" fn invoke(env: Env, info: CallbackInfo) -> raw::Local {
        unsafe {
            info.with_cx::<JsObject, _, _>(env, |cx| {
                let data = info.data(env);
                let dynamic_callback: fn(FunctionContext) -> JsResult<T> =
                    mem::transmute(neon_runtime::fun::get_dynamic_callback(env.to_raw(), data));
                if let Ok(value) = convert_panics(|| { dynamic_callback(cx) }) {
                    value.to_raw()
                } else {
                    // What should we return if the function panicked?
                    //
                    // `ptr::null_mut()` may work, but we should have a test to verify that, which
                    // can be created after [#505][0]. For now, let's not guess!
                    //
                    // [0]: https://github.com/neon-bindings/neon/pull/505.
                    unimplemented!("cannot return from function after a panic")
                }
            })
        }
    }

    fn as_ptr(self) -> *mut c_void {
        unsafe { mem::transmute(self.0) }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use std::iter::FromIterator;

use util::map_char;

#[derive(Clone, Debug)]
pub struct Rotor {
    mapping: Vec<char>,
    inverse: Vec<char>,
    notches: HashSet<usize>,
    offset: usize,
}

impl Rotor {
    /// Creates a new `Rotor`.
    pub fn new(mapping: &str, notches: &str) -> Rotor {
        let mapping: Vec<char> = mapping.chars().collect();

        if mapping.len() != 26 {
            panic!("Rotor mappings must be 26 characters long.");
        }

        let inverse = {
            let mut inverse = vec!['A'; 26];
            for (i, &c) in mapping.iter().enumerate() {
                let index = ((c as u8) - 65) as usize;
                let letter = ((i as u8) + 65) as char;
                inverse[index % 26] = letter;
            }
            inverse
        };

        Rotor {
            mapping: mapping,
            inverse: inverse,
            notches: HashSet::from_iter(notches.chars().map(|c| (c as usize) - 65)),
            offset: 0,
        }
    }

    /// Returns the substitution of a given character, dependent
    /// on the current offset of the rotor. For non-alphabetic
    /// characters, simply return the character itself.
    pub fn substitute(&self, c: char) -> char {
        map_char(c, &self.mapping, self.offset)
    }

    /// Returns the substitution of a given character when run through
    /// the rotor in reverse (on the path back from the reflector).
    pub fn invert(&self, c: char) -> char {
        map_char(c, &self.inverse, self.offset)
    }

    /// Advances this rotor, returning `true` if the rotor adjacent to
    /// it should be advanced as well.
    pub fn advance(&mut self) -> bool {
        let advance_next = self.notches.contains(&self.offset);
        self.offset = (self.offset + 1) % 26;
        return advance_next;
    }
}

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

    #[test]
    fn char_substitution() {
        let rotor = Rotor::new("EKMFLGDQVZNTOWYHXUSPAIBRCJ", "A");
        assert_eq!(rotor.substitute('A'), 'E');
        assert_eq!(rotor.substitute('b'), 'K');
        assert_eq!(rotor.substitute(' '), ' ');
        assert_eq!(rotor.substitute('é'), 'é');
    }

    #[test]
    fn step_rotor() {
        let mut rotor = Rotor::new("EKMFLGDQVZNTOWYHXUSPAIBRCJ", "B");
        assert_eq!(rotor.substitute('A'), 'E');

        // Step the rotor one position
        assert!(!rotor.advance());
        assert_eq!(rotor.offset, 1);
        assert_eq!(rotor.substitute('A'), 'K');

        // Moving from B to C should advance the next rotor
        assert!(rotor.advance());
        assert_eq!(rotor.offset, 2);
        assert_eq!(rotor.substitute('A'), 'M');
    }

    #[test]
    fn rotor_inverse() {
        // Rotor I of the Enigma
        let rotor = Rotor::new("EKMFLGDQVZNTOWYHXUSPAIBRCJ", "A");
        let inverse: String = rotor.inverse.into_iter().collect();
        assert_eq!(&inverse, "UWYGADFPVZBECKMTHXSLRINQOJ");
    }

    #[test]
    #[should_panic(expected = "Rotor mappings must be 26 characters long.")]
    fn invalid_rotor() {
        Rotor::new("ABC", "A");
    }
}
<commit_msg>Fix rotor inversions with non-zero offsets<commit_after>use std::collections::HashSet;
use std::iter::FromIterator;

use util::map_char;

#[derive(Clone, Debug)]
pub struct Rotor {
    mapping: Vec<char>,
    inverse: Vec<char>,
    notches: HashSet<usize>,
    offset: usize,
}

impl Rotor {
    /// Creates a new `Rotor`.
    pub fn new(mapping: &str, notches: &str) -> Rotor {
        let mapping: Vec<char> = mapping.chars().collect();

        if mapping.len() != 26 {
            panic!("Rotor mappings must be 26 characters long.");
        }

        let inverse = {
            let mut inverse = vec!['A'; 26];
            for (i, &c) in mapping.iter().enumerate() {
                let index = ((c as u8) - 65) as usize;
                let letter = ((i as u8) + 65) as char;
                inverse[index % 26] = letter;
            }
            inverse
        };

        Rotor {
            mapping: mapping,
            inverse: inverse,
            notches: HashSet::from_iter(notches.chars().map(|c| (c as usize) - 65)),
            offset: 0,
        }
    }

    /// Returns the substitution of a given character, dependent
    /// on the current offset of the rotor. For non-alphabetic
    /// characters, simply return the character itself.
    pub fn substitute(&self, c: char) -> char {
        map_char(c, &self.mapping, self.offset)
    }

    /// Returns the substitution of a given character when run through
    /// the rotor in reverse (on the path back from the reflector).
    pub fn invert(&self, c: char) -> char {
        let index = self.inverse[(c as usize) - 65] as usize - 65;
        (((index + 26 - self.offset) % 26) + 65) as u8 as char
    }

    /// Advances this rotor, returning `true` if the rotor adjacent to
    /// it should be advanced as well.
    pub fn advance(&mut self) -> bool {
        let advance_next = self.notches.contains(&self.offset);
        self.offset = (self.offset + 1) % 26;
        return advance_next;
    }
}

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

    #[test]
    fn char_substitution() {
        let rotor = Rotor::new("EKMFLGDQVZNTOWYHXUSPAIBRCJ", "A");
        assert_eq!(rotor.substitute('A'), 'E');
        assert_eq!(rotor.substitute('b'), 'K');
        assert_eq!(rotor.substitute(' '), ' ');
        assert_eq!(rotor.substitute('é'), 'é');
    }

    #[test]
    fn step_rotor() {
        let mut rotor = Rotor::new("EKMFLGDQVZNTOWYHXUSPAIBRCJ", "B");
        assert_eq!(rotor.substitute('A'), 'E');

        // Step the rotor one position
        assert!(!rotor.advance());
        assert_eq!(rotor.offset, 1);
        assert_eq!(rotor.substitute('A'), 'K');

        // Moving from B to C should advance the next rotor
        assert!(rotor.advance());
        assert_eq!(rotor.offset, 2);
        assert_eq!(rotor.substitute('A'), 'M');
    }

    #[test]
    fn step_inverse() {
        let mut rotor = Rotor::new("EKMFLGDQVZNTOWYHXUSPAIBRCJ", "B");
        assert_eq!(rotor.invert('E'), 'A');
        rotor.advance();
        assert_eq!(rotor.invert('K'), 'A');
        rotor.advance();
        assert_eq!(rotor.invert('M'), 'A');
    }

    #[test]
    fn rotor_inverse() {
        // Rotor I of the Enigma
        let rotor = Rotor::new("EKMFLGDQVZNTOWYHXUSPAIBRCJ", "A");
        let inverse: String = rotor.inverse.into_iter().collect();
        assert_eq!(&inverse, "UWYGADFPVZBECKMTHXSLRINQOJ");
    }

    #[test]
    #[should_panic(expected = "Rotor mappings must be 26 characters long.")]
    fn invalid_rotor() {
        Rotor::new("ABC", "A");
    }
}
<|endoftext|>


<commit_before>#![recursion_limit="256"]
extern crate chrono;
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate diesel_infer_schema;
extern crate diesel_full_text_search;
extern crate dotenv;
#[macro_use]
extern crate error_chain;
extern crate hyper;
extern crate hyper_tls;
extern crate futures;
extern crate futures_cpupool;
extern crate jsonwebtoken;
extern crate kuchiki;
#[macro_use]
extern crate log;
extern crate log4rs;
#[macro_use]
extern crate nom;
extern crate r2d2;
extern crate r2d2_diesel;
extern crate rusoto_core;
extern crate rusoto_credential;
extern crate rusoto_s3;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate tokio_core;
extern crate tokio_postgres;
extern crate tokio_timer;
extern crate unicase;
extern crate url;

pub mod errors;
pub mod models;
pub mod schema;
pub mod server;
pub mod targeting_parser;

use log::LevelFilter;
use log4rs::append::console::ConsoleAppender;
use log4rs::config::{Appender, Config as LogConfig, Logger, Root};
use std::string;

pub fn start_logging() {
    let stdout = ConsoleAppender::builder().build();
    let config = LogConfig::builder()
        .appender(Appender::builder().build("stdout", Box::new(stdout)))
        .logger(Logger::builder().build("hyper", LevelFilter::Info))
        .logger(Logger::builder().build("server", LevelFilter::Info))
        .build(Root::builder().appender("stdout").build(
            LevelFilter::Error,
        ))
        .expect("Log config didn't work");
    log4rs::init_config(config).expect("Logging encountered an error.");
}
<commit_msg>adds regex crate; deps automatically alphabetized<commit_after>#![recursion_limit = "256"]
extern crate chrono;
#[macro_use]
extern crate diesel;
extern crate diesel_full_text_search;
#[macro_use]
extern crate diesel_infer_schema;
extern crate dotenv;
#[macro_use]
extern crate error_chain;
extern crate futures;
extern crate futures_cpupool;
extern crate hyper;
extern crate hyper_tls;
extern crate jsonwebtoken;
extern crate kuchiki;
extern crate log4rs;
#[macro_use]
extern crate log;
#[macro_use]
extern crate nom;
extern crate r2d2;
extern crate r2d2_diesel;
extern crate regex;
extern crate rusoto_core;
extern crate rusoto_credential;
extern crate rusoto_s3;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate tokio_core;
extern crate tokio_postgres;
extern crate tokio_timer;
extern crate unicase;
extern crate url;

pub mod errors;
pub mod models;
pub mod schema;
pub mod server;
pub mod targeting_parser;

use log::LevelFilter;
use log4rs::append::console::ConsoleAppender;
use log4rs::config::{Appender, Config as LogConfig, Logger, Root};
use std::string;

pub fn start_logging() {
    let stdout = ConsoleAppender::builder().build();
    let config = LogConfig::builder()
        .appender(Appender::builder().build("stdout", Box::new(stdout)))
        .logger(Logger::builder().build("hyper", LevelFilter::Info))
        .logger(Logger::builder().build("server", LevelFilter::Info))
        .build(Root::builder().appender("stdout").build(LevelFilter::Error))
        .expect("Log config didn't work");
    log4rs::init_config(config).expect("Logging encountered an error.");
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use uuid::Uuid;

use graphics::*;
use graphics::vecmath::Matrix2d;

use event::GenericEvent;
use ai_behavior::{
    Behavior,
    State,
    Running,
};

use sprite::Sprite;

use animation::{
    Animation,
    AnimationState,
};

/// A scene is used to manage sprite's life and run animation with sprite
pub struct Scene<I: ImageSize> {
    children: Vec<Sprite<I>>,
    children_index: HashMap<Uuid, usize>,
    running: HashMap<Uuid,
        Vec<(Behavior<Animation>, State<Animation, AnimationState>, bool)>>,
}

impl<I: ImageSize> Scene<I> {
    /// Create a new scene
    pub fn new() -> Scene<I> {
        Scene {
            children: Vec::new(),
            children_index: HashMap::new(),
            running: HashMap::new(),
        }
    }

    /// Update animation's state
    pub fn event<E: GenericEvent>(&mut self, e: &E) {
        // regenerate the animations and their states
        let running = self.running.clone();
        self.running.clear();

        for (id, animations) in running.into_iter() {
            let mut new_animations = Vec::new();

            for (b, mut a, paused) in animations.into_iter() {
                if paused {
                    new_animations.push((b, a, paused));
                    continue;
                }

                let sprite = self.child_mut(id.clone()).unwrap();
                let (status, _) = a.event(e, &mut |_, dt, animation, s| {
                    let (state, status, remain) = {
                        let start_state;
                        let state = match *s {
                            None => { start_state = animation.to_state(sprite); &start_state },
                            Some(ref state) => state,
                        };
                        state.update(sprite, dt)
                    };
                    *s = state;
                    (status, remain)
                });

                match status {
                    // the behavior is still running, add it for next update
                    Running => {
                        new_animations.push((b, a, paused));
                    },
                    _ => {},
                }
            }

            if new_animations.len() > 0 {
                self.running.insert(id, new_animations);
            }
        }
    }

    /// Render this scene
    pub fn draw<B: BackEnd<Texture = I>>(&self, t: Matrix2d, b: &mut B) {
        for child in self.children.iter() {
            child.draw(t, b);
        }
    }

    /// Register animation with sprite
    pub fn run(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        use std::collections::hash_map::Entry::{ Vacant, Occupied };
        let animations = match self.running.entry(sprite_id) {
            Vacant(entry) => entry.insert(Vec::new()),
            Occupied(entry) => entry.into_mut()
        };
        let state = State::new(animation.clone());
        animations.push((animation.clone(), state, false));
    }

    fn find(&self, sprite_id: Uuid, animation: &Behavior<Animation>) -> Option<usize> {
        let mut index = None;
        if let Some(animations) = self.running.get(&sprite_id) {
            for i in 0..animations.len() {
                let (ref b, _, _) = animations[i];
                if b == animation {
                    index = Some(i);
                    break;
                }
            }
        }
        index
    }

    /// Pause a running animation of the sprite
    pub fn pause(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id.clone(), animation) {
            let animations = &mut self.running[sprite_id];
            let (b, s, _) = animations.remove(index);
            animations.push((b, s, true));
        }
    }

    /// Resume a paused animation of the sprite
    pub fn resume(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id.clone(), animation) {
            let animations = &mut self.running[sprite_id];
            let (b, s, _) = animations.remove(index);
            animations.push((b, s, false));
        }
    }

    /// Toggle an animation of the sprite
    pub fn toggle(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id.clone(), animation) {
            let animations = &mut self.running[sprite_id];
            let (b, s, paused) = animations.remove(index);
            animations.push((b, s, !paused));
        }
    }

    /// Stop a running animation of the sprite
    pub fn stop(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id.clone(), animation) {
            &mut self.running[sprite_id].remove(index);
        }
    }

    /// Stop all running animations of the sprite
    pub fn stop_all(&mut self, sprite_id: Uuid) {
        self.running.remove(&sprite_id);
    }

    /// Get all the running animations in the scene
    pub fn running(&self) -> usize {
        let mut total = 0;
        for (_, animations) in self.running.iter() {
            total += animations.len();
        }
        total
    }

    /// Add sprite to scene
    pub fn add_child(&mut self, sprite: Sprite<I>) -> Uuid {
        let id = sprite.id();
        self.children.push(sprite);
        self.children_index.insert(id.clone(), self.children.len() - 1);
        id
    }

    fn stop_all_including_children(&mut self, sprite: &Sprite<I>) {
        self.stop_all(sprite.id());
        for child in sprite.children().iter() {
            self.stop_all_including_children(child);
        }
    }

    /// Remove the child by `id` from the scene's children or grandchild
    /// will stop all the animations run by this child
    pub fn remove_child(&mut self, id: Uuid) -> Option<Sprite<I>> {
        let removed = if let Some(index) = self.children_index.remove(&id) {
            let removed = self.children.remove(index);
            // Removing a element of vector will alter the index,
            // update the mapping from uuid to index.
            for i in index..self.children.len() {
                let uuid = self.children[i].id();
                self.children_index.insert(uuid, i);
            }
            Some(removed)
        } else {
            for child in self.children.iter_mut() {
                if let Some(c) = child.remove_child(id.clone()) {
                    return Some(c);
                }
            }
            None
        };

        if removed.is_some() {
            self.stop_all_including_children(removed.as_ref().unwrap());
        }

        removed
    }

    /// Find the child by `id` from the scene's children or grandchild
    pub fn child(&self, id: Uuid) -> Option<&Sprite<I>> {
        if let Some(index) = self.children_index.get(&id) {
            Some(&self.children[*index])
        } else {
            for child in self.children.iter() {
                if let Some(c) = child.child(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Find the child by `id` from this sprite's children or grandchild, mutability
    pub fn child_mut(&mut self, id: Uuid) -> Option<&mut Sprite<I>> {
        if let Some(index) = self.children_index.get(&id) {
            Some(&mut self.children[*index])
        } else {
            for child in self.children.iter_mut() {
                if let Some(c) = child.child_mut(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }
}
<commit_msg>Upgrade to latest rust<commit_after>use std::collections::HashMap;
use uuid::Uuid;

use graphics::*;
use graphics::vecmath::Matrix2d;

use event::GenericEvent;
use ai_behavior::{
    Behavior,
    State,
    Running,
};

use sprite::Sprite;

use animation::{
    Animation,
    AnimationState,
};

/// A scene is used to manage sprite's life and run animation with sprite
pub struct Scene<I: ImageSize> {
    children: Vec<Sprite<I>>,
    children_index: HashMap<Uuid, usize>,
    running: HashMap<Uuid,
        Vec<(Behavior<Animation>, State<Animation, AnimationState>, bool)>>,
}

impl<I: ImageSize> Scene<I> {
    /// Create a new scene
    pub fn new() -> Scene<I> {
        Scene {
            children: Vec::new(),
            children_index: HashMap::new(),
            running: HashMap::new(),
        }
    }

    /// Update animation's state
    pub fn event<E: GenericEvent>(&mut self, e: &E) {
        // regenerate the animations and their states
        let running = self.running.clone();
        self.running.clear();

        for (id, animations) in running.into_iter() {
            let mut new_animations = Vec::new();

            for (b, mut a, paused) in animations.into_iter() {
                if paused {
                    new_animations.push((b, a, paused));
                    continue;
                }

                let sprite = self.child_mut(id.clone()).unwrap();
                let (status, _) = a.event(e, &mut |_, dt, animation, s| {
                    let (state, status, remain) = {
                        let start_state;
                        let state = match *s {
                            None => { start_state = animation.to_state(sprite); &start_state },
                            Some(ref state) => state,
                        };
                        state.update(sprite, dt)
                    };
                    *s = state;
                    (status, remain)
                });

                match status {
                    // the behavior is still running, add it for next update
                    Running => {
                        new_animations.push((b, a, paused));
                    },
                    _ => {},
                }
            }

            if new_animations.len() > 0 {
                self.running.insert(id, new_animations);
            }
        }
    }

    /// Render this scene
    pub fn draw<B: BackEnd<Texture = I>>(&self, t: Matrix2d, b: &mut B) {
        for child in self.children.iter() {
            child.draw(t, b);
        }
    }

    /// Register animation with sprite
    pub fn run(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        use std::collections::hash_map::Entry::{ Vacant, Occupied };
        let animations = match self.running.entry(sprite_id) {
            Vacant(entry) => entry.insert(Vec::new()),
            Occupied(entry) => entry.into_mut()
        };
        let state = State::new(animation.clone());
        animations.push((animation.clone(), state, false));
    }

    fn find(&self, sprite_id: Uuid, animation: &Behavior<Animation>) -> Option<usize> {
        let mut index = None;
        if let Some(animations) = self.running.get(&sprite_id) {
            for i in 0..animations.len() {
                let (ref b, _, _) = animations[i];
                if b == animation {
                    index = Some(i);
                    break;
                }
            }
        }
        index
    }

    /// Pause a running animation of the sprite
    pub fn pause(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id.clone(), animation) {
            let animations = self.running.get_mut(&sprite_id).unwrap();
            let (b, s, _) = animations.remove(index);
            animations.push((b, s, true));
        }
    }

    /// Resume a paused animation of the sprite
    pub fn resume(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id.clone(), animation) {
            let animations = self.running.get_mut(&sprite_id).unwrap();
            let (b, s, _) = animations.remove(index);
            animations.push((b, s, false));
        }
    }

    /// Toggle an animation of the sprite
    pub fn toggle(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id.clone(), animation) {
            let animations = self.running.get_mut(&sprite_id).unwrap();
            let (b, s, paused) = animations.remove(index);
            animations.push((b, s, !paused));
        }
    }

    /// Stop a running animation of the sprite
    pub fn stop(&mut self, sprite_id: Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id.clone(), animation) {
            self.running.get_mut(&sprite_id).unwrap().remove(index);
        }
    }

    /// Stop all running animations of the sprite
    pub fn stop_all(&mut self, sprite_id: Uuid) {
        self.running.remove(&sprite_id);
    }

    /// Get all the running animations in the scene
    pub fn running(&self) -> usize {
        let mut total = 0;
        for (_, animations) in self.running.iter() {
            total += animations.len();
        }
        total
    }

    /// Add sprite to scene
    pub fn add_child(&mut self, sprite: Sprite<I>) -> Uuid {
        let id = sprite.id();
        self.children.push(sprite);
        self.children_index.insert(id.clone(), self.children.len() - 1);
        id
    }

    fn stop_all_including_children(&mut self, sprite: &Sprite<I>) {
        self.stop_all(sprite.id());
        for child in sprite.children().iter() {
            self.stop_all_including_children(child);
        }
    }

    /// Remove the child by `id` from the scene's children or grandchild
    /// will stop all the animations run by this child
    pub fn remove_child(&mut self, id: Uuid) -> Option<Sprite<I>> {
        let removed = if let Some(index) = self.children_index.remove(&id) {
            let removed = self.children.remove(index);
            // Removing a element of vector will alter the index,
            // update the mapping from uuid to index.
            for i in index..self.children.len() {
                let uuid = self.children[i].id();
                self.children_index.insert(uuid, i);
            }
            Some(removed)
        } else {
            for child in self.children.iter_mut() {
                if let Some(c) = child.remove_child(id.clone()) {
                    return Some(c);
                }
            }
            None
        };

        if removed.is_some() {
            self.stop_all_including_children(removed.as_ref().unwrap());
        }

        removed
    }

    /// Find the child by `id` from the scene's children or grandchild
    pub fn child(&self, id: Uuid) -> Option<&Sprite<I>> {
        if let Some(index) = self.children_index.get(&id) {
            Some(&self.children[*index])
        } else {
            for child in self.children.iter() {
                if let Some(c) = child.child(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Find the child by `id` from this sprite's children or grandchild, mutability
    pub fn child_mut(&mut self, id: Uuid) -> Option<&mut Sprite<I>> {
        if let Some(index) = self.children_index.get(&id) {
            Some(&mut self.children[*index])
        } else {
            for child in self.children.iter_mut() {
                if let Some(c) = child.child_mut(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }
}
<|endoftext|>