<commit_before>use ra_parser::{Token, TokenSource};
use ra_syntax::{classify_literal, SmolStr, SyntaxKind, SyntaxKind::*, T};
use std::cell::{Cell, RefCell};
use tt::buffer::{Cursor, TokenBuffer};

#[derive(Debug, Clone, Eq, PartialEq)]
struct TtToken {
    pub kind: SyntaxKind,
    pub is_joint_to_next: bool,
    pub text: SmolStr,
}

pub(crate) struct SubtreeTokenSource<'a> {
    cached_cursor: Cell<Cursor<'a>>,
    cached: RefCell<Vec<Option<TtToken>>>,
    curr: (Token, usize),
}

impl<'a> SubtreeTokenSource<'a> {
    // Helper function used in test
    #[cfg(test)]
    pub fn text(&self) -> SmolStr {
        let idx = self.get(self.curr.1);
        let cached = self.cached.borrow();
        match cached[idx] {
            Some(ref tt) => tt.text.clone(),
            _ => SmolStr::new(""),
        }
    }
}

impl<'a> SubtreeTokenSource<'a> {
    pub fn new(buffer: &'a TokenBuffer) -> SubtreeTokenSource<'a> {
        let cursor = buffer.begin();

        let mut res = SubtreeTokenSource {
            curr: (Token { kind: EOF, is_jointed_to_next: false }, 0),
            cached_cursor: Cell::new(cursor),
            cached: RefCell::new(Vec::with_capacity(10)),
        };
        res.curr = (res.mk_token(0), 0);
        res
    }

    fn mk_token(&self, pos: usize) -> Token {
        let idx = self.get(pos);
        let cached = self.cached.borrow();
        match cached[idx] {
            Some(ref tt) => Token { kind: tt.kind, is_jointed_to_next: tt.is_joint_to_next },
            None => Token { kind: EOF, is_jointed_to_next: false },
        }
    }

    fn get(&self, pos: usize) -> usize {
        let mut cached = self.cached.borrow_mut();
        if pos < cached.len() {
            return pos;
        }

        while pos >= cached.len() {
            let cursor = self.cached_cursor.get();
            if cursor.eof() {
                cached.push(None);
                continue;
            }

            match cursor.token_tree() {
                Some(tt::TokenTree::Leaf(leaf)) => {
                    cached.push(Some(convert_leaf(&leaf)));
                    self.cached_cursor.set(cursor.bump());
                }
                Some(tt::TokenTree::Subtree(subtree)) => {
                    self.cached_cursor.set(cursor.subtree().unwrap());
                    cached.push(Some(convert_delim(subtree.delimiter, false)));
                }
                None => {
                    if let Some(subtree) = cursor.end() {
                        cached.push(Some(convert_delim(subtree.delimiter, true)));
                        self.cached_cursor.set(cursor.bump());
                    }
                }
            }
        }

        pos
    }
}

impl<'a> TokenSource for SubtreeTokenSource<'a> {
    fn current(&self) -> Token {
        self.curr.0
    }

    /// Lookahead n token
    fn lookahead_nth(&self, n: usize) -> Token {
        self.mk_token(self.curr.1 + n)
    }

    /// bump cursor to next token
    fn bump(&mut self) {
        if self.current().kind == EOF {
            return;
        }

        self.curr = (self.mk_token(self.curr.1 + 1), self.curr.1 + 1);
    }

    /// Is the current token a specified keyword?
    fn is_keyword(&self, kw: &str) -> bool {
        let idx = self.get(self.curr.1);
        let cached = self.cached.borrow();
        match cached[idx] {
            Some(ref t) => t.text == *kw,
            _ => false,
        }
    }
}

fn convert_delim(d: tt::Delimiter, closing: bool) -> TtToken {
    let (kinds, texts) = match d {
        tt::Delimiter::Parenthesis => ([T!['('], T![')']], "()"),
        tt::Delimiter::Brace => ([T!['{'], T!['}']], "{}"),
        tt::Delimiter::Bracket => ([T!['['], T![']']], "[]"),
        tt::Delimiter::None => ([L_DOLLAR, R_DOLLAR], ""),
    };

    let idx = closing as usize;
    let kind = kinds[idx];
    let text = if texts.len() > 0 { &texts[idx..texts.len() - (1 - idx)] } else { "" };
    TtToken { kind, is_joint_to_next: false, text: SmolStr::new(text) }
}

fn convert_literal(l: &tt::Literal) -> TtToken {
    let kind =
        classify_literal(&l.text).map(|tkn| tkn.kind).unwrap_or_else(|| match l.text.as_ref() {
            "true" => T![true],
            "false" => T![false],
            _ => panic!("Fail to convert given literal {:#?}", &l),
        });

    TtToken { kind, is_joint_to_next: false, text: l.text.clone() }
}

fn convert_ident(ident: &tt::Ident) -> TtToken {
    let kind = if let Some('\'') = ident.text.chars().next() {
        LIFETIME
    } else {
        SyntaxKind::from_keyword(ident.text.as_str()).unwrap_or(IDENT)
    };

    TtToken { kind, is_joint_to_next: false, text: ident.text.clone() }
}

fn convert_punct(p: tt::Punct) -> TtToken {
    let kind = match p.char {
        // lexer may produce compound tokens for these ones
        '.' => T![.],
        ':' => T![:],
        '=' => T![=],
        '!' => T![!],
        '-' => T![-],
        c => SyntaxKind::from_char(c).unwrap(),
    };
    let text = {
        let mut buf = [0u8; 4];
        let s: &str = p.char.encode_utf8(&mut buf);
        SmolStr::new(s)
    };
    TtToken { kind, is_joint_to_next: p.spacing == tt::Spacing::Joint, text }
}

fn convert_leaf(leaf: &tt::Leaf) -> TtToken {
    match leaf {
        tt::Leaf::Literal(l) => convert_literal(l),
        tt::Leaf::Ident(ident) => convert_ident(ident),
        tt::Leaf::Punct(punct) => convert_punct(*punct),
    }
}
<commit_msg>Return a Ref from SubtreeTokenSource::get<commit_after>use ra_parser::{Token, TokenSource};
use ra_syntax::{classify_literal, SmolStr, SyntaxKind, SyntaxKind::*, T};
use std::cell::{Cell, Ref, RefCell};
use tt::buffer::{Cursor, TokenBuffer};

#[derive(Debug, Clone, Eq, PartialEq)]
struct TtToken {
    pub kind: SyntaxKind,
    pub is_joint_to_next: bool,
    pub text: SmolStr,
}

pub(crate) struct SubtreeTokenSource<'a> {
    cached_cursor: Cell<Cursor<'a>>,
    cached: RefCell<Vec<Option<TtToken>>>,
    curr: (Token, usize),
}

impl<'a> SubtreeTokenSource<'a> {
    // Helper function used in test
    #[cfg(test)]
    pub fn text(&self) -> SmolStr {
        match *self.get(self.curr.1) {
            Some(ref tt) => tt.text.clone(),
            _ => SmolStr::new(""),
        }
    }
}

impl<'a> SubtreeTokenSource<'a> {
    pub fn new(buffer: &'a TokenBuffer) -> SubtreeTokenSource<'a> {
        let cursor = buffer.begin();

        let mut res = SubtreeTokenSource {
            curr: (Token { kind: EOF, is_jointed_to_next: false }, 0),
            cached_cursor: Cell::new(cursor),
            cached: RefCell::new(Vec::with_capacity(10)),
        };
        res.curr = (res.mk_token(0), 0);
        res
    }

    fn mk_token(&self, pos: usize) -> Token {
        match *self.get(pos) {
            Some(ref tt) => Token { kind: tt.kind, is_jointed_to_next: tt.is_joint_to_next },
            None => Token { kind: EOF, is_jointed_to_next: false },
        }
    }

    fn get(&self, pos: usize) -> Ref<Option<TtToken>> {
        if pos < self.cached.borrow().len() {
            return Ref::map(self.cached.borrow(), |c| &c[pos]);
        }

        {
            let mut cached = self.cached.borrow_mut();
            while pos >= cached.len() {
                let cursor = self.cached_cursor.get();
                if cursor.eof() {
                    cached.push(None);
                    continue;
                }

                match cursor.token_tree() {
                    Some(tt::TokenTree::Leaf(leaf)) => {
                        cached.push(Some(convert_leaf(&leaf)));
                        self.cached_cursor.set(cursor.bump());
                    }
                    Some(tt::TokenTree::Subtree(subtree)) => {
                        self.cached_cursor.set(cursor.subtree().unwrap());
                        cached.push(Some(convert_delim(subtree.delimiter, false)));
                    }
                    None => {
                        if let Some(subtree) = cursor.end() {
                            cached.push(Some(convert_delim(subtree.delimiter, true)));
                            self.cached_cursor.set(cursor.bump());
                        }
                    }
                }
            }
        }

        Ref::map(self.cached.borrow(), |c| &c[pos])
    }
}

impl<'a> TokenSource for SubtreeTokenSource<'a> {
    fn current(&self) -> Token {
        self.curr.0
    }

    /// Lookahead n token
    fn lookahead_nth(&self, n: usize) -> Token {
        self.mk_token(self.curr.1 + n)
    }

    /// bump cursor to next token
    fn bump(&mut self) {
        if self.current().kind == EOF {
            return;
        }

        self.curr = (self.mk_token(self.curr.1 + 1), self.curr.1 + 1);
    }

