<commit_before>use std::cmp::Ordering;
use std::fmt;
use std::slice;

use goblin::mach;

use {Machine, Object, ObjectSection, ObjectSegment, SectionKind, Symbol, SymbolKind};

/// A Mach-O object file.
#[derive(Debug)]
pub struct MachOFile<'a> {
    macho: mach::MachO<'a>,
}

/// An iterator over the segments of a `MachOFile`.
#[derive(Debug)]
pub struct MachOSegmentIterator<'a> {
    segments: slice::Iter<'a, mach::segment::Segment<'a>>,
}

/// A segment of a `MachOFile`.
#[derive(Debug)]
pub struct MachOSegment<'a> {
    segment: &'a mach::segment::Segment<'a>,
}

/// An iterator over the sections of a `MachOFile`.
pub struct MachOSectionIterator<'a> {
    segments: slice::Iter<'a, mach::segment::Segment<'a>>,
    sections: Option<mach::segment::SectionIterator<'a>>,
}

/// A section of a `MachOFile`.
#[derive(Debug)]
pub struct MachOSection<'a> {
    section: mach::segment::Section,
    data: mach::segment::SectionData<'a>,
}

impl<'a> MachOFile<'a> {
    /// Get the Mach-O headers of the file.
    // TODO: this is temporary to allow access to features this crate doesn't provide yet
    #[inline]
    pub fn macho(&self) -> &mach::MachO<'a> {
        &self.macho
    }
}

impl<'a> Object<'a> for MachOFile<'a> {
    type Segment = MachOSegment<'a>;
    type SegmentIterator = MachOSegmentIterator<'a>;
    type Section = MachOSection<'a>;
    type SectionIterator = MachOSectionIterator<'a>;

    fn parse(data: &'a [u8]) -> Result<Self, &'static str> {
        let macho = mach::MachO::parse(data, 0).map_err(|_| "Could not parse Mach-O header")?;
        Ok(MachOFile { macho })
    }

    fn machine(&self) -> Machine {
        match self.macho.header.cputype {
            mach::cputype::CPU_TYPE_ARM => Machine::Arm,
            mach::cputype::CPU_TYPE_ARM64 => Machine::Arm64,
            mach::cputype::CPU_TYPE_X86 => Machine::X86,
            mach::cputype::CPU_TYPE_X86_64 => Machine::X86_64,
            _ => Machine::Other,
        }
    }

    fn segments(&'a self) -> MachOSegmentIterator<'a> {
        MachOSegmentIterator {
            segments: self.macho.segments.iter(),
        }
    }

    fn section_data_by_name(&self, section_name: &str) -> Option<&'a [u8]> {
        // Translate the "." prefix to the "__" prefix used by OSX/Mach-O, eg
        // ".debug_info" to "__debug_info".
        let (system_section, section_name) = if section_name.starts_with(".") {
            (true, &section_name[1..])
        } else {
            (false, section_name)
        };
        let cmp_section_name = |name: &str| if system_section {
            name.starts_with("__") && section_name == &name[2..]
        } else {
            section_name == name
        };

        for segment in &self.macho.segments {
            for section in segment {
                if let Ok((section, data)) = section {
                    if let Ok(name) = section.name() {
                        if cmp_section_name(name) {
                            return Some(data);
                        }
                    }
                }
            }
        }
        None
    }

    fn sections(&'a self) -> MachOSectionIterator<'a> {
        MachOSectionIterator {
            segments: self.macho.segments.iter(),
            sections: None,
        }
    }

    fn symbols(&self) -> Vec<Symbol<'a>> {
        // Determine section kinds and end addresses.
        // The section kinds are inherited by symbols in those sections.
        // The section end addresses are needed for calculating symbol sizes.
        let mut section_kinds = Vec::new();
        let mut section_ends = Vec::new();
        for segment in &self.macho.segments {
            for section in segment {
                if let Ok((section, _)) = section {
                    let sectname = section.name().ok();
                    let segname = section.segname().ok();
                    let (section_kind, symbol_kind) = match (segname, sectname) {
                        (Some("__TEXT"), Some("__text")) => (SectionKind::Text, SymbolKind::Text),
                        (Some("__DATA"), Some("__data")) => (SectionKind::Data, SymbolKind::Data),
                        (Some("__DATA"), Some("__bss")) => {
                            (SectionKind::UninitializedData, SymbolKind::Data)
                        }
                        _ => (SectionKind::Other, SymbolKind::Unknown),
                    };
                    let section_index = section_kinds.len();
                    section_kinds.push((section_kind, symbol_kind));
                    section_ends.push(Symbol {
                        kind: SymbolKind::Section,
                        section: section_index + 1,
                        section_kind: Some(section_kind),
                        global: false,
                        name: None,
                        address: section.addr + section.size,
                        size: 0,
                    });
                } else {
                    // Add placeholder so that indexing works.
                    section_kinds.push((SectionKind::Unknown, SymbolKind::Unknown));
                }
            }
        }

        let mut symbols = Vec::new();
        for sym in self.macho.symbols() {
            if let Ok((name, nlist)) = sym {
                // Skip STAB debugging symbols.
                // FIXME: use N_STAB constant
                if nlist.n_type & 0xe0 != 0 {
                    continue;
                }
                let n_type = nlist.n_type & mach::symbols::NLIST_TYPE_MASK;
                let (section_kind, kind) = if n_type == mach::symbols::N_SECT {
                    if nlist.n_sect == 0 || nlist.n_sect - 1 >= section_kinds.len() {
                        (None, SymbolKind::Unknown)
                    } else {
                        let (section_kind, kind) = section_kinds[nlist.n_sect - 1];
                        (Some(section_kind), kind)
                    }
                } else {
                    (None, SymbolKind::Unknown)
                };
                symbols.push(Symbol {
                    kind,
                    section: nlist.n_sect,
                    section_kind,
                    global: nlist.is_global(),
                    name: Some(name),
                    address: nlist.n_value,
                    size: 0,
                });
            }
        }

        {
            // Calculate symbol sizes by sorting and finding the next symbol.
            let mut symbol_refs = Vec::with_capacity(symbols.len() + section_ends.len());
            symbol_refs.extend(symbols.iter_mut().filter(|s| !s.is_undefined()));
            symbol_refs.extend(section_ends.iter_mut());
            symbol_refs.sort_by(|a, b| {
                let ord = a.section.cmp(&b.section);
                if ord != Ordering::Equal {
                    return ord;
                }
                let ord = a.address.cmp(&b.address);
                if ord != Ordering::Equal {
                    return ord;
                }
                // Place the dummy end of section symbols last.
                (a.kind == SymbolKind::Section).cmp(&(b.kind == SymbolKind::Section))
            });

            for i in 0..symbol_refs.len() {
                let (before, after) = symbol_refs.split_at_mut(i + 1);
                let sym = &mut before[i];
                if sym.kind != SymbolKind::Section {
                    if let Some(next) = after
                        .iter()
                        .skip_while(|x| {
                            x.kind != SymbolKind::Section && x.address == sym.address
                        })
                        .next()
                    {
                        sym.size = next.address - sym.address;
                    }
                }
            }
        }

        symbols
    }

    #[inline]
    fn is_little_endian(&self) -> bool {
        self.macho.header.is_little_endian()
    }
}

impl<'a> Iterator for MachOSegmentIterator<'a> {
    type Item = MachOSegment<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        self.segments.next().map(|segment| MachOSegment { segment })
    }
}

impl<'a> ObjectSegment<'a> for MachOSegment<'a> {
    #[inline]
    fn address(&self) -> u64 {
        self.segment.vmaddr
    }

    #[inline]
    fn size(&self) -> u64 {
        self.segment.vmsize
    }

    #[inline]
    fn data(&self) -> &'a [u8] {
        self.segment.data
    }

    #[inline]
    fn name(&self) -> Option<&str> {
        self.segment.name().ok()
    }
}

