<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use serde::{de, Serialize};
use std::fmt::{Display, Formatter};

/// This file implements length and character set limited string types needed
/// for DiemID as defined by DIP-10: https://github.com/diem/dip/blob/main/dips/dip-10.md

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DiemId {
    // A reusable identifier that represents either the source or destination
    // end-user of a payment transaction. It is unique to per user at VASP level
    user_identifier: DiemIdUserIdentifier,
    // A unique string that is mapped to a VASP
    vasp_domain_identifier: DiemIdVaspDomainIdentifier,
}

impl DiemId {
    pub fn new(
        user_identifier: DiemIdUserIdentifier,
        vasp_domain_identifier: DiemIdVaspDomainIdentifier,
    ) -> Self {
        Self {
            user_identifier,
            vasp_domain_identifier,
        }
    }

    pub fn user_identifier(&self) -> &DiemIdUserIdentifier {
        &self.user_identifier
    }

    pub fn vasp_domain_identifier(&self) -> &DiemIdVaspDomainIdentifier {
        &self.vasp_domain_identifier
    }

    pub fn get_diem_id_identifier(&self) -> String {
        format!(
            "{}@{}",
            self.user_identifier.as_str(),
            self.vasp_domain_identifier.as_str()
        )
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub struct DiemIdUserIdentifier(Box<str>);

impl DiemIdUserIdentifier {
    pub fn new(s: &str) -> Result<Self, DiemIdParseError> {
        if s.len() > 64 || s.is_empty() {
            return Err(DiemIdParseError);
        }
        let mut chars = s.chars();
        match chars.next() {
            Some('a'..='z') | Some('A'..='Z') | Some('0'..='9') => {}
            Some(_) => return Err(DiemIdParseError),
            None => return Err(DiemIdParseError),
        }
        for c in chars {
            match c {
                'a'..='z' | 'A'..='Z' | '0'..='9' | '.' => {}
                _ => return Err(DiemIdParseError),
            }
        }
        Ok(DiemIdUserIdentifier(s.into()))
    }

    pub fn as_str(&self) -> &str {
        &self.0
    }
}

impl<'de> de::Deserialize<'de> for DiemIdUserIdentifier {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: de::Deserializer<'de>,
    {
        use serde::de::Error;

        let s = <String>::deserialize(deserializer)?;
        DiemIdUserIdentifier::new(&s).map_err(D::Error::custom)
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub struct DiemIdVaspDomainIdentifier(Box<str>);

impl DiemIdVaspDomainIdentifier {
    pub fn new(s: &str) -> Result<Self, DiemIdParseError> {
        if s.len() > 63 || s.is_empty() {
            return Err(DiemIdParseError);
        }
        let mut chars = s.chars();
        match chars.next() {
            Some('a'..='z') | Some('A'..='Z') | Some('0'..='9') => {}
            Some(_) => return Err(DiemIdParseError),
            None => return Err(DiemIdParseError),
        }
        for c in chars {
            match c {
                'a'..='z' | 'A'..='Z' | '0'..='9' | '.' => {}
                _ => return Err(DiemIdParseError),
            }
        }
        Ok(DiemIdVaspDomainIdentifier(s.into()))
    }

    pub fn as_str(&self) -> &str {
        &self.0
    }
}

impl<'de> de::Deserialize<'de> for DiemIdVaspDomainIdentifier {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: de::Deserializer<'de>,
    {
        use serde::de::Error;

        let s = <String>::deserialize(deserializer)?;
        DiemIdVaspDomainIdentifier::new(&s).map_err(D::Error::custom)
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DiemIdParseError;

impl Display for DiemIdParseError {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(f, "Unable to parse DiemId")
    }
}

#[test]
fn test_invalid_user_identifier() {
    // Test valid domain
    let raw_identifier = "abcd1234";
    let identifier = DiemIdUserIdentifier::new(&raw_identifier);
    assert!(identifier.is_ok());

    // Test having 64 characters is valid
    let raw_identifier = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffff1234";
    let identifier = DiemIdUserIdentifier::new(&raw_identifier);
    assert!(identifier.is_ok());

    // Test using "-" character is invalid
    let raw_identifier = "abcd!!!1234";
    let identifier = DiemIdUserIdentifier::new(&raw_identifier);
    assert_eq!(identifier.unwrap_err(), DiemIdParseError,);
    // Test having 64 characters is invalid
    let raw_identifier = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffff12345";
    let identifier = DiemIdUserIdentifier::new(&raw_identifier);
    assert_eq!(identifier.unwrap_err(), DiemIdParseError,);
}

#[test]
fn test_invalid_vasp_domain_identifier() {
    // Test valid domain
    let raw_identifier = "diem";
    let identifier = DiemIdVaspDomainIdentifier::new(&raw_identifier);
    assert!(identifier.is_ok());

    // Test having 63 characters is valid
    let raw_identifier = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffff123";
    let identifier = DiemIdVaspDomainIdentifier::new(&raw_identifier);
    assert!(identifier.is_ok());

    // Test using "-" character is invalid
    let raw_identifier = "diem-domain";
    let identifier = DiemIdVaspDomainIdentifier::new(&raw_identifier);
    assert_eq!(identifier.unwrap_err(), DiemIdParseError,);
    // Test having 64 characters is invalid
    let raw_identifier = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggg";
    let identifier = DiemIdVaspDomainIdentifier::new(&raw_identifier);
    assert_eq!(identifier.unwrap_err(), DiemIdParseError,);
}

#[test]
fn test_get_diem_id() {
    let user_identifier = DiemIdUserIdentifier::new(&"username").unwrap();
    let vasp_domain_identifier = DiemIdVaspDomainIdentifier::new(&"diem").unwrap();
    let diem_id = DiemId::new(user_identifier, vasp_domain_identifier);
    let full_id = diem_id.get_diem_id_identifier();
    assert_eq!(full_id, "username@diem");
}
<commit_msg>implement fromstr<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use serde::{de, Serialize};
use std::{
    fmt::{Display, Formatter},
    str::FromStr,
};

/// This file implements length and character set limited string types needed
/// for DiemID as defined by DIP-10: https://github.com/diem/dip/blob/main/dips/dip-10.md

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DiemId {
    // A reusable identifier that represents either the source or destination
    // end-user of a payment transaction. It is unique to per user at VASP level
    user_identifier: DiemIdUserIdentifier,
    // A unique string that is mapped to a VASP
    vasp_domain_identifier: DiemIdVaspDomainIdentifier,
}

impl DiemId {
    pub fn new(
        user_identifier: DiemIdUserIdentifier,
        vasp_domain_identifier: DiemIdVaspDomainIdentifier,
    ) -> Self {
        Self {
            user_identifier,
            vasp_domain_identifier,
        }
    }

    pub fn new_from_raw(
        user_identifier: &str,
        vasp_domain_identifier: &str,
    ) -> Result<Self, DiemIdParseError> {
        Ok(DiemId::new(
            DiemIdUserIdentifier::new(user_identifier)?,
            DiemIdVaspDomainIdentifier::new(vasp_domain_identifier)?,
        ))
    }

    pub fn user_identifier(&self) -> &DiemIdUserIdentifier {
        &self.user_identifier
    }

    pub fn vasp_domain_identifier(&self) -> &DiemIdVaspDomainIdentifier {
        &self.vasp_domain_identifier
    }
}

impl Display for DiemId {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(
            f,
            "{}@{}",
            self.user_identifier.as_str(),
            self.vasp_domain_identifier.as_str()
        )
    }
}

impl FromStr for DiemId {
    type Err = DiemIdParseError;

    fn from_str(s: &str) -> Result<Self, DiemIdParseError> {
        if !s.contains('@') {
            return Err(DiemIdParseError);
        };
        let split = s.split('@');
        let vec = split.collect::<Vec<&str>>();
        DiemId::new_from_raw(&vec[0], &vec[1])
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub struct DiemIdUserIdentifier(Box<str>);

impl DiemIdUserIdentifier {
    pub fn new(s: &str) -> Result<Self, DiemIdParseError> {
        if s.len() > 64 || s.is_empty() {
            return Err(DiemIdParseError);
        }
        let mut chars = s.chars();
        match chars.next() {
            Some('a'..='z') | Some('A'..='Z') | Some('0'..='9') => {}
            Some(_) => return Err(DiemIdParseError),
            None => return Err(DiemIdParseError),
        }
        for c in chars {
            match c {
                'a'..='z' | 'A'..='Z' | '0'..='9' | '.' => {}
                _ => return Err(DiemIdParseError),
            }
        }
        Ok(DiemIdUserIdentifier(s.into()))
    }

    pub fn as_str(&self) -> &str {
        &self.0
    }
}

impl<'de> de::Deserialize<'de> for DiemIdUserIdentifier {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: de::Deserializer<'de>,
    {
        use serde::de::Error;

        let s = <String>::deserialize(deserializer)?;
        DiemIdUserIdentifier::new(&s).map_err(D::Error::custom)
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub struct DiemIdVaspDomainIdentifier(Box<str>);

impl DiemIdVaspDomainIdentifier {
    pub fn new(s: &str) -> Result<Self, DiemIdParseError> {
        if s.len() > 63 || s.is_empty() {
            return Err(DiemIdParseError);
        }
        let mut chars = s.chars();
        match chars.next() {
            Some('a'..='z') | Some('A'..='Z') | Some('0'..='9') => {}
            Some(_) => return Err(DiemIdParseError),
            None => return Err(DiemIdParseError),
        }
        for c in chars {
            match c {
                'a'..='z' | 'A'..='Z' | '0'..='9' | '.' => {}
                _ => return Err(DiemIdParseError),
            }
        }
        Ok(DiemIdVaspDomainIdentifier(s.into()))
    }

    pub fn as_str(&self) -> &str {
        &self.0
    }
}

impl<'de> de::Deserialize<'de> for DiemIdVaspDomainIdentifier {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: de::Deserializer<'de>,
    {
        use serde::de::Error;

        let s = <String>::deserialize(deserializer)?;
        DiemIdVaspDomainIdentifier::new(&s).map_err(D::Error::custom)
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DiemIdParseError;

impl Display for DiemIdParseError {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(f, "Unable to parse DiemId")
    }
}

#[test]
fn test_invalid_user_identifier() {
    // Test valid domain
    let raw_identifier = "abcd1234";
    let identifier = DiemIdUserIdentifier::new(&raw_identifier);
    assert!(identifier.is_ok());

    // Test having 64 characters is valid
    let raw_identifier = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffff1234";
    let identifier = DiemIdUserIdentifier::new(&raw_identifier);
    assert!(identifier.is_ok());

    // Test using "-" character is invalid
    let raw_identifier = "abcd!!!1234";
    let identifier = DiemIdUserIdentifier::new(&raw_identifier);
    assert_eq!(identifier.unwrap_err(), DiemIdParseError,);
    // Test having 64 characters is invalid
    let raw_identifier = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffff12345";
    let identifier = DiemIdUserIdentifier::new(&raw_identifier);
    assert_eq!(identifier.unwrap_err(), DiemIdParseError,);
}

#[test]
fn test_invalid_vasp_domain_identifier() {
    // Test valid domain
    let raw_identifier = "diem";
    let identifier = DiemIdVaspDomainIdentifier::new(&raw_identifier);
    assert!(identifier.is_ok());

    // Test having 63 characters is valid
    let raw_identifier = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffff123";
    let identifier = DiemIdVaspDomainIdentifier::new(&raw_identifier);
    assert!(identifier.is_ok());

    // Test using "-" character is invalid
    let raw_identifier = "diem-domain";
    let identifier = DiemIdVaspDomainIdentifier::new(&raw_identifier);
    assert_eq!(identifier.unwrap_err(), DiemIdParseError,);
    // Test having 64 characters is invalid
    let raw_identifier = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggg";
    let identifier = DiemIdVaspDomainIdentifier::new(&raw_identifier);
    assert_eq!(identifier.unwrap_err(), DiemIdParseError,);
}

#[test]
fn test_get_diem_id_string_from_components() {
    let user_identifier = DiemIdUserIdentifier::new(&"username").unwrap();
    let vasp_domain_identifier = DiemIdVaspDomainIdentifier::new(&"diem").unwrap();
    let diem_id = DiemId::new(user_identifier, vasp_domain_identifier);
    let full_id = diem_id.to_string();
    assert_eq!(full_id, "username@diem");
}

#[test]
fn test_get_diem_id_from_identifier_string() {
    let diem_id_str = "username@diem";
    let diem_id = DiemId::from_str(diem_id_str).unwrap();
    assert_eq!(diem_id.user_identifier().as_str(), "username");
    assert_eq!(diem_id.vasp_domain_identifier().as_str(), "diem");
}
<|endoftext|>


<commit_before>//! Convert config defined styles into actual ANSI styles

use crate::config::styling;
use ansi_term::{Color, Style};

impl Into<Color> for styling::Color {
    fn into(self) -> Color {
        match self {
            styling::Color::Black => Color::Black,
            styling::Color::Red => Color::Red,
            styling::Color::Yellow => Color::Yellow,
            styling::Color::Green => Color::Green,
            styling::Color::Blue => Color::Blue,
            styling::Color::Purple => Color::Purple,
            styling::Color::Cyan => Color::Cyan,
            styling::Color::White => Color::White,
            styling::Color::Fixed(n) => Color::Fixed(n),
            styling::Color::RGB(r, g, b) => Color::RGB(r, g, b),
        }
    }
}

impl Into<Style> for styling::Style {
    fn into(self) -> Style {
        self.into_iter()
            .fold(Style::default(), |acc, rule| match rule {
                styling::Rule::Reset => Style::default(),
                styling::Rule::Underline => acc.underline(),
                styling::Rule::Strikethrough => acc.strikethrough(),
                styling::Rule::Reverse => acc.reverse(),
                styling::Rule::Bold => acc.bold(),
                styling::Rule::Italic => acc.italic(),
                styling::Rule::Dimmed => acc.dimmed(),
                styling::Rule::Fg(color) => acc.fg(color.into()),
                styling::Rule::Bg(color) => acc.on(color.into()),
            })
    }
}
<commit_msg>Allow clippy::from-over-into rule<commit_after>//! Convert config defined styles into actual ANSI styles

// The structs ansi_term::{Color,Style} belong to an external crate,
// which means we can't implement, for example, From<ansi_term::Color>
#![allow(clippy::from_over_into)]

use crate::config::styling;
use ansi_term::{Color, Style};

impl Into<Color> for styling::Color {
    fn into(self) -> Color {
        match self {
            styling::Color::Black => Color::Black,
            styling::Color::Red => Color::Red,
            styling::Color::Yellow => Color::Yellow,
            styling::Color::Green => Color::Green,
            styling::Color::Blue => Color::Blue,
            styling::Color::Purple => Color::Purple,
            styling::Color::Cyan => Color::Cyan,
            styling::Color::White => Color::White,
            styling::Color::Fixed(n) => Color::Fixed(n),
            styling::Color::RGB(r, g, b) => Color::RGB(r, g, b),
        }
    }
}

impl Into<Style> for styling::Style {
    fn into(self) -> Style {
        self.into_iter()
            .fold(Style::default(), |acc, rule| match rule {
                styling::Rule::Reset => Style::default(),
                styling::Rule::Underline => acc.underline(),
                styling::Rule::Strikethrough => acc.strikethrough(),
                styling::Rule::Reverse => acc.reverse(),
                styling::Rule::Bold => acc.bold(),
                styling::Rule::Italic => acc.italic(),
                styling::Rule::Dimmed => acc.dimmed(),
                styling::Rule::Fg(color) => acc.fg(color.into()),
                styling::Rule::Bg(color) => acc.on(color.into()),
            })
    }
}
<|endoftext|>


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

use CodeSuggestion;
use Substitution;
use Level;
use RenderSpan;
use std::fmt;
use syntax_pos::{MultiSpan, Span};
use snippet::Style;

#[must_use]
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub struct Diagnostic {
    pub level: Level,
    pub message: Vec<(String, Style)>,
    pub code: Option<String>,
    pub span: MultiSpan,
    pub children: Vec<SubDiagnostic>,
    pub suggestions: Vec<CodeSuggestion>,
}

/// For example a note attached to an error.
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub struct SubDiagnostic {
    pub level: Level,
    pub message: Vec<(String, Style)>,
    pub span: MultiSpan,
    pub render_span: Option<RenderSpan>,
}

#[derive(PartialEq, Eq)]
pub struct DiagnosticStyledString(pub Vec<StringPart>);

impl DiagnosticStyledString {
    pub fn new() -> DiagnosticStyledString {
        DiagnosticStyledString(vec![])
    }
    pub fn push_normal<S: Into<String>>(&mut self, t: S) {
        self.0.push(StringPart::Normal(t.into()));
    }
    pub fn push_highlighted<S: Into<String>>(&mut self, t: S) {
        self.0.push(StringPart::Highlighted(t.into()));
    }
    pub fn normal<S: Into<String>>(t: S) -> DiagnosticStyledString {
        DiagnosticStyledString(vec![StringPart::Normal(t.into())])
    }

    pub fn highlighted<S: Into<String>>(t: S) -> DiagnosticStyledString {
        DiagnosticStyledString(vec![StringPart::Highlighted(t.into())])
    }

    pub fn content(&self) -> String {
        self.0.iter().map(|x| x.content()).collect::<String>()
    }
}

#[derive(PartialEq, Eq)]
pub enum StringPart {
    Normal(String),
    Highlighted(String),
}

impl StringPart {
    pub fn content(&self) -> String {
        match self {
            &StringPart::Normal(ref s) | & StringPart::Highlighted(ref s) => s.to_owned()
        }
    }
}

impl Diagnostic {
    pub fn new(level: Level, message: &str) -> Self {
        Diagnostic::new_with_code(level, None, message)
    }

    pub fn new_with_code(level: Level, code: Option<String>, message: &str) -> Self {
        Diagnostic {
            level,
            message: vec![(message.to_owned(), Style::NoStyle)],
            code,
            span: MultiSpan::new(),
            children: vec![],
            suggestions: vec![],
        }
    }

    /// Cancel the diagnostic (a structured diagnostic must either be emitted or
    /// canceled or it will panic when dropped).
    /// BEWARE: if this DiagnosticBuilder is an error, then creating it will
    /// bump the error count on the Handler and canceling it won't undo that.
    /// If you want to decrement the error count you should use `Handler::cancel`.
    pub fn cancel(&mut self) {
        self.level = Level::Cancelled;
    }

    pub fn cancelled(&self) -> bool {
        self.level == Level::Cancelled
    }

    /// Add a span/label to be included in the resulting snippet.
    /// This is pushed onto the `MultiSpan` that was created when the
    /// diagnostic was first built. If you don't call this function at
    /// all, and you just supplied a `Span` to create the diagnostic,
    /// then the snippet will just include that `Span`, which is
    /// called the primary span.
    pub fn span_label<T: Into<String>>(&mut self, span: Span, label: T) -> &mut Self {
        self.span.push_span_label(span, label.into());
        self
    }

    pub fn note_expected_found(&mut self,
                               label: &fmt::Display,
                               expected: DiagnosticStyledString,
                               found: DiagnosticStyledString)
                               -> &mut Self
    {
        self.note_expected_found_extra(label, expected, found, &"", &"")
    }

    pub fn note_expected_found_extra(&mut self,
                                     label: &fmt::Display,
                                     expected: DiagnosticStyledString,
                                     found: DiagnosticStyledString,
                                     expected_extra: &fmt::Display,
                                     found_extra: &fmt::Display)
                                     -> &mut Self
    {
        let mut msg: Vec<_> = vec![(format!("expected {} `", label), Style::NoStyle)];
        msg.extend(expected.0.iter()
                   .map(|x| match *x {
                       StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
                       StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
                   }));
        msg.push((format!("`{}\n", expected_extra), Style::NoStyle));
        msg.push((format!("   found {} `", label), Style::NoStyle));
        msg.extend(found.0.iter()
                   .map(|x| match *x {
                       StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
                       StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
                   }));
        msg.push((format!("`{}", found_extra), Style::NoStyle));

        // For now, just attach these as notes
        self.highlighted_note(msg);
        self
    }

    pub fn note_trait_signature(&mut self, name: String, signature: String) -> &mut Self {
        self.highlighted_note(vec![
            (format!("`{}` from trait: `", name), Style::NoStyle),
            (signature, Style::Highlight),
            ("`".to_string(), Style::NoStyle)]);
        self
    }

    pub fn note(&mut self, msg: &str) -> &mut Self {
        self.sub(Level::Note, msg, MultiSpan::new(), None);
        self
    }

    pub fn highlighted_note(&mut self, msg: Vec<(String, Style)>) -> &mut Self {
        self.sub_with_highlights(Level::Note, msg, MultiSpan::new(), None);
        self
    }

    pub fn span_note<S: Into<MultiSpan>>(&mut self,
                                         sp: S,
                                         msg: &str)
                                         -> &mut Self {
        self.sub(Level::Note, msg, sp.into(), None);
        self
    }

    pub fn warn(&mut self, msg: &str) -> &mut Self {
        self.sub(Level::Warning, msg, MultiSpan::new(), None);
        self
    }

    pub fn span_warn<S: Into<MultiSpan>>(&mut self,
                                         sp: S,
                                         msg: &str)
                                         -> &mut Self {
        self.sub(Level::Warning, msg, sp.into(), None);
        self
    }

    pub fn help(&mut self , msg: &str) -> &mut Self {
        self.sub(Level::Help, msg, MultiSpan::new(), None);
        self
    }

    pub fn span_help<S: Into<MultiSpan>>(&mut self,
                                         sp: S,
                                         msg: &str)
                                         -> &mut Self {
        self.sub(Level::Help, msg, sp.into(), None);
        self
    }

    /// Prints out a message with a suggested edit of the code. If the suggestion is presented
    /// inline it will only show the text message and not the text.
    ///
    /// See `CodeSuggestion` for more information.
    pub fn span_suggestion_short(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
        self.suggestions.push(CodeSuggestion {
            substitution_parts: vec![Substitution {
                span: sp,
                substitutions: vec![suggestion],
            }],
            msg: msg.to_owned(),
            show_code_when_inline: false,
        });
        self
    }

    /// Prints out a message with a suggested edit of the code.
    ///
    /// In case of short messages and a simple suggestion,
    /// rustc displays it as a label like
    ///
    /// "try adding parentheses: `(tup.0).1`"
    ///
    /// The message
    /// * should not end in any punctuation (a `:` is added automatically)
    /// * should not be a question
    /// * should not contain any parts like "the following", "as shown"
    /// * may look like "to do xyz, use" or "to do xyz, use abc"
    /// * may contain a name of a function, variable or type, but not whole expressions
    ///
    /// See `CodeSuggestion` for more information.
    pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
        self.suggestions.push(CodeSuggestion {
            substitution_parts: vec![Substitution {
                span: sp,
                substitutions: vec![suggestion],
            }],
            msg: msg.to_owned(),
            show_code_when_inline: true,
        });
        self
    }

    pub fn span_suggestions(&mut self, sp: Span, msg: &str, suggestions: Vec<String>) -> &mut Self {
        self.suggestions.push(CodeSuggestion {
            substitution_parts: vec![Substitution {
                span: sp,
                substitutions: suggestions,
            }],
            msg: msg.to_owned(),
            show_code_when_inline: true,
        });
        self
    }

    pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self {
        self.span = sp.into();
        self
    }

    pub fn code(&mut self, s: String) -> &mut Self {
        self.code = Some(s);
        self
    }

    pub fn message(&self) -> String {
        self.message.iter().map(|i| i.0.to_owned()).collect::<String>()
    }

    pub fn styled_message(&self) -> &Vec<(String, Style)> {
        &self.message
    }

    /// Used by a lint. Copies over all details *but* the "main
    /// message".
    pub fn copy_details_not_message(&mut self, from: &Diagnostic) {
        self.span = from.span.clone();
        self.code = from.code.clone();
        self.children.extend(from.children.iter().cloned())
    }

    /// Convenience function for internal use, clients should use one of the
    /// public methods above.
    pub(crate) fn sub(&mut self,
           level: Level,
           message: &str,
           span: MultiSpan,
           render_span: Option<RenderSpan>) {
        let sub = SubDiagnostic {
            level,
            message: vec![(message.to_owned(), Style::NoStyle)],
            span,
            render_span,
        };
        self.children.push(sub);
    }

    /// Convenience function for internal use, clients should use one of the
    /// public methods above.
    fn sub_with_highlights(&mut self,
                           level: Level,
                           message: Vec<(String, Style)>,
                           span: MultiSpan,
                           render_span: Option<RenderSpan>) {
        let sub = SubDiagnostic {
            level,
            message,
            span,
            render_span,
        };
        self.children.push(sub);
    }
}

impl SubDiagnostic {
    pub fn message(&self) -> String {
        self.message.iter().map(|i| i.0.to_owned()).collect::<String>()
    }

    pub fn styled_message(&self) -> &Vec<(String, Style)> {
        &self.message
    }
}
<commit_msg>Rollup merge of #45486 - oli-obk:patch-9, r=kennytm<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use CodeSuggestion;
use Substitution;
use Level;
use RenderSpan;
use std::fmt;
use syntax_pos::{MultiSpan, Span};
use snippet::Style;

#[must_use]
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub struct Diagnostic {
    pub level: Level,
    pub message: Vec<(String, Style)>,
    pub code: Option<String>,
    pub span: MultiSpan,
    pub children: Vec<SubDiagnostic>,
    pub suggestions: Vec<CodeSuggestion>,
}

/// For example a note attached to an error.
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub struct SubDiagnostic {
    pub level: Level,
    pub message: Vec<(String, Style)>,
    pub span: MultiSpan,
    pub render_span: Option<RenderSpan>,
}

#[derive(PartialEq, Eq)]
pub struct DiagnosticStyledString(pub Vec<StringPart>);

impl DiagnosticStyledString {
    pub fn new() -> DiagnosticStyledString {
        DiagnosticStyledString(vec![])
    }
    pub fn push_normal<S: Into<String>>(&mut self, t: S) {
        self.0.push(StringPart::Normal(t.into()));
    }
    pub fn push_highlighted<S: Into<String>>(&mut self, t: S) {
        self.0.push(StringPart::Highlighted(t.into()));
    }
    pub fn normal<S: Into<String>>(t: S) -> DiagnosticStyledString {
        DiagnosticStyledString(vec![StringPart::Normal(t.into())])
    }

    pub fn highlighted<S: Into<String>>(t: S) -> DiagnosticStyledString {
        DiagnosticStyledString(vec![StringPart::Highlighted(t.into())])
    }

    pub fn content(&self) -> String {
        self.0.iter().map(|x| x.content()).collect::<String>()
    }
}

#[derive(PartialEq, Eq)]
pub enum StringPart {
    Normal(String),
    Highlighted(String),
}

impl StringPart {
    pub fn content(&self) -> String {
        match self {
            &StringPart::Normal(ref s) | & StringPart::Highlighted(ref s) => s.to_owned()
        }
    }
}

impl Diagnostic {
    pub fn new(level: Level, message: &str) -> Self {
        Diagnostic::new_with_code(level, None, message)
    }

    pub fn new_with_code(level: Level, code: Option<String>, message: &str) -> Self {
        Diagnostic {
            level,
            message: vec![(message.to_owned(), Style::NoStyle)],
            code,
            span: MultiSpan::new(),
            children: vec![],
            suggestions: vec![],
        }
    }

    /// Cancel the diagnostic (a structured diagnostic must either be emitted or
    /// canceled or it will panic when dropped).
    /// BEWARE: if this DiagnosticBuilder is an error, then creating it will
    /// bump the error count on the Handler and canceling it won't undo that.
    /// If you want to decrement the error count you should use `Handler::cancel`.
    pub fn cancel(&mut self) {
        self.level = Level::Cancelled;
    }

    pub fn cancelled(&self) -> bool {
        self.level == Level::Cancelled
    }

    /// Add a span/label to be included in the resulting snippet.
    /// This is pushed onto the `MultiSpan` that was created when the
    /// diagnostic was first built. If you don't call this function at
    /// all, and you just supplied a `Span` to create the diagnostic,
    /// then the snippet will just include that `Span`, which is
    /// called the primary span.
    pub fn span_label<T: Into<String>>(&mut self, span: Span, label: T) -> &mut Self {
        self.span.push_span_label(span, label.into());
        self
    }

    pub fn note_expected_found(&mut self,
                               label: &fmt::Display,
                               expected: DiagnosticStyledString,
                               found: DiagnosticStyledString)
                               -> &mut Self
    {
        self.note_expected_found_extra(label, expected, found, &"", &"")
    }

    pub fn note_expected_found_extra(&mut self,
                                     label: &fmt::Display,
                                     expected: DiagnosticStyledString,
                                     found: DiagnosticStyledString,
                                     expected_extra: &fmt::Display,
                                     found_extra: &fmt::Display)
                                     -> &mut Self
    {
        let mut msg: Vec<_> = vec![(format!("expected {} `", label), Style::NoStyle)];
        msg.extend(expected.0.iter()
                   .map(|x| match *x {
                       StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
                       StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
                   }));
        msg.push((format!("`{}\n", expected_extra), Style::NoStyle));
        msg.push((format!("   found {} `", label), Style::NoStyle));
        msg.extend(found.0.iter()
                   .map(|x| match *x {
                       StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
                       StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
                   }));
        msg.push((format!("`{}", found_extra), Style::NoStyle));

        // For now, just attach these as notes
        self.highlighted_note(msg);
        self
    }

    pub fn note_trait_signature(&mut self, name: String, signature: String) -> &mut Self {
        self.highlighted_note(vec![
            (format!("`{}` from trait: `", name), Style::NoStyle),
            (signature, Style::Highlight),
            ("`".to_string(), Style::NoStyle)]);
        self
    }

    pub fn note(&mut self, msg: &str) -> &mut Self {
        self.sub(Level::Note, msg, MultiSpan::new(), None);
        self
    }

    pub fn highlighted_note(&mut self, msg: Vec<(String, Style)>) -> &mut Self {
        self.sub_with_highlights(Level::Note, msg, MultiSpan::new(), None);
        self
    }

    pub fn span_note<S: Into<MultiSpan>>(&mut self,
                                         sp: S,
                                         msg: &str)
                                         -> &mut Self {
        self.sub(Level::Note, msg, sp.into(), None);
        self
    }

    pub fn warn(&mut self, msg: &str) -> &mut Self {
        self.sub(Level::Warning, msg, MultiSpan::new(), None);
        self
    }

    pub fn span_warn<S: Into<MultiSpan>>(&mut self,
                                         sp: S,
                                         msg: &str)
                                         -> &mut Self {
        self.sub(Level::Warning, msg, sp.into(), None);
        self
    }

    pub fn help(&mut self , msg: &str) -> &mut Self {
        self.sub(Level::Help, msg, MultiSpan::new(), None);
        self
    }

    pub fn span_help<S: Into<MultiSpan>>(&mut self,
                                         sp: S,
                                         msg: &str)
                                         -> &mut Self {
        self.sub(Level::Help, msg, sp.into(), None);
        self
    }

    /// Prints out a message with a suggested edit of the code. If the suggestion is presented
    /// inline it will only show the text message and not the text.
    ///
    /// See `CodeSuggestion` for more information.
    pub fn span_suggestion_short(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
        self.suggestions.push(CodeSuggestion {
            substitution_parts: vec![Substitution {
                span: sp,
                substitutions: vec![suggestion],
            }],
            msg: msg.to_owned(),
            show_code_when_inline: false,
        });
        self
    }

    /// Prints out a message with a suggested edit of the code.
    ///
    /// In case of short messages and a simple suggestion,
    /// rustc displays it as a label like
    ///
    /// "try adding parentheses: `(tup.0).1`"
    ///
    /// The message
    ///
    /// * should not end in any punctuation (a `:` is added automatically)
    /// * should not be a question
    /// * should not contain any parts like "the following", "as shown"
    /// * may look like "to do xyz, use" or "to do xyz, use abc"
    /// * may contain a name of a function, variable or type, but not whole expressions
    ///
    /// See `CodeSuggestion` for more information.
    pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
        self.suggestions.push(CodeSuggestion {
            substitution_parts: vec![Substitution {
                span: sp,
                substitutions: vec![suggestion],
            }],
            msg: msg.to_owned(),
            show_code_when_inline: true,
        });
        self
    }

    /// Prints out a message with multiple suggested edits of the code.
    pub fn span_suggestions(&mut self, sp: Span, msg: &str, suggestions: Vec<String>) -> &mut Self {
        self.suggestions.push(CodeSuggestion {
            substitution_parts: vec![Substitution {
                span: sp,
                substitutions: suggestions,
            }],
            msg: msg.to_owned(),
            show_code_when_inline: true,
        });
        self
    }

    pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self {
        self.span = sp.into();
        self
    }

    pub fn code(&mut self, s: String) -> &mut Self {
        self.code = Some(s);
        self
    }

    pub fn message(&self) -> String {
        self.message.iter().map(|i| i.0.to_owned()).collect::<String>()
    }

    pub fn styled_message(&self) -> &Vec<(String, Style)> {
        &self.message
    }

    /// Used by a lint. Copies over all details *but* the "main
    /// message".
    pub fn copy_details_not_message(&mut self, from: &Diagnostic) {
        self.span = from.span.clone();
        self.code = from.code.clone();
        self.children.extend(from.children.iter().cloned())
    }

    /// Convenience function for internal use, clients should use one of the
    /// public methods above.
    pub(crate) fn sub(&mut self,
           level: Level,
           message: &str,
           span: MultiSpan,
           render_span: Option<RenderSpan>) {
        let sub = SubDiagnostic {
            level,
            message: vec![(message.to_owned(), Style::NoStyle)],
            span,
            render_span,
        };
        self.children.push(sub);
    }

    /// Convenience function for internal use, clients should use one of the
    /// public methods above.
    fn sub_with_highlights(&mut self,
                           level: Level,
                           message: Vec<(String, Style)>,
                           span: MultiSpan,
                           render_span: Option<RenderSpan>) {
        let sub = SubDiagnostic {
            level,
            message,
            span,
            render_span,
        };
        self.children.push(sub);
    }
}

impl SubDiagnostic {
    pub fn message(&self) -> String {
        self.message.iter().map(|i| i.0.to_owned()).collect::<String>()
    }

    pub fn styled_message(&self) -> &Vec<(String, Style)> {
        &self.message
    }
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

extern crate glutin;
extern crate cgmath;
extern crate serialize;

use core_types::{Size2, MInt};
use visualizer_types::{Color3, Color4, ColorId, MatId};
use mgl::Mgl;
use mgl;
use std::mem;
use camera::Camera;

// TODO: remove 'gl'
use gl;
use gl::types::{GLfloat, GLuint};

static VS_SRC: &'static str = "\
    #version 100\n\
    uniform mat4 mvp_mat;\n\
    attribute vec2 position;\n\
    void main() {\n\
        gl_Position = mvp_mat * vec4(position, 0.0, 1.0);\n\
    }\n\
";

static FS_SRC: &'static str = "\
    #version 100\n\
    precision mediump float;
    uniform vec4 col;\n\
    void main() {\n\
        gl_FragColor = col;\n\
    }\n\
";

fn get_win_size(window: &glutin::Window) -> Size2<MInt> {
    let (w, h) = window.get_inner_size().expect("Can`t get window size");
    Size2{w: w as MInt, h: h as MInt}
}

fn print_gl_info(mgl: &Mgl) {
    println!("GL_VERSION: {}", mgl.get_info(gl::VERSION));
    println!("GL_SHADING_LANGUAGE_VERSION: {}", mgl.get_info(gl::SHADING_LANGUAGE_VERSION));
    println!("GL_VENDOR: {}", mgl.get_info(gl::VENDOR));
    println!("GL_RENDERER: {}", mgl.get_info(gl::RENDERER));
    // println!("GL_EXTENSIONS: {}", mgl.get_info(gl::EXTENSIONS));
}

// TODO: Create 'Shader' class
fn compile_shaders(mgl: &Mgl) -> GLuint {
    let vs = mgl::compile_shader(&mgl.gl, VS_SRC, gl::VERTEX_SHADER);
    let fs = mgl::compile_shader(&mgl.gl, FS_SRC, gl::FRAGMENT_SHADER);
    mgl::link_program(&mgl.gl, vs, fs)
}

pub struct Visualizer {
    mgl: Mgl,
    window: glutin::Window,
    should_close: bool,
    color_counter: i32, // TODO: remove
    test_color: Color4,
    program: GLuint,
    color_uniform_location: ColorId,
    mvp_uniform_location: MatId,
    camera: Camera,
}

impl Visualizer {
    pub fn new() -> Visualizer {
        let window_builder = glutin::WindowBuilder::new().with_gl_version((2, 0));
        let window = window_builder.build().ok().expect("Can`t create window");
        unsafe {
            window.make_current();
        };
        let win_size = get_win_size(&window);
        let mut mgl = Mgl::new(|s| window.get_proc_address(s));
        print_gl_info(&mgl);
        let program = compile_shaders(&mgl);
        let color_uniform_location = ColorId {
            id: mgl.get_uniform(program, "col") as GLuint
        };
        let mvp_uniform_location = MatId {
            id: mgl.get_uniform(program, "mvp_mat") as GLuint
        };
        mgl.set_clear_color(Color3{r: 0.0, g: 0.0, b: 0.4});
        Visualizer {
            mgl: mgl,
            window: window,
            should_close: false,
            color_counter: 0,
            test_color: Color4{r: 0.0, g: 0.0, b: 0.0, a: 0.0},
            program: program,
            color_uniform_location: color_uniform_location,
            mvp_uniform_location: mvp_uniform_location,
            camera: Camera::new(win_size),
        }
    }

    pub fn is_running(&self) -> bool {
        !self.should_close
    }

    fn handle_events(&mut self) {
        let events = self.window.poll_events().collect::<Vec<_>>();
        if events.is_empty() {
            return;
        }
        println!("{}", events);
        for event in events.iter() {
            match *event {
                glutin::Event::Closed
                    | glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Q))
                    | glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Escape))
                => {
                    self.should_close = true;
                },
                _ => {},
            }
        }
    }

    fn update_test_color(&mut self) {
        self.test_color = match self.color_counter {
            0 => Color4{r: 1.0, g: 0.0, b: 0.0, a: 1.0},
            30 => Color4{r: 0.0, g: 1.0, b: 0.0, a: 1.0},
            60 => Color4{r: 0.0, g: 0.0, b: 1.0, a: 1.0},
            _ => self.test_color,
        };
        self.color_counter += 1;
        if self.color_counter > 90 {
            self.color_counter = -1;
        }
    }

    fn draw(&mut self) {
        self.mgl.clear_screen();
        let vertices: [GLfloat, ..3 * 3] = [
            0.0,  0.5, 0.0,
            0.5, -0.5, 0.0,
            -0.5, -0.5, 0.0,
        ];
        let win_size = get_win_size(&self.window);
        self.mgl.set_viewport(win_size);
        unsafe {
            self.mgl.gl.UseProgram(self.program);
        }
        self.mgl.set_uniform_color(self.color_uniform_location, &self.test_color);
        self.camera.add_z_angle(1.0); // TODO: move to events handling
        self.mgl.set_uniform_mat4f(
            self.mvp_uniform_location,
            &self.camera.mat(&self.mgl),
        );
        unsafe {
            self.mgl.gl.VertexAttribPointer(
                0, 3, gl::FLOAT, gl::FALSE, 0, mem::transmute(&vertices));
            self.mgl.gl.EnableVertexAttribArray(0);
            self.mgl.gl.DrawArrays(gl::TRIANGLES, 0, 3);
        }
        self.window.swap_buffers();
    }

    pub fn tick(&mut self) {
        self.handle_events();
        // self.logic();
        self.update_test_color();
        self.draw();
        // self.update_time();
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>visualizer.rs: refactored key handling<commit_after>// See LICENSE file for copyright and license details.

extern crate glutin;
extern crate cgmath;
extern crate serialize;

use core_types::{Size2, MInt};
use visualizer_types::{Color3, Color4, ColorId, MatId};
use mgl::Mgl;
use mgl;
use std::mem;
use camera::Camera;

// TODO: remove 'gl'
use gl;
use gl::types::{GLfloat, GLuint};

static VS_SRC: &'static str = "\
    #version 100\n\
    uniform mat4 mvp_mat;\n\
    attribute vec2 position;\n\
    void main() {\n\
        gl_Position = mvp_mat * vec4(position, 0.0, 1.0);\n\
    }\n\
";

static FS_SRC: &'static str = "\
    #version 100\n\
    precision mediump float;
    uniform vec4 col;\n\
    void main() {\n\
        gl_FragColor = col;\n\
    }\n\
";

fn get_win_size(window: &glutin::Window) -> Size2<MInt> {
    let (w, h) = window.get_inner_size().expect("Can`t get window size");
    Size2{w: w as MInt, h: h as MInt}
}

fn print_gl_info(mgl: &Mgl) {
    println!("GL_VERSION: {}", mgl.get_info(gl::VERSION));
    println!("GL_SHADING_LANGUAGE_VERSION: {}", mgl.get_info(gl::SHADING_LANGUAGE_VERSION));
    println!("GL_VENDOR: {}", mgl.get_info(gl::VENDOR));
    println!("GL_RENDERER: {}", mgl.get_info(gl::RENDERER));
    // println!("GL_EXTENSIONS: {}", mgl.get_info(gl::EXTENSIONS));
}

// TODO: Create 'Shader' class
fn compile_shaders(mgl: &Mgl) -> GLuint {
    let vs = mgl::compile_shader(&mgl.gl, VS_SRC, gl::VERTEX_SHADER);
    let fs = mgl::compile_shader(&mgl.gl, FS_SRC, gl::FRAGMENT_SHADER);
    mgl::link_program(&mgl.gl, vs, fs)
}

pub struct Visualizer {
    mgl: Mgl,
    window: glutin::Window,
    should_close: bool,
    color_counter: i32, // TODO: remove
    test_color: Color4,
    program: GLuint,
    color_uniform_location: ColorId,
    mvp_uniform_location: MatId,
    camera: Camera,
}

impl Visualizer {
    pub fn new() -> Visualizer {
        let window_builder = glutin::WindowBuilder::new().with_gl_version((2, 0));
        let window = window_builder.build().ok().expect("Can`t create window");
        unsafe {
            window.make_current();
        };
        let win_size = get_win_size(&window);
        let mut mgl = Mgl::new(|s| window.get_proc_address(s));
        print_gl_info(&mgl);
        let program = compile_shaders(&mgl);
        let color_uniform_location = ColorId {
            id: mgl.get_uniform(program, "col") as GLuint
        };
        let mvp_uniform_location = MatId {
            id: mgl.get_uniform(program, "mvp_mat") as GLuint
        };
        mgl.set_clear_color(Color3{r: 0.0, g: 0.0, b: 0.4});
        Visualizer {
            mgl: mgl,
            window: window,
            should_close: false,
            color_counter: 0,
            test_color: Color4{r: 0.0, g: 0.0, b: 0.0, a: 0.0},
            program: program,
            color_uniform_location: color_uniform_location,
            mvp_uniform_location: mvp_uniform_location,
            camera: Camera::new(win_size),
        }
    }

    pub fn is_running(&self) -> bool {
        !self.should_close
    }

    fn handle_events(&mut self) {
        let events = self.window.poll_events().collect::<Vec<_>>();
        if events.is_empty() {
            return;
        }
        println!("{}", events);
        for event in events.iter() {
            match *event {
                glutin::Event::Closed => {
                    self.should_close = true;
                },
                glutin::Event::KeyboardInput(_, _, Some(key)) => match key {
                    glutin::VirtualKeyCode::Q | glutin::VirtualKeyCode::Escape => {
                        self.should_close = true;
                    }
                    _ => {},
                },
                _ => {},
            }
        }
    }

    fn update_test_color(&mut self) {
        self.test_color = match self.color_counter {
            0 => Color4{r: 1.0, g: 0.0, b: 0.0, a: 1.0},
            30 => Color4{r: 0.0, g: 1.0, b: 0.0, a: 1.0},
            60 => Color4{r: 0.0, g: 0.0, b: 1.0, a: 1.0},
            _ => self.test_color,
        };
        self.color_counter += 1;
        if self.color_counter > 90 {
            self.color_counter = -1;
        }
    }

    fn draw(&mut self) {
        self.mgl.clear_screen();
        let vertices: [GLfloat, ..3 * 3] = [
            0.0,  0.5, 0.0,
            0.5, -0.5, 0.0,
            -0.5, -0.5, 0.0,
        ];
        let win_size = get_win_size(&self.window);
        self.mgl.set_viewport(win_size);
        unsafe {
            self.mgl.gl.UseProgram(self.program);
        }
        self.mgl.set_uniform_color(self.color_uniform_location, &self.test_color);
        self.camera.add_z_angle(1.0); // TODO: move to events handling
        self.mgl.set_uniform_mat4f(
            self.mvp_uniform_location,
            &self.camera.mat(&self.mgl),
        );
        unsafe {
            self.mgl.gl.VertexAttribPointer(
                0, 3, gl::FLOAT, gl::FALSE, 0, mem::transmute(&vertices));
            self.mgl.gl.EnableVertexAttribArray(0);
            self.mgl.gl.DrawArrays(gl::TRIANGLES, 0, 3);
        }
        self.window.swap_buffers();
    }

    pub fn tick(&mut self) {
        self.handle_events();
        // self.logic();
        self.update_test_color();
        self.draw();
        // self.update_time();
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>//! This provides wrappers around the StdoutTerminal and StderrTerminal types
//! that does not fail if StdoutTerminal etc can't be constructed, which happens
//! if TERM isn't defined.

use std::io;
use term;
use rustup_utils::tty;
use markdown::parser::{Block, Span, ListItem};
use markdown::tokenize;

pub use term::color;
pub use term::Attr;

pub trait Instantiable {
    fn instance() -> Self;
}

impl Instantiable for io::Stdout {
    fn instance() -> Self { io::stdout() }
}

impl Instantiable for io::Stderr {
    fn instance() -> Self { io::stderr() }
}

pub struct Terminal<T: Instantiable + io::Write>(Option<Box<term::Terminal<Output = T> + Send>>);
pub type StdoutTerminal = Terminal<io::Stdout>;
pub type StderrTerminal = Terminal<io::Stderr>;

pub fn stdout() -> StdoutTerminal {
    Terminal(term::stdout())
}

pub fn stderr() -> StderrTerminal {
    Terminal(term::stderr())
}

// Handles the wrapping of text written to the console
struct LineWrapper<'a, T: io::Write + 'a> {
    indent: u32,
    margin: u32,
    pos: u32,
    pub w: &'a mut T
}

impl<'a, T: io::Write + 'a> LineWrapper<'a, T> {
    // Just write a newline
    fn write_line(&mut self) {
        let _ = writeln!(self.w, "");
        // Reset column position to start of line
        self.pos = 0;
    }
    // Called before writing text to ensure indent is applied
    fn write_indent(&mut self) {
        if self.pos == 0 {
            // Write a space for each level of indent
            for _ in 0..self.indent {
                let _ = write!(self.w, " ");
            }
            self.pos = self.indent;
        }
    }
    // Write a non-breaking word
    fn write_word(&mut self, word: &str) {
        // Ensure correct indentation
        self.write_indent();
        let word_len = word.len() as u32;

        // If this word goes past the margin
        if self.pos + word_len > self.margin {
            // And adding a newline would give us more space
            if self.pos > self.indent {
                // Then add a newline!
                self.write_line();
                self.write_indent();
            }
        }

        // Write the word
        let _ = write!(self.w, "{}", word);
        self.pos += word_len;
    }
    fn write_space(&mut self) {
        if self.pos > self.indent {
            if self.pos < self.margin {
                self.write_word(" ");
            } else {
                self.write_line();
            }
        }
    }
    // Writes a span of text which wraps at the margin
    fn write_span(&mut self, text: &str) {
        // Allow words to wrap on whitespace
        let mut is_first = true;
        for word in text.split(char::is_whitespace) {
            if is_first {
                is_first = false;
            } else {
                self.write_space();
            }
            self.write_word(word);
        }
    }
    // Constructor
    fn new(w: &'a mut T, indent: u32, margin: u32) -> Self {
        LineWrapper {
            indent: indent,
            margin: margin,
            pos: indent,
            w: w
        }
    }
}

// Handles the formatting of text
struct LineFormatter<'a, T: Instantiable + io::Write + 'a> {
    wrapper: LineWrapper<'a, Terminal<T>>,
    attrs: Vec<Attr>
}

impl<'a, T: Instantiable + io::Write + 'a> LineFormatter<'a, T> {
    fn new(w: &'a mut Terminal<T>, indent: u32, margin: u32) -> Self {
        LineFormatter {
            wrapper: LineWrapper::new(w, indent, margin),
            attrs: Vec::new()
        }
    }
    fn push_attr(&mut self, attr: Attr) {
        self.attrs.push(attr);
        let _ = self.wrapper.w.attr(attr);
    }
    fn pop_attr(&mut self) {
        self.attrs.pop();
        let _ = self.wrapper.w.reset();
        for attr in &self.attrs {
            let _ = self.wrapper.w.attr(*attr);
        }
    }
    fn do_spans(&mut self, spans: Vec<Span>) {
        for span in spans {
            match span {
                Span::Break => {},
                Span::Text(text) => {
                    self.wrapper.write_span(&text);
                },
                Span::Code(code) => {
                    self.push_attr(Attr::Bold);
                    self.wrapper.write_word(&code);
                    self.pop_attr();
                },
                Span::Emphasis(spans) => {
                    self.push_attr(Attr::ForegroundColor(color::BRIGHT_RED));
                    self.do_spans(spans);
                    self.pop_attr();
                }
                _ => {}
            }
        }
    }
    fn do_block(&mut self, b: Block) {
        match b {
            Block::Header(spans, _) => {
                self.push_attr(Attr::ForegroundColor(color::BRIGHT_WHITE));
                self.wrapper.write_line();
                self.do_spans(spans);
                self.wrapper.write_line();
                self.pop_attr();
            },
            Block::CodeBlock(code) => {
                self.wrapper.write_line();
                self.wrapper.indent += 2;
                for line in code.lines() {
                    // Don't word-wrap code lines
                    self.wrapper.write_word(line);
                    self.wrapper.write_line();
                }
                self.wrapper.indent -= 2;
            },
            Block::Paragraph(spans) => {
                self.wrapper.write_line();
                self.do_spans(spans);
                self.wrapper.write_line();
            },
            Block::UnorderedList(items) => {
                self.wrapper.write_line();
                for item in items {
                    self.wrapper.indent += 2;
                    match item {
                        ListItem::Simple(spans) => {
                            self.do_spans(spans);
                        },
                        ListItem::Paragraph(blocks) => {
                            for block in blocks {
                                self.do_block(block);
                            }
                        }
                    }
                    self.wrapper.write_line();
                    self.wrapper.indent -= 2;
                }
            }
            _ => {}
        }
    }
}

impl<T: Instantiable + io::Write> io::Write for Terminal<T> {
    fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
        if let Some(ref mut t) = self.0 {
            t.write(buf)
        } else {
            let mut t = T::instance();
            t.write(buf)
        }
    }

    fn flush(&mut self) -> Result<(), io::Error> {
        if let Some(ref mut t) = self.0 {
            t.flush()
        } else {
            let mut t = T::instance();
            t.flush()
        }
    }
}

impl<T: Instantiable + io::Write> Terminal<T> {
    pub fn fg(&mut self, color: color::Color) -> Result<(), term::Error> {
        if !tty::stderr_isatty() { return Ok(()) }

        if let Some(ref mut t) = self.0 {
            t.fg(color)
        } else {
            Ok(())
        }
    }

    pub fn attr(&mut self, attr: Attr) -> Result<(), term::Error> {
        if !tty::stderr_isatty() { return Ok(()) }

        if let Some(ref mut t) = self.0 {
            if let Err(e) = t.attr(attr) {
                // If `attr` is not supported, try to emulate it
                match attr {
                    Attr::Bold => t.fg(color::BRIGHT_WHITE),
                    _ => Err(e)
                }
            } else {
                Ok(())
            }
        } else {
            Ok(())
        }
    }

    pub fn reset(&mut self) -> Result<(), term::Error> {
        if !tty::stderr_isatty() { return Ok(()) }

        if let Some(ref mut t) = self.0 {
            t.reset()
        } else {
            Ok(())
        }
    }

    pub fn md<S: AsRef<str>>(&mut self, content: S) {
        let mut f = LineFormatter::new(self, 0, 79);
        let blocks = tokenize(content.as_ref());
        for b in blocks {
            f.do_block(b);
        }
    }
}
<commit_msg>Check stdout is a tty before using terminal features<commit_after>//! This provides wrappers around the StdoutTerminal and StderrTerminal types
//! that does not fail if StdoutTerminal etc can't be constructed, which happens
//! if TERM isn't defined.

use std::io;
use term;
use rustup_utils::tty;
use markdown::parser::{Block, Span, ListItem};
use markdown::tokenize;

pub use term::color;
pub use term::Attr;

pub trait Instantiable {
    fn instance() -> Self;
}

impl Instantiable for io::Stdout {
    fn instance() -> Self { io::stdout() }
}

impl Instantiable for io::Stderr {
    fn instance() -> Self { io::stderr() }
}

pub trait Isatty {
    fn isatty() -> bool;
}

impl Isatty for io::Stdout {
    fn isatty() -> bool {
        tty::stdout_isatty()
    }
}

impl Isatty for io::Stderr {
    fn isatty() -> bool {
        tty::stderr_isatty()
    }
}

pub struct Terminal<T>(Option<Box<term::Terminal<Output = T> + Send>>)
    where T: Instantiable + Isatty + io::Write;
pub type StdoutTerminal = Terminal<io::Stdout>;
pub type StderrTerminal = Terminal<io::Stderr>;

pub fn stdout() -> StdoutTerminal {
    Terminal(term::stdout())
}

pub fn stderr() -> StderrTerminal {
    Terminal(term::stderr())
}

// Handles the wrapping of text written to the console
struct LineWrapper<'a, T: io::Write + 'a> {
    indent: u32,
    margin: u32,
    pos: u32,
    pub w: &'a mut T
}

impl<'a, T: io::Write + 'a> LineWrapper<'a, T> {
    // Just write a newline
    fn write_line(&mut self) {
        let _ = writeln!(self.w, "");
        // Reset column position to start of line
        self.pos = 0;
    }
    // Called before writing text to ensure indent is applied
    fn write_indent(&mut self) {
        if self.pos == 0 {
            // Write a space for each level of indent
            for _ in 0..self.indent {
                let _ = write!(self.w, " ");
            }
            self.pos = self.indent;
        }
    }
    // Write a non-breaking word
    fn write_word(&mut self, word: &str) {
        // Ensure correct indentation
        self.write_indent();
        let word_len = word.len() as u32;

        // If this word goes past the margin
        if self.pos + word_len > self.margin {
            // And adding a newline would give us more space
            if self.pos > self.indent {
                // Then add a newline!
                self.write_line();
                self.write_indent();
            }
        }

        // Write the word
        let _ = write!(self.w, "{}", word);
        self.pos += word_len;
    }
    fn write_space(&mut self) {
        if self.pos > self.indent {
            if self.pos < self.margin {
                self.write_word(" ");
            } else {
                self.write_line();
            }
        }
    }
    // Writes a span of text which wraps at the margin
    fn write_span(&mut self, text: &str) {
        // Allow words to wrap on whitespace
        let mut is_first = true;
        for word in text.split(char::is_whitespace) {
            if is_first {
                is_first = false;
            } else {
                self.write_space();
            }
            self.write_word(word);
        }
    }
    // Constructor
    fn new(w: &'a mut T, indent: u32, margin: u32) -> Self {
        LineWrapper {
            indent: indent,
            margin: margin,
            pos: indent,
            w: w
        }
    }
}

// Handles the formatting of text
struct LineFormatter<'a, T: Instantiable + Isatty + io::Write + 'a> {
    wrapper: LineWrapper<'a, Terminal<T>>,
    attrs: Vec<Attr>
}

impl<'a, T: Instantiable + Isatty + io::Write + 'a> LineFormatter<'a, T> {
    fn new(w: &'a mut Terminal<T>, indent: u32, margin: u32) -> Self {
        LineFormatter {
            wrapper: LineWrapper::new(w, indent, margin),
            attrs: Vec::new()
        }
    }
    fn push_attr(&mut self, attr: Attr) {
        self.attrs.push(attr);
        let _ = self.wrapper.w.attr(attr);
    }
    fn pop_attr(&mut self) {
        self.attrs.pop();
        let _ = self.wrapper.w.reset();
        for attr in &self.attrs {
            let _ = self.wrapper.w.attr(*attr);
        }
    }
    fn do_spans(&mut self, spans: Vec<Span>) {
        for span in spans {
            match span {
                Span::Break => {},
                Span::Text(text) => {
                    self.wrapper.write_span(&text);
                },
                Span::Code(code) => {
                    self.push_attr(Attr::Bold);
                    self.wrapper.write_word(&code);
                    self.pop_attr();
                },
                Span::Emphasis(spans) => {
                    self.push_attr(Attr::ForegroundColor(color::BRIGHT_RED));
                    self.do_spans(spans);
                    self.pop_attr();
                }
                _ => {}
            }
        }
    }
    fn do_block(&mut self, b: Block) {
        match b {
            Block::Header(spans, _) => {
                self.push_attr(Attr::ForegroundColor(color::BRIGHT_WHITE));
                self.wrapper.write_line();
                self.do_spans(spans);
                self.wrapper.write_line();
                self.pop_attr();
            },
            Block::CodeBlock(code) => {
                self.wrapper.write_line();
                self.wrapper.indent += 2;
                for line in code.lines() {
                    // Don't word-wrap code lines
                    self.wrapper.write_word(line);
                    self.wrapper.write_line();
                }
                self.wrapper.indent -= 2;
            },
            Block::Paragraph(spans) => {
                self.wrapper.write_line();
                self.do_spans(spans);
                self.wrapper.write_line();
            },
            Block::UnorderedList(items) => {
                self.wrapper.write_line();
                for item in items {
                    self.wrapper.indent += 2;
                    match item {
                        ListItem::Simple(spans) => {
                            self.do_spans(spans);
                        },
                        ListItem::Paragraph(blocks) => {
                            for block in blocks {
                                self.do_block(block);
                            }
                        }
                    }
                    self.wrapper.write_line();
                    self.wrapper.indent -= 2;
                }
            }
            _ => {}
        }
    }
}

impl<T: Instantiable + Isatty + io::Write> io::Write for Terminal<T> {
    fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
        if let Some(ref mut t) = self.0 {
            t.write(buf)
        } else {
            let mut t = T::instance();
            t.write(buf)
        }
    }

    fn flush(&mut self) -> Result<(), io::Error> {
        if let Some(ref mut t) = self.0 {
            t.flush()
        } else {
            let mut t = T::instance();
            t.flush()
        }
    }
}

impl<T: Instantiable + Isatty + io::Write> Terminal<T> {
    pub fn fg(&mut self, color: color::Color) -> Result<(), term::Error> {
        if !T::isatty() { return Ok(()) }

        if let Some(ref mut t) = self.0 {
            t.fg(color)
        } else {
            Ok(())
        }
    }

    pub fn attr(&mut self, attr: Attr) -> Result<(), term::Error> {
        if !T::isatty() { return Ok(()) }

        if let Some(ref mut t) = self.0 {
            if let Err(e) = t.attr(attr) {
                // If `attr` is not supported, try to emulate it
                match attr {
                    Attr::Bold => t.fg(color::BRIGHT_WHITE),
                    _ => Err(e)
                }
            } else {
                Ok(())
            }
        } else {
            Ok(())
        }
    }

    pub fn reset(&mut self) -> Result<(), term::Error> {
        if !T::isatty() { return Ok(()) }

        if let Some(ref mut t) = self.0 {
            t.reset()
        } else {
            Ok(())
        }
    }

    pub fn md<S: AsRef<str>>(&mut self, content: S) {
        let mut f = LineFormatter::new(self, 0, 79);
        let blocks = tokenize(content.as_ref());
        for b in blocks {
            f.do_block(b);
        }
    }
}
<|endoftext|>


<commit_before>use {
    // Error,
    // MetaReader,
    Parameter,
    Rule,
    Token,
};

/// Stores information about whitespace.
pub struct Whitespace {
    /// Whether the whitespace is optional or required.
    pub optional: bool,
}

/*
impl MetaReader for Whitespace {
    fn start_node(&mut self, name: &str) -> Option<Error> {
        Some(Error::NotSupported)
    }
    fn end_node(&mut self) -> Option<Error> {
        Some(Error::NotSupported)
    }
    fn start_optional(&mut self) -> Option<Error> {
        Some(Error::NotSupported)
    }
    fn end_optional(&mut self) -> Option<Error>;
    fn start_select(&mut self) -> Option<Error>;
    fn reset_select(&mut self) -> Option<Error>;
    fn end_select(&mut self) -> Option<Error>;
    fn set_as_bool(&mut self, name: &str, val: bool) -> Option<Error>;
    fn set_as_str(&mut self, name: &str, val: &str) -> Option<Error>;
}
*/

/// A hard coded parameter rule for whitespace.
pub static WHITESPACE: Parameter<'static> = Parameter {
    name: "whitespace",
    args: &["optional"],
    value: None,
    body: &[
        Rule::Whitespace(Whitespace { optional: true }),
        Rule::Token(Token {
            text: "whitespace",
            inverted: None,
            predicate: None
        }),
        Rule::Select(&[
            Rule::Token(Token {
                text: "?",
                inverted: Some(false),
                predicate: Some("optional"),
            }),
            Rule::Token(Token {
                text: "!",
                inverted: Some(true),
                predicate: Some("optional"),
            }),
        ]),
    ],
};
<commit_msg>Removed some old code<commit_after>use {
    // Error,
    // MetaReader,
    Parameter,
    Rule,
    Token,
};

/// Stores information about whitespace.
pub struct Whitespace {
    /// Whether the whitespace is optional or required.
    pub optional: bool,
}

/// A hard coded parameter rule for whitespace.
pub static WHITESPACE: Parameter<'static> = Parameter {
    name: "whitespace",
    args: &["optional"],
    value: None,
    body: &[
        Rule::Whitespace(Whitespace { optional: true }),
        Rule::Token(Token {
            text: "whitespace",
            inverted: None,
            predicate: None
        }),
        Rule::Select(&[
            Rule::Token(Token {
                text: "?",
                inverted: Some(false),
                predicate: Some("optional"),
            }),
            Rule::Token(Token {
                text: "!",
                inverted: Some(true),
                predicate: Some("optional"),
            }),
        ]),
    ],
};
<|endoftext|>