    /// Is the current token a specified keyword?
    fn is_keyword(&self, kw: &str) -> bool {
        match *self.get(self.curr.1) {
            Some(ref t) => t.text == *kw,
            _ => false,
        }
    }
}

fn convert_delim(d: tt::Delimiter, closing: bool) -> TtToken {
    let (kinds, texts) = match d {
        tt::Delimiter::Parenthesis => ([T!['('], T![')']], "()"),
        tt::Delimiter::Brace => ([T!['{'], T!['}']], "{}"),
        tt::Delimiter::Bracket => ([T!['['], T![']']], "[]"),
        tt::Delimiter::None => ([L_DOLLAR, R_DOLLAR], ""),
    };

    let idx = closing as usize;
    let kind = kinds[idx];
    let text = if texts.len() > 0 { &texts[idx..texts.len() - (1 - idx)] } else { "" };
    TtToken { kind, is_joint_to_next: false, text: SmolStr::new(text) }
}

fn convert_literal(l: &tt::Literal) -> TtToken {
    let kind =
        classify_literal(&l.text).map(|tkn| tkn.kind).unwrap_or_else(|| match l.text.as_ref() {
            "true" => T![true],
            "false" => T![false],
            _ => panic!("Fail to convert given literal {:#?}", &l),
        });

    TtToken { kind, is_joint_to_next: false, text: l.text.clone() }
}

fn convert_ident(ident: &tt::Ident) -> TtToken {
    let kind = if let Some('\'') = ident.text.chars().next() {
        LIFETIME
    } else {
        SyntaxKind::from_keyword(ident.text.as_str()).unwrap_or(IDENT)
    };

    TtToken { kind, is_joint_to_next: false, text: ident.text.clone() }
}

fn convert_punct(p: tt::Punct) -> TtToken {
    let kind = match p.char {
        // lexer may produce compound tokens for these ones
        '.' => T![.],
        ':' => T![:],
        '=' => T![=],
        '!' => T![!],
        '-' => T![-],
        c => SyntaxKind::from_char(c).unwrap(),
    };
    let text = {
        let mut buf = [0u8; 4];
        let s: &str = p.char.encode_utf8(&mut buf);
        SmolStr::new(s)
    };
    TtToken { kind, is_joint_to_next: p.spacing == tt::Spacing::Joint, text }
}

fn convert_leaf(leaf: &tt::Leaf) -> TtToken {
    match leaf {
        tt::Leaf::Literal(l) => convert_literal(l),
        tt::Leaf::Ident(ident) => convert_ident(ident),
        tt::Leaf::Punct(punct) => convert_punct(*punct),
    }
}
<|endoftext|>


<commit_before>use chrono::prelude::*;
use itertools::Itertools;

pub(crate) trait PrettyPrint {
    fn pretty_print(&self) -> String;
}

impl PrettyPrint for eva::Schedule<eva::Task> {
    fn pretty_print(&self) -> String {
        format!(
            "Schedule:\n  {}",
            self.0.iter().map(PrettyPrint::pretty_print).join("\n  ")
        )
    }
}

impl PrettyPrint for eva::Scheduled<eva::Task> {
    fn pretty_print(&self) -> String {
        format!("{}: {}", self.when.pretty_print(), self.task.pretty_print())
    }
}

impl PrettyPrint for DateTime<Utc> {
    fn pretty_print(&self) -> String {
        let format = if self.year() == Utc::now().year() {
            "%a %-d %b %-H:%M"
        } else {
            "%a %-d %b %Y %-H:%M"
        };
        self.format(format).to_string()
    }
}

impl PrettyPrint for eva::Task {
    fn pretty_print(&self) -> String {
        let prefix = format!("{}. ", self.id);
        format!(
            "{}{}\n{}(deadline: {}, duration: {}, importance: {})",
            prefix,
            self.content,
            " ".repeat(prefix.len()),
            self.deadline.pretty_print(),
            self.duration.pretty_print(),
            self.importance
        )
    }
}

impl PrettyPrint for chrono::Duration {
    fn pretty_print(&self) -> String {
        if self.num_minutes() > 0 {
            format!("{}h{}", self.num_hours(), self.num_minutes() % 60)
        } else {
            format!("{}h", self.num_hours())
        }
    }
}
<commit_msg>cli: show dates in the local timezone<commit_after>use chrono::prelude::*;
use itertools::Itertools;

pub(crate) trait PrettyPrint {
    fn pretty_print(&self) -> String;
}

impl PrettyPrint for eva::Schedule<eva::Task> {
    fn pretty_print(&self) -> String {
        format!(
            "Schedule:\n  {}",
            self.0.iter().map(PrettyPrint::pretty_print).join("\n  ")
        )
    }
}

impl PrettyPrint for eva::Scheduled<eva::Task> {
    fn pretty_print(&self) -> String {
        format!("{}: {}", self.when.pretty_print(), self.task.pretty_print())
    }
}

impl PrettyPrint for DateTime<Utc> {
    fn pretty_print(&self) -> String {
        let local = self.with_timezone(&Local);
        let format = if local.year() == Local::now().year() {
            "%a %-d %b %-H:%M"
        } else {
            "%a %-d %b %Y %-H:%M"
        };
        local.format(format).to_string()
    }
}

impl PrettyPrint for eva::Task {
    fn pretty_print(&self) -> String {
        let prefix = format!("{}. ", self.id);
        format!(
            "{}{}\n{}(deadline: {}, duration: {}, importance: {})",
            prefix,
            self.content,
            " ".repeat(prefix.len()),
            self.deadline.pretty_print(),
            self.duration.pretty_print(),
            self.importance
        )
    }
}

impl PrettyPrint for chrono::Duration {
    fn pretty_print(&self) -> String {
        if self.num_minutes() > 0 {
            format!("{}h{}", self.num_hours(), self.num_minutes() % 60)
        } else {
            format!("{}h", self.num_hours())
        }
    }
}
<|endoftext|>


<commit_before>use cargo_test_support::{basic_lib_manifest, project};

#[cargo_test]
fn inherits_on_release() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            cargo-features = ["named-profiles"]

            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [profile.release]
            inherits = "dev"
        "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build")
        .masquerade_as_nightly_cargo()
        .with_status(101)
        .with_stderr(
            "\
[ERROR] failed to parse manifest at [..]

Caused by:
  An 'inherits' must not specified root profile 'release'
"
        )
        .run();
}

#[cargo_test]
fn missing_inherits() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            cargo-features = ["named-profiles"]

            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [profile.release-lto]
            codegen-units = 7
        "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build")
        .masquerade_as_nightly_cargo()
        .with_status(101)
        .with_stderr(
            "\
[ERROR] failed to parse manifest at [..]

Caused by:
  An 'inherits' directive is needed for all profiles that are not 'dev' or 'release'. Here it is missing from 'release-lto'",
        )
        .run();
}

#[cargo_test]
fn non_existent_inherits() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            cargo-features = ["named-profiles"]

            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [profile.release-lto]
            codegen-units = 7
            inherits = "non-existent"
        "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build")
        .masquerade_as_nightly_cargo()
        .with_status(101)
        .with_stderr(
            "\
[ERROR] failed to parse manifest at [..]

Caused by:
  Profile 'non-existent' not found in Cargo.toml",
        )
        .run();
}

#[cargo_test]
fn self_inherits() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            cargo-features = ["named-profiles"]

            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [profile.release-lto]
            codegen-units = 7
            inherits = "release-lto"
        "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build")
        .masquerade_as_nightly_cargo()
        .with_status(101)
        .with_stderr(
            "\
[ERROR] failed to parse manifest at [..]

Caused by:
  Inheritance loop of profiles cycles with profile 'release-lto'",
        )
        .run();
}

#[cargo_test]
fn inherits_loop() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            cargo-features = ["named-profiles"]

            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [profile.release-lto]
            codegen-units = 7
            inherits = "release-lto2"

            [profile.release-lto2]
            codegen-units = 7
            inherits = "release-lto"
        "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build")
        .masquerade_as_nightly_cargo()
        .with_status(101)
        .with_stderr(
            "\
[ERROR] failed to parse manifest at [..]

Caused by:
  Inheritance loop of profiles cycles with profile 'release-lto'",
        )
        .run();
}