impl<'a> fmt::Debug for MachOSectionIterator<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // It's painful to do much better than this
        f.debug_struct("MachOSectionIterator").finish()
    }
}

impl<'a> Iterator for MachOSectionIterator<'a> {
    type Item = MachOSection<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if let Some(ref mut sections) = self.sections {
                while let Some(section) = sections.next() {
                    if let Ok((section, data)) = section {
                        return Some(MachOSection { section, data });
                    }
                }
            }
            match self.segments.next() {
                None => return None,
                Some(segment) => {
                    self.sections = Some(segment.into_iter());
                }
            }
        }
    }
}

impl<'a> ObjectSection<'a> for MachOSection<'a> {
    #[inline]
    fn address(&self) -> u64 {
        self.section.addr
    }

    #[inline]
    fn size(&self) -> u64 {
        self.section.size
    }

    #[inline]
    fn data(&self) -> &'a [u8] {
        self.data
    }

    #[inline]
    fn name(&self) -> Option<&str> {
        self.section.name().ok()
    }

    #[inline]
    fn segment_name(&self) -> Option<&str> {
        self.section.segname().ok()
    }
}
<commit_msg>Fix clippy warning<commit_after>use std::cmp::Ordering;
use std::fmt;
use std::slice;

use goblin::mach;

use {Machine, Object, ObjectSection, ObjectSegment, SectionKind, Symbol, SymbolKind};

/// A Mach-O object file.
#[derive(Debug)]
pub struct MachOFile<'a> {
    macho: mach::MachO<'a>,
}

/// An iterator over the segments of a `MachOFile`.
#[derive(Debug)]
pub struct MachOSegmentIterator<'a> {
    segments: slice::Iter<'a, mach::segment::Segment<'a>>,
}

/// A segment of a `MachOFile`.
#[derive(Debug)]
pub struct MachOSegment<'a> {
    segment: &'a mach::segment::Segment<'a>,
}

/// An iterator over the sections of a `MachOFile`.
pub struct MachOSectionIterator<'a> {
    segments: slice::Iter<'a, mach::segment::Segment<'a>>,
    sections: Option<mach::segment::SectionIterator<'a>>,
}

/// A section of a `MachOFile`.
#[derive(Debug)]
pub struct MachOSection<'a> {
    section: mach::segment::Section,
    data: mach::segment::SectionData<'a>,
}

impl<'a> MachOFile<'a> {
    /// Get the Mach-O headers of the file.
    // TODO: this is temporary to allow access to features this crate doesn't provide yet
    #[inline]
    pub fn macho(&self) -> &mach::MachO<'a> {
        &self.macho
    }
}

impl<'a> Object<'a> for MachOFile<'a> {
    type Segment = MachOSegment<'a>;
    type SegmentIterator = MachOSegmentIterator<'a>;
    type Section = MachOSection<'a>;
    type SectionIterator = MachOSectionIterator<'a>;

    fn parse(data: &'a [u8]) -> Result<Self, &'static str> {
        let macho = mach::MachO::parse(data, 0).map_err(|_| "Could not parse Mach-O header")?;
        Ok(MachOFile { macho })
    }

    fn machine(&self) -> Machine {
        match self.macho.header.cputype {
            mach::cputype::CPU_TYPE_ARM => Machine::Arm,
            mach::cputype::CPU_TYPE_ARM64 => Machine::Arm64,
            mach::cputype::CPU_TYPE_X86 => Machine::X86,
            mach::cputype::CPU_TYPE_X86_64 => Machine::X86_64,
            _ => Machine::Other,
        }
    }

    fn segments(&'a self) -> MachOSegmentIterator<'a> {
        MachOSegmentIterator {
            segments: self.macho.segments.iter(),
        }
    }

    fn section_data_by_name(&self, section_name: &str) -> Option<&'a [u8]> {
        // Translate the "." prefix to the "__" prefix used by OSX/Mach-O, eg
        // ".debug_info" to "__debug_info".
        let (system_section, section_name) = if section_name.starts_with('.') {
            (true, &section_name[1..])
        } else {
            (false, section_name)
        };
        let cmp_section_name = |name: &str| if system_section {
            name.starts_with("__") && section_name == &name[2..]
        } else {
            section_name == name
        };

        for segment in &self.macho.segments {
            for section in segment {
                if let Ok((section, data)) = section {
                    if let Ok(name) = section.name() {
                        if cmp_section_name(name) {
                            return Some(data);
                        }
                    }
                }
            }
        }
        None
    }

    fn sections(&'a self) -> MachOSectionIterator<'a> {
        MachOSectionIterator {
            segments: self.macho.segments.iter(),
            sections: None,
        }
    }

    fn symbols(&self) -> Vec<Symbol<'a>> {
        // Determine section kinds and end addresses.
        // The section kinds are inherited by symbols in those sections.
        // The section end addresses are needed for calculating symbol sizes.
        let mut section_kinds = Vec::new();
        let mut section_ends = Vec::new();
        for segment in &self.macho.segments {
            for section in segment {
                if let Ok((section, _)) = section {
                    let sectname = section.name().ok();
                    let segname = section.segname().ok();
                    let (section_kind, symbol_kind) = match (segname, sectname) {
                        (Some("__TEXT"), Some("__text")) => (SectionKind::Text, SymbolKind::Text),
                        (Some("__DATA"), Some("__data")) => (SectionKind::Data, SymbolKind::Data),
                        (Some("__DATA"), Some("__bss")) => {
                            (SectionKind::UninitializedData, SymbolKind::Data)
                        }
                        _ => (SectionKind::Other, SymbolKind::Unknown),
                    };
                    let section_index = section_kinds.len();
                    section_kinds.push((section_kind, symbol_kind));
                    section_ends.push(Symbol {
                        kind: SymbolKind::Section,
                        section: section_index + 1,
                        section_kind: Some(section_kind),
                        global: false,
                        name: None,
                        address: section.addr + section.size,
                        size: 0,
                    });
                } else {
                    // Add placeholder so that indexing works.
                    section_kinds.push((SectionKind::Unknown, SymbolKind::Unknown));
                }
            }
        }

        let mut symbols = Vec::new();
        for sym in self.macho.symbols() {
            if let Ok((name, nlist)) = sym {
                // Skip STAB debugging symbols.
                // FIXME: use N_STAB constant
                if nlist.n_type & 0xe0 != 0 {
                    continue;
                }
                let n_type = nlist.n_type & mach::symbols::NLIST_TYPE_MASK;
                let (section_kind, kind) = if n_type == mach::symbols::N_SECT {
                    if nlist.n_sect == 0 || nlist.n_sect - 1 >= section_kinds.len() {
                        (None, SymbolKind::Unknown)
                    } else {
                        let (section_kind, kind) = section_kinds[nlist.n_sect - 1];
                        (Some(section_kind), kind)
                    }
                } else {
                    (None, SymbolKind::Unknown)
                };
                symbols.push(Symbol {
                    kind,
                    section: nlist.n_sect,
                    section_kind,
                    global: nlist.is_global(),
                    name: Some(name),
                    address: nlist.n_value,
                    size: 0,
                });
            }
        }

        {
            // Calculate symbol sizes by sorting and finding the next symbol.
            let mut symbol_refs = Vec::with_capacity(symbols.len() + section_ends.len());
            symbol_refs.extend(symbols.iter_mut().filter(|s| !s.is_undefined()));
            symbol_refs.extend(section_ends.iter_mut());
            symbol_refs.sort_by(|a, b| {
                let ord = a.section.cmp(&b.section);
                if ord != Ordering::Equal {
                    return ord;
                }
                let ord = a.address.cmp(&b.address);
                if ord != Ordering::Equal {
                    return ord;
                }
                // Place the dummy end of section symbols last.
                (a.kind == SymbolKind::Section).cmp(&(b.kind == SymbolKind::Section))
            });

            for i in 0..symbol_refs.len() {
                let (before, after) = symbol_refs.split_at_mut(i + 1);
                let sym = &mut before[i];
                if sym.kind != SymbolKind::Section {
                    if let Some(next) = after
                        .iter()
                        .skip_while(|x| {
                            x.kind != SymbolKind::Section && x.address == sym.address
                        })
                        .next()
                    {
                        sym.size = next.address - sym.address;
                    }
                }
            }
        }

        symbols
    }

    #[inline]
    fn is_little_endian(&self) -> bool {
        self.macho.header.is_little_endian()
    }
}