#[cargo_test]
fn overrides_with_custom() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            cargo-features = ["profile-overrides", "named-profiles"]

            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies]
            xxx = {path = "xxx"}
            yyy = {path = "yyy"}

            [profile.dev]
            codegen-units = 7

            [profile.dev.overrides.xxx]
            codegen-units = 5
            [profile.dev.overrides.yyy]
            codegen-units = 3

            [profile.other]
            inherits = "dev"
            codegen-units = 2

            [profile.other.overrides.yyy]
            codegen-units = 6
        "#,
        )
        .file("src/lib.rs", "")
        .file("xxx/Cargo.toml", &basic_lib_manifest("xxx"))
        .file("xxx/src/lib.rs", "")
        .file("yyy/Cargo.toml", &basic_lib_manifest("yyy"))
        .file("yyy/src/lib.rs", "")
        .build();

    // profile overrides are inherited between profiles using inherits and have a
    // higher priority than profile options provided by custom profiles
    p.cargo("build -v")
        .masquerade_as_nightly_cargo()
        .with_stderr_unordered(
            "\
[COMPILING] xxx [..]
[COMPILING] yyy [..]
[COMPILING] foo [..]
[RUNNING] `rustc --crate-name xxx [..] -C codegen-units=5 [..]`
[RUNNING] `rustc --crate-name yyy [..] -C codegen-units=3 [..]`
[RUNNING] `rustc --crate-name foo [..] -C codegen-units=7 [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();

    // This also verifies that the custom profile names appears in the finished line.
    p.cargo("build --profile=other -Z unstable-options -v")
        .masquerade_as_nightly_cargo()
        .with_stderr_unordered(
            "\
[COMPILING] xxx [..]
[COMPILING] yyy [..]
[COMPILING] foo [..]
[RUNNING] `rustc --crate-name xxx [..] -C codegen-units=5 [..]`
[RUNNING] `rustc --crate-name yyy [..] -C codegen-units=6 [..]`
[RUNNING] `rustc --crate-name foo [..] -C codegen-units=2 [..]`
[FINISHED] other [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn conflicting_usage() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []
        "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build -Z unstable-options --profile=dev --release")
        .masquerade_as_nightly_cargo()
        .with_status(101)
        .with_stderr_unordered("error: Conflicting usage of --profile and --release")
        .run();

    p.cargo("install -Z unstable-options --profile=release --debug")
        .masquerade_as_nightly_cargo()
        .with_status(101)
        .with_stderr_unordered("error: Conflicting usage of --profile and --debug")
        .run();
}

#[cargo_test]
fn clean_custom_dirname() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            cargo-features = ["named-profiles"]

            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [profile.other]
            inherits = "release"
        "#,
        )
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build --release")
        .masquerade_as_nightly_cargo()
        .run();

    p.cargo("clean -p foo").masquerade_as_nightly_cargo().run();

    p.cargo("build --release")
        .masquerade_as_nightly_cargo()
        .with_stdout("")
        .run();

    p.cargo("clean -p foo --release")
        .masquerade_as_nightly_cargo()
        .run();

    p.cargo("build --release")
        .masquerade_as_nightly_cargo()
        .with_stderr(
            "\
[COMPILING] foo v0.0.1 ([..])
[FINISHED] release [optimized] target(s) in [..]
",
        )
        .run();

    p.cargo("build").masquerade_as_nightly_cargo().run();

    p.cargo("build -Z unstable-options --profile=other")
        .masquerade_as_nightly_cargo()
        .with_stderr(
            "\
[COMPILING] foo v0.0.1 ([..])
[FINISHED] other [optimized] target(s) in [..]
",
        )
        .run();

    p.cargo("clean")
        .arg("--release")
        .masquerade_as_nightly_cargo()
        .run();

    // Make sure that 'other' was not cleaned
    assert!(p.build_dir().is_dir());
    assert!(p.build_dir().join("debug").is_dir());
    assert!(p.build_dir().join("other").is_dir());
    assert!(!p.build_dir().join("release").is_dir());

    // This should clean 'other'
    p.cargo("clean -Z unstable-options --profile=other")
        .masquerade_as_nightly_cargo()
        .with_stderr("")
        .run();
    assert!(p.build_dir().join("debug").is_dir());
    assert!(!p.build_dir().join("other").is_dir());
}
<commit_msg>tests: profile_custom - add missing stdout/stderr checks<commit_after>use cargo_test_support::{basic_lib_manifest, project};

#[cargo_test]
fn inherits_on_release() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            cargo-features = ["named-profiles"]

            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [profile.release]
            inherits = "dev"
        "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build")
        .masquerade_as_nightly_cargo()
        .with_status(101)
        .with_stderr(
            "\
[ERROR] failed to parse manifest at [..]

Caused by:
  An 'inherits' must not specified root profile 'release'
"
        )
        .run();
}

#[cargo_test]
fn missing_inherits() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            cargo-features = ["named-profiles"]

            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [profile.release-lto]
            codegen-units = 7
        "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build")
        .masquerade_as_nightly_cargo()
        .with_status(101)
        .with_stderr(
            "\
[ERROR] failed to parse manifest at [..]

Caused by:
  An 'inherits' directive is needed for all profiles that are not 'dev' or 'release'. Here it is missing from 'release-lto'",
        )
        .run();
}

#[cargo_test]
fn non_existent_inherits() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            cargo-features = ["named-profiles"]

            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [profile.release-lto]
            codegen-units = 7
            inherits = "non-existent"
        "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build")
        .masquerade_as_nightly_cargo()
        .with_status(101)
        .with_stderr(
            "\
[ERROR] failed to parse manifest at [..]

Caused by:
  Profile 'non-existent' not found in Cargo.toml",
        )
        .run();
}

#[cargo_test]
fn self_inherits() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            cargo-features = ["named-profiles"]

            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [profile.release-lto]
            codegen-units = 7
            inherits = "release-lto"
        "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build")
        .masquerade_as_nightly_cargo()
        .with_status(101)
        .with_stderr(
            "\
[ERROR] failed to parse manifest at [..]

Caused by:
  Inheritance loop of profiles cycles with profile 'release-lto'",
        )
        .run();
}

#[cargo_test]
fn inherits_loop() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            cargo-features = ["named-profiles"]

            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [profile.release-lto]
            codegen-units = 7
            inherits = "release-lto2"

            [profile.release-lto2]
            codegen-units = 7
            inherits = "release-lto"
        "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build")
        .masquerade_as_nightly_cargo()
        .with_status(101)
        .with_stderr(
            "\
[ERROR] failed to parse manifest at [..]

Caused by:
  Inheritance loop of profiles cycles with profile 'release-lto'",
        )
        .run();
}

#[cargo_test]
fn overrides_with_custom() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            cargo-features = ["profile-overrides", "named-profiles"]

            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies]
            xxx = {path = "xxx"}
            yyy = {path = "yyy"}

            [profile.dev]
            codegen-units = 7

            [profile.dev.overrides.xxx]
            codegen-units = 5
            [profile.dev.overrides.yyy]
            codegen-units = 3

            [profile.other]
            inherits = "dev"
            codegen-units = 2

            [profile.other.overrides.yyy]
            codegen-units = 6
        "#,
        )
        .file("src/lib.rs", "")
        .file("xxx/Cargo.toml", &basic_lib_manifest("xxx"))
        .file("xxx/src/lib.rs", "")
        .file("yyy/Cargo.toml", &basic_lib_manifest("yyy"))
        .file("yyy/src/lib.rs", "")
        .build();

    // profile overrides are inherited between profiles using inherits and have a
    // higher priority than profile options provided by custom profiles
    p.cargo("build -v")
        .masquerade_as_nightly_cargo()
        .with_stderr_unordered(
            "\
[COMPILING] xxx [..]
[COMPILING] yyy [..]
[COMPILING] foo [..]
[RUNNING] `rustc --crate-name xxx [..] -C codegen-units=5 [..]`
[RUNNING] `rustc --crate-name yyy [..] -C codegen-units=3 [..]`
[RUNNING] `rustc --crate-name foo [..] -C codegen-units=7 [..]`
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();

    // This also verifies that the custom profile names appears in the finished line.
    p.cargo("build --profile=other -Z unstable-options -v")
        .masquerade_as_nightly_cargo()
        .with_stderr_unordered(
            "\
[COMPILING] xxx [..]
[COMPILING] yyy [..]
[COMPILING] foo [..]
[RUNNING] `rustc --crate-name xxx [..] -C codegen-units=5 [..]`
[RUNNING] `rustc --crate-name yyy [..] -C codegen-units=6 [..]`
[RUNNING] `rustc --crate-name foo [..] -C codegen-units=2 [..]`
[FINISHED] other [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn conflicting_usage() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []
        "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build -Z unstable-options --profile=dev --release")
        .masquerade_as_nightly_cargo()
        .with_status(101)
        .with_stderr_unordered("error: Conflicting usage of --profile and --release")
        .run();

    p.cargo("install -Z unstable-options --profile=release --debug")
        .masquerade_as_nightly_cargo()
        .with_status(101)
        .with_stderr_unordered("error: Conflicting usage of --profile and --debug")
        .run();
}

#[cargo_test]
fn clean_custom_dirname() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            cargo-features = ["named-profiles"]

            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [profile.other]
            inherits = "release"
        "#,
        )
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build --release")
        .masquerade_as_nightly_cargo()
        .with_stdout("")
        .with_stderr(
            "\
[COMPILING] foo v0.0.1 ([..])
[FINISHED] release [optimized] target(s) in [..]
",
        )
        .run();

    p.cargo("clean -p foo").masquerade_as_nightly_cargo().run();

    p.cargo("build --release")
        .masquerade_as_nightly_cargo()
        .with_stdout("")
        .with_stderr(
            "\
[FINISHED] release [optimized] target(s) in [..]
",
        )
        .run();

    p.cargo("clean -p foo --release")
        .masquerade_as_nightly_cargo()
        .run();

    p.cargo("build --release")
        .masquerade_as_nightly_cargo()
        .with_stderr(
            "\
[COMPILING] foo v0.0.1 ([..])
[FINISHED] release [optimized] target(s) in [..]
",
        )
        .run();

    p.cargo("build")
        .masquerade_as_nightly_cargo()
        .with_stdout("")
        .with_stderr(
            "\
[COMPILING] foo v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();

    p.cargo("build -Z unstable-options --profile=other")
        .masquerade_as_nightly_cargo()
        .with_stderr(
            "\
[COMPILING] foo v0.0.1 ([..])
[FINISHED] other [optimized] target(s) in [..]
",
        )
        .run();

    p.cargo("clean")
        .arg("--release")
        .masquerade_as_nightly_cargo()
        .run();

    // Make sure that 'other' was not cleaned
    assert!(p.build_dir().is_dir());
    assert!(p.build_dir().join("debug").is_dir());
    assert!(p.build_dir().join("other").is_dir());
    assert!(!p.build_dir().join("release").is_dir());

    // This should clean 'other'
    p.cargo("clean -Z unstable-options --profile=other")
        .masquerade_as_nightly_cargo()
        .with_stderr("")
        .run();
    assert!(p.build_dir().join("debug").is_dir());
    assert!(!p.build_dir().join("other").is_dir());
}
<|endoftext|>


<commit_before><commit_msg>Fix size_hint function<commit_after><|endoftext|>


<commit_before>use time;
use std::io::timer::sleep;

use GameWindow;
use keyboard;
use mouse;
use event;

/// Render argument.
#[deriving(Clone)]
pub struct RenderArgs {
    /// Extrapolated time in seconds, used to do smooth animation.
    pub ext_dt: f64,
    /// The width of rendered area.
    pub width: u32,
    /// The height of rendered area.
    pub height: u32,
}

/// Update argument.
#[deriving(Clone)]
pub struct UpdateArgs {
    /// Delta time in seconds.
    pub dt: f64,
}

/// Key press arguments.
#[deriving(Clone)]
pub struct KeyPressArgs {
    /// Keyboard key.
    pub key: keyboard::Key,
}

/// Key release arguments.
#[deriving(Clone)]
pub struct KeyReleaseArgs {
    /// Keyboard key.
    pub key: keyboard::Key,
}

/// Mouse press arguments.
#[deriving(Clone)]
pub struct MousePressArgs {
    /// Mouse button.
    pub button: mouse::Button,
}

/// Mouse release arguments.
#[deriving(Clone)]
pub struct MouseReleaseArgs {
    /// Mouse button.
    pub button: mouse::Button,
}

/// Mouse move arguments.
#[deriving(Clone)]
pub struct MouseMoveArgs {
    /// x.
    pub x: f64,
    /// y.
    pub y: f64,
}

/// Mouse relative move arguments.
#[deriving(Clone)]
pub struct MouseRelativeMoveArgs {
    /// Delta x.
    pub dx: f64,
    /// Delta y.
    pub dy: f64,
}

/// Mouse scroll arguments.
#[deriving(Clone)]
pub struct MouseScrollArgs {
    /// x.
    pub x: f64,
    /// y.
    pub y: f64,
}

/// Contains the different game events.
#[deriving(Clone)]
pub enum GameEvent {
    /// Render graphics.
    Render(RenderArgs),
    /// Update physical state of the game.
    Update(UpdateArgs),
    /// Pressed a keyboard key.
    KeyPress(KeyPressArgs),
    /// Released a keyboard key.
    KeyRelease(KeyReleaseArgs),
    /// Pressed a mouse button.
    MousePress(MousePressArgs),
    /// Released a mouse button.
    MouseRelease(MouseReleaseArgs),
    /// Moved mouse cursor.
    MouseMove(MouseMoveArgs),
    /// Moved mouse relative, not bounded by cursor.
    MouseRelativeMove(MouseRelativeMoveArgs),
    /// Scrolled mouse.
    MouseScroll(MouseScrollArgs)
}

impl GameEvent {
    /// Maps event to something that can be sent between tasks if possible.
    ///
    /// Render events are not sendable between tasks.
    pub fn to_sendable(&self) -> Option<GameEvent> {
        match *self {
            Render(_) => None,
            Update(args) => Some(Update(args)),
            KeyPress(args) => Some(KeyPress(args)),
            KeyRelease(args) => Some(KeyRelease(args)),
            MousePress(args) => Some(MousePress(args)),
            MouseRelease(args) => Some(MouseRelease(args)),
            MouseMove(args) => Some(MouseMove(args)),
            MouseRelativeMove(args) => Some(MouseRelativeMove(args)),
            MouseScroll(args) => Some(MouseScroll(args)),
        }
    }
}

enum GameIteratorState {
    RenderState,
    SwapBuffersState,
    PrepareUpdateLoopState,
    UpdateLoopState,
    HandleEventsState,
    MouseRelativeMoveState(f64, f64),
    UpdateState,
}

/// Settings for the game loop behavior.
#[deriving(Clone)]
pub struct GameIteratorSettings {
    /// The number of updates per second (UPS).
    pub updates_per_second: u64,
    /// The maximum number of frames per second (FPS target).
    pub max_frames_per_second: u64,
}

/// A game loop iterator.
///
/// Example:
///
/// ```Rust
/// let game_iter_settings = GameIteratorSettings {
///     updates_per_second: 120,
///     max_frames_per_second: 60,
/// };
/// let mut game_iter = GameIterator::new(&mut window, &game_iter_settings);
/// loop {
///     match game_iter.next() {
///         None => break,
///         Some(mut e) => match e {
///             Render(ref mut args) => {
///                 // Create graphics context with absolute coordinates.
///                 let c = Context::abs(args.width as f64, args.height as f64);
///                 // Do rendering here.
///             },
///             _ => {},
///         },
///     }
/// }
/// ```
pub struct GameIterator<'a, W> {
    game_window: &'a mut W,
    state: GameIteratorState,
    last_update: u64,
    update_time_in_ns: u64,
    dt: f64,
    min_updates_per_frame: u64,
    min_ns_per_frame: u64,
    start_render: u64,
    next_render: u64,
    updated: u64,
}

static billion: u64 = 1_000_000_000;