impl<'a> Iterator for MachOSegmentIterator<'a> {
    type Item = MachOSegment<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        self.segments.next().map(|segment| MachOSegment { segment })
    }
}

impl<'a> ObjectSegment<'a> for MachOSegment<'a> {
    #[inline]
    fn address(&self) -> u64 {
        self.segment.vmaddr
    }

    #[inline]
    fn size(&self) -> u64 {
        self.segment.vmsize
    }

    #[inline]
    fn data(&self) -> &'a [u8] {
        self.segment.data
    }

    #[inline]
    fn name(&self) -> Option<&str> {
        self.segment.name().ok()
    }
}

impl<'a> fmt::Debug for MachOSectionIterator<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // It's painful to do much better than this
        f.debug_struct("MachOSectionIterator").finish()
    }
}

impl<'a> Iterator for MachOSectionIterator<'a> {
    type Item = MachOSection<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if let Some(ref mut sections) = self.sections {
                while let Some(section) = sections.next() {
                    if let Ok((section, data)) = section {
                        return Some(MachOSection { section, data });
                    }
                }
            }
            match self.segments.next() {
                None => return None,
                Some(segment) => {
                    self.sections = Some(segment.into_iter());
                }
            }
        }
    }
}

impl<'a> ObjectSection<'a> for MachOSection<'a> {
    #[inline]
    fn address(&self) -> u64 {
        self.section.addr
    }

    #[inline]
    fn size(&self) -> u64 {
        self.section.size
    }

    #[inline]
    fn data(&self) -> &'a [u8] {
        self.data
    }

    #[inline]
    fn name(&self) -> Option<&str> {
        self.section.name().ok()
    }

    #[inline]
    fn segment_name(&self) -> Option<&str> {
        self.section.segname().ok()
    }
}
<|endoftext|>


<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 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)
    }
}
<commit_msg>Fix parsing error (hotfix)<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 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>use core;
use core::mem;
use traits::checked_pow;
use traits::PrimInt;
use Integer;

/// Provides methods to compute an integer's square root, cube root,
/// and arbitrary `n`th root.
pub trait Roots: Integer {
    /// Returns the truncated principal `n`th root of an integer
    /// -- `if x >= 0 { ⌊ⁿ√x⌋ } else { ⌈ⁿ√x⌉ }`
    ///
    /// This is solving for `r` in `rⁿ = x`, rounding toward zero.
    /// If `x` is positive, the result will satisfy `rⁿ ≤ x < (r+1)ⁿ`.
    /// If `x` is negative and `n` is odd, then `(r-1)ⁿ < x ≤ rⁿ`.
    ///
    /// # Panics
    ///
    /// Panics if `n` is zero:
    ///
    /// ```should_panic
    /// # use num_integer::Roots;
    /// println!("can't compute ⁰√x : {}", 123.nth_root(0));
    /// ```
    ///
    /// or if `n` is even and `self` is negative:
    ///
    /// ```should_panic
    /// # use num_integer::Roots;
    /// println!("no imaginary numbers... {}", (-1).nth_root(10));
    /// ```
    ///
    /// # Examples
    ///
    /// ```
    /// use num_integer::Roots;
    ///
    /// let x: i32 = 12345;
    /// assert_eq!(x.nth_root(1), x);
    /// assert_eq!(x.nth_root(2), x.sqrt());
    /// assert_eq!(x.nth_root(3), x.cbrt());
    /// assert_eq!(x.nth_root(4), 10);
    /// assert_eq!(x.nth_root(13), 2);
    /// assert_eq!(x.nth_root(14), 1);
    /// assert_eq!(x.nth_root(std::u32::MAX), 1);
    ///
    /// assert_eq!(std::i32::MAX.nth_root(30), 2);
    /// assert_eq!(std::i32::MAX.nth_root(31), 1);
    /// assert_eq!(std::i32::MIN.nth_root(31), -2);
    /// assert_eq!((std::i32::MIN + 1).nth_root(31), -1);
    ///
    /// assert_eq!(std::u32::MAX.nth_root(31), 2);
    /// assert_eq!(std::u32::MAX.nth_root(32), 1);
    /// ```
    fn nth_root(&self, n: u32) -> Self;

    /// Returns the truncated principal square root of an integer -- `⌊√x⌋`
    ///
    /// This is solving for `r` in `r² = x`, rounding toward zero.
    /// The result will satisfy `r² ≤ x < (r+1)²`.
    ///
    /// # Panics
    ///
    /// Panics if `self` is less than zero:
    ///
    /// ```should_panic
    /// # use num_integer::Roots;
    /// println!("no imaginary numbers... {}", (-1).sqrt());
    /// ```
    ///
    /// # Examples
    ///
    /// ```
    /// use num_integer::Roots;
    ///
    /// let x: i32 = 12345;
    /// assert_eq!((x * x).sqrt(), x);
    /// assert_eq!((x * x + 1).sqrt(), x);
    /// assert_eq!((x * x - 1).sqrt(), x - 1);
    /// ```
    #[inline]
    fn sqrt(&self) -> Self {
        self.nth_root(2)
    }

    /// Returns the truncated principal cube root of an integer --
    /// `if x >= 0 { ⌊∛x⌋ } else { ⌈∛x⌉ }`
    ///
    /// This is solving for `r` in `r³ = x`, rounding toward zero.
    /// If `x` is positive, the result will satisfy `r³ ≤ x < (r+1)³`.
    /// If `x` is negative, then `(r-1)³ < x ≤ r³`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_integer::Roots;
    ///
    /// let x: i32 = 1234;
    /// assert_eq!((x * x * x).cbrt(), x);
    /// assert_eq!((x * x * x + 1).cbrt(), x);
    /// assert_eq!((x * x * x - 1).cbrt(), x - 1);
    ///
    /// assert_eq!((-(x * x * x)).cbrt(), -x);
    /// assert_eq!((-(x * x * x + 1)).cbrt(), -x);
    /// assert_eq!((-(x * x * x - 1)).cbrt(), -(x - 1));
    /// ```
    #[inline]
    fn cbrt(&self) -> Self {
        self.nth_root(3)
    }
}

/// Returns the truncated principal square root of an integer --
/// see [Roots::sqrt](trait.Roots.html#method.sqrt).
#[inline]
pub fn sqrt<T: Roots>(x: T) -> T {
    x.sqrt()
}

/// Returns the truncated principal cube root of an integer --
/// see [Roots::cbrt](trait.Roots.html#method.cbrt).
#[inline]
pub fn cbrt<T: Roots>(x: T) -> T {
    x.cbrt()
}

/// Returns the truncated principal `n`th root of an integer --
/// see [Roots::nth_root](trait.Roots.html#tymethod.nth_root).
#[inline]
pub fn nth_root<T: Roots>(x: T, n: u32) -> T {
    x.nth_root(n)
}

macro_rules! signed_roots {
    ($T:ty, $U:ty) => {
        impl Roots for $T {
            #[inline]
            fn nth_root(&self, n: u32) -> Self {
                if *self >= 0 {
                    (*self as $U).nth_root(n) as Self
                } else {
                    assert!(n.is_odd(), "even roots of a negative are imaginary");
                    -((self.wrapping_neg() as $U).nth_root(n) as Self)
                }
            }

            #[inline]
            fn sqrt(&self) -> Self {
                assert!(*self >= 0, "the square root of a negative is imaginary");
                (*self as $U).sqrt() as Self
            }

            #[inline]
            fn cbrt(&self) -> Self {
                if *self >= 0 {
                    (*self as $U).cbrt() as Self
                } else {
                    -((self.wrapping_neg() as $U).cbrt() as Self)
                }
            }
        }
    };
}

signed_roots!(i8, u8);
signed_roots!(i16, u16);
signed_roots!(i32, u32);
signed_roots!(i64, u64);
#[cfg(has_i128)]
signed_roots!(i128, u128);
signed_roots!(isize, usize);

#[inline]
fn fixpoint<T, F>(mut x: T, f: F) -> T
where
    T: Integer + Copy,
    F: Fn(T) -> T,
{
    let mut xn = f(x);
    while x < xn {
        x = xn;
        xn = f(x);
    }
    while x > xn {
        x = xn;
        xn = f(x);
    }
    x
}

#[inline]
fn bits<T>() -> u32 {
    8 * mem::size_of::<T>() as u32
}

#[inline]
fn log2<T: PrimInt>(x: T) -> u32 {
    debug_assert!(x > T::zero());
    bits::<T>() - 1 - x.leading_zeros()
}

macro_rules! unsigned_roots {
    ($T:ident) => {
        impl Roots for $T {
            fn nth_root(&self, n: u32) -> Self {
                // Specialize small roots
                match n {
                    0 => panic!("can't find a root of degree 0!"),
                    1 => return *self,
                    2 => return self.sqrt(),
                    3 => return self.cbrt(),
                    _ => (),
                }

                // The root of values less than 2ⁿ can only be 0 or 1.
                if bits::<$T>() <= n || *self < (1 << n) {
                    return (*self > 0) as $T;
                }

                if bits::<$T>() > 64 {
                    // 128-bit division is slow, so do a bitwise `nth_root` until it's small enough.
                    return if *self <= core::u64::MAX as $T {
                        (*self as u64).nth_root(n) as $T
                    } else {
                        let lo = (self >> n).nth_root(n) << 1;
                        let hi = lo + 1;
                        // 128-bit `checked_mul` also involves division, but we can't always
                        // compute `hiⁿ` without risking overflow.  Try to avoid it though...
                        if hi.next_power_of_two().trailing_zeros() * n >= bits::<$T>() {
                            match checked_pow(hi, n as usize) {
                                Some(x) if x <= *self => hi,
                                _ => lo,
                            }
                        } else {
                            if hi.pow(n) <= *self {
                                hi
                            } else {
                                lo
                            }
                        }
                    };
                }

                #[cfg(feature = "std")]
                #[inline]
                fn guess(x: $T, n: u32) -> $T {
                    // for smaller inputs, `f64` doesn't justify its cost.
                    if bits::<$T>() <= 32 || x <= core::u32::MAX as $T {
                        1 << ((log2(x) + n - 1) / n)
                    } else {
                        ((x as f64).ln() / f64::from(n)).exp() as $T
                    }
                }

                #[cfg(not(feature = "std"))]
                #[inline]
                fn guess(x: $T, n: u32) -> $T {
                    1 << ((log2(x) + n - 1) / n)
                }

                // https://en.wikipedia.org/wiki/Nth_root_algorithm
                let n1 = n - 1;
                let next = |x: $T| {
                    let y = match checked_pow(x, n1 as usize) {
                        Some(ax) => self / ax,
                        None => 0,
                    };
                    (y + x * n1 as $T) / n as $T
                };
                fixpoint(guess(*self, n), next)
            }

            fn sqrt(&self) -> Self {
                if bits::<$T>() > 64 {
                    // 128-bit division is slow, so do a bitwise `sqrt` until it's small enough.
                    // https://en.wikipedia.org/wiki/Integer_square_root#Using_bitwise_operations
                    return if *self <= core::u64::MAX as $T {
                        (*self as u64).sqrt() as $T
                    } else {
                        let lo = (self >> 2u32).sqrt() << 1;
                        let hi = lo + 1;
                        if hi * hi <= *self {
                            hi
                        } else {
                            lo
                        }
                    };
                }

                if *self < 4 {
                    return (*self > 0) as Self;
                }

                #[cfg(feature = "std")]
                #[inline]
                fn guess(x: $T) -> $T {
                    (x as f64).sqrt() as $T
                }

                #[cfg(not(feature = "std"))]
                #[inline]
                fn guess(x: $T) -> $T {
                    1 << ((log2(x) + 1) / 2)
                }

                // https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
                let next = |x: $T| (self / x + x) >> 1;
                fixpoint(guess(*self), next)
            }

            fn cbrt(&self) -> Self {
                if bits::<$T>() > 64 {
                    // 128-bit division is slow, so do a bitwise `cbrt` until it's small enough.
                    return if *self <= core::u64::MAX as $T {
                        (*self as u64).cbrt() as $T
                    } else {
                        let lo = (self >> 3u32).cbrt() << 1;
                        let hi = lo + 1;
                        if hi * hi * hi <= *self {
                            hi
                        } else {
                            lo
                        }
                    };
                }

                if bits::<$T>() <= 32 {
                    // Implementation based on Hacker's Delight `icbrt2`
                    let mut x = *self;
                    let mut y2 = 0;
                    let mut y = 0;
                    let smax = bits::<$T>() / 3;
                    for s in (0..smax + 1).rev() {
                        let s = s * 3;
                        y2 *= 4;
                        y *= 2;
                        let b = 3 * (y2 + y) + 1;
                        if x >> s >= b {
                            x -= b << s;
                            y2 += 2 * y + 1;
                            y += 1;
                        }
                    }
                    return y;
                }

                if *self < 8 {
                    return (*self > 0) as Self;
                }
                if *self <= core::u32::MAX as $T {
                    return (*self as u32).cbrt() as $T;
                }

                #[cfg(feature = "std")]
                #[inline]
                fn guess(x: $T) -> $T {
                    (x as f64).cbrt() as $T
                }

                #[cfg(not(feature = "std"))]
                #[inline]
                fn guess(x: $T) -> $T {
                    1 << ((log2(x) + 2) / 3)
                }

                // https://en.wikipedia.org/wiki/Cube_root#Numerical_methods
                let next = |x: $T| (self / (x * x) + x * 2) / 3;
                fixpoint(guess(*self), next)
            }
        }
    };
}

unsigned_roots!(u8);
unsigned_roots!(u16);
unsigned_roots!(u32);
unsigned_roots!(u64);
#[cfg(has_i128)]
unsigned_roots!(u128);
unsigned_roots!(usize);
<commit_msg>elide pass-by-ref in root functions<commit_after>use core;
use core::mem;
use traits::checked_pow;
use traits::PrimInt;
use Integer;

/// Provides methods to compute an integer's square root, cube root,
/// and arbitrary `n`th root.
pub trait Roots: Integer {
    /// Returns the truncated principal `n`th root of an integer
    /// -- `if x >= 0 { ⌊ⁿ√x⌋ } else { ⌈ⁿ√x⌉ }`
    ///
    /// This is solving for `r` in `rⁿ = x`, rounding toward zero.
    /// If `x` is positive, the result will satisfy `rⁿ ≤ x < (r+1)ⁿ`.
    /// If `x` is negative and `n` is odd, then `(r-1)ⁿ < x ≤ rⁿ`.
    ///
    /// # Panics
    ///
    /// Panics if `n` is zero:
    ///
    /// ```should_panic
    /// # use num_integer::Roots;
    /// println!("can't compute ⁰√x : {}", 123.nth_root(0));
    /// ```
    ///
    /// or if `n` is even and `self` is negative:
    ///
    /// ```should_panic
    /// # use num_integer::Roots;
    /// println!("no imaginary numbers... {}", (-1).nth_root(10));
    /// ```
    ///
    /// # Examples
    ///
    /// ```
    /// use num_integer::Roots;
    ///
    /// let x: i32 = 12345;
    /// assert_eq!(x.nth_root(1), x);
    /// assert_eq!(x.nth_root(2), x.sqrt());
    /// assert_eq!(x.nth_root(3), x.cbrt());
    /// assert_eq!(x.nth_root(4), 10);
    /// assert_eq!(x.nth_root(13), 2);
    /// assert_eq!(x.nth_root(14), 1);
    /// assert_eq!(x.nth_root(std::u32::MAX), 1);
    ///
    /// assert_eq!(std::i32::MAX.nth_root(30), 2);
    /// assert_eq!(std::i32::MAX.nth_root(31), 1);
    /// assert_eq!(std::i32::MIN.nth_root(31), -2);
    /// assert_eq!((std::i32::MIN + 1).nth_root(31), -1);
    ///
    /// assert_eq!(std::u32::MAX.nth_root(31), 2);
    /// assert_eq!(std::u32::MAX.nth_root(32), 1);
    /// ```
    fn nth_root(&self, n: u32) -> Self;