impl<'a, W: GameWindow> GameIterator<'a, W> {
    /// Creates a new game iterator.
    pub fn new(
        game_window: &'a mut W,
        settings: &GameIteratorSettings
    ) -> GameIterator<'a, W> {
        let updates_per_second: u64 = settings.updates_per_second;
        let max_frames_per_second: u64 = settings.max_frames_per_second;

        let start = time::precise_time_ns();
        GameIterator {
            game_window: game_window,
            state: RenderState,
            last_update: start,
            update_time_in_ns: billion / updates_per_second,
            dt: 1.0 / updates_per_second as f64,
            // You can make this lower if needed.
            min_updates_per_frame: updates_per_second / max_frames_per_second,
            min_ns_per_frame: billion / max_frames_per_second,
            start_render: start,
            next_render: start,
            updated: 0,
        }
    }

    /// Returns the next game event.
    pub fn next(&mut self) -> Option<GameEvent> {
        match self.state {
            RenderState => {
                if self.game_window.should_close() { return None; }

                self.start_render = time::precise_time_ns();
                // Rendering code
                let (w, h) = self.game_window.get_size();
                if w != 0 && h != 0 {
                    // Swap buffers next time.
                    self.state = SwapBuffersState;
                    return Some(Render(RenderArgs {
                            // Extrapolate time forward to allow smooth motion.
                            // 'start_render' is always bigger than 'last_update'.
                            ext_dt: (self.start_render - self.last_update) as f64 / billion as f64,
                            width: w,
                            height: h,
                        }
                    ));
                }

                self.state = PrepareUpdateLoopState;
                return self.next();
            },
            SwapBuffersState => {
                self.game_window.swap_buffers();
                self.state = PrepareUpdateLoopState;
                return self.next();
            },
            PrepareUpdateLoopState => {
                self.updated = 0;
                self.next_render = self.start_render + self.min_ns_per_frame;
                self.state = UpdateLoopState;
                return self.next();
            },
            UpdateLoopState => {
                let got_min_updates = self.updated < self.min_updates_per_frame;
                let got_time_to_update = time::precise_time_ns() < self.next_render;
                let before_next_frame = self.last_update + self.update_time_in_ns < self.next_render;

                if ( got_time_to_update || got_min_updates ) && before_next_frame {
                    self.state = HandleEventsState;
                    return self.next();
                }

                // Wait if possible.
                // Convert to ms because that is what the sleep function takes.
                let t = (self.next_render - time::precise_time_ns() ) / 1_000_000;
                if t > 1 && t < 1000000 { // The second half just checks if it overflowed,
                                          // which tells us that t should have been negative
                                          // and we are running slow and shouldn't sleep.
                    sleep( t );
                }
                self.state = RenderState;
                return self.next();
            },
            HandleEventsState => {
                // Handle all events before updating.
                return match self.game_window.poll_event() {
                    event::KeyPressed(key) => {
                        Some(KeyPress(KeyPressArgs {
                            key: key,
                        }))
                    },
                    event::KeyReleased(key) => {
                        Some(KeyRelease(KeyReleaseArgs {
                            key: key,
                        }))
                    },
                    event::MouseButtonPressed(mouse_button) => {
                        Some(MousePress(MousePressArgs {
                            button: mouse_button,
                        }))
                    },
                    event::MouseButtonReleased(mouse_button) => {
                        Some(MouseRelease(MouseReleaseArgs {
                            button: mouse_button,
                        }))
                    },
                    event::MouseMoved(x, y, relative_move) => {
                        match relative_move {
                            Some((dx, dy)) =>
                                self.state = MouseRelativeMoveState(dx, dy),
                            None => {},
                        };
                        Some(MouseMove(MouseMoveArgs {
                            x: x,
                            y: y,
                        }))
                    },
                    event::MouseScrolled(x, y) => {
                        Some(MouseScroll(MouseScrollArgs {
                            x: x,
                            y: y
                        }))
                    },
                    event::NoEvent => {
                        self.state = UpdateState;
                        self.next()
                    },
                }
            },
            MouseRelativeMoveState(dx, dy) => {
                self.state = HandleEventsState;
                return Some(MouseRelativeMove(MouseRelativeMoveArgs {
                    dx: dx,
                    dy: dy,
                }));
            },
            UpdateState => {
                self.updated += 1;
                self.state = UpdateLoopState;
                self.last_update += self.update_time_in_ns;
                return Some(Update(UpdateArgs{
                    dt: self.dt,
                }));
            },
        };

        /*
        // copied.

        while !self.should_close(game_window) {

            let start_render = time::precise_time_ns();

            // Rendering code
            let (w, h) = game_window.get_size();
            if w != 0 && h != 0 {
                self.viewport(game_window);
                let mut gl = Gl::new(&mut gl_data, asset_store);
                bg.clear(&mut gl);
                // Extrapolate time forward to allow smooth motion.
                // 'now' is always bigger than 'last_update'.
                let ext_dt = (start_render - last_update) as f64 / billion as f64;
                self.render(
                    ext_dt,
                    &context
                        .trans(-1.0, 1.0)
                        .scale(2.0 / w as f64, -2.0 / h as f64)
                        .store_view(),
                    &mut gl
                        );
                self.swap_buffers(game_window);
            }

            let next_render = start_render + min_ns_per_frame;

            // Update gamestate
            let mut updated = 0;

            while // If we haven't reached the required number of updates yet
                  ( updated < min_updates_per_frame ||
                    // Or we have the time to update further
                    time::precise_time_ns() < next_render ) &&
                  //And we haven't already progressed time to far
                  last_update + update_time_in_ns < next_render {

                self.handle_events(game_window, asset_store);
                self.update(dt, asset_store);

                updated += 1;
                last_update += update_time_in_ns;
            }

            // Wait if possible

            let t = (next_render - time::precise_time_ns() ) / 1_000_000;
            if t > 1 && t < 1000000 { // The second half just checks if it overflowed,
                                      // which tells us that t should have been negative
                                      // and we are running slow and shouldn't sleep.
                sleep( t );
            }

        }
        */
    }
}

<commit_msg>Removed `to_sendable`<commit_after>use time;
use std::io::timer::sleep;

use GameWindow;
use keyboard;
use mouse;
use event;

/// Render argument.
#[deriving(Clone)]
pub struct RenderArgs {
    /// Extrapolated time in seconds, used to do smooth animation.
    pub ext_dt: f64,
    /// The width of rendered area.
    pub width: u32,
    /// The height of rendered area.
    pub height: u32,
}

/// Update argument.
#[deriving(Clone)]
pub struct UpdateArgs {
    /// Delta time in seconds.
    pub dt: f64,
}

/// Key press arguments.
#[deriving(Clone)]
pub struct KeyPressArgs {
    /// Keyboard key.
    pub key: keyboard::Key,
}

/// Key release arguments.
#[deriving(Clone)]
pub struct KeyReleaseArgs {
    /// Keyboard key.
    pub key: keyboard::Key,
}

/// Mouse press arguments.
#[deriving(Clone)]
pub struct MousePressArgs {
    /// Mouse button.
    pub button: mouse::Button,
}

/// Mouse release arguments.
#[deriving(Clone)]
pub struct MouseReleaseArgs {
    /// Mouse button.
    pub button: mouse::Button,
}

/// Mouse move arguments.
#[deriving(Clone)]
pub struct MouseMoveArgs {
    /// x.
    pub x: f64,
    /// y.
    pub y: f64,
}

/// Mouse relative move arguments.
#[deriving(Clone)]
pub struct MouseRelativeMoveArgs {
    /// Delta x.
    pub dx: f64,
    /// Delta y.
    pub dy: f64,
}

/// Mouse scroll arguments.
#[deriving(Clone)]
pub struct MouseScrollArgs {
    /// x.
    pub x: f64,
    /// y.
    pub y: f64,
}

/// Contains the different game events.
#[deriving(Clone)]
pub enum GameEvent {
    /// Render graphics.
    Render(RenderArgs),
    /// Update physical state of the game.
    Update(UpdateArgs),
    /// Pressed a keyboard key.
    KeyPress(KeyPressArgs),
    /// Released a keyboard key.
    KeyRelease(KeyReleaseArgs),
    /// Pressed a mouse button.
    MousePress(MousePressArgs),
    /// Released a mouse button.
    MouseRelease(MouseReleaseArgs),
    /// Moved mouse cursor.
    MouseMove(MouseMoveArgs),
    /// Moved mouse relative, not bounded by cursor.
    MouseRelativeMove(MouseRelativeMoveArgs),
    /// Scrolled mouse.
    MouseScroll(MouseScrollArgs)
}

enum GameIteratorState {
    RenderState,
    SwapBuffersState,
    PrepareUpdateLoopState,
    UpdateLoopState,
    HandleEventsState,
    MouseRelativeMoveState(f64, f64),
    UpdateState,
}

/// Settings for the game loop behavior.
#[deriving(Clone)]
pub struct GameIteratorSettings {
    /// The number of updates per second (UPS).
    pub updates_per_second: u64,
    /// The maximum number of frames per second (FPS target).
    pub max_frames_per_second: u64,
}

/// A game loop iterator.
///
/// Example:
///
/// ```Rust
/// let game_iter_settings = GameIteratorSettings {
///     updates_per_second: 120,
///     max_frames_per_second: 60,
/// };
/// let mut game_iter = GameIterator::new(&mut window, &game_iter_settings);
/// loop {
///     match game_iter.next() {
///         None => break,
///         Some(mut e) => match e {
///             Render(ref mut args) => {
///                 // Create graphics context with absolute coordinates.
///                 let c = Context::abs(args.width as f64, args.height as f64);
///                 // Do rendering here.
///             },
///             _ => {},
///         },
///     }
/// }
/// ```
pub struct GameIterator<'a, W> {
    game_window: &'a mut W,
    state: GameIteratorState,
    last_update: u64,
    update_time_in_ns: u64,
    dt: f64,
    min_updates_per_frame: u64,
    min_ns_per_frame: u64,
    start_render: u64,
    next_render: u64,
    updated: u64,
}

static billion: u64 = 1_000_000_000;

impl<'a, W: GameWindow> GameIterator<'a, W> {
    /// Creates a new game iterator.
    pub fn new(
        game_window: &'a mut W,
        settings: &GameIteratorSettings
    ) -> GameIterator<'a, W> {
        let updates_per_second: u64 = settings.updates_per_second;
        let max_frames_per_second: u64 = settings.max_frames_per_second;