    /// Returns the truncated principal square root of an integer -- `⌊√x⌋`
    ///
    /// This is solving for `r` in `r² = x`, rounding toward zero.
    /// The result will satisfy `r² ≤ x < (r+1)²`.
    ///
    /// # Panics
    ///
    /// Panics if `self` is less than zero:
    ///
    /// ```should_panic
    /// # use num_integer::Roots;
    /// println!("no imaginary numbers... {}", (-1).sqrt());
    /// ```
    ///
    /// # Examples
    ///
    /// ```
    /// use num_integer::Roots;
    ///
    /// let x: i32 = 12345;
    /// assert_eq!((x * x).sqrt(), x);
    /// assert_eq!((x * x + 1).sqrt(), x);
    /// assert_eq!((x * x - 1).sqrt(), x - 1);
    /// ```
    #[inline]
    fn sqrt(&self) -> Self {
        self.nth_root(2)
    }

    /// Returns the truncated principal cube root of an integer --
    /// `if x >= 0 { ⌊∛x⌋ } else { ⌈∛x⌉ }`
    ///
    /// This is solving for `r` in `r³ = x`, rounding toward zero.
    /// If `x` is positive, the result will satisfy `r³ ≤ x < (r+1)³`.
    /// If `x` is negative, then `(r-1)³ < x ≤ r³`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_integer::Roots;
    ///
    /// let x: i32 = 1234;
    /// assert_eq!((x * x * x).cbrt(), x);
    /// assert_eq!((x * x * x + 1).cbrt(), x);
    /// assert_eq!((x * x * x - 1).cbrt(), x - 1);
    ///
    /// assert_eq!((-(x * x * x)).cbrt(), -x);
    /// assert_eq!((-(x * x * x + 1)).cbrt(), -x);
    /// assert_eq!((-(x * x * x - 1)).cbrt(), -(x - 1));
    /// ```
    #[inline]
    fn cbrt(&self) -> Self {
        self.nth_root(3)
    }
}

/// Returns the truncated principal square root of an integer --
/// see [Roots::sqrt](trait.Roots.html#method.sqrt).
#[inline]
pub fn sqrt<T: Roots>(x: T) -> T {
    x.sqrt()
}

/// Returns the truncated principal cube root of an integer --
/// see [Roots::cbrt](trait.Roots.html#method.cbrt).
#[inline]
pub fn cbrt<T: Roots>(x: T) -> T {
    x.cbrt()
}

/// Returns the truncated principal `n`th root of an integer --
/// see [Roots::nth_root](trait.Roots.html#tymethod.nth_root).
#[inline]
pub fn nth_root<T: Roots>(x: T, n: u32) -> T {
    x.nth_root(n)
}

macro_rules! signed_roots {
    ($T:ty, $U:ty) => {
        impl Roots for $T {
            #[inline]
            fn nth_root(&self, n: u32) -> Self {
                if *self >= 0 {
                    (*self as $U).nth_root(n) as Self
                } else {
                    assert!(n.is_odd(), "even roots of a negative are imaginary");
                    -((self.wrapping_neg() as $U).nth_root(n) as Self)
                }
            }

            #[inline]
            fn sqrt(&self) -> Self {
                assert!(*self >= 0, "the square root of a negative is imaginary");
                (*self as $U).sqrt() as Self
            }

            #[inline]
            fn cbrt(&self) -> Self {
                if *self >= 0 {
                    (*self as $U).cbrt() as Self
                } else {
                    -((self.wrapping_neg() as $U).cbrt() as Self)
                }
            }
        }
    };
}

signed_roots!(i8, u8);
signed_roots!(i16, u16);
signed_roots!(i32, u32);
signed_roots!(i64, u64);
#[cfg(has_i128)]
signed_roots!(i128, u128);
signed_roots!(isize, usize);

#[inline]
fn fixpoint<T, F>(mut x: T, f: F) -> T
where
    T: Integer + Copy,
    F: Fn(T) -> T,
{
    let mut xn = f(x);
    while x < xn {
        x = xn;
        xn = f(x);
    }
    while x > xn {
        x = xn;
        xn = f(x);
    }
    x
}

#[inline]
fn bits<T>() -> u32 {
    8 * mem::size_of::<T>() as u32
}

#[inline]
fn log2<T: PrimInt>(x: T) -> u32 {
    debug_assert!(x > T::zero());
    bits::<T>() - 1 - x.leading_zeros()
}

macro_rules! unsigned_roots {
    ($T:ident) => {
        impl Roots for $T {
            #[inline]
            fn nth_root(&self, n: u32) -> Self {
                fn go(a: $T, n: u32) -> $T {
                    // Specialize small roots
                    match n {
                        0 => panic!("can't find a root of degree 0!"),
                        1 => return a,
                        2 => return a.sqrt(),
                        3 => return a.cbrt(),
                        _ => (),
                    }

                    // The root of values less than 2ⁿ can only be 0 or 1.
                    if bits::<$T>() <= n || a < (1 << n) {
                        return (a > 0) as $T;
                    }

                    if bits::<$T>() > 64 {
                        // 128-bit division is slow, so do a bitwise `nth_root` until it's small enough.
                        return if a <= core::u64::MAX as $T {
                            (a as u64).nth_root(n) as $T
                        } else {
                            let lo = (a >> n).nth_root(n) << 1;
                            let hi = lo + 1;
                            // 128-bit `checked_mul` also involves division, but we can't always
                            // compute `hiⁿ` without risking overflow.  Try to avoid it though...
                            if hi.next_power_of_two().trailing_zeros() * n >= bits::<$T>() {
                                match checked_pow(hi, n as usize) {
                                    Some(x) if x <= a => hi,
                                    _ => lo,
                                }
                            } else {
                                if hi.pow(n) <= a {
                                    hi
                                } else {
                                    lo
                                }
                            }
                        };
                    }

                    #[cfg(feature = "std")]
                    #[inline]
                    fn guess(x: $T, n: u32) -> $T {
                        // for smaller inputs, `f64` doesn't justify its cost.
                        if bits::<$T>() <= 32 || x <= core::u32::MAX as $T {
                            1 << ((log2(x) + n - 1) / n)
                        } else {
                            ((x as f64).ln() / f64::from(n)).exp() as $T
                        }
                    }

                    #[cfg(not(feature = "std"))]
                    #[inline]
                    fn guess(x: $T, n: u32) -> $T {
                        1 << ((log2(x) + n - 1) / n)
                    }

                    // https://en.wikipedia.org/wiki/Nth_root_algorithm
                    let n1 = n - 1;
                    let next = |x: $T| {
                        let y = match checked_pow(x, n1 as usize) {
                            Some(ax) => a / ax,
                            None => 0,
                        };
                        (y + x * n1 as $T) / n as $T
                    };
                    fixpoint(guess(a, n), next)
                }
                go(*self, n)
            }

            #[inline]
            fn sqrt(&self) -> Self {
                fn go(a: $T) -> $T {
                    if bits::<$T>() > 64 {
                        // 128-bit division is slow, so do a bitwise `sqrt` until it's small enough.
                        return if a <= core::u64::MAX as $T {
                            (a as u64).sqrt() as $T
                        } else {
                            let lo = (a >> 2u32).sqrt() << 1;
                            let hi = lo + 1;
                            if hi * hi <= a {
                                hi
                            } else {
                                lo
                            }
                        };
                    }

                    if a < 4 {
                        return (a > 0) as $T;
                    }

                    #[cfg(feature = "std")]
                    #[inline]
                    fn guess(x: $T) -> $T {
                        (x as f64).sqrt() as $T
                    }

                    #[cfg(not(feature = "std"))]
                    #[inline]
                    fn guess(x: $T) -> $T {
                        1 << ((log2(x) + 1) / 2)
                    }

                    // https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method
                    let next = |x: $T| (a / x + x) >> 1;
                    fixpoint(guess(a), next)
                }
                go(*self)
            }

            #[inline]
            fn cbrt(&self) -> Self {
                fn go(a: $T) -> $T {
                    if bits::<$T>() > 64 {
                        // 128-bit division is slow, so do a bitwise `cbrt` until it's small enough.
                        return if a <= core::u64::MAX as $T {
                            (a as u64).cbrt() as $T
                        } else {
                            let lo = (a >> 3u32).cbrt() << 1;
                            let hi = lo + 1;
                            if hi * hi * hi <= a {
                                hi
                            } else {
                                lo
                            }
                        };
                    }

                    if bits::<$T>() <= 32 {
                        // Implementation based on Hacker's Delight `icbrt2`
                        let mut x = a ;
                        let mut y2 = 0;
                        let mut y = 0;
                        let smax = bits::<$T>() / 3;
                        for s in (0..smax + 1).rev() {
                            let s = s * 3;
                            y2 *= 4;
                            y *= 2;
                            let b = 3 * (y2 + y) + 1;
                            if x >> s >= b {
                                x -= b << s;
                                y2 += 2 * y + 1;
                                y += 1;
                            }
                        }
                        return y;
                    }

                    if a < 8 {
                        return (a > 0) as $T;
                    }
                    if a <= core::u32::MAX as $T {
                        return (a as u32).cbrt() as $T;
                    }

                    #[cfg(feature = "std")]
                    #[inline]
                    fn guess(x: $T) -> $T {
                        (x as f64).cbrt() as $T
                    }

                    #[cfg(not(feature = "std"))]
                    #[inline]
                    fn guess(x: $T) -> $T {
                        1 << ((log2(x) + 2) / 3)
                    }

                    // https://en.wikipedia.org/wiki/Cube_root#Numerical_methods
                    let next = |x: $T| (a / (x * x) + x * 2) / 3;
                    fixpoint(guess(a), next)
                }
                go(*self)
            }
        }
    };
}