        let start = time::precise_time_ns();
        GameIterator {
            game_window: game_window,
            state: RenderState,
            last_update: start,
            update_time_in_ns: billion / updates_per_second,
            dt: 1.0 / updates_per_second as f64,
            // You can make this lower if needed.
            min_updates_per_frame: updates_per_second / max_frames_per_second,
            min_ns_per_frame: billion / max_frames_per_second,
            start_render: start,
            next_render: start,
            updated: 0,
        }
    }

    /// Returns the next game event.
    pub fn next(&mut self) -> Option<GameEvent> {
        match self.state {
            RenderState => {
                if self.game_window.should_close() { return None; }

                self.start_render = time::precise_time_ns();
                // Rendering code
                let (w, h) = self.game_window.get_size();
                if w != 0 && h != 0 {
                    // Swap buffers next time.
                    self.state = SwapBuffersState;
                    return Some(Render(RenderArgs {
                            // Extrapolate time forward to allow smooth motion.
                            // 'start_render' is always bigger than 'last_update'.
                            ext_dt: (self.start_render - self.last_update) as f64 / billion as f64,
                            width: w,
                            height: h,
                        }
                    ));
                }

                self.state = PrepareUpdateLoopState;
                return self.next();
            },
            SwapBuffersState => {
                self.game_window.swap_buffers();
                self.state = PrepareUpdateLoopState;
                return self.next();
            },
            PrepareUpdateLoopState => {
                self.updated = 0;
                self.next_render = self.start_render + self.min_ns_per_frame;
                self.state = UpdateLoopState;
                return self.next();
            },
            UpdateLoopState => {
                let got_min_updates = self.updated < self.min_updates_per_frame;
                let got_time_to_update = time::precise_time_ns() < self.next_render;
                let before_next_frame = self.last_update + self.update_time_in_ns < self.next_render;

                if ( got_time_to_update || got_min_updates ) && before_next_frame {
                    self.state = HandleEventsState;
                    return self.next();
                }

                // Wait if possible.
                // Convert to ms because that is what the sleep function takes.
                let t = (self.next_render - time::precise_time_ns() ) / 1_000_000;
                if t > 1 && t < 1000000 { // The second half just checks if it overflowed,
                                          // which tells us that t should have been negative
                                          // and we are running slow and shouldn't sleep.
                    sleep( t );
                }
                self.state = RenderState;
                return self.next();
            },
            HandleEventsState => {
                // Handle all events before updating.
                return match self.game_window.poll_event() {
                    event::KeyPressed(key) => {
                        Some(KeyPress(KeyPressArgs {
                            key: key,
                        }))
                    },
                    event::KeyReleased(key) => {
                        Some(KeyRelease(KeyReleaseArgs {
                            key: key,
                        }))
                    },
                    event::MouseButtonPressed(mouse_button) => {
                        Some(MousePress(MousePressArgs {
                            button: mouse_button,
                        }))
                    },
                    event::MouseButtonReleased(mouse_button) => {
                        Some(MouseRelease(MouseReleaseArgs {
                            button: mouse_button,
                        }))
                    },
                    event::MouseMoved(x, y, relative_move) => {
                        match relative_move {
                            Some((dx, dy)) =>
                                self.state = MouseRelativeMoveState(dx, dy),
                            None => {},
                        };
                        Some(MouseMove(MouseMoveArgs {
                            x: x,
                            y: y,
                        }))
                    },
                    event::MouseScrolled(x, y) => {
                        Some(MouseScroll(MouseScrollArgs {
                            x: x,
                            y: y
                        }))
                    },
                    event::NoEvent => {
                        self.state = UpdateState;
                        self.next()
                    },
                }
            },
            MouseRelativeMoveState(dx, dy) => {
                self.state = HandleEventsState;
                return Some(MouseRelativeMove(MouseRelativeMoveArgs {
                    dx: dx,
                    dy: dy,
                }));
            },
            UpdateState => {
                self.updated += 1;
                self.state = UpdateLoopState;
                self.last_update += self.update_time_in_ns;
                return Some(Update(UpdateArgs{
                    dt: self.dt,
                }));
            },
        };

        /*
        // copied.

        while !self.should_close(game_window) {

            let start_render = time::precise_time_ns();

            // Rendering code
            let (w, h) = game_window.get_size();
            if w != 0 && h != 0 {
                self.viewport(game_window);
                let mut gl = Gl::new(&mut gl_data, asset_store);
                bg.clear(&mut gl);
                // Extrapolate time forward to allow smooth motion.
                // 'now' is always bigger than 'last_update'.
                let ext_dt = (start_render - last_update) as f64 / billion as f64;
                self.render(
                    ext_dt,
                    &context
                        .trans(-1.0, 1.0)
                        .scale(2.0 / w as f64, -2.0 / h as f64)
                        .store_view(),
                    &mut gl
                        );
                self.swap_buffers(game_window);
            }

            let next_render = start_render + min_ns_per_frame;

            // Update gamestate
            let mut updated = 0;

            while // If we haven't reached the required number of updates yet
                  ( updated < min_updates_per_frame ||
                    // Or we have the time to update further
                    time::precise_time_ns() < next_render ) &&
                  //And we haven't already progressed time to far
                  last_update + update_time_in_ns < next_render {

                self.handle_events(game_window, asset_store);
                self.update(dt, asset_store);

                updated += 1;
                last_update += update_time_in_ns;
            }

            // Wait if possible

            let t = (next_render - time::precise_time_ns() ) / 1_000_000;
            if t > 1 && t < 1000000 { // The second half just checks if it overflowed,
                                      // which tells us that t should have been negative
                                      // and we are running slow and shouldn't sleep.
                sleep( t );
            }

        }
        */
    }
}

<|endoftext|>


<commit_before>use super::{
    gpu::text::{Extra, TextRenderer},
    Canvas, Color, Draw, DrawParam, Drawable, GraphicsContext, Rect,
};
use crate::{context::Has, filesystem::Filesystem, GameError, GameResult};
use glyph_brush::{ab_glyph, FontId, GlyphCruncher};
use std::{collections::HashMap, io::Read, path::Path};

/// Font data that can be used to create a new font in [super::context::GraphicsContext].
#[derive(Debug)]
pub struct FontData {
    pub(crate) font: ab_glyph::FontArc,
}

impl FontData {
    /// Loads font data from a given path in the filesystem.
    #[allow(unused_results)]
    pub fn from_path(fs: &impl Has<Filesystem>, path: impl AsRef<Path>) -> GameResult<Self> {
        let fs = fs.retrieve();

        let mut bytes = vec![];
        fs.open(path)?.read_to_end(&mut bytes)?;
        Ok(FontData {
            font: ab_glyph::FontArc::try_from_vec(bytes)?,
        })
    }

    /// Loads font data from owned bytes.
    pub fn from_vec(data: Vec<u8>) -> GameResult<Self> {
        Ok(FontData {
            font: ab_glyph::FontArc::try_from_vec(data)?,
        })
    }

    /// Loads font data from static bytes.
    pub fn from_slice(data: &'static [u8]) -> GameResult<Self> {
        Ok(FontData {
            font: ab_glyph::FontArc::try_from_slice(data)?,
        })
    }
}

pub use glyph_brush::ab_glyph::PxScale;

/// Parameters of a single piece ("fragment") of text, including font, color, and size.
#[derive(Debug, Clone)]
pub struct TextFragment {
    /// The text itself.
    pub text: String,
    /// Font name of the text framgnet, defaults to text's font.
    pub font: Option<String>,
    /// Pixel scale of the text framgent, defaults to text's scale.
    pub scale: Option<PxScale>,
    /// Color of the text fragment, defaults to the text's color.
    pub color: Option<Color>,
}

impl Default for TextFragment {
    fn default() -> Self {
        TextFragment {
            text: "".into(),
            font: None,
            scale: None,
            color: None,
        }
    }
}

impl TextFragment {
    /// Creates a new fragment with text set to a string.
    pub fn new(text: impl Into<String>) -> Self {
        TextFragment {
            text: text.into(),
            ..Default::default()
        }
    }

    /// Sets the `font` field, overriding the text's font.
    pub fn font(self, font: impl Into<String>) -> Self {
        TextFragment {
            font: Some(font.into()),
            ..self
        }
    }

    /// Sets the `scale` field, overriding the text's scale.
    pub fn scale(self, scale: impl Into<PxScale>) -> Self {
        TextFragment {
            scale: Some(scale.into()),
            ..self
        }
    }

    /// Sets the `color` field, overriding the text's color.
    pub fn color(self, color: impl Into<Color>) -> Self {
        TextFragment {
            color: Some(color.into()),
            ..self
        }
    }
}

impl<S: Into<String>> From<S> for TextFragment {
    fn from(text: S) -> Self {
        TextFragment::new(text)
    }
}

/// Drawable text object.  Essentially a list of [`TextFragment`].
/// and some cached size information.
///
/// It implements [`Drawable`] so it can be drawn immediately with [`Canvas::draw()`].
#[derive(Debug, Clone)]
pub struct Text {
    fragments: Vec<TextFragment>,
    layout: TextLayout,
    bounds: mint::Vector2<f32>,
    scale: PxScale,
    font: String,
}

impl Default for Text {
    fn default() -> Self {
        Self {
            fragments: Vec::new(),
            layout: TextLayout::tl_wrap(),
            bounds: mint::Vector2::<f32> {
                x: f32::INFINITY,
                y: f32::INFINITY,
            },
            scale: 16.0.into(),
            font: "LiberationMono-Regular".into(),
        }
    }
}

impl Text {
    /// Creates a `Text` from a `TextFragment`.
    ///
    /// ```rust
    /// # use ggez::graphics::Text;
    /// # fn main() {
    /// let text = Text::new("foo");
    /// # }
    /// ```
    pub fn new(fragment: impl Into<TextFragment>) -> Self {
        let mut text = Text::default();
        let _ = text.add(fragment);
        text
    }

    /// Appends a `TextFragment` to the `Text`.
    pub fn add(&mut self, fragment: impl Into<TextFragment>) -> &mut Self {
        self.fragments.push(fragment.into());
        self
    }

    /// Returns an immutable slice of all `TextFragment`s.
    #[inline]
    pub fn fragments(&self) -> &[TextFragment] {
        &self.fragments
    }

    /// Returns a mutable slice of all `TextFragment`s.
    #[inline]
    pub fn fragments_mut(&mut self) -> &mut [TextFragment] {
        &mut self.fragments
    }

    /// Specifies rectangular dimensions to fit text inside of,
    /// wrapping where necessary. Within these bounds is also where
    /// text alignment occurs.
    pub fn set_bounds(&mut self, bounds: impl Into<mint::Vector2<f32>>) -> &mut Self {
        self.bounds = bounds.into();
        self
    }

    /// Specifies how the text will wrap within the bounds specified by [`Text::set_bounds`].
    ///
    /// Wrapping can be disabled by setting `layout` to `TextLayout::SingleLine`.
    pub fn set_layout(&mut self, layout: TextLayout) -> &mut Self {
        self.layout = layout;
        self
    }

    /// Specifies the text's font for fragments that don't specify their own font.
    pub fn set_font(&mut self, font: impl Into<String>) -> &mut Self {
        self.font = font.into();
        self
    }

    /// Specifies the text's font scael for fragments that don't specify their own scale.
    pub fn set_scale(&mut self, scale: impl Into<PxScale>) -> &mut Self {
        self.scale = scale.into();
        self
    }

    /// Returns the string that the text represents.
    pub fn contents(&self) -> String {
        self.fragments.iter().map(|f| f.text.as_str()).collect()
    }

    /// Returns a `Vec` containing the coordinates of the formatted and wrapped text.
    pub fn glyph_positions(
        &self,
        gfx: &impl Has<GraphicsContext>,
    ) -> GameResult<Vec<mint::Point2<f32>>> {
        let gfx = gfx.retrieve();
        Ok(gfx
            .text
            .glyph_brush
            .borrow_mut()
            .glyphs(self.as_section(&gfx.fonts, DrawParam::default())?)
            .map(|glyph| mint::Point2::<f32> {
                x: glyph.glyph.position.x,
                y: glyph.glyph.position.y,
            })
            .collect())
    }

    /// Measures the glyph boundaries for the text.
    #[inline]
    pub fn measure(&self, gfx: &impl Has<GraphicsContext>) -> GameResult<mint::Vector2<f32>> {
        let gfx = gfx.retrieve();
        self.measure_raw(&gfx.text, &gfx.fonts)
    }

    pub(crate) fn measure_raw(
        &self,
        text: &TextRenderer,
        fonts: &HashMap<String, FontId>,
    ) -> GameResult<mint::Vector2<f32>> {
        Ok(text
            .glyph_brush
            .borrow_mut()
            .glyph_bounds(self.as_section(fonts, DrawParam::default())?)
            .map(|rect| mint::Vector2::<f32> {
                x: rect.width(),
                y: rect.height(),
            })
            .unwrap_or_else(|| mint::Vector2::<f32> { x: 0., y: 0. }))
    }

    pub(crate) fn as_section<'a>(
        &'a self,
        fonts: &HashMap<String, FontId>,
        param: DrawParam,
    ) -> GameResult<glyph_brush::Section<'a, Extra>> {
        let x = match self.layout.h_align() {
            TextAlign::Begin => 0.,
            TextAlign::Middle => self.bounds.x / 2.,
            TextAlign::End => self.bounds.x,
        };

        let y = match self.layout.v_align() {
            TextAlign::Begin => 0.,
            TextAlign::Middle => self.bounds.y / 2.,
            TextAlign::End => self.bounds.y,
        };

        Ok(glyph_brush::Section {
            screen_position: (x, y),
            bounds: (self.bounds.x, self.bounds.x),
            layout: match self.layout {
                TextLayout::SingleLine { h_align, v_align } => {
                    glyph_brush::Layout::default_single_line()
                        .h_align(h_align.into())
                        .v_align(v_align.into())
                }
                TextLayout::Wrap { h_align, v_align } => glyph_brush::Layout::default_wrap()
                    .h_align(h_align.into())
                    .v_align(v_align.into()),
            },
            text: self
                .fragments
                .iter()
                .map(|text| {
                    let font = text.font.as_ref().unwrap_or(&self.font);
                    Ok(glyph_brush::Text {
                        text: &text.text,
                        scale: text.scale.unwrap_or(self.scale),
                        font_id: *fonts
                            .get(font)
                            .ok_or_else(|| GameError::FontSelectError(font.clone()))?,
                        extra: Extra {
                            color: text.color.unwrap_or(param.color).into(),
                            transform: param.transform.to_bare_matrix().into(),
                        },
                    })
                })
                .collect::<GameResult<Vec<_>>>()?,
        })
    }
}

impl Drawable for Text {
    fn draw(&self, canvas: &mut Canvas, param: impl Into<DrawParam>) {
        canvas.push_draw(Draw::BoundedText { text: self.clone() }, param.into());
    }

    fn dimensions(&self, gfx: &impl Has<GraphicsContext>) -> Option<Rect> {
        let bounds = self.measure(gfx).ok()?;
        Some(Rect {
            x: 0.,
            y: 0.,
            w: bounds.x,
            h: bounds.y,
        })
    }
}

/// Describes text alignment along a single axis.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum TextAlign {
    /// Text is aligned to the beginning of the axis (left, top).
    Begin,
    /// Text is aligned to the center of the axis.
    Middle,
    /// Text is aligned to the end of the axis (right, bottom).
    End,
}

impl From<TextAlign> for glyph_brush::HorizontalAlign {
    fn from(align: TextAlign) -> Self {
        match align {
            TextAlign::Begin => glyph_brush::HorizontalAlign::Left,
            TextAlign::Middle => glyph_brush::HorizontalAlign::Center,
            TextAlign::End => glyph_brush::HorizontalAlign::Right,
        }
    }
}

impl From<TextAlign> for glyph_brush::VerticalAlign {
    fn from(align: TextAlign) -> Self {
        match align {
            TextAlign::Begin => glyph_brush::VerticalAlign::Top,
            TextAlign::Middle => glyph_brush::VerticalAlign::Center,
            TextAlign::End => glyph_brush::VerticalAlign::Bottom,
        }
    }
}

/// Describes text alignment along both axes.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum TextLayout {
    /// Text is layed out in a single line.
    SingleLine {
        /// Horizontal alignment.
        h_align: TextAlign,
        /// Vertical alignment.
        v_align: TextAlign,
    },
    /// Text wraps around the bounds.
    Wrap {
        /// Horizontal alignment.
        h_align: TextAlign,
        /// Vertical alignment.
        v_align: TextAlign,
    },
}

impl TextLayout {
    /// Text on a single line aligned to the top-left.
    pub fn tl_single_line() -> Self {
        TextLayout::SingleLine {
            h_align: TextAlign::Begin,
            v_align: TextAlign::Begin,
        }
    }

    /// Text wrapped and aligned to the top-left.
    pub fn tl_wrap() -> Self {
        TextLayout::Wrap {
            h_align: TextAlign::Begin,
            v_align: TextAlign::Begin,
        }
    }

    /// Returns the horizontal alignment, regardless of wrapping behaviour.
    pub fn h_align(&self) -> TextAlign {
        match self {
            TextLayout::SingleLine { h_align, .. } | TextLayout::Wrap { h_align, .. } => *h_align,
        }
    }

    /// Returns the vertical alignment, regardless of wrapping behaviour.
    pub fn v_align(&self) -> TextAlign {
        match self {
            TextLayout::SingleLine { v_align, .. } | TextLayout::Wrap { v_align, .. } => *v_align,
        }
    }
}
<commit_msg>add center_wrap() method<commit_after>use super::{
    gpu::text::{Extra, TextRenderer},
    Canvas, Color, Draw, DrawParam, Drawable, GraphicsContext, Rect,
};
use crate::{context::Has, filesystem::Filesystem, GameError, GameResult};
use glyph_brush::{ab_glyph, FontId, GlyphCruncher};
use std::{collections::HashMap, io::Read, path::Path};

/// Font data that can be used to create a new font in [super::context::GraphicsContext].
#[derive(Debug)]
pub struct FontData {
    pub(crate) font: ab_glyph::FontArc,
}

impl FontData {
    /// Loads font data from a given path in the filesystem.
    #[allow(unused_results)]
    pub fn from_path(fs: &impl Has<Filesystem>, path: impl AsRef<Path>) -> GameResult<Self> {
        let fs = fs.retrieve();

        let mut bytes = vec![];
        fs.open(path)?.read_to_end(&mut bytes)?;
        Ok(FontData {
            font: ab_glyph::FontArc::try_from_vec(bytes)?,
        })
    }

    /// Loads font data from owned bytes.
    pub fn from_vec(data: Vec<u8>) -> GameResult<Self> {
        Ok(FontData {
            font: ab_glyph::FontArc::try_from_vec(data)?,
        })
    }

    /// Loads font data from static bytes.
    pub fn from_slice(data: &'static [u8]) -> GameResult<Self> {
        Ok(FontData {
            font: ab_glyph::FontArc::try_from_slice(data)?,
        })
    }
}

pub use glyph_brush::ab_glyph::PxScale;

/// Parameters of a single piece ("fragment") of text, including font, color, and size.
#[derive(Debug, Clone)]
pub struct TextFragment {
    /// The text itself.
    pub text: String,
    /// Font name of the text framgnet, defaults to text's font.
    pub font: Option<String>,
    /// Pixel scale of the text framgent, defaults to text's scale.
    pub scale: Option<PxScale>,
    /// Color of the text fragment, defaults to the text's color.
    pub color: Option<Color>,
}

impl Default for TextFragment {
    fn default() -> Self {
        TextFragment {
            text: "".into(),
            font: None,
            scale: None,
            color: None,
        }
    }
}

impl TextFragment {
    /// Creates a new fragment with text set to a string.
    pub fn new(text: impl Into<String>) -> Self {
        TextFragment {
            text: text.into(),
            ..Default::default()
        }
    }

    /// Sets the `font` field, overriding the text's font.
    pub fn font(self, font: impl Into<String>) -> Self {
        TextFragment {
            font: Some(font.into()),
            ..self
        }
    }

    /// Sets the `scale` field, overriding the text's scale.
    pub fn scale(self, scale: impl Into<PxScale>) -> Self {
        TextFragment {
            scale: Some(scale.into()),
            ..self
        }
    }

    /// Sets the `color` field, overriding the text's color.
    pub fn color(self, color: impl Into<Color>) -> Self {
        TextFragment {
            color: Some(color.into()),
            ..self
        }
    }
}

impl<S: Into<String>> From<S> for TextFragment {
    fn from(text: S) -> Self {
        TextFragment::new(text)
    }
}

/// Drawable text object.  Essentially a list of [`TextFragment`].
/// and some cached size information.
///
/// It implements [`Drawable`] so it can be drawn immediately with [`Canvas::draw()`].
#[derive(Debug, Clone)]
pub struct Text {
    fragments: Vec<TextFragment>,
    layout: TextLayout,
    bounds: mint::Vector2<f32>,
    scale: PxScale,
    font: String,
}

impl Default for Text {
    fn default() -> Self {
        Self {
            fragments: Vec::new(),
            layout: TextLayout::tl_wrap(),
            bounds: mint::Vector2::<f32> {
                x: f32::INFINITY,
                y: f32::INFINITY,
            },
            scale: 16.0.into(),
            font: "LiberationMono-Regular".into(),
        }
    }
}

impl Text {
    /// Creates a `Text` from a `TextFragment`.
    ///
    /// ```rust
    /// # use ggez::graphics::Text;
    /// # fn main() {
    /// let text = Text::new("foo");
    /// # }
    /// ```
    pub fn new(fragment: impl Into<TextFragment>) -> Self {
        let mut text = Text::default();
        let _ = text.add(fragment);
        text
    }

    /// Appends a `TextFragment` to the `Text`.
    pub fn add(&mut self, fragment: impl Into<TextFragment>) -> &mut Self {
        self.fragments.push(fragment.into());
        self
    }

    /// Returns an immutable slice of all `TextFragment`s.
    #[inline]
    pub fn fragments(&self) -> &[TextFragment] {
        &self.fragments
    }

    /// Returns a mutable slice of all `TextFragment`s.
    #[inline]
    pub fn fragments_mut(&mut self) -> &mut [TextFragment] {
        &mut self.fragments
    }

    /// Specifies rectangular dimensions to fit text inside of,
    /// wrapping where necessary. Within these bounds is also where
    /// text alignment occurs.
    pub fn set_bounds(&mut self, bounds: impl Into<mint::Vector2<f32>>) -> &mut Self {
        self.bounds = bounds.into();
        self
    }

    /// Specifies how the text will wrap within the bounds specified by [`Text::set_bounds`].
    ///
    /// Wrapping can be disabled by setting `layout` to `TextLayout::SingleLine`.
    pub fn set_layout(&mut self, layout: TextLayout) -> &mut Self {
        self.layout = layout;
        self
    }

    /// Specifies the text's font for fragments that don't specify their own font.
    pub fn set_font(&mut self, font: impl Into<String>) -> &mut Self {
        self.font = font.into();
        self
    }