unsigned_roots!(u8);
unsigned_roots!(u16);
unsigned_roots!(u32);
unsigned_roots!(u64);
#[cfg(has_i128)]
unsigned_roots!(u128);
unsigned_roots!(usize);
<|endoftext|>


<commit_before>
use ggez;
use ggez::GameResult;
use ggez::conf;
use ggez::event;
use ggez::event::EventHandler;

use std::collections::BTreeMap;
use std::time::Duration;

pub trait SavedScene {
    fn load(&self) -> Box<Scene>;
    fn name(&self) -> &str;
}

pub trait Scene: EventHandler {
    fn unload(&mut self) -> Box<SavedScene>;
}

/// The GameData trait just provides
/// a method to create a new object of type T, instantiating
/// your global game data.
///
/// It also provides a method that is called to generate
/// the first scene of your game.
pub trait GameData
    where Self: Sized
{
    fn load(ctx: &mut ggez::Context, conf: &conf::Conf) -> GameResult<Self>;
    fn starting_scene() -> Box<SavedScene>;
}

pub struct SceneStore<T> {
    states: BTreeMap<String, Box<SavedScene>>,
    pub game_data: T,
}

impl<T> SceneStore<T> {
    pub fn add<S: SavedScene + 'static>(&mut self, scene_state: S) {
        self.states.insert(scene_state.name().to_string(), Box::new(scene_state));
    }
}

/// A SceneManager is a GameState that handles Scene's
/// and switches from one to another when requested.
///
/// The stuff you would normally store in your GameState
/// type should implement GameData and go into the T type.
pub struct SceneManager<T> {
    store: SceneStore<T>,
    current: Box<Scene>,
    next_scene: Option<String>,
}

impl<T> EventHandler for SceneManager<T>
{
    fn update(&mut self, ctx: &mut ggez::Context, dt: Duration) -> GameResult<()> {
        // TODO: Get rid of this hacky clone!
        if let Some(ref scene_name) = self.next_scene.clone() {
            self.switch_scene(&scene_name)?;
        }
        self.current.update(ctx, dt)?;
        Ok(())
    }

    fn draw(&mut self, ctx: &mut ggez::Context) -> GameResult<()> {
        self.current.draw(ctx)
    }

    fn mouse_button_down_event(&mut self, button: event::MouseButton, x: i32, y: i32) {
        self.current.mouse_button_down_event(button, x, y)
    }

    fn mouse_button_up_event(&mut self, button: event::MouseButton, x: i32, y: i32) {
        self.current.mouse_button_up_event(button, x, y)
    }

    fn mouse_motion_event(&mut self,
                          _state: event::MouseState,
                          _x: i32,
                          _y: i32,
                          _xrel: i32,
                          _yrel: i32) {
        self.current.mouse_motion_event(_state, _x, _y, _xrel, _yrel)
    }

    fn mouse_wheel_event(&mut self, _x: i32, _y: i32) {
        self.current.mouse_wheel_event(_x, _y)
    }

    fn key_down_event(&mut self,
                      _keycode: event::Keycode,
                      _keymod: event::Mod,
                      _repeat: bool) {
        self.current.key_down_event(_keycode, _keymod, _repeat)
    }

    fn key_up_event(&mut self,
                    _keycode: event::Keycode,
                    _keymod: event::Mod,
                    _repeat: bool) {
        self.current.key_up_event(_keycode, _keymod, _repeat)
    }

    fn focus_event(&mut self, _gained: bool) {
        self.current.focus_event(_gained)
    }

    /// Called upon a quit event.  If it returns true,
    /// the game does not exit.
    fn quit_event(&mut self) -> bool {
        self.current.quit_event()
    }
}

impl<T> SceneManager<T> {
    /// This lets us create a SceneManager by providing the data for it,
    /// instead of having it implicitly created via the GameData trait.
    fn new(starting_scene_state: Box<SavedScene>, game_data: T) -> Self {
        let starting_scene = starting_scene_state.load();
        let mut scenes: BTreeMap<String, Box<SavedScene>> = BTreeMap::new();
        scenes.insert(starting_scene_state.name().to_string(),
                      starting_scene_state);
        let store = SceneStore {
            states: scenes,

            game_data: game_data,
        };
        let sm = SceneManager {
            current: starting_scene,
            store: store,
            next_scene: None,
        };
        sm
    }

    pub fn current(&self) -> &Scene {
        &*self.current
    }

    pub fn current_mut(&mut self) -> &mut Scene {
        &mut *self.current
    }

    pub fn switch_scene(&mut self, scene_name: &str) -> GameResult<()> {
        // Save current scene
        let old_scene_state = self.current.unload();
        let old_scene_name = old_scene_state.name().to_string();
        self.store.states.insert(old_scene_name, old_scene_state);
        // Then load the new one.
        if let Some(scene_state) = self.store.states.get_mut(scene_name) {
            let new_scene = scene_state.load();
            self.current = new_scene;
            Ok(())
        } else {
            let msg = format!("SceneManager: Asked to load scene {} but it did not exist?",
                              scene_name);
            Err(ggez::GameError::ResourceNotFound(msg, vec![]))
        }
    }
}

#[cfg(test)]
mod tests {

    use ggez;
    use ggez::GameResult;
    use ggez::event::EventHandler;

    use std::time::Duration;

    use super::{Scene, SavedScene, SceneManager, SceneStore};

    #[derive(Clone, Debug)]
    struct TestSavedScene {
        value: i32,
        name: String,
    }

    impl SavedScene for TestSavedScene {
        fn load(&self) -> Box<Scene> {
            Box::new(TestScene(self.clone()))
        }
        fn name(&self) -> &str {
            &self.name
        }
    }

    #[derive(Clone, Debug)]
    struct TestScene(TestSavedScene);

    impl EventHandler for TestScene {
        fn update(&mut self,
                  _ctx: &mut ggez::Context,
                  _dt: Duration)
                  -> GameResult<()> {
            Ok(())
        }

        fn draw(&mut self,
                _ctx: &mut ggez::Context)
                -> GameResult<()> {
            Ok(())
        }

    }

    impl Scene for TestScene {
        fn unload(&mut self) -> Box<SavedScene> {
            Box::new(self.0.clone())
        }
    }

    #[test]
    fn test_scene_switching() {
        let default_scene = TestSavedScene {
            name: "default scene".to_string(),
            value: 42,
        };
        let new_scene = TestSavedScene {
            name: "other scene".to_string(),
            value: 23,
        };
        let mut sm = SceneManager::new(Box::new(default_scene), ());
        sm.store.add(new_scene);

        {
            let s = sm.current_mut().unload();
            assert_eq!(s.name(), "default scene");
        }
        let res = sm.switch_scene("other scene");
        assert!(res.is_ok());

        {
            let s = sm.current_mut().unload();
            assert_eq!(s.name(), "other scene");
        }

        let res = sm.switch_scene("non existent scene");
        assert!(res.is_err());
    }

}
<commit_msg>Gnawing on scene manager.  Augh.<commit_after>
use ggez;
use ggez::GameResult;
use ggez::conf;
use ggez::event;
use ggez::event::EventHandler;

use std::collections::BTreeMap;
use std::time::Duration;

pub trait SavedScene {
    fn load(&self) -> Box<Scene>;
    fn name(&self) -> &str;
}

pub trait Scene: EventHandler {
    fn unload(&mut self) -> Box<SavedScene>;
}

/// A SceneManager is a GameState that handles Scene's
/// and switches from one to another when requested.
///
/// The stuff you would normally store in your GameState
/// type should go into the T type.
pub struct SceneManager<T> {
    states: BTreeMap<String, Box<SavedScene>>,
    pub game_data: T,
    current: Box<Scene>,
    next_scene: Option<String>,
}

impl<T> EventHandler for SceneManager<T>
{
    fn update(&mut self, ctx: &mut ggez::Context, dt: Duration) -> GameResult<()> {
        // TODO: Get rid of this hacky clone!
        if let Some(ref scene_name) = self.next_scene.clone() {
            self.switch_scene(&scene_name)?;
        }
        self.current.update(ctx, dt)?;
        Ok(())
    }

    fn draw(&mut self, ctx: &mut ggez::Context) -> GameResult<()> {
        self.current.draw(ctx)
    }

    fn mouse_button_down_event(&mut self, button: event::MouseButton, x: i32, y: i32) {
        self.current.mouse_button_down_event(button, x, y)
    }

    fn mouse_button_up_event(&mut self, button: event::MouseButton, x: i32, y: i32) {
        self.current.mouse_button_up_event(button, x, y)
    }

    fn mouse_motion_event(&mut self,
                          _state: event::MouseState,
                          _x: i32,
                          _y: i32,
                          _xrel: i32,
                          _yrel: i32) {
        self.current.mouse_motion_event(_state, _x, _y, _xrel, _yrel)
    }

    fn mouse_wheel_event(&mut self, _x: i32, _y: i32) {
        self.current.mouse_wheel_event(_x, _y)
    }

    fn key_down_event(&mut self,
                      _keycode: event::Keycode,
                      _keymod: event::Mod,
                      _repeat: bool) {
        self.current.key_down_event(_keycode, _keymod, _repeat)
    }

    fn key_up_event(&mut self,
                    _keycode: event::Keycode,
                    _keymod: event::Mod,
                    _repeat: bool) {
        self.current.key_up_event(_keycode, _keymod, _repeat)
    }

    fn focus_event(&mut self, _gained: bool) {
        self.current.focus_event(_gained)
    }

    /// Called upon a quit event.  If it returns true,
    /// the game does not exit.
    fn quit_event(&mut self) -> bool {
        self.current.quit_event()
    }
}

impl<T> SceneManager<T> {
    /// This lets us create a SceneManager by providing the data for it.
    fn new(starting_scene_state: Box<SavedScene>, game_data: T) -> Self {
        let starting_scene = starting_scene_state.load();
        let mut scenes: BTreeMap<String, Box<SavedScene>> = BTreeMap::new();
        scenes.insert(starting_scene_state.name().to_string(),
                      starting_scene_state);
        let sm = SceneManager {
            states: scenes,
            current: starting_scene,
            next_scene: None,
            game_data: game_data,
        };
        sm
    }

    pub fn add<S: SavedScene + 'static>(&mut self, scene_state: S) {
        self.states.insert(scene_state.name().to_string(), Box::new(scene_state));
    }

    pub fn current(&self) -> &Scene {
        &*self.current
    }

    pub fn current_mut(&mut self) -> &mut Scene {
        &mut *self.current
    }

    pub fn switch_scene(&mut self, scene_name: &str) -> GameResult<()> {
        // Save current scene
        let old_scene_state = self.current.unload();
        let old_scene_name = old_scene_state.name().to_string();
        self.states.insert(old_scene_name, old_scene_state);
        // Then load the new one.
        if let Some(scene_state) = self.states.get_mut(scene_name) {
            let new_scene = scene_state.load();
            self.current = new_scene;
            Ok(())
        } else {
            let msg = format!("SceneManager: Asked to load scene {} but it did not exist?",
                              scene_name);
            Err(ggez::GameError::ResourceNotFound(msg, vec![]))
        }
    }
}

#[cfg(test)]
mod tests {

    use ggez;
    use ggez::GameResult;
    use ggez::event::EventHandler;

    use std::time::Duration;

    use super::{Scene, SavedScene, SceneManager};

    #[derive(Clone, Debug)]
    struct TestSavedScene {
        value: i32,
        name: String,
    }

    impl SavedScene for TestSavedScene {
        fn load(&self) -> Box<Scene> {
            Box::new(TestScene(self.clone()))
        }
        fn name(&self) -> &str {
            &self.name
        }
    }

    #[derive(Clone, Debug)]
    struct TestScene(TestSavedScene);

    impl EventHandler for TestScene {
        fn update(&mut self,
                  _ctx: &mut ggez::Context,
                  _dt: Duration)
                  -> GameResult<()> {
            Ok(())
        }

        fn draw(&mut self,
                _ctx: &mut ggez::Context)
                -> GameResult<()> {
            Ok(())
        }

    }

    impl Scene for TestScene {
        fn unload(&mut self) -> Box<SavedScene> {
            Box::new(self.0.clone())
        }
    }

    #[test]
    fn test_scene_switching() {
        let default_scene = TestSavedScene {
            name: "default scene".to_string(),
            value: 42,
        };
        let new_scene = TestSavedScene {
            name: "other scene".to_string(),
            value: 23,
        };
        let mut sm = SceneManager::new(Box::new(default_scene), ());
        sm.add(new_scene);

        {
            let s = sm.current_mut().unload();
            assert_eq!(s.name(), "default scene");
        }
        let res = sm.switch_scene("other scene");
        assert!(res.is_ok());

        {
            let s = sm.current_mut().unload();
            assert_eq!(s.name(), "other scene");
        }

        let res = sm.switch_scene("non existent scene");
        assert!(res.is_err());
    }

}
<|endoftext|>


<commit_before>extern crate serde;

use core::fmt;
use self::serde::{de, Deserialize, Deserializer, Serialize, Serializer};

use Uuid;

impl Serialize for Uuid {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        if serializer.is_human_readable() {
            serializer.collect_str(&self.hyphenated())
        } else {
            serializer.serialize_bytes(self.as_bytes())
        }
    }
}