    /// Specifies the text's font scael for fragments that don't specify their own scale.
    pub fn set_scale(&mut self, scale: impl Into<PxScale>) -> &mut Self {
        self.scale = scale.into();
        self
    }

    /// Returns the string that the text represents.
    pub fn contents(&self) -> String {
        self.fragments.iter().map(|f| f.text.as_str()).collect()
    }

    /// Returns a `Vec` containing the coordinates of the formatted and wrapped text.
    pub fn glyph_positions(
        &self,
        gfx: &impl Has<GraphicsContext>,
    ) -> GameResult<Vec<mint::Point2<f32>>> {
        let gfx = gfx.retrieve();
        Ok(gfx
            .text
            .glyph_brush
            .borrow_mut()
            .glyphs(self.as_section(&gfx.fonts, DrawParam::default())?)
            .map(|glyph| mint::Point2::<f32> {
                x: glyph.glyph.position.x,
                y: glyph.glyph.position.y,
            })
            .collect())
    }

    /// Measures the glyph boundaries for the text.
    #[inline]
    pub fn measure(&self, gfx: &impl Has<GraphicsContext>) -> GameResult<mint::Vector2<f32>> {
        let gfx = gfx.retrieve();
        self.measure_raw(&gfx.text, &gfx.fonts)
    }

    pub(crate) fn measure_raw(
        &self,
        text: &TextRenderer,
        fonts: &HashMap<String, FontId>,
    ) -> GameResult<mint::Vector2<f32>> {
        Ok(text
            .glyph_brush
            .borrow_mut()
            .glyph_bounds(self.as_section(fonts, DrawParam::default())?)
            .map(|rect| mint::Vector2::<f32> {
                x: rect.width(),
                y: rect.height(),
            })
            .unwrap_or_else(|| mint::Vector2::<f32> { x: 0., y: 0. }))
    }

    pub(crate) fn as_section<'a>(
        &'a self,
        fonts: &HashMap<String, FontId>,
        param: DrawParam,
    ) -> GameResult<glyph_brush::Section<'a, Extra>> {
        let x = match self.layout.h_align() {
            TextAlign::Begin => 0.,
            TextAlign::Middle => self.bounds.x / 2.,
            TextAlign::End => self.bounds.x,
        };

        let y = match self.layout.v_align() {
            TextAlign::Begin => 0.,
            TextAlign::Middle => self.bounds.y / 2.,
            TextAlign::End => self.bounds.y,
        };

        Ok(glyph_brush::Section {
            screen_position: (x, y),
            bounds: (self.bounds.x, self.bounds.x),
            layout: match self.layout {
                TextLayout::SingleLine { h_align, v_align } => {
                    glyph_brush::Layout::default_single_line()
                        .h_align(h_align.into())
                        .v_align(v_align.into())
                }
                TextLayout::Wrap { h_align, v_align } => glyph_brush::Layout::default_wrap()
                    .h_align(h_align.into())
                    .v_align(v_align.into()),
            },
            text: self
                .fragments
                .iter()
                .map(|text| {
                    let font = text.font.as_ref().unwrap_or(&self.font);
                    Ok(glyph_brush::Text {
                        text: &text.text,
                        scale: text.scale.unwrap_or(self.scale),
                        font_id: *fonts
                            .get(font)
                            .ok_or_else(|| GameError::FontSelectError(font.clone()))?,
                        extra: Extra {
                            color: text.color.unwrap_or(param.color).into(),
                            transform: param.transform.to_bare_matrix().into(),
                        },
                    })
                })
                .collect::<GameResult<Vec<_>>>()?,
        })
    }
}

impl Drawable for Text {
    fn draw(&self, canvas: &mut Canvas, param: impl Into<DrawParam>) {
        canvas.push_draw(Draw::BoundedText { text: self.clone() }, param.into());
    }

    fn dimensions(&self, gfx: &impl Has<GraphicsContext>) -> Option<Rect> {
        let bounds = self.measure(gfx).ok()?;
        Some(Rect {
            x: 0.,
            y: 0.,
            w: bounds.x,
            h: bounds.y,
        })
    }
}

/// Describes text alignment along a single axis.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum TextAlign {
    /// Text is aligned to the beginning of the axis (left, top).
    Begin,
    /// Text is aligned to the center of the axis.
    Middle,
    /// Text is aligned to the end of the axis (right, bottom).
    End,
}

impl From<TextAlign> for glyph_brush::HorizontalAlign {
    fn from(align: TextAlign) -> Self {
        match align {
            TextAlign::Begin => glyph_brush::HorizontalAlign::Left,
            TextAlign::Middle => glyph_brush::HorizontalAlign::Center,
            TextAlign::End => glyph_brush::HorizontalAlign::Right,
        }
    }
}

impl From<TextAlign> for glyph_brush::VerticalAlign {
    fn from(align: TextAlign) -> Self {
        match align {
            TextAlign::Begin => glyph_brush::VerticalAlign::Top,
            TextAlign::Middle => glyph_brush::VerticalAlign::Center,
            TextAlign::End => glyph_brush::VerticalAlign::Bottom,
        }
    }
}

/// Describes text alignment along both axes.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum TextLayout {
    /// Text is layed out in a single line.
    SingleLine {
        /// Horizontal alignment.
        h_align: TextAlign,
        /// Vertical alignment.
        v_align: TextAlign,
    },
    /// Text wraps around the bounds.
    Wrap {
        /// Horizontal alignment.
        h_align: TextAlign,
        /// Vertical alignment.
        v_align: TextAlign,
    },
}

impl TextLayout {
    /// Text on a single line aligned to the top-left.
    pub fn tl_single_line() -> Self {
        TextLayout::SingleLine {
            h_align: TextAlign::Begin,
            v_align: TextAlign::Begin,
        }
    }

    /// Text wrapped and aligned to the top-left.
    pub fn tl_wrap() -> Self {
        TextLayout::Wrap {
            h_align: TextAlign::Begin,
            v_align: TextAlign::Begin,
        }
    }

    /// Text wrapped and aligned to the center.
    pub fn center_wrap() -> Self {
        TextLayout::Wrap {
            h_align: TextAlign::Middle,
            v_align: TextAlign::Middle,
        }
    }

    /// Returns the horizontal alignment, regardless of wrapping behaviour.
    pub fn h_align(&self) -> TextAlign {
        match self {
            TextLayout::SingleLine { h_align, .. } | TextLayout::Wrap { h_align, .. } => *h_align,
        }
    }

    /// Returns the vertical alignment, regardless of wrapping behaviour.
    pub fn v_align(&self) -> TextAlign {
        match self {
            TextLayout::SingleLine { v_align, .. } | TextLayout::Wrap { v_align, .. } => *v_align,
        }
    }
}
<|endoftext|>


<commit_before>pub use self::core::TextRange;

mod core {
    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
    pub struct TextRange {
        start: u32,
        end: u32,
    }

    impl TextRange {
        pub fn from_to(start: u32, end: u32) -> TextRange {
            assert!(start <= end);
            TextRange { start: start, end: end }
        }

        pub fn start(&self) -> u32 {
            self.start
        }

        pub fn end(&self) -> u32 {
            self.end
        }
    }
}

impl TextRange {
    pub fn empty() -> TextRange {
        TextRange::from_to(0, 0)
    }

    pub fn is_subrange_of(self, other: TextRange) -> bool {
        other.start() <= self.start() && self.end() <= other.end()
    }

    pub fn glue(&self, right: TextRange) -> TextRange {
        assert_eq!(self.end(), right.start());
        TextRange::from_to(self.start(), right.end())
    }
}

impl ::std::ops::Index<TextRange> for str {
    type Output = str;

    fn index(&self, index: TextRange) -> &str {
        &self[index.start() as usize..index.end() as usize]
    }
}

impl ::std::ops::Index<TextRange> for String {
    type Output = str;

    fn index(&self, index: TextRange) -> &str {
        &self[index.start() as usize..index.end() as usize]
    }
}
<commit_msg>Minor<commit_after>#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TextRange {
    start: u32,
    end: u32,
}

impl TextRange {
    pub fn from_to(start: u32, end: u32) -> TextRange {
        assert!(start <= end);
        TextRange { start: start, end: end }
    }

    pub fn start(&self) -> u32 {
        self.start
    }

    pub fn end(&self) -> u32 {
        self.end
    }

    pub fn empty() -> TextRange {
        TextRange::from_to(0, 0)
    }

    pub fn is_subrange_of(self, other: TextRange) -> bool {
        other.start() <= self.start() && self.end() <= other.end()
    }

    pub fn glue(&self, right: TextRange) -> TextRange {
        assert_eq!(self.end(), right.start());
        TextRange::from_to(self.start(), right.end())
    }
}

impl ::std::ops::Index<TextRange> for str {
    type Output = str;

    fn index(&self, index: TextRange) -> &str {
        &self[index.start() as usize..index.end() as usize]
    }
}

impl ::std::ops::Index<TextRange> for String {
    type Output = str;

    fn index(&self, index: TextRange) -> &str {
        &self[index.start() as usize..index.end() as usize]
    }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::rc::Rc;

use futures::{future, stream, Future};
use lazy_static::lazy_static;

use spectral::prelude::*;
use speculate::speculate;

use gerritbot_spark as spark;
use spark::{Email, EmailRef};

use gerritbot::*;

#[derive(Debug, Clone, Default)]
struct TestGerritCommandRunner;
impl GerritCommandRunner for TestGerritCommandRunner {}

#[derive(Debug, Clone)]
struct Reply {
    email: Email,
    message: String,
}

type Replies = Rc<RefCell<Vec<Reply>>>;

#[derive(Debug, Clone, Default)]
struct TestSparkClient {
    replies: Replies,
}

impl SparkClient for TestSparkClient {
    type ReplyFuture = future::FutureResult<(), spark::Error>;
    fn send_message(&self, email: &EmailRef, msg: &str) -> Self::ReplyFuture {
        self.replies.borrow_mut().push(Reply {
            email: email.to_owned(),
            message: msg.to_string(),
        });
        future::ok(())
    }
}

type TestBot = Bot<TestGerritCommandRunner, TestSparkClient>;

lazy_static! {
    static ref TEST_PERSON_EMAIL: &'static EmailRef = EmailRef::new("test@person.test");
}

trait TestBotTrait: Sized {
    fn new() -> (Self, Replies);
    fn send_message(self, message: &str);
    fn send_messages(self, messages: &[&str]);
}

impl TestBotTrait for TestBot {
    fn new() -> (Self, Replies) {
        let replies = Replies::default();
        let bot = Builder::new(State::new()).build(
            Default::default(),
            TestSparkClient {
                replies: replies.clone(),
            },
        );
        (bot, replies)
    }

    fn send_messages(self, messages: &[&str]) {
        let spark_messages = stream::iter_ok(messages.iter().map(|msg| spark::Message {
            person_email: TEST_PERSON_EMAIL.to_owned(),
            text: msg.to_string(),
            ..Default::default()
        }));
        let gerrit_events = stream::empty();
        self.run(gerrit_events, spark_messages).wait().unwrap();
    }