impl<'de> Deserialize<'de> for Uuid {
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        if deserializer.is_human_readable() {
            struct UuidStringVisitor;

            impl<'vi> de::Visitor<'vi> for UuidStringVisitor {
                type Value = Uuid;

                fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                    write!(formatter, "a UUID string")
                }

                fn visit_str<E: de::Error>(self, value: &str) -> Result<Uuid, E> {
                    value.parse::<Uuid>().map_err(E::custom)
                }

                fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Uuid, E> {
                    Uuid::from_bytes(value).map_err(E::custom)
                }
            }

            deserializer.deserialize_str(UuidStringVisitor)
        } else {
            struct UuidBytesVisitor;

            impl<'vi> de::Visitor<'vi> for UuidBytesVisitor {
                type Value = Uuid;

                fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                    write!(formatter, "bytes")
                }

                fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Uuid, E> {
                    Uuid::from_bytes(value).map_err(E::custom)
                }
            }

            deserializer.deserialize_bytes(UuidBytesVisitor)
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate serde_test;

    use self::serde_test::{assert_tokens, Configure, Token};

    use Uuid;

    #[test]
    fn test_serialize_readable() {
        let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
        let u = Uuid::parse_str(uuid_str).unwrap();
        assert_tokens(&u.readable(), &[Token::Str(uuid_str)]);
    }

    #[test]
    fn test_serialize_compact() {
        let uuid_bytes = b"F9168C5E-CEB2-4F";
        let u = Uuid::from_bytes(uuid_bytes).unwrap();
        assert_tokens(&u.compact(), &[Token::Bytes(uuid_bytes)]);
    }
}
<commit_msg>run fmt<commit_after>extern crate serde;

use self::serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use core::fmt;

use Uuid;

impl Serialize for Uuid {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        if serializer.is_human_readable() {
            serializer.collect_str(&self.hyphenated())
        } else {
            serializer.serialize_bytes(self.as_bytes())
        }
    }
}

impl<'de> Deserialize<'de> for Uuid {
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        if deserializer.is_human_readable() {
            struct UuidStringVisitor;

            impl<'vi> de::Visitor<'vi> for UuidStringVisitor {
                type Value = Uuid;

                fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                    write!(formatter, "a UUID string")
                }

                fn visit_str<E: de::Error>(self, value: &str) -> Result<Uuid, E> {
                    value.parse::<Uuid>().map_err(E::custom)
                }

                fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Uuid, E> {
                    Uuid::from_bytes(value).map_err(E::custom)
                }
            }

            deserializer.deserialize_str(UuidStringVisitor)
        } else {
            struct UuidBytesVisitor;

            impl<'vi> de::Visitor<'vi> for UuidBytesVisitor {
                type Value = Uuid;

                fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                    write!(formatter, "bytes")
                }

                fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Uuid, E> {
                    Uuid::from_bytes(value).map_err(E::custom)
                }
            }

            deserializer.deserialize_bytes(UuidBytesVisitor)
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate serde_test;

    use self::serde_test::{assert_tokens, Configure, Token};

    use Uuid;

    #[test]
    fn test_serialize_readable() {
        let uuid_str = "f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4";
        let u = Uuid::parse_str(uuid_str).unwrap();
        assert_tokens(&u.readable(), &[Token::Str(uuid_str)]);
    }

    #[test]
    fn test_serialize_compact() {
        let uuid_bytes = b"F9168C5E-CEB2-4F";
        let u = Uuid::from_bytes(uuid_bytes).unwrap();
        assert_tokens(&u.compact(), &[Token::Bytes(uuid_bytes)]);
    }
}
<|endoftext|>


<commit_before>pub fn clear() -> String {
    "\x1b[0;0H".to_string()
}

pub fn begin() -> String {
    "\x1bPq".to_string()
}

pub fn end() -> String {
    "\x1b\\".to_string()
}

pub fn from(memory: &[u32], width: usize, height: usize, border: bool) -> String {
    let mut pixels: Vec<u8> = Vec::new();
    let mut row = 0;

    if border {
        for _ in 0..(width + 2) {
            pixels.push(95);
        }
        pixels.push(36);
        pixels.push(45);
    }

    while row < height {
        if border {
            pixels.push(126);
        }

        for x in 0..width {
            let mut byte: u8 = 0;

            for y in 0..6 {
                let offset = x + (y * width);
                if memory[offset] > 0 {
                    byte = byte | (1 << y);
                }
            }

            pixels.push(byte + 63);
        }

        if border {
            pixels.push(126);
        }

        // Push "$-" to move to the next row.
        pixels.push(36);
        pixels.push(45);
        row += 6;
    }

    if border {
        for _ in 0..(width + 2) {
            pixels.push(64);
        }
        pixels.push(36);
        pixels.push(45);
    }

    String::from_utf8(pixels).unwrap()
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_converts_000000_to_question_mark() {
        assert_eq!(super::from(&[0, 0, 0, 0, 0, 0], 1, 6, false), "?$-");
    }

    #[test]
    fn it_converts_000111_to_w() {
        assert_eq!(super::from(&[0, 0, 0, 1, 1, 1], 1, 6, false), "w$-");
    }

    #[test]
    fn it_converts_111000_to_capital_f() {
        assert_eq!(super::from(&[1, 1, 1, 0, 0, 0], 1, 6, false), "F$-");
    }

    #[test]
    fn it_converts_111111_to_tilde() {
        assert_eq!(super::from(&[1, 1, 1, 1, 1, 1], 1, 6, false), "~$-");
    }

    #[test]
    fn it_displays_capital_a() {
        assert_eq!(super::from(&[0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0,
                                 0, 0, 0],
                               4,
                               6,
                               false),
                   "]DD]$-");
    }
}
<commit_msg>ANSI escape sequences are one-based, not zero-based.<commit_after>pub fn clear() -> String {
    "\x1b[1;1H".to_string()
}

pub fn begin() -> String {
    "\x1bPq".to_string()
}

pub fn end() -> String {
    "\x1b\\".to_string()
}

pub fn from(memory: &[u32], width: usize, height: usize, border: bool) -> String {
    let mut pixels: Vec<u8> = Vec::new();
    let mut row = 0;

    if border {
        for _ in 0..(width + 2) {
            pixels.push(95);
        }
        pixels.push(36);
        pixels.push(45);
    }

    while row < height {
        if border {
            pixels.push(126);
        }

        for x in 0..width {
            let mut byte: u8 = 0;

            for y in 0..6 {
                let offset = x + (y * width);
                if memory[offset] > 0 {
                    byte = byte | (1 << y);
                }
            }

            pixels.push(byte + 63);
        }

        if border {
            pixels.push(126);
        }

        // Push "$-" to move to the next row.
        pixels.push(36);
        pixels.push(45);
        row += 6;
    }

    if border {
        for _ in 0..(width + 2) {
            pixels.push(64);
        }
        pixels.push(36);
        pixels.push(45);
    }

    String::from_utf8(pixels).unwrap()
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_converts_000000_to_question_mark() {
        assert_eq!(super::from(&[0, 0, 0, 0, 0, 0], 1, 6, false), "?$-");
    }

    #[test]
    fn it_converts_000111_to_w() {
        assert_eq!(super::from(&[0, 0, 0, 1, 1, 1], 1, 6, false), "w$-");
    }

    #[test]
    fn it_converts_111000_to_capital_f() {
        assert_eq!(super::from(&[1, 1, 1, 0, 0, 0], 1, 6, false), "F$-");
    }

    #[test]
    fn it_converts_111111_to_tilde() {
        assert_eq!(super::from(&[1, 1, 1, 1, 1, 1], 1, 6, false), "~$-");
    }

    #[test]
    fn it_displays_capital_a() {
        assert_eq!(super::from(&[0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0,
                                 0, 0, 0],
                               4,
                               6,
                               false),
                   "]DD]$-");
    }
}
<|endoftext|>