    fn send_message(self, message: &str) {
        self.send_messages(&[message][..]);
    }
}

speculate! {
    before {
        let (bot, replies) = TestBot::new();
    }

    describe "command tests" {
        test "status" {
            bot.send_message("status");
            let replies = Rc::try_unwrap(replies).unwrap().into_inner();
            assert_that!(replies).has_length(1);
            assert_that!(replies[0].email).is_equal_to(TEST_PERSON_EMAIL.to_owned());
            assert_that!(replies[0].message).contains("disabled");
        }

        test "enable then status" {
            bot.send_messages(&["enable", "status"][..]);
            let replies = Rc::try_unwrap(replies).unwrap().into_inner();
            assert_that!(replies).has_length(2);
            assert_that!(replies[0].email).is_equal_to(TEST_PERSON_EMAIL.to_owned());
            assert_that!(replies[0].message).contains("Happy reviewing!");
            assert_that!(replies[1].email).is_equal_to(TEST_PERSON_EMAIL.to_owned());
            assert_that!(replies[1].message).contains("enabled");
        }

        test "unknown command" {
            bot.send_message("this is not a known command");
            let replies = Rc::try_unwrap(replies).unwrap().into_inner();
            assert_that!(replies).has_length(1);
            assert_that!(replies[0].email).is_equal_to(TEST_PERSON_EMAIL.to_owned());
            assert_that!(replies[0].message).contains("I am GerritBot");
        }

        test "version" {
            bot.send_message("version");
            let replies = Rc::try_unwrap(replies).unwrap().into_inner();
            assert_that!(replies).has_length(1);
            assert_that!(replies[0].email).is_equal_to(TEST_PERSON_EMAIL.to_owned());
            assert_that!(replies[0].message).contains(env!("CARGO_PKG_NAME"));
            assert_that!(replies[0].message).contains(env!("CARGO_PKG_VERSION"));
            assert_that!(replies[0].message).contains(env!("VERGEN_SHA"));
        }
    }
}
<commit_msg>remove test_command<commit_after><|endoftext|>


<commit_before>//! Parse byte iterators to float.

use super::algorithm::*;
use super::digit::*;
use super::exponent::*;
use super::num::*;

// PARSERS
// -------

/// Parse the significant digits of the float.
///
/// * `integer`     - Slice containing the integer digits.
/// * `fraction`    - Slice containing the fraction digits.
fn parse_mantissa(integer: &[u8], fraction: &[u8]) -> (u64, usize) {
    let mut value: u64 = 0;
    // On overflow, calculate the number of truncated digits.
    let mut integer = integer.iter();
    while let Some(c) = integer.next() {
        value = match add_digit(value, to_digit(*c).unwrap()) {
            Some(v) => v,
            None => return (value, 1 + integer.count() + fraction.len()),
        };
    }
    let mut fraction = fraction.iter();
    while let Some(c) = fraction.next() {
        value = match add_digit(value, to_digit(*c).unwrap()) {
            Some(v) => v,
            None => return (value, 1 + fraction.count()),
        };
    }
    (value, 0)
}

/// Parse float from extracted float components.
///
/// * `integer`     - Slice containing the integer digits.
/// * `fraction`    - Slice containing the fraction digits.
/// * `exponent`    - Parsed, 32-bit exponent.
///
/// Precondition: The integer must not have leading zeros.
pub fn parse_float<F>(integer: &[u8], mut fraction: &[u8], exponent: i32) -> F
where
    F: Float,
{
    // Trim trailing zeroes from the fraction part.
    while fraction.last() == Some(&b'0') {
        fraction = &fraction[..fraction.len() - 1];
    }

    // Parse the mantissa and attempt the fast and moderate-path algorithms.
    let (mantissa, truncated) = parse_mantissa(integer, fraction);
    let is_truncated = truncated != 0;

    // Process the state to a float.
    if mantissa == 0 {
        // Literal 0, return early.
        // Value cannot be truncated, since truncation only occurs on
        // overflow or underflow.
        F::ZERO
    } else if !is_truncated {
        // Try the fast path, no mantissa truncation.
        let mant_exp = mantissa_exponent(exponent, fraction.len(), 0);
        if let Some(float) = fast_path(mantissa, mant_exp) {
            float
        } else {
            fallback_path(
                integer,
                fraction,
                mantissa,
                exponent,
                mant_exp,
                is_truncated,
            )
        }
    } else {
        let mant_exp = mantissa_exponent(exponent, fraction.len(), truncated);
        fallback_path(
            integer,
            fraction,
            mantissa,
            exponent,
            mant_exp,
            is_truncated,
        )
    }
}
<commit_msg>Remove redundant codepath from parse_float<commit_after>//! Parse byte iterators to float.

use super::algorithm::*;
use super::digit::*;
use super::exponent::*;
use super::num::*;

// PARSERS
// -------

/// Parse the significant digits of the float.
///
/// * `integer`     - Slice containing the integer digits.
/// * `fraction`    - Slice containing the fraction digits.
fn parse_mantissa(integer: &[u8], fraction: &[u8]) -> (u64, usize) {
    let mut value: u64 = 0;
    // On overflow, calculate the number of truncated digits.
    let mut integer = integer.iter();
    while let Some(c) = integer.next() {
        value = match add_digit(value, to_digit(*c).unwrap()) {
            Some(v) => v,
            None => return (value, 1 + integer.count() + fraction.len()),
        };
    }
    let mut fraction = fraction.iter();
    while let Some(c) = fraction.next() {
        value = match add_digit(value, to_digit(*c).unwrap()) {
            Some(v) => v,
            None => return (value, 1 + fraction.count()),
        };
    }
    (value, 0)
}

/// Parse float from extracted float components.
///
/// * `integer`     - Slice containing the integer digits.
/// * `fraction`    - Slice containing the fraction digits.
/// * `exponent`    - Parsed, 32-bit exponent.
///
/// Precondition: The integer must not have leading zeros.
pub fn parse_float<F>(integer: &[u8], mut fraction: &[u8], exponent: i32) -> F
where
    F: Float,
{
    // Trim trailing zeroes from the fraction part.
    while fraction.last() == Some(&b'0') {
        fraction = &fraction[..fraction.len() - 1];
    }

    // Parse the mantissa and attempt the fast and moderate-path algorithms.
    let (mantissa, truncated) = parse_mantissa(integer, fraction);

    if mantissa == 0 {
        // Literal 0, return early. Value cannot be truncated since truncation
        // only occurs on overflow or underflow.
        return F::ZERO;
    }

    let mant_exp = mantissa_exponent(exponent, fraction.len(), truncated);

    // Try the fast path if no mantissa truncation.
    let is_truncated = truncated != 0;
    if !is_truncated {
        if let Some(float) = fast_path(mantissa, mant_exp) {
            return float;
        }
    }

    fallback_path(
        integer,
        fraction,
        mantissa,
        exponent,
        mant_exp,
        is_truncated,
    )
}
<|endoftext|>


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

//! The `Clone` trait for types that cannot be 'implicitly copied'.
//!
//! In Rust, some simple types are "implicitly copyable" and when you
//! assign them or pass them as arguments, the receiver will get a copy,
//! leaving the original value in place. These types do not require
//! allocation to copy and do not have finalizers (i.e. they do not
//! contain owned boxes or implement `Drop`), so the compiler considers
//! them cheap and safe to copy. For other types copies must be made
//! explicitly, by convention implementing the `Clone` trait and calling
//! the `clone` method.

#![stable(feature = "rust1", since = "1.0.0")]

use marker::Sized;

/// A common trait for cloning an object.
///
/// This trait can be used with `#[derive]`.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Clone : Sized {
    /// Returns a copy of the value.
    ///
    /// # Examples
    ///
    /// ```
    /// let hello = "Hello"; // &str implements Clone
    ///
    /// assert_eq!("Hello", hello.clone());
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn clone(&self) -> Self;

    /// Performs copy-assignment from `source`.
    ///
    /// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality,
    /// but can be overridden to reuse the resources of `a` to avoid unnecessary
    /// allocations.
    #[inline(always)]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn clone_from(&mut self, source: &Self) {
        *self = source.clone()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Clone for &'a T {
    /// Returns a shallow copy of the reference.
    #[inline]
    fn clone(&self) -> &'a T { *self }
}

macro_rules! clone_impl {
    ($t:ty) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl Clone for $t {
            /// Returns a deep copy of the value.
            #[inline]
            fn clone(&self) -> $t { *self }
        }
    }
}

clone_impl! { isize }
clone_impl! { i8 }
clone_impl! { i16 }
clone_impl! { i32 }
clone_impl! { i64 }

clone_impl! { usize }
clone_impl! { u8 }
clone_impl! { u16 }
clone_impl! { u32 }
clone_impl! { u64 }

clone_impl! { f32 }
clone_impl! { f64 }

clone_impl! { () }
clone_impl! { bool }
clone_impl! { char }
<commit_msg>Add doc example to clone trait<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The `Clone` trait for types that cannot be 'implicitly copied'.
//!
//! In Rust, some simple types are "implicitly copyable" and when you
//! assign them or pass them as arguments, the receiver will get a copy,
//! leaving the original value in place. These types do not require
//! allocation to copy and do not have finalizers (i.e. they do not
//! contain owned boxes or implement `Drop`), so the compiler considers
//! them cheap and safe to copy. For other types copies must be made
//! explicitly, by convention implementing the `Clone` trait and calling
//! the `clone` method.
//!
//! Basic usage example:
//!
//! ```
//! let s = String::new(); // String type implements Clone
//! let copy = s.clone(); // so we can clone it
//! ```
//!
//! To easily implement the Clone trait, you can also use
//! `#[derive(Clone)]`. Example:
//!
//! ```
//! #[derive(Clone)] // we add the Clone trait to Morpheus struct
//! struct Morpheus {
//!    blue_pill: f32,
//!    red_pill: i64,
//! }
//!
//! fn main() {
//!    let f = Morpheus { blue_pill: 0.0, red_pill: 0 };
//!    let copy = f.clone(); // and now we can clone it!
//! }
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

use marker::Sized;

/// A common trait for cloning an object.
///
/// This trait can be used with `#[derive]`.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Clone : Sized {
    /// Returns a copy of the value.
    ///
    /// # Examples
    ///
    /// ```
    /// let hello = "Hello"; // &str implements Clone
    ///
    /// assert_eq!("Hello", hello.clone());
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn clone(&self) -> Self;

    /// Performs copy-assignment from `source`.
    ///
    /// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality,
    /// but can be overridden to reuse the resources of `a` to avoid unnecessary
    /// allocations.
    #[inline(always)]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn clone_from(&mut self, source: &Self) {
        *self = source.clone()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Clone for &'a T {
    /// Returns a shallow copy of the reference.
    #[inline]
    fn clone(&self) -> &'a T { *self }
}

macro_rules! clone_impl {
    ($t:ty) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl Clone for $t {
            /// Returns a deep copy of the value.
            #[inline]
            fn clone(&self) -> $t { *self }
        }
    }
}

clone_impl! { isize }
clone_impl! { i8 }
clone_impl! { i16 }
clone_impl! { i32 }
clone_impl! { i64 }

clone_impl! { usize }
clone_impl! { u8 }
clone_impl! { u16 }
clone_impl! { u32 }
clone_impl! { u64 }

clone_impl! { f32 }
clone_impl! { f64 }

clone_impl! { () }
clone_impl! { bool }
clone_impl! { char }
<|endoftext